python.ts
This commit is contained in:
179
python-ts/main.ts
Normal file → Executable file
179
python-ts/main.ts
Normal file → Executable file
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env runts -- --allow-env --allow-run
|
#!/usr/bin/env runts -- --allow-env --allow-run --allow-import --allow-read --allow-write
|
||||||
|
|
||||||
import {
|
import {
|
||||||
execCommand,
|
execCommand,
|
||||||
@@ -9,16 +9,15 @@ import {
|
|||||||
ProcessBar,
|
ProcessBar,
|
||||||
readFileToString,
|
readFileToString,
|
||||||
resolveFilename,
|
resolveFilename,
|
||||||
|
term,
|
||||||
|
writeStringToFile,
|
||||||
} from "https://global.hatter.ink/script/get/@16/deno-commons-mod.ts";
|
} from "https://global.hatter.ink/script/get/@16/deno-commons-mod.ts";
|
||||||
import { parseArgs } from "jsr:@std/cli/parse-args";
|
import { parseArgs } from "jsr:@std/cli/parse-args";
|
||||||
import {writeStringToFile} from "../libraries/deno-commons-mod.ts";
|
|
||||||
|
|
||||||
const PYTHON_CONFIG_FILE = "~/.config/python-config.json";
|
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_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>;
|
||||||
@@ -36,6 +35,11 @@ interface PythonVenv {
|
|||||||
comment?: string;
|
comment?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function isFile(path: string): Promise<boolean> {
|
||||||
|
const fileInfo = await Deno.stat(path);
|
||||||
|
return fileInfo?.isFile;
|
||||||
|
}
|
||||||
|
|
||||||
async function loadPythonConfig(): Promise<PythonConfig> {
|
async function loadPythonConfig(): Promise<PythonConfig> {
|
||||||
const pythonConfigFile = resolveFilename(PYTHON_CONFIG_FILE);
|
const pythonConfigFile = resolveFilename(PYTHON_CONFIG_FILE);
|
||||||
const pythonConfigJson = await readFileToString(pythonConfigFile);
|
const pythonConfigJson = await readFileToString(pythonConfigFile);
|
||||||
@@ -53,25 +57,56 @@ async function savePythonConfig(pythonConfig: PythonConfig): Promise<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findVirtualEnv(pythonVenvVersion: string): Promise<PythonVenv> {
|
function handleHelp(_args: string[]) {
|
||||||
const pythonConfig = await loadPythonConfig();
|
const help = [];
|
||||||
if (!pythonConfig.profiles) {
|
help.push(
|
||||||
throw "No Python venvs configured";
|
`${
|
||||||
|
term.green("python.ts")
|
||||||
|
} - Python version and virtual environment management tool
|
||||||
|
|
||||||
|
${term.green("python.ts")} ${
|
||||||
|
term.bold("python")
|
||||||
|
} - management python version ${
|
||||||
|
term.yellow("[alias: py, ver, version]")
|
||||||
}
|
}
|
||||||
const pythonVenv = pythonConfig.profiles[pythonVenvVersion];
|
${term.green("python.ts")} ${term.bold("add-python")} - add python version ${
|
||||||
if (!pythonVenv) {
|
term.yellow("[alias: add-py]")
|
||||||
throw `Python venv not found: ${pythonVenvVersion}`;
|
|
||||||
}
|
}
|
||||||
return pythonVenv;
|
${term.green("python.ts")} ${
|
||||||
|
term.bold("venv")
|
||||||
|
} - management python virtual environment ${
|
||||||
|
term.yellow("[alias: env]")
|
||||||
|
}
|
||||||
|
${term.green("python.ts")} ${
|
||||||
|
term.bold("add-venv")
|
||||||
|
} - add python virtual environment ${term.yellow("[alias: add-env]")}
|
||||||
|
${term.green("python.ts")} ${
|
||||||
|
term.bold("remove-venv")
|
||||||
|
} - remove python virtual environment ${
|
||||||
|
term.yellow("[alias: rm-venv, rm-env]")
|
||||||
|
}
|
||||||
|
${term.green("python.ts")} ${
|
||||||
|
term.bold("active-venv")
|
||||||
|
} - active python virtual environment ${
|
||||||
|
term.yellow("[alias: active, active-env]")
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
// source <(cat ~/.venv-python-3.13.5/bin/activate)
|
||||||
|
// source <(python.ts venv test1)
|
||||||
|
console.log(help.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addVirtualEnv(pythonVersion: string | null, pythonVenv: string) {
|
async function addVirtualEnv(
|
||||||
|
pythonVersion: string | null,
|
||||||
|
pythonVenv: string,
|
||||||
|
comment?: string,
|
||||||
|
) {
|
||||||
const pythonConfig = await loadPythonConfig();
|
const pythonConfig = await loadPythonConfig();
|
||||||
if (!pythonVersion) {
|
if (!pythonVersion) {
|
||||||
throw `No Python version assigned.`;
|
throw `No Python version assigned.`;
|
||||||
}
|
}
|
||||||
if (!pythonVenv) {
|
if (!pythonVenv) {
|
||||||
throw `No Python venv assigned.`;
|
throw `No Python virtual environment assigned.`;
|
||||||
}
|
}
|
||||||
const pythonVersionProfile = pythonConfig.versions[pythonVersion];
|
const pythonVersionProfile = pythonConfig.versions[pythonVersion];
|
||||||
if (!pythonVersionProfile) {
|
if (!pythonVersionProfile) {
|
||||||
@@ -84,13 +119,15 @@ async function addVirtualEnv(pythonVersion: string | null, pythonVenv: string) {
|
|||||||
const pythonVenvProfile = pythonConfig.profiles &&
|
const pythonVenvProfile = pythonConfig.profiles &&
|
||||||
pythonConfig.profiles[pythonVenv];
|
pythonConfig.profiles[pythonVenv];
|
||||||
if (pythonVenvProfile) {
|
if (pythonVenvProfile) {
|
||||||
throw `Python venv already exists: ${pythonVenv}`;
|
throw `Python virtual environment 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 (!await existsPath(pythonVenvBaseDir)) {
|
if (!await existsPath(pythonVenvBaseDir)) {
|
||||||
log.info(`Make python venv base dir: ${pythonVenvBaseDir}`);
|
log.info(
|
||||||
|
`Make python virtual environment base dir: ${pythonVenvBaseDir}`,
|
||||||
|
);
|
||||||
Deno.mkdirSync(pythonVenvBaseDir);
|
Deno.mkdirSync(pythonVenvBaseDir);
|
||||||
}
|
}
|
||||||
const pythonVenvLeafDir = `${pythonVenv}_python_${realPythonVersion}`;
|
const pythonVenvLeafDir = `${pythonVenv}_python_${realPythonVersion}`;
|
||||||
@@ -105,12 +142,18 @@ async function addVirtualEnv(pythonVersion: string | null, pythonVenv: string) {
|
|||||||
const pythonVenvArgs = ["-m", "venv", pythonVenvDir];
|
const pythonVenvArgs = ["-m", "venv", pythonVenvDir];
|
||||||
|
|
||||||
log.info("Create Python venv, python:", [python3Cmd, pythonVenvArgs]);
|
log.info("Create Python venv, python:", [python3Cmd, pythonVenvArgs]);
|
||||||
|
await new ProcessBar("Creating Python virtual environment").call(
|
||||||
|
async () => {
|
||||||
await execCommandShell(python3Cmd, pythonVenvArgs);
|
await execCommandShell(python3Cmd, pythonVenvArgs);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const newPythonVenvProfile: PythonVenv = {
|
const newPythonVenvProfile: PythonVenv = {
|
||||||
version: realPythonVersion,
|
version: realPythonVersion,
|
||||||
path: pythonVenvDir,
|
path: pythonVenvDir,
|
||||||
comment: `Python venv:${pythonVenv}, version: ${realPythonVersion}`,
|
comment: `Python venv:${pythonVenv}, version: ${realPythonVersion}${
|
||||||
|
comment ? (", user comment: " + comment) : ""
|
||||||
|
}`,
|
||||||
};
|
};
|
||||||
if (!pythonConfig.profiles) {
|
if (!pythonConfig.profiles) {
|
||||||
pythonConfig.profiles = {};
|
pythonConfig.profiles = {};
|
||||||
@@ -119,40 +162,14 @@ async function addVirtualEnv(pythonVersion: string | null, pythonVenv: string) {
|
|||||||
await savePythonConfig(pythonConfig);
|
await savePythonConfig(pythonConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isFile(path: string): Promise<boolean> {
|
|
||||||
const fileInfo = await Deno.stat(path);
|
|
||||||
return fileInfo?.isFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleHelp(_args: string[]) {
|
|
||||||
const help = [];
|
|
||||||
help.push(
|
|
||||||
`python.ts - Python version and virtual environment management tool
|
|
||||||
|
|
||||||
python.ts python - management python version [alias: py]
|
|
||||||
python.ts add-python - add python version [alias: py]
|
|
||||||
python.ts venv - management python virtual environment
|
|
||||||
python.ts add-venv - add python virtual environment
|
|
||||||
python.ts remove-venv - remove python virtual environment`,
|
|
||||||
);
|
|
||||||
// source <(cat ~/.venv-python-3.13.5/bin/activate)
|
|
||||||
// source <(python.ts venv test1)
|
|
||||||
console.log(help.join("\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handlePython(args: string[]) {
|
async function handlePython(args: string[]) {
|
||||||
const flags = parseArgs(Deno.args, {
|
const flags = parseArgs(Deno.args, {
|
||||||
boolean: ["help"],
|
boolean: ["help"],
|
||||||
string: ["version"],
|
|
||||||
alias: {
|
|
||||||
V: "version",
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
if (flags.help) {
|
if (flags.help) {
|
||||||
console.log("Help massage for python");
|
console.log("Help massage for python");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!flags.version) {
|
|
||||||
const pythonConfig = await loadPythonConfig();
|
const pythonConfig = await loadPythonConfig();
|
||||||
if (!pythonConfig.versions) {
|
if (!pythonConfig.versions) {
|
||||||
log.error("No Python versions configured");
|
log.error("No Python versions configured");
|
||||||
@@ -176,17 +193,11 @@ async function handlePython(args: string[]) {
|
|||||||
maxVersionLength - version.length,
|
maxVersionLength - version.length,
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
`- Python ${version} ${versionPadding}: ${pythonVersion.path} [version: ${
|
"- Python:",
|
||||||
pythonVersion.version || "unknown"
|
version,
|
||||||
}]`,
|
pythonVersion,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pythonVirtualEnv = await findVirtualEnv(flags.version);
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getPythonVersion(pythonBinPath: string): Promise<string> {
|
async function getPythonVersion(pythonBinPath: string): Promise<string> {
|
||||||
@@ -204,8 +215,10 @@ async function handleAddPython(args: string[]) {
|
|||||||
boolean: ["help"],
|
boolean: ["help"],
|
||||||
string: ["path"],
|
string: ["path"],
|
||||||
});
|
});
|
||||||
if (flags.help) {
|
if (args.length === 0 || flags.help) {
|
||||||
console.log("Help massage for python add-python");
|
console.log(`Help massage for python add-python
|
||||||
|
|
||||||
|
python.ts add-python --path python-path`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!flags.path) {
|
if (!flags.path) {
|
||||||
@@ -290,7 +303,14 @@ python.ts venv [--name|-n filter-name]`);
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
filterProfilesCount++;
|
filterProfilesCount++;
|
||||||
console.log("-", venv, pythonVenvProfile);
|
console.log(
|
||||||
|
"-",
|
||||||
|
venv,
|
||||||
|
pythonVenvProfile,
|
||||||
|
`, active virtual environment command: ${
|
||||||
|
term.green("source <(python.ts active-venv " + venv + ")")
|
||||||
|
}`,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -307,15 +327,16 @@ python.ts venv [--name|-n filter-name]`);
|
|||||||
async function handleAddVenv(args: string[]) {
|
async function handleAddVenv(args: string[]) {
|
||||||
const flags = parseArgs(args, {
|
const flags = parseArgs(args, {
|
||||||
boolean: ["help"],
|
boolean: ["help"],
|
||||||
string: ["version", "venv"],
|
string: ["version", "venv", "comment"],
|
||||||
alias: {
|
alias: {
|
||||||
V: "version",
|
V: "version",
|
||||||
|
c: "comment",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (args.length === 0 || flags.help) {
|
if (args.length === 0 || flags.help) {
|
||||||
console.log(`Help massage for add-venv
|
console.log(`Help massage for add-venv
|
||||||
|
|
||||||
python.ts add-venv --version 3.10 --venv test-env`);
|
python.ts add-venv --version 3.10 --venv test-env [--comment comment]`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!flags.version) {
|
if (!flags.version) {
|
||||||
@@ -326,7 +347,7 @@ python.ts add-venv --version 3.10 --venv test-env`);
|
|||||||
log.error("Venv is missing");
|
log.error("Venv is missing");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await addVirtualEnv(flags.version, flags.venv);
|
await addVirtualEnv(flags.version, flags.venv, flags.comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleRemoveVenv(args: string[]) {
|
async function handleRemoveVenv(args: string[]) {
|
||||||
@@ -348,7 +369,7 @@ python.ts remove-venv --venv test-env`);
|
|||||||
const pythonVenvProfile = pythonConfig.profiles &&
|
const pythonVenvProfile = pythonConfig.profiles &&
|
||||||
pythonConfig.profiles[flags.venv];
|
pythonConfig.profiles[flags.venv];
|
||||||
if (!pythonVenvProfile) {
|
if (!pythonVenvProfile) {
|
||||||
throw `Python venv not exists: ${flags.venv}`;
|
throw `Python virtual environment not exists: ${flags.venv}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
@@ -375,6 +396,33 @@ python.ts remove-venv --venv test-env`);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleActiveVenv(args: string[]) {
|
||||||
|
if (args.length === 0) {
|
||||||
|
console.log(`Help massage for active-venv
|
||||||
|
|
||||||
|
source <(python.rs active[-venv] test-env)`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const venv = args[0];
|
||||||
|
const pythonConfig = await loadPythonConfig();
|
||||||
|
const pythonVenvProfile = pythonConfig.profiles &&
|
||||||
|
pythonConfig.profiles[venv];
|
||||||
|
if (!pythonVenvProfile) {
|
||||||
|
throw `Python virtual environment not exists: ${venv}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pythonVenvActiveFile = joinPath(
|
||||||
|
pythonVenvProfile.path,
|
||||||
|
"bin",
|
||||||
|
"activate",
|
||||||
|
);
|
||||||
|
const pythonVenvActiveFileContent = await readFileToString(
|
||||||
|
pythonVenvActiveFile,
|
||||||
|
);
|
||||||
|
console.log(pythonVenvActiveFileContent);
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const args = Deno.args;
|
const args = Deno.args;
|
||||||
|
|
||||||
@@ -391,6 +439,8 @@ async function main() {
|
|||||||
handleHelp(remainingArgs);
|
handleHelp(remainingArgs);
|
||||||
break;
|
break;
|
||||||
case "py":
|
case "py":
|
||||||
|
case "ver":
|
||||||
|
case "version":
|
||||||
case "python":
|
case "python":
|
||||||
await handlePython(remainingArgs);
|
await handlePython(remainingArgs);
|
||||||
break;
|
break;
|
||||||
@@ -398,16 +448,24 @@ async function main() {
|
|||||||
case "add-python":
|
case "add-python":
|
||||||
await handleAddPython(remainingArgs);
|
await handleAddPython(remainingArgs);
|
||||||
break;
|
break;
|
||||||
|
case "env":
|
||||||
case "venv":
|
case "venv":
|
||||||
await handleVenv(remainingArgs);
|
await handleVenv(remainingArgs);
|
||||||
break;
|
break;
|
||||||
case "add-venv":
|
case "add-venv":
|
||||||
|
case "add-env":
|
||||||
await handleAddVenv(remainingArgs);
|
await handleAddVenv(remainingArgs);
|
||||||
break;
|
break;
|
||||||
case "rm-venv":
|
case "rm-venv":
|
||||||
|
case "rm-env":
|
||||||
case "remove-venv":
|
case "remove-venv":
|
||||||
await handleRemoveVenv(remainingArgs);
|
await handleRemoveVenv(remainingArgs);
|
||||||
break;
|
break;
|
||||||
|
case "active":
|
||||||
|
case "active-env":
|
||||||
|
case "active-venv":
|
||||||
|
await handleActiveVenv(remainingArgs);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log.error(`Unknown subcommand: ${subcommand}`);
|
log.error(`Unknown subcommand: ${subcommand}`);
|
||||||
break;
|
break;
|
||||||
@@ -415,3 +473,6 @@ async function main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main().catch((e) => log.error(e));
|
main().catch((e) => log.error(e));
|
||||||
|
|
||||||
|
// @SCRIPT-SIGNATURE-V1: yk-r1.ES256.20260125T224529+08:00.MEUCIQCxxJGIlQDOd0HEbsC0
|
||||||
|
// 1WCLBtgT7T2TMyTgs9TMCWw97QIgINUQ6SNPJ0NePXi12pp66pCoxh37VqSqaE9TURldmNs=
|
||||||
|
|||||||
Reference in New Issue
Block a user