This commit is contained in:
2026-01-25 21:16:17 +08:00
parent bd77dc5182
commit 721832e556

View File

@@ -16,8 +16,8 @@ const PYTHON_CONFIG_FILE = "~/.config/python-config.json";
const PYTHON_VENV_DEFAULT_BASE_DIR = "~/.venv/"; const PYTHON_VENV_DEFAULT_BASE_DIR = "~/.venv/";
interface PythonConfig { interface PythonConfig {
default_version?: string; // default_version?: string;
default_profile?: string; // default_profile?: string;
python_venv_base_path?: string; python_venv_base_path?: string;
versions: Map<string, PythonVersion>; versions: Map<string, PythonVersion>;
profiles?: Map<string, PythonVenv>; profiles?: Map<string, PythonVenv>;
@@ -64,34 +64,37 @@ async function findVirtualEnv(pythonVenvVersion: string): Promise<PythonVenv> {
return pythonVenv; return pythonVenv;
} }
async function newVirtualEnv(pythonVersion: string | null, pythonVenv: string) { async function addVirtualEnv(pythonVersion: string | null, pythonVenv: string) {
const pythonConfig = await loadPythonConfig(); const pythonConfig = await loadPythonConfig();
const selectedPythonVersion = pythonVersion || if (!pythonVersion) {
pythonConfig.default_version || null;
if (!selectedPythonVersion) {
throw `No Python version assigned.`; throw `No Python version assigned.`;
} }
if (!selectedPythonVersion) { if (!pythonVenv) {
throw `No Python venv assigned.`; throw `No Python venv assigned.`;
} }
const pythonVersionProfile = pythonConfig.versions[pythonVersion]; const pythonVersionProfile = pythonConfig.versions[pythonVersion];
if (!pythonVersionProfile) { if (!pythonVersionProfile) {
throw `Python version: ${pythonVersion} not found`; throw `Python version: ${pythonVersion} not found`;
} }
log.success(`Found Python version: ${pythonVersion}`); const realPythonVersion = pythonVersionProfile.version || pythonVersion;
const pythonVenvProfile = pythonConfig.profiles[pythonVenv]; log.success(
`Found Python version: ${realPythonVersion}`,
);
const pythonVenvProfile = pythonConfig.profiles &&
pythonConfig.profiles[pythonVenv];
if (pythonVenvProfile) { if (pythonVenvProfile) {
throw `Python venv already exists: ${pythonVenv}`; throw `Python venv already exists: ${pythonVenv}`;
} }
const pythonVenvBaseDir = resolveFilename( const pythonVenvBaseDir = resolveFilename(
pythonConfig.python_venv_base_path || PYTHON_VENV_DEFAULT_BASE_DIR, pythonConfig.python_venv_base_path || PYTHON_VENV_DEFAULT_BASE_DIR,
); );
if (!existsPath(pythonVenvBaseDir)) { if (!await existsPath(pythonVenvBaseDir)) {
log.info(`Make python venv base dir: ${pythonVenvBaseDir}`); log.info(`Make python venv base dir: ${pythonVenvBaseDir}`);
Deno.mkdirSync(pythonVenvBaseDir); Deno.mkdirSync(pythonVenvBaseDir);
} }
const pythonVenvDir = joinPath(pythonVenvBaseDir, pythonVenv); const pythonVenvLeafDir = `${pythonVenv}_python_${realPythonVersion}`;
if (existsPath(pythonVenvDir)) { const pythonVenvDir = joinPath(pythonVenvBaseDir, pythonVenvLeafDir);
if (await existsPath(pythonVenvDir)) {
throw `Python venv: ${pythonVenvDir} already exists`; throw `Python venv: ${pythonVenvDir} already exists`;
} }
@@ -100,10 +103,19 @@ async function newVirtualEnv(pythonVersion: string | null, pythonVenv: string) {
log.success(`Found Python: ${python3Cmd}`); log.success(`Found Python: ${python3Cmd}`);
const pythonVenvArgs = ["-m", "venv", pythonVenvDir]; const pythonVenvArgs = ["-m", "venv", pythonVenvDir];
log.info( log.info("Create Python venv, python:", [python3Cmd, pythonVenvArgs]);
`Create Python venv, python: ${python3Cmd}, args: ${pythonVenvArgs}`,
);
await execCommandShell(python3Cmd, pythonVenvArgs); await execCommandShell(python3Cmd, pythonVenvArgs);
const newPythonVenvProfile: PythonVenv = {
version: realPythonVersion,
path: pythonVenvDir,
comment: `Python venv:${pythonVenv}, version: ${realPythonVersion}`,
};
if (!pythonConfig.profiles) {
pythonConfig.profiles = {};
}
pythonConfig.profiles[pythonVenv] = newPythonVenvProfile;
await savePythonConfig(pythonConfig);
} }
async function isFile(path: string): Promise<boolean> { async function isFile(path: string): Promise<boolean> {
@@ -118,7 +130,8 @@ function handleHelp(_args: string[]) {
python.ts python - management python version [alias: py] python.ts python - management python version [alias: py]
python.ts add-python - add python version [alias: py] python.ts add-python - add python version [alias: py]
python.ts venv - management python virtual environment`, python.ts venv - management python virtual environment
python.ts add-venv - add python virtual environment`,
); );
// source <(cat ~/.venv-python-3.13.5/bin/activate) // source <(cat ~/.venv-python-3.13.5/bin/activate)
// source <(python.ts venv test1) // source <(python.ts venv test1)
@@ -246,35 +259,84 @@ async function handleAddPython(args: string[]) {
} }
async function handleVenv(args: string[]) { async function handleVenv(args: string[]) {
const flags = parseArgs(Deno.args, { const flags = parseArgs(args, {
boolean: ["help"], boolean: ["help"],
string: ["version"], string: ["name"],
alias: {
n: "name",
},
});
if (flags.help) {
console.log(`Help massage for venv
python.ts venv [--name|-n filter-name]`);
return;
}
let pythonConfig = await loadPythonConfig();
if (!pythonConfig.profiles) {
console.warn("No Python virtual environments found");
return;
}
let totalProfilesCount = 0;
let filterProfilesCount = 0;
Object.entries(pythonConfig.profiles).forEach(
([venv, pythonVenvProfile]) => {
totalProfilesCount++;
if (flags.name && venv.indexOf(flags.name) < 0) {
return;
}
filterProfilesCount++;
console.log("-", venv, pythonVenvProfile);
},
);
if (totalProfilesCount !== filterProfilesCount) {
console.log(
`\nFilter profiles with '${flags.name}': ${filterProfilesCount} of ${totalProfilesCount}`,
);
}
console.log(
"\nNOTE: use --name|-n filter virtual environments, use `source <(python.rs active[-venv] venv-name)`",
);
}
async function handleAddVenv(args: string[]) {
const flags = parseArgs(args, {
boolean: ["help"],
string: ["version", "venv"],
alias: { alias: {
V: "version", V: "version",
}, },
}); });
if (flags.help) { if (args.length === 0 || flags.help) {
console.log("Help massage for venv"); console.log(`Help massage for add-venv
python.ts add-venv --version 3.10 --venv test-env`);
return; return;
} }
if (!flags.version) { if (!flags.version) {
log.warn("Version missing"); log.error("Version missing");
return; return;
} }
const pythonVirtualEnv = await findVirtualEnv(flags.version); if (!flags.venv) {
log.error("Venv is missing");
// TODO return;
}
await addVirtualEnv(flags.version, flags.venv);
} }
async function main() { async function main() {
const args = parseArgs(Deno.args); const args = Deno.args;
const [subcommand, ...remainingArgs] = args._;
if (!subcommand) { if (args.length === 0) {
log.warn("Subcommand not found, `python.ts help` for help message"); log.warn("Subcommand not found, `python.ts help` for help message");
return; return;
} }
const subcommand = args[0];
const remainingArgs = args.slice(1);
switch (subcommand) { switch (subcommand) {
case "help": case "help":
handleHelp(remainingArgs); handleHelp(remainingArgs);
@@ -290,6 +352,9 @@ async function main() {
case "venv": case "venv":
await handleVenv(remainingArgs); await handleVenv(remainingArgs);
break; break;
case "add-venv":
await handleAddVenv(remainingArgs);
break;
default: default:
log.error(`Unknown subcommand: ${subcommand}`); log.error(`Unknown subcommand: ${subcommand}`);
break; break;