@styx-api/core 0.5.0 → 0.5.2
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/dist/index.cjs +42 -22
- package/dist/index.mjs +42 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/backend/python/packaging.ts +38 -12
- package/src/backend/python/python.ts +26 -14
package/dist/index.cjs
CHANGED
|
@@ -4461,17 +4461,19 @@ function licenseField(proj) {
|
|
|
4461
4461
|
return `{ text = "${tomlStr(proj.license?.description ?? "unknown")}" }`;
|
|
4462
4462
|
}
|
|
4463
4463
|
/**
|
|
4464
|
-
* Per-suite `pyproject.toml`. The
|
|
4465
|
-
*
|
|
4466
|
-
* import
|
|
4464
|
+
* Per-suite `pyproject.toml`. The suite source stays in a flat directory
|
|
4465
|
+
* (`python/<pkg>/bet.py`), but setuptools' `package-dir` maps that directory onto
|
|
4466
|
+
* the dotted import package `<project>.<pkg>`, so every suite nests under the
|
|
4467
|
+
* metapackage's `<project>/` namespace. That restores `from <project> import
|
|
4468
|
+
* <pkg>` while keeping each suite a separately-installable distribution (and
|
|
4469
|
+
* leaves no top-level `<pkg>` polluting the global namespace). With no project
|
|
4470
|
+
* name the import name is the bare `<pkg>` (top-level fallback). The styxdefs
|
|
4467
4471
|
* floor is the only runtime dependency.
|
|
4468
4472
|
*
|
|
4469
|
-
* Precondition: `
|
|
4470
|
-
*
|
|
4471
|
-
* it verbatim as the directory name, so this stays consistent with that.
|
|
4473
|
+
* Precondition: `importName` is a valid (possibly dotted) Python package path -
|
|
4474
|
+
* the caller scrubs the project + package names into identifiers accordingly.
|
|
4472
4475
|
*/
|
|
4473
|
-
function generateSubPyproject(proj, pkg) {
|
|
4474
|
-
const importName = pkgDir(pkg);
|
|
4476
|
+
function generateSubPyproject(proj, pkg, importName) {
|
|
4475
4477
|
const cb = new CodeBuilder(" ");
|
|
4476
4478
|
cb.line("[project]");
|
|
4477
4479
|
cb.line(`name = "${tomlStr(pyDistName(proj, pkg))}"`);
|
|
@@ -4508,11 +4510,24 @@ function generateRootInitPy() {
|
|
|
4508
4510
|
}
|
|
4509
4511
|
/**
|
|
4510
4512
|
* Root `pyproject.toml`: a metapackage depending on `styxkit[all]` (the runner
|
|
4511
|
-
* stack it re-exports) plus each per-suite distribution
|
|
4512
|
-
*
|
|
4513
|
-
*
|
|
4513
|
+
* stack it re-exports) plus each per-suite distribution, pinned to this exact
|
|
4514
|
+
* project version (`niwrap_fsl==1.2.3`). The suites all ride the project version
|
|
4515
|
+
* and ship in lockstep, so an exact pin keeps `pip install niwrap==X` consistent:
|
|
4516
|
+
* during the post-release index-propagation window (or any momentary registry
|
|
4517
|
+
* inconsistency) pip errors cleanly instead of silently grafting an older suite
|
|
4518
|
+
* whose layout no longer matches the metapackage. Mirrors the way the CLI pins
|
|
4519
|
+
* `@styx-api/core` exactly.
|
|
4520
|
+
*
|
|
4521
|
+
* `packages` lists only the metapackage's own module so setuptools ships the
|
|
4522
|
+
* styxkit re-export without sweeping the sibling suite directories into this
|
|
4523
|
+
* distribution. The module is the `<project>/` namespace package the suites nest
|
|
4524
|
+
* into, so installing the metapackage makes `<project>.use_docker()` reachable
|
|
4525
|
+
* alongside the suites' `from <project> import <pkg>`. `moduleDir` is the on-disk
|
|
4526
|
+
* source directory; it differs from the import `moduleName` only when a suite is
|
|
4527
|
+
* named after the project, in which case a `package-dir` remap keeps the import
|
|
4528
|
+
* name intact.
|
|
4514
4529
|
*/
|
|
4515
|
-
function generateRootPyproject(proj, distNames, moduleName) {
|
|
4530
|
+
function generateRootPyproject(proj, distNames, moduleName, moduleDir) {
|
|
4516
4531
|
const cb = new CodeBuilder(" ");
|
|
4517
4532
|
cb.line("[project]");
|
|
4518
4533
|
cb.line(`name = "${tomlStr(proj.name ?? "project")}"`);
|
|
@@ -4524,11 +4539,13 @@ function generateRootPyproject(proj, distNames, moduleName) {
|
|
|
4524
4539
|
cb.line(`requires-python = "${REQUIRES_PYTHON}"`);
|
|
4525
4540
|
cb.line("dependencies = [");
|
|
4526
4541
|
for (const dep of PYTHON_RUNNER_DEPS) cb.line(` "${dep}",`);
|
|
4527
|
-
|
|
4542
|
+
const suitePin = tomlStr(proj.version ?? "0.0.0");
|
|
4543
|
+
for (const dist of distNames) cb.line(` "${tomlStr(dist)}==${suitePin}",`);
|
|
4528
4544
|
cb.line("]");
|
|
4529
4545
|
cb.blank();
|
|
4530
4546
|
cb.line("[tool.setuptools]");
|
|
4531
4547
|
cb.line(`packages = ["${moduleName}"]`);
|
|
4548
|
+
if (moduleDir !== moduleName) cb.line(`package-dir = { "${moduleName}" = "${moduleDir}" }`);
|
|
4532
4549
|
cb.blank();
|
|
4533
4550
|
cb.line("[tool.setuptools.package-data]");
|
|
4534
4551
|
cb.line(`"${moduleName}" = ["py.typed"]`);
|
|
@@ -5548,23 +5565,26 @@ var PythonBackend = class {
|
|
|
5548
5565
|
const distNames = [];
|
|
5549
5566
|
const pkgDirs = [];
|
|
5550
5567
|
const warnings = [];
|
|
5568
|
+
const nsName = proj.name && proj.name.trim() ? pyScrubIdent(proj.name, PY_RESERVED) : void 0;
|
|
5551
5569
|
for (const p of packages) {
|
|
5552
5570
|
const pkg = p.meta ?? {};
|
|
5553
5571
|
const dir = pkg.name ?? "package";
|
|
5554
5572
|
pkgDirs.push(dir);
|
|
5555
5573
|
distNames.push(pyDistName(proj, pkg));
|
|
5556
|
-
|
|
5574
|
+
const importPkg = nsName ? `${nsName}.${dir}` : dir;
|
|
5575
|
+
files.set(`${dir}/pyproject.toml`, generateSubPyproject(proj, pkg, importPkg));
|
|
5557
5576
|
files.set(`${dir}/README.md`, generateSubReadme(proj, pkg));
|
|
5558
5577
|
}
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5578
|
+
const metaImport = nsName ?? "project";
|
|
5579
|
+
let metaDir = metaImport;
|
|
5580
|
+
if (pkgDirs.includes(metaDir)) {
|
|
5581
|
+
const collided = metaDir;
|
|
5582
|
+
while (pkgDirs.includes(metaDir)) metaDir += "_";
|
|
5583
|
+
warnings.push({ message: `metapackage directory "${collided}" collides with a suite directory; emitting its sources in "${metaDir}" instead (import name stays "${metaImport}")` });
|
|
5564
5584
|
}
|
|
5565
|
-
files.set(`${
|
|
5566
|
-
files.set(`${
|
|
5567
|
-
files.set("pyproject.toml", generateRootPyproject(proj, distNames,
|
|
5585
|
+
files.set(`${metaDir}/__init__.py`, generateRootInitPy());
|
|
5586
|
+
files.set(`${metaDir}/py.typed`, "");
|
|
5587
|
+
files.set("pyproject.toml", generateRootPyproject(proj, distNames, metaImport, metaDir));
|
|
5568
5588
|
files.set("README.md", generateRootReadme(proj, distNames));
|
|
5569
5589
|
files.set("requirements.txt", generateRequirementsTxt(pkgDirs));
|
|
5570
5590
|
return {
|
package/dist/index.mjs
CHANGED
|
@@ -4460,17 +4460,19 @@ function licenseField(proj) {
|
|
|
4460
4460
|
return `{ text = "${tomlStr(proj.license?.description ?? "unknown")}" }`;
|
|
4461
4461
|
}
|
|
4462
4462
|
/**
|
|
4463
|
-
* Per-suite `pyproject.toml`. The
|
|
4464
|
-
*
|
|
4465
|
-
* import
|
|
4463
|
+
* Per-suite `pyproject.toml`. The suite source stays in a flat directory
|
|
4464
|
+
* (`python/<pkg>/bet.py`), but setuptools' `package-dir` maps that directory onto
|
|
4465
|
+
* the dotted import package `<project>.<pkg>`, so every suite nests under the
|
|
4466
|
+
* metapackage's `<project>/` namespace. That restores `from <project> import
|
|
4467
|
+
* <pkg>` while keeping each suite a separately-installable distribution (and
|
|
4468
|
+
* leaves no top-level `<pkg>` polluting the global namespace). With no project
|
|
4469
|
+
* name the import name is the bare `<pkg>` (top-level fallback). The styxdefs
|
|
4466
4470
|
* floor is the only runtime dependency.
|
|
4467
4471
|
*
|
|
4468
|
-
* Precondition: `
|
|
4469
|
-
*
|
|
4470
|
-
* it verbatim as the directory name, so this stays consistent with that.
|
|
4472
|
+
* Precondition: `importName` is a valid (possibly dotted) Python package path -
|
|
4473
|
+
* the caller scrubs the project + package names into identifiers accordingly.
|
|
4471
4474
|
*/
|
|
4472
|
-
function generateSubPyproject(proj, pkg) {
|
|
4473
|
-
const importName = pkgDir(pkg);
|
|
4475
|
+
function generateSubPyproject(proj, pkg, importName) {
|
|
4474
4476
|
const cb = new CodeBuilder(" ");
|
|
4475
4477
|
cb.line("[project]");
|
|
4476
4478
|
cb.line(`name = "${tomlStr(pyDistName(proj, pkg))}"`);
|
|
@@ -4507,11 +4509,24 @@ function generateRootInitPy() {
|
|
|
4507
4509
|
}
|
|
4508
4510
|
/**
|
|
4509
4511
|
* Root `pyproject.toml`: a metapackage depending on `styxkit[all]` (the runner
|
|
4510
|
-
* stack it re-exports) plus each per-suite distribution
|
|
4511
|
-
*
|
|
4512
|
-
*
|
|
4512
|
+
* stack it re-exports) plus each per-suite distribution, pinned to this exact
|
|
4513
|
+
* project version (`niwrap_fsl==1.2.3`). The suites all ride the project version
|
|
4514
|
+
* and ship in lockstep, so an exact pin keeps `pip install niwrap==X` consistent:
|
|
4515
|
+
* during the post-release index-propagation window (or any momentary registry
|
|
4516
|
+
* inconsistency) pip errors cleanly instead of silently grafting an older suite
|
|
4517
|
+
* whose layout no longer matches the metapackage. Mirrors the way the CLI pins
|
|
4518
|
+
* `@styx-api/core` exactly.
|
|
4519
|
+
*
|
|
4520
|
+
* `packages` lists only the metapackage's own module so setuptools ships the
|
|
4521
|
+
* styxkit re-export without sweeping the sibling suite directories into this
|
|
4522
|
+
* distribution. The module is the `<project>/` namespace package the suites nest
|
|
4523
|
+
* into, so installing the metapackage makes `<project>.use_docker()` reachable
|
|
4524
|
+
* alongside the suites' `from <project> import <pkg>`. `moduleDir` is the on-disk
|
|
4525
|
+
* source directory; it differs from the import `moduleName` only when a suite is
|
|
4526
|
+
* named after the project, in which case a `package-dir` remap keeps the import
|
|
4527
|
+
* name intact.
|
|
4513
4528
|
*/
|
|
4514
|
-
function generateRootPyproject(proj, distNames, moduleName) {
|
|
4529
|
+
function generateRootPyproject(proj, distNames, moduleName, moduleDir) {
|
|
4515
4530
|
const cb = new CodeBuilder(" ");
|
|
4516
4531
|
cb.line("[project]");
|
|
4517
4532
|
cb.line(`name = "${tomlStr(proj.name ?? "project")}"`);
|
|
@@ -4523,11 +4538,13 @@ function generateRootPyproject(proj, distNames, moduleName) {
|
|
|
4523
4538
|
cb.line(`requires-python = "${REQUIRES_PYTHON}"`);
|
|
4524
4539
|
cb.line("dependencies = [");
|
|
4525
4540
|
for (const dep of PYTHON_RUNNER_DEPS) cb.line(` "${dep}",`);
|
|
4526
|
-
|
|
4541
|
+
const suitePin = tomlStr(proj.version ?? "0.0.0");
|
|
4542
|
+
for (const dist of distNames) cb.line(` "${tomlStr(dist)}==${suitePin}",`);
|
|
4527
4543
|
cb.line("]");
|
|
4528
4544
|
cb.blank();
|
|
4529
4545
|
cb.line("[tool.setuptools]");
|
|
4530
4546
|
cb.line(`packages = ["${moduleName}"]`);
|
|
4547
|
+
if (moduleDir !== moduleName) cb.line(`package-dir = { "${moduleName}" = "${moduleDir}" }`);
|
|
4531
4548
|
cb.blank();
|
|
4532
4549
|
cb.line("[tool.setuptools.package-data]");
|
|
4533
4550
|
cb.line(`"${moduleName}" = ["py.typed"]`);
|
|
@@ -5547,23 +5564,26 @@ var PythonBackend = class {
|
|
|
5547
5564
|
const distNames = [];
|
|
5548
5565
|
const pkgDirs = [];
|
|
5549
5566
|
const warnings = [];
|
|
5567
|
+
const nsName = proj.name && proj.name.trim() ? pyScrubIdent(proj.name, PY_RESERVED) : void 0;
|
|
5550
5568
|
for (const p of packages) {
|
|
5551
5569
|
const pkg = p.meta ?? {};
|
|
5552
5570
|
const dir = pkg.name ?? "package";
|
|
5553
5571
|
pkgDirs.push(dir);
|
|
5554
5572
|
distNames.push(pyDistName(proj, pkg));
|
|
5555
|
-
|
|
5573
|
+
const importPkg = nsName ? `${nsName}.${dir}` : dir;
|
|
5574
|
+
files.set(`${dir}/pyproject.toml`, generateSubPyproject(proj, pkg, importPkg));
|
|
5556
5575
|
files.set(`${dir}/README.md`, generateSubReadme(proj, pkg));
|
|
5557
5576
|
}
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5577
|
+
const metaImport = nsName ?? "project";
|
|
5578
|
+
let metaDir = metaImport;
|
|
5579
|
+
if (pkgDirs.includes(metaDir)) {
|
|
5580
|
+
const collided = metaDir;
|
|
5581
|
+
while (pkgDirs.includes(metaDir)) metaDir += "_";
|
|
5582
|
+
warnings.push({ message: `metapackage directory "${collided}" collides with a suite directory; emitting its sources in "${metaDir}" instead (import name stays "${metaImport}")` });
|
|
5563
5583
|
}
|
|
5564
|
-
files.set(`${
|
|
5565
|
-
files.set(`${
|
|
5566
|
-
files.set("pyproject.toml", generateRootPyproject(proj, distNames,
|
|
5584
|
+
files.set(`${metaDir}/__init__.py`, generateRootInitPy());
|
|
5585
|
+
files.set(`${metaDir}/py.typed`, "");
|
|
5586
|
+
files.set("pyproject.toml", generateRootPyproject(proj, distNames, metaImport, metaDir));
|
|
5567
5587
|
files.set("README.md", generateRootReadme(proj, distNames));
|
|
5568
5588
|
files.set("requirements.txt", generateRequirementsTxt(pkgDirs));
|
|
5569
5589
|
return {
|