#!/usr/bin/env bash # Set up a side environment where the app runs against n3xd-ocp instead of the # stock wheel. # # The app's manifests are never touched: a swap is per-environment because both # distributions own the OCP/ import path and a process can hold only one OCCT # build. Since the Phase 10C cutover the app resolves n3xd-ocp itself, so the # uninstall below is a no-op on a fresh venv; what the script still buys is a # side environment pinned to the image's interpreter, and `--local` for trying # an unpublished wheelhouse build against the full app suite. # # tools/parity_venv.sh install from the Gitea registry # tools/parity_venv.sh --local install the local wheelhouse build # # Then run whichever slice of the app suite you care about — with the venv's own # interpreter, NOT `uv run`, which re-syncs the environment against the manifest # and so puts the pinned wheel straight back over a `--local` build: # cd ../app && .venv-ocp-parity/bin/python -m pytest backend/tests/test_geom_memo.py set -euo pipefail HERE=$(cd "$(dirname "$0")" && pwd) OCP_REPO=$(dirname "$HERE") APP="${APP_DIR:-$(dirname "$OCP_REPO")/app}" VENV_NAME="${VENV_NAME:-.venv-ocp-parity}" INDEX="https://git.stroblme.de/api/packages/N3XD/pypi/simple/" SOURCE="registry" [ "${1:-}" = "--local" ] && SOURCE="local" cd "$APP" export UV_PROJECT_ENVIRONMENT="$VENV_NAME" echo "--- syncing the app's dependencies into $VENV_NAME ---" # 3.13 explicitly: uv would otherwise pick the newest interpreter on the box and # the parity venv would stop resembling what the image ships. Move this pin # whenever the app's floor moves (roadmap 10D). uv sync --all-groups --python 3.13 # `uv pip` does NOT honour UV_PROJECT_ENVIRONMENT — it discovers an environment # the way pip does, which here means the app's own .venv. Without --python it # swaps the wrong environment entirely, and the sanity check below still passes # because `uv run` *does* honour the variable and reads the untouched parity # venv. Pass the target explicitly to both commands. PY_BIN="$APP/$VENV_NAME/bin/python" # Removal must precede installation: both distributions install a top-level # OCP/, so installing over the stock wheel would leave a half-overwritten mix. echo "--- removing the stock wheel ---" uv pip uninstall --python "$PY_BIN" cadquery-ocp-novtk || true echo "--- installing n3xd-ocp ($SOURCE) ---" if [ "$SOURCE" = "local" ]; then uv pip install --python "$PY_BIN" "$OCP_REPO"/wheelhouse/*.whl else uv pip install --python "$PY_BIN" --index-url "$INDEX" \ --prerelease=allow n3xd-ocp fi # Everything below runs the venv's interpreter directly. `uv run` would re-sync # the environment against the app's manifest first, reinstalling the pinned # version on top of the swap — which across a kernel bump means silently # testing the old OCCT while believing you are on the new one. echo "--- sanity ---" # Asserted, not printed: __occt_version__ exists only on our wheel, so this is # also the check that the swap landed in the environment we meant. "$PY_BIN" -c " import OCP assert hasattr(OCP, '__occt_version__'), 'this is not n3xd-ocp — the swap missed' print('OCP', OCP.__version__, '/ OCCT', OCP.__occt_version__) print('modules:', len(OCP._OCP.__all_modules__)) " echo "--- coverage against the app's symbol inventory ---" "$PY_BIN" "$HERE/inventory.py" --check || \ echo "(incomplete coverage is expected until the increments land)" # The binding's own suite, run from the swapped venv: this is what exercises the # published artifact inside the app's exact dependency set. It imports only # OCP/n3xd_ocp, so it works long before the app's own tests can collect (their # conftest imports n3xd.main, i.e. the whole OCP surface). echo "--- ocp suite under the swapped venv ---" "$PY_BIN" -m pytest "$OCP_REPO/tests" -q