fix(run): run Python modules with relative imports with -m (#1338)

Run or Debug on a Python file started it as a script
(`python src/tasks/cli.py`), so a module of a package that imports
relatively (`from .models import TaskList`) always failed with
"attempted relative import with no known parent package".

A file with relative imports now runs as `python -m package.module`
from the directory above its top package (the enclosing directories
with `__init__.py`, read once and re-read when one is added or
removed), with a venv-relative interpreter resolved against the project
root. Files without relative imports still run as scripts.
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-11-05 02:01:35 +08:00
1 джерело fd69664ca7
коміт 70a7c6dd2c
5 files changed
+104 -1

No files matched your search

+30
Переглянути файл
@@ -0,0 +1,30 @@
/**
* Which directories are Python packages (`__init__.py`), for running a module with relative
* imports as `python -m package.module`. Read once per directory.
*/
import { call, commands, isTauri } from "@/platform/ipc";
const known = new Map<string, boolean>();
export function invalidatePythonPackages() {
known.clear();
}
/** Whether `dir` is a package, when already read. */
export function isPythonPackage(dir: string): boolean | undefined {
return known.get(dir);
}
const parent = (p: string) => (p.includes("/") ? p.slice(0, p.lastIndexOf("/")) || "/" : "");
/** Reads the packages enclosing `path`'s directory, up to the first directory that isn't one. */
export async function loadPythonPackages(path: string): Promise<void> {
if (!isTauri()) return;
for (let dir = parent(parent(path)); dir; dir = parent(dir)) {
if (!known.has(dir)) {
const kind = await call(commands.fsEntryKind(`${dir}/__init__.py`)).catch(() => null);
known.set(dir, kind === "file");
}
if (!known.get(dir) || dir === "/") return;
}
}