Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/accuracy-regression-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ jobs:
OLD_VENV="${OLD_ROOT}/.venv"
python -m venv "${OLD_VENV}"
"${OLD_VENV}/bin/python" -m pip install --upgrade pip
# Split-era revisions need the payload-bearing Maturin core installed
# first. Newer revisions keep this path only as a compatibility
# metapackage, which must not be installed ahead of the root package.
# Split-era revisions need the historical payload-bearing Maturin core
# installed first. Current revisions have no separate Python core
# project, but regression tests still need to install old baselines.
if grep -q 'build-backend = "maturin"' "${OLD_ROOT}/src/aiconfigurator-core/pyproject.toml" 2>/dev/null; then
"${OLD_VENV}/bin/python" -m pip install -e "${OLD_ROOT}/src/aiconfigurator-core"
fi
Expand Down
8 changes: 2 additions & 6 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,8 @@ jobs:
- name: Build the aiconfigurator_core Rust extension
# The AICONFIGURATOR_RUST_CORE_AUTOBUILD env var is a no-op; the compiled
# aiconfigurator_core extension must be built explicitly with maturin so
# the parity suite exercises the current Rust source. On release/0.10.0 the
# maturin project is the core-wheel package at src/aiconfigurator-core (its
# [tool.maturin] manifest-path points at rust/aiconfigurator-core/Cargo.toml);
# the repo-root pyproject.toml still uses setuptools on this branch, so
# maturin must run from the core package dir, not the repo root.
working-directory: src/aiconfigurator-core
# the parity suite exercises the current Rust source. The maturin project
# is the repo root (see root pyproject.toml [tool.maturin]).
run: |
VIRTUAL_ENV="${GITHUB_WORKSPACE}/.venv" \
"${GITHUB_WORKSPACE}/.venv/bin/maturin" develop --release
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ pip3 install aiconfigurator
```

The `aiconfigurator` wheel is self-contained: it includes the CLI, SDK, model
and system data, Spica, and the native core extension. The
`aiconfigurator-core` distribution remains available as a payload-free
compatibility package that installs the matching `aiconfigurator` version.
and system data, Spica, and the native core extension. No separate Python core
distribution is required.

### Build and Install from Source

Expand All @@ -65,7 +64,7 @@ pip3 install .
### Build with Docker

```bash
# This creates the self-contained AIC wheel and a compatibility metapackage wheel
# This creates the self-contained AIC wheel
docker build -f docker/Dockerfile --no-cache --target build -t aiconfigurator:latest .
docker create --name aic aiconfigurator:latest && docker cp aic:/workspace/dist dist/ && docker rm aic
```
Expand Down
12 changes: 5 additions & 7 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ ENV MPLCONFIGDIR=/tmp/matplotlib

FROM base AS build
# The `aiconfigurator` wheel owns the Rust extension, SDK/data payload, CLI,
# generator, webapp, and Spica packages. The small `aiconfigurator-core` wheel
# built afterward is only a compatibility metapackage. Maturin needs the Rust
# crate sources, a C linker (gcc), and ca-certificates so cargo can fetch crates
# from crates.io over TLS. Rust itself is bootstrapped by maturin's build backend.
# generator, webapp, and Spica packages. Maturin needs the Rust crate sources,
# a C linker (gcc), and ca-certificates so cargo can fetch crates from crates.io
# over TLS. Rust itself is bootstrapped by maturin's build backend.
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates gcc libc6-dev && \
rm -rf /var/lib/apt/lists/*
Expand All @@ -39,12 +38,11 @@ RUN set -e; \
exit 1; \
fi
RUN uv build --wheel --out-dir /workspace/dist && \
cd src/aiconfigurator-core && uv build --wheel --out-dir /workspace/dist && \
cd /workspace && python tools/verify_release_wheels.py /workspace/dist
python tools/verify_release_wheels.py /workspace/dist

FROM base AS runtime
COPY --from=build /workspace/dist /wheelhouse
RUN uv pip install /wheelhouse/*.whl && \
RUN uv pip install /wheelhouse/aiconfigurator-*.whl && \
rm -rf /wheelhouse

FROM runtime AS test
Expand Down
23 changes: 0 additions & 23 deletions src/aiconfigurator-core/pyproject.toml

This file was deleted.

4 changes: 2 additions & 2 deletions src/aiconfigurator/sdk/config_builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

"""Shared ModelConfig construction helpers.

These helpers are used by both the upper CLI layer and lower modeling/engine
paths. Keeping them in ``sdk`` prevents the core wheel from importing CLI code.
These helpers are used by both the CLI layer and lower modeling/engine paths.
Keeping them in ``sdk`` prevents lower-level code from importing CLI code.
"""

from __future__ import annotations
Expand Down
37 changes: 10 additions & 27 deletions tools/verify_release_wheels.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Verify that release wheels have one owner for the complete AIC payload."""
"""Verify the self-contained AIC release wheel."""

from __future__ import annotations

Expand Down Expand Up @@ -47,7 +47,7 @@ def _source_payload() -> set[str]:
return expected


def _verify_main_wheel(wheel: Path) -> str:
def _verify_main_wheel(wheel: Path) -> None:
names, metadata = _wheel_files(wheel)
required = {
"aiconfigurator/cli/main.py",
Expand Down Expand Up @@ -82,29 +82,10 @@ def _verify_main_wheel(wheel: Path) -> str:

requirements = metadata.get_all("Requires-Dist", [])
if any(requirement.lower().startswith("aiconfigurator-core") for requirement in requirements):
raise RuntimeError(f"{wheel.name}: must not depend on the compatibility metapackage")
raise RuntimeError(f"{wheel.name}: must not depend on the removed aiconfigurator-core distribution")

version = metadata.get("Version")
if not version:
if not metadata.get("Version"):
raise RuntimeError(f"{wheel.name}: missing distribution version")
return version


def _verify_core_metapackage(wheel: Path, aic_version: str) -> None:
names, metadata = _wheel_files(wheel)
payload = sorted(name for name in names if ".dist-info/" not in name)
if payload:
raise RuntimeError(f"{wheel.name}: compatibility wheel must not own payload files: {payload}")

if metadata.get("Version") != aic_version:
raise RuntimeError(
f"{wheel.name}: version {metadata.get('Version')!r} does not match aiconfigurator {aic_version!r}"
)

requirements = metadata.get_all("Requires-Dist", [])
expected = f"aiconfigurator=={aic_version}"
if expected not in requirements:
raise RuntimeError(f"{wheel.name}: expected Requires-Dist {expected!r}, found {requirements}")


def main() -> int:
Expand All @@ -113,10 +94,12 @@ def main() -> int:
args = parser.parse_args()

main_wheel = _one_wheel(args.dist_dir, "aiconfigurator-*.whl")
core_wheel = _one_wheel(args.dist_dir, "aiconfigurator_core-*.whl")
aic_version = _verify_main_wheel(main_wheel)
_verify_core_metapackage(core_wheel, aic_version)
print(f"Verified self-contained {main_wheel.name} and payload-free {core_wheel.name}")
removed_core_wheels = sorted(args.dist_dir.glob("aiconfigurator_core-*.whl"))
if removed_core_wheels:
raise RuntimeError(f"unexpected aiconfigurator-core wheel: {[path.name for path in removed_core_wheels]}")

_verify_main_wheel(main_wheel)
print(f"Verified self-contained {main_wheel.name}")
return 0


Expand Down
Loading