@gorlitzer-labs/seldon 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/seldon.js +43 -8
- package/modules.mjs +3 -0
- package/package.json +1 -1
package/bin/seldon.js
CHANGED
|
@@ -55,6 +55,30 @@ function run(cmd, args, opts = {}) {
|
|
|
55
55
|
// Is a command on PATH? (used to pick the fastest package manager)
|
|
56
56
|
const has = (bin) => { try { execSync(`command -v ${bin}`, { stdio: "ignore" }); return true; } catch { return false; } };
|
|
57
57
|
|
|
58
|
+
// A usable uv, for Python modules. Prefer one on PATH; else a prior isolated
|
|
59
|
+
// copy; else bootstrap uv into ~/.seldon/bin with NO shell/profile changes.
|
|
60
|
+
// uv can fetch a standalone CPython (e.g. 3.12) itself, so the user's own
|
|
61
|
+
// Python is never touched — which is the whole point for demerzel. null = give up.
|
|
62
|
+
function ensureUv() {
|
|
63
|
+
if (has("uv")) return "uv";
|
|
64
|
+
const dir = path.join(process.env.HOME, ".seldon", "bin");
|
|
65
|
+
const local = path.join(dir, "uv");
|
|
66
|
+
if (fs.existsSync(local)) return local;
|
|
67
|
+
console.log(C.dim(" installing uv (isolated → ~/.seldon/bin, no shell changes)"));
|
|
68
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
69
|
+
const ok = run("bash", ["-c",
|
|
70
|
+
`curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR='${dir}' UV_NO_MODIFY_PATH=1 sh`]);
|
|
71
|
+
return ok && fs.existsSync(local) ? local : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Fallback interpreter when uv is unavailable: an exact minor already on PATH
|
|
75
|
+
// (python3.12 → 3.11 → 3.10). Used only to seed an isolated venv, never modified.
|
|
76
|
+
function pickPython(ver) {
|
|
77
|
+
const [maj, min] = ver.split(".").map(Number);
|
|
78
|
+
for (let m = min; m >= 10; m--) { const b = `python${maj}.${m}`; if (has(b)) return b; }
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
58
82
|
// pnpm can only `add -g` when a global bin dir is configured (else ERR_PNPM_NO_GLOBAL_BIN_DIR).
|
|
59
83
|
const pnpmGlobalReady = () => {
|
|
60
84
|
if (process.env.PNPM_HOME) return true;
|
|
@@ -64,13 +88,13 @@ const pnpmGlobalReady = () => {
|
|
|
64
88
|
} catch { return false; }
|
|
65
89
|
};
|
|
66
90
|
|
|
67
|
-
// Pick the node package manager: --pm=<x> override, else
|
|
68
|
-
//
|
|
91
|
+
// Pick the node package manager: --pm=<x> override (pnpm|bun|npm), else pnpm
|
|
92
|
+
// when it can global-install, else npm (the universal fallback). bun is not
|
|
93
|
+
// auto-preferred — opt in with --pm=bun.
|
|
69
94
|
function nodePM() {
|
|
70
95
|
const ov = (process.argv.find((a) => a.startsWith("--pm=")) || "").split("=")[1];
|
|
71
96
|
if (ov) return ov;
|
|
72
97
|
if (has("pnpm") && pnpmGlobalReady()) return "pnpm";
|
|
73
|
-
if (has("bun")) return "bun";
|
|
74
98
|
return "npm";
|
|
75
99
|
}
|
|
76
100
|
|
|
@@ -127,12 +151,23 @@ function installPython(m, dev) {
|
|
|
127
151
|
// venv+pip is the isolated fallback. No `--system`, no active-env writes.
|
|
128
152
|
const venv = path.join(dest, ".venv");
|
|
129
153
|
const req = path.join(dest, "requirements.txt");
|
|
154
|
+
fs.rmSync(venv, { recursive: true, force: true }); // never reuse a venv built on the wrong Python
|
|
130
155
|
let ok;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
156
|
+
const uv = ensureUv();
|
|
157
|
+
if (uv) {
|
|
158
|
+
const venvArgs = ["venv", venv];
|
|
159
|
+
if (m.pyVersion) venvArgs.push("--python", m.pyVersion); // uv fetches a standalone CPython
|
|
160
|
+
if (!run(uv, venvArgs)) return false;
|
|
161
|
+
ok = run(uv, ["pip", "install", "--python", path.join(venv, "bin", "python"), "-r", req]);
|
|
134
162
|
} else {
|
|
135
|
-
|
|
163
|
+
// No uv (and couldn't bootstrap it). Fall back to a matching system python.
|
|
164
|
+
const py = m.pyVersion ? pickPython(m.pyVersion) : "python3";
|
|
165
|
+
if (!py) {
|
|
166
|
+
console.log(C.red(` ${m.id} needs Python ${m.pyVersion} but uv is unavailable and no python${m.pyVersion} is on PATH.`));
|
|
167
|
+
console.log(C.dim(` install uv (fetches Python ${m.pyVersion} in isolation): https://astral.sh/uv`));
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
run(py, ["-m", "venv", venv]);
|
|
136
171
|
ok = run(path.join(venv, "bin", "pip"), ["install", "-r", req]);
|
|
137
172
|
}
|
|
138
173
|
if (ok) console.log(C.dim(` run it: ${path.join(dest, m.bin)} (isolated venv at ${venv})`));
|
|
@@ -236,7 +271,7 @@ ${C.bold("seldon")} — install the Seldon stack, pick what you use.
|
|
|
236
271
|
|
|
237
272
|
${C.dim("node tools install via pnpm/bun if present (faster), else npm.")}
|
|
238
273
|
${C.dim("python (demerzel) installs into its own isolated venv — never your system Python;")}
|
|
239
|
-
${C.dim("uses uv if
|
|
274
|
+
${C.dim("uses uv (auto-installed to ~/.seldon/bin if missing) to fetch a standalone CPython 3.12.")}
|
|
240
275
|
|
|
241
276
|
modules: ${MODULES.map((m) => m.id).join(", ")}
|
|
242
277
|
`);
|
package/modules.mjs
CHANGED
|
@@ -76,6 +76,9 @@ export const MODULES = [
|
|
|
76
76
|
bin: "demerzel",
|
|
77
77
|
needs: ["python3"],
|
|
78
78
|
requires: [],
|
|
79
|
+
// kokoro==0.9.4 caps Python at <3.13; the venv is pinned to 3.12 and uv
|
|
80
|
+
// fetches a standalone CPython 3.12 in isolation (never the system Python).
|
|
81
|
+
pyVersion: "3.12",
|
|
79
82
|
platforms: { platform: "darwin", arch: "arm64" }, // macOS + Apple silicon only
|
|
80
83
|
},
|
|
81
84
|
];
|