diff --git a/src/features/run/configs.test.ts b/src/features/run/configs.test.ts index ce70a443f..162e0adf8 100644 --- a/src/features/run/configs.test.ts +++ b/src/features/run/configs.test.ts @@ -271,4 +271,26 @@ describe("context configuration", () => { const uv = [cfg({ id: "pytest", kind: "pytest", command: "uv", args: ["run", "pytest"], isTest: true })]; expect(contextConfig("tools/gen.py", uv)).toMatchObject({ command: "uv", args: ["run", "python", "tools/gen.py"] }); }); + + it("takes the interpreter from a Django runserver config without its arguments", () => { + const runserver = (command: string, args: string[]) => + cfg({ id: "django:runserver", kind: "python", command, args: [...args, "manage.py", "runserver"] }); + expect(contextConfig("tools/seed.py", [runserver(".venv/bin/python", [])])).toMatchObject({ + command: ".venv/bin/python", + args: ["tools/seed.py"], + }); + expect(contextConfig("tools/seed.py", [runserver("uv", ["run", "python"])])).toMatchObject({ + command: "uv", + args: ["run", "python", "tools/seed.py"], + }); + expect(contextConfig("worker/test_worker.py", [runserver(".venv/bin/python", [])])).toMatchObject({ + args: ["-m", "pytest", "worker/test_worker.py"], + }); + }); + + it("keeps the interpreter of a plain python config", () => { + const plain = [cfg({ id: "python:module:app", kind: "python", command: "python3", args: ["-m", "app"] })]; + expect(contextConfig("tools/gen.py", plain)).toMatchObject({ command: "python3", args: ["tools/gen.py"] }); + expect(contextConfig("tools/gen.py", [])).toMatchObject({ command: "python3", args: ["tools/gen.py"] }); + }); }); diff --git a/src/features/run/context.ts b/src/features/run/context.ts index 768e3c017..c71bf6e6d 100644 --- a/src/features/run/context.ts +++ b/src/features/run/context.ts @@ -91,8 +91,11 @@ function derived(base: RunConfig, relPath: string, patch: Partial): R export function projectPython(configs: RunConfig[]): { command: string; prefix: string[] } | null { const py = configs.find((c) => c.kind === "python"); if (py) { - const m = py.args.indexOf("-m"); - return { command: py.command, prefix: m >= 0 ? py.args.slice(0, m) : py.args.filter((a) => !a.endsWith(".py")) }; + // The interpreter part ends where the program starts: `-m`, or the script (`manage.py`). What follows + // (`runserver`, `test`…) belongs to that program, never to the interpreter. + const end = py.args.findIndex((a) => a === "-m" || a.endsWith(".py")); + const python = py.args.findIndex((a) => /^python[\d.]*$/.test(a)); + return { command: py.command, prefix: py.args.slice(0, end >= 0 ? end : python + 1) }; } const pytest = configs.find((c) => c.kind === "pytest"); if (!pytest) return null;