nab-python 0.0.4__tar.gz → 0.0.6__tar.gz
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.
- {nab_python-0.0.4 → nab_python-0.0.6}/PKG-INFO +3 -3
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/_profile_runner.py +1 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/canary.py +92 -48
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/compare.py +0 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pdm-lowest-direct.toml +0 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pdm-lowest.toml +0 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pdm.toml +0 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/uv-lowest-direct.toml +3 -4
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/uv-lowest.toml +3 -4
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/uv.toml +3 -4
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios.py +42 -39
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/strategy_sweep.py +18 -10
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/universal_scenarios.py +76 -2
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/universal_summary.py +23 -3
- {nab_python-0.0.4 → nab_python-0.0.6}/pyproject.toml +3 -3
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_build/env.py +17 -9
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_build/runner.py +2 -2
- nab_python-0.0.6/src/nab_python/_conflict_kind.py +62 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_lockfile/builder.py +81 -38
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_lockfile/disjointness.py +5 -5
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_lockfile/pylock.py +83 -5
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_lockfile/requirements.py +17 -5
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_provider/build_remote.py +39 -4
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_provider/extras.py +38 -23
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_provider/listing.py +189 -60
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_provider/metadata_resolver.py +126 -36
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_provider/priority.py +3 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_provider/sources.py +3 -5
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_testing/coordinator_fake.py +6 -1
- nab_python-0.0.6/src/nab_python/_testing/overrides.py +18 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vcs_admission.py +37 -17
- nab_python-0.0.6/src/nab_python/_vendor/packaging/PROVENANCE.md +92 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/_elffile.py +5 -5
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/_manylinux.py +30 -15
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/_parser.py +21 -4
- nab_python-0.0.6/src/nab_python/_vendor/packaging/_ranges.py +836 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/_tokenizer.py +5 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/dependency_groups.py +29 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/direct_url.py +19 -4
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/licenses/__init__.py +18 -6
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/markers.py +29 -6
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/metadata.py +3 -2
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/pylock.py +6 -1
- nab_python-0.0.6/src/nab_python/_vendor/packaging/ranges.py +1306 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/requirements.py +60 -20
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/specifiers.py +290 -374
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/tags.py +106 -43
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/utils.py +33 -5
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/build_backend.py +11 -3
- nab_python-0.0.6/src/nab_python/config.py +2200 -0
- nab_python-0.0.6/src/nab_python/config_sources.py +1799 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/download.py +45 -14
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/fetch.py +185 -78
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/lockfile.py +60 -5
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/metadata.py +29 -6
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/provider.py +469 -93
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/requirements_file.py +143 -18
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/resolve.py +168 -58
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/universal/matrix.py +11 -6
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/universal/provider.py +7 -8
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/universal/reresolve.py +38 -22
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/universal/resolve.py +62 -50
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/universal/validate.py +140 -29
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/universal/wheel_selection.py +89 -21
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/workspace.py +8 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/property_python/strategies.py +47 -0
- nab_python-0.0.6/tests/property_python/test_build_policy_never.py +151 -0
- nab_python-0.0.6/tests/property_python/test_download_hashes.py +123 -0
- nab_python-0.0.6/tests/property_python/test_fetch_coordinator.py +272 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/property_python/test_multi_index_pep503.py +12 -4
- nab_python-0.0.6/tests/property_python/test_override_overlap.py +79 -0
- nab_python-0.0.6/tests/property_python/test_prerelease_admission.py +163 -0
- nab_python-0.0.6/tests/property_python/test_vcs_admission.py +227 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_async_transports.py +26 -1
- nab_python-0.0.6/tests/test_benchmark_parse_requirements.py +41 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_build_backend.py +135 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_build_runner.py +32 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_cached_client.py +275 -4
- nab_python-0.0.6/tests/test_config.py +3067 -0
- nab_python-0.0.6/tests/test_config_sources.py +2330 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_download.py +147 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_fetch.py +427 -73
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_local_index.py +80 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_lockfile.py +581 -7
- nab_python-0.0.6/tests/test_marker_evaluation.py +221 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_metadata.py +58 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_multi_index.py +10 -2
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_provider.py +2288 -202
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_requirements_file.py +231 -5
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_resolve.py +554 -58
- nab_python-0.0.6/tests/test_resolver_packaging.py +923 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_simple_client_filenames.py +16 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_simple_client_hashes.py +12 -0
- nab_python-0.0.6/tests/test_simple_client_upload_time.py +33 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_vcs.py +34 -1
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_vcs_admission.py +94 -12
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_workspace.py +18 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/test_matrix.py +10 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/test_reresolve.py +100 -3
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/test_resolve.py +138 -13
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/test_universal_provider.py +73 -7
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/test_validate.py +393 -14
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/test_wheel_selection.py +139 -2
- nab_python-0.0.4/src/nab_python/_conflict_kind.py +0 -20
- nab_python-0.0.4/src/nab_python/_vendor/packaging/PROVENANCE.md +0 -73
- nab_python-0.0.4/src/nab_python/_vendor/packaging/_range_utils.py +0 -998
- nab_python-0.0.4/src/nab_python/_vendor/packaging/_version_utils.py +0 -90
- nab_python-0.0.4/src/nab_python/_vendor/packaging/ranges.py +0 -2112
- nab_python-0.0.4/src/nab_python/config.py +0 -1443
- nab_python-0.0.4/tests/test_config.py +0 -1860
- nab_python-0.0.4/tests/test_resolver_packaging.py +0 -503
- {nab_python-0.0.4 → nab_python-0.0.6}/.gitignore +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/LICENSE +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/README.md +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/README.md +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/cache/.gitignore +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/canary_results/.gitignore +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/results/.gitignore +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/ai-stack-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/ai-stack-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/ai-stack.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/airflow-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/airflow-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/airflow.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/big-packages-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/big-packages-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/big-packages.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/cross-tracker-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/cross-tracker-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/cross-tracker.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/ecosystem-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/ecosystem-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/ecosystem.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/forums-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/forums-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/forums.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pip-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pip-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pip.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/poetry-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/poetry-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/poetry.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pytorch-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pytorch-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/pytorch.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/quick-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/quick-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/quick.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/rip-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/rip-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/rip.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/universal.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/unsupported-lowest-direct.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/unsupported-lowest.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/scenarios/unsupported.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/strategy_sweep_results/summary.json +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/benchmarks/strategy_sweep_summary.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_build/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_build/errors.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_lockfile/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_packaging_provider.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_provider/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_provider/lookahead.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_testing/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_toml.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/LICENSE +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/LICENSE.APACHE +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/LICENSE.BSD +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/_musllinux.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/_structures.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/errors.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/licenses/_spdx.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/py.typed +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/_vendor/packaging/version.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/py.typed +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/src/nab_python/universal/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/property_python/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/property_python/test_extras_pep685.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/property_python/test_lockfile_pep751.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/property_python/test_marker_overlay.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/property_python/test_resolver_pep440.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/ruff.toml +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/test_cache.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/property_universal/__init__.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/property_universal/strategies.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/property_universal/test_alignment.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/property_universal/test_matrix.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/property_universal/test_provider_pep425.py +0 -0
- {nab_python-0.0.4 → nab_python-0.0.6}/tests/universal/property_universal/test_validate.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nab-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.6
|
|
4
4
|
Summary: Index-backed provider, lockfile emitter, and downloader for nab
|
|
5
5
|
Project-URL: Homepage, https://github.com/notatallshaw/nab
|
|
6
6
|
Project-URL: Documentation, https://nab.readthedocs.io/
|
|
@@ -20,8 +20,8 @@ Classifier: Typing :: Typed
|
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
21
|
Requires-Dist: build>=1.2
|
|
22
22
|
Requires-Dist: installer>=0.7
|
|
23
|
-
Requires-Dist: nab-index==0.0.
|
|
24
|
-
Requires-Dist: nab-resolver==0.0.
|
|
23
|
+
Requires-Dist: nab-index==0.0.6
|
|
24
|
+
Requires-Dist: nab-resolver==0.0.6
|
|
25
25
|
Requires-Dist: pyproject-hooks>=1.2
|
|
26
26
|
Requires-Dist: tomli-w>=1.2
|
|
27
27
|
Requires-Dist: tomli>=2.0
|
|
@@ -96,7 +96,7 @@ def build_inputs(name: str, scenario: dict) -> dict:
|
|
|
96
96
|
"constraints": constraints,
|
|
97
97
|
"marker_environment": marker_environment or None,
|
|
98
98
|
"indexes": sc.parse_indexes(name, scenario),
|
|
99
|
-
"
|
|
99
|
+
"index_routes": sc.parse_index_routes(name, scenario) or None,
|
|
100
100
|
"build_policy_overrides": build_policy_overrides or None,
|
|
101
101
|
"resolution_strategy": resolution_strategy,
|
|
102
102
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""Quick canary benchmark for fast iteration.
|
|
2
2
|
|
|
3
3
|
Runs a curated subset of scenarios (canaries + hard cases) N times each
|
|
4
|
-
and reports median decisions,
|
|
5
|
-
small enough to finish in a few minutes so it can
|
|
6
|
-
algorithm change.
|
|
4
|
+
and reports median decisions, distributions seen (search breadth), and
|
|
5
|
+
wall time. The set is small enough to finish in a few minutes so it can
|
|
6
|
+
be re-run after each algorithm change.
|
|
7
7
|
|
|
8
8
|
Usage:
|
|
9
9
|
python nab-python/benchmarks/canary.py [--commit LABEL] [--runs N]
|
|
@@ -38,11 +38,12 @@ from nab_python._vendor.packaging.markers import default_environment
|
|
|
38
38
|
from nab_python._vendor.packaging.ranges import VersionRange
|
|
39
39
|
from nab_python._vendor.packaging.requirements import Requirement
|
|
40
40
|
from nab_python._vendor.packaging.utils import canonicalize_name
|
|
41
|
+
from nab_python.config import PackageOverride
|
|
41
42
|
from nab_python.fetch import (
|
|
42
43
|
DEFAULT_INDEX_NAME,
|
|
43
44
|
DEFAULT_INDEX_URL,
|
|
44
45
|
FetchCoordinator,
|
|
45
|
-
|
|
46
|
+
IndexRoute,
|
|
46
47
|
)
|
|
47
48
|
from nab_python.provider import (
|
|
48
49
|
BuildPolicy,
|
|
@@ -62,26 +63,30 @@ DEFAULT_INDEXES: tuple[IndexConfig, ...] = (
|
|
|
62
63
|
IndexConfig(DEFAULT_INDEX_NAME, DEFAULT_INDEX_URL),
|
|
63
64
|
)
|
|
64
65
|
|
|
66
|
+
# Each entry pins its TOML variant as ``stem:name``. Most of these names also
|
|
67
|
+
# live in -lowest / -lowest-direct siblings with different counts; the pins
|
|
68
|
+
# record the variant the suite already ran so the numbers are reproducible
|
|
69
|
+
# instead of depending on directory scan order.
|
|
65
70
|
CANARY_SCENARIOS = [
|
|
66
|
-
"boto3-urllib3-transient",
|
|
67
|
-
"trustllm",
|
|
68
|
-
"copick",
|
|
69
|
-
"promptflow-vectordb",
|
|
70
|
-
"ultralytics-export",
|
|
71
|
-
"datacontract-cli",
|
|
72
|
-
"pandas-aws-boto3-dandi-frenzy",
|
|
73
|
-
"vllm-transformers-floor",
|
|
74
|
-
"google-bigquery-soda",
|
|
75
|
-
"langchain-ml-course",
|
|
76
|
-
"airflow-3-0-2-awswrangler",
|
|
77
|
-
"airflow-3-0-3-pandas-sqlalchemy",
|
|
78
|
-
"airflow-portalocker-qdrant",
|
|
79
|
-
"airflow-fastapi-121",
|
|
80
|
-
"so-dbt-core-snowflake-79744735",
|
|
81
|
-
"uv-issue-16601-xinference",
|
|
82
|
-
"uv-issue-16601-xinference-fixed",
|
|
83
|
-
"rag-chroma-langchain",
|
|
84
|
-
"streamlit-langchain",
|
|
71
|
+
"uv-lowest:boto3-urllib3-transient",
|
|
72
|
+
"pip-lowest:trustllm",
|
|
73
|
+
"pip-lowest:copick",
|
|
74
|
+
"pip-lowest:promptflow-vectordb",
|
|
75
|
+
"pip-lowest:ultralytics-export",
|
|
76
|
+
"pip-lowest:datacontract-cli",
|
|
77
|
+
"pip-lowest:pandas-aws-boto3-dandi-frenzy",
|
|
78
|
+
"ai-stack:vllm-transformers-floor",
|
|
79
|
+
"pip-lowest:google-bigquery-soda",
|
|
80
|
+
"pip-lowest:langchain-ml-course",
|
|
81
|
+
"airflow-lowest-direct:airflow-3-0-2-awswrangler",
|
|
82
|
+
"airflow-lowest-direct:airflow-3-0-3-pandas-sqlalchemy",
|
|
83
|
+
"airflow-lowest-direct:airflow-portalocker-qdrant",
|
|
84
|
+
"airflow-lowest-direct:airflow-fastapi-121",
|
|
85
|
+
"forums-lowest-direct:so-dbt-core-snowflake-79744735",
|
|
86
|
+
"uv-lowest:uv-issue-16601-xinference",
|
|
87
|
+
"uv-lowest:uv-issue-16601-xinference-fixed",
|
|
88
|
+
"ai-stack:rag-chroma-langchain",
|
|
89
|
+
"ai-stack:streamlit-langchain",
|
|
85
90
|
]
|
|
86
91
|
|
|
87
92
|
WALL_TIMEOUT_S = 60
|
|
@@ -150,7 +155,7 @@ def parse_requirements(
|
|
|
150
155
|
)
|
|
151
156
|
raise NotImplementedError(msg)
|
|
152
157
|
name = canonicalize_name(req.name)
|
|
153
|
-
reqs[name] = req.specifier.to_range()
|
|
158
|
+
reqs[name] = reqs.get(name, VersionRange.full()) & req.specifier.to_range()
|
|
154
159
|
for extra in req.extras:
|
|
155
160
|
reqs[f"{name}[{extra}]"] = VersionRange.full()
|
|
156
161
|
return reqs
|
|
@@ -208,17 +213,25 @@ def run_one( # noqa: PLR0913 - one wrapper per scenario knob
|
|
|
208
213
|
constraints: dict[str, VersionRange] | None,
|
|
209
214
|
marker_environment: dict[str, str] | None = None,
|
|
210
215
|
indexes: list[IndexConfig] | None = None,
|
|
211
|
-
|
|
216
|
+
index_routes: list[IndexRoute] | None = None,
|
|
212
217
|
build_policy_overrides: Mapping[str, BuildPolicy] | None = None,
|
|
213
218
|
*,
|
|
214
219
|
trust_unverified_sdist_deps: bool = False,
|
|
215
220
|
) -> dict:
|
|
221
|
+
package_overrides = tuple(
|
|
222
|
+
PackageOverride(
|
|
223
|
+
requirement=Requirement(name),
|
|
224
|
+
name=canonicalize_name(name),
|
|
225
|
+
version_range=VersionRange.full(),
|
|
226
|
+
build_policy=policy,
|
|
227
|
+
)
|
|
228
|
+
for name, policy in (build_policy_overrides or {}).items()
|
|
229
|
+
)
|
|
216
230
|
with FetchCoordinator(
|
|
217
231
|
HttpxAsyncTransport(),
|
|
218
232
|
indexes=indexes,
|
|
219
233
|
cache_dir=CACHE_DIR,
|
|
220
|
-
|
|
221
|
-
marker_environment=marker_environment,
|
|
234
|
+
index_routes=index_routes,
|
|
222
235
|
) as coordinator:
|
|
223
236
|
provider = Provider(
|
|
224
237
|
coordinator,
|
|
@@ -227,7 +240,7 @@ def run_one( # noqa: PLR0913 - one wrapper per scenario knob
|
|
|
227
240
|
uploaded_prior_to=uploaded_prior_to,
|
|
228
241
|
dist_policy=DistPolicy.WHEEL_OR_SDIST,
|
|
229
242
|
build_policy=BuildPolicy.NEVER,
|
|
230
|
-
|
|
243
|
+
package_overrides=package_overrides,
|
|
231
244
|
trust_unverified_sdist_deps=trust_unverified_sdist_deps,
|
|
232
245
|
marker_environment=marker_environment,
|
|
233
246
|
)
|
|
@@ -268,19 +281,46 @@ def run_one( # noqa: PLR0913 - one wrapper per scenario knob
|
|
|
268
281
|
"restarts": rs.restarts,
|
|
269
282
|
"incompatibilities_learned": rs.incompatibilities_learned,
|
|
270
283
|
"metadata_fetched": ps.metadata_fetched,
|
|
284
|
+
"distributions_seen": ps.distributions_seen,
|
|
271
285
|
"look_ahead_rejections": ps.look_ahead_rejections,
|
|
272
286
|
"packages": packages,
|
|
273
287
|
"wall_time_seconds": round(elapsed, 3),
|
|
274
288
|
}
|
|
275
289
|
|
|
276
290
|
|
|
277
|
-
def find_scenario(
|
|
278
|
-
|
|
291
|
+
def find_scenario(spec: str) -> dict | None:
|
|
292
|
+
"""Locate a scenario by name, or by ``stem:name`` to pin a specific TOML file.
|
|
293
|
+
|
|
294
|
+
Many names live in several variant TOMLs (a ``highest`` file plus
|
|
295
|
+
``-lowest`` / ``-lowest-direct`` siblings) with different decision counts.
|
|
296
|
+
A bare name scans the files in sorted order so the match is reproducible
|
|
297
|
+
across machines, and warns when the name is ambiguous so an exact-count run
|
|
298
|
+
can pin the variant with ``stem:name``.
|
|
299
|
+
"""
|
|
300
|
+
if ":" in spec:
|
|
301
|
+
toml_stem, name = spec.split(":", 1)
|
|
302
|
+
toml_path = SCENARIOS_DIR / f"{toml_stem}.toml"
|
|
303
|
+
if not toml_path.is_file():
|
|
304
|
+
return None
|
|
305
|
+
with toml_path.open("rb") as f:
|
|
306
|
+
return tomllib.load(f).get(name)
|
|
307
|
+
|
|
308
|
+
matches: list[tuple[str, dict]] = []
|
|
309
|
+
for toml_file in sorted(SCENARIOS_DIR.glob("*.toml")):
|
|
279
310
|
with toml_file.open("rb") as f:
|
|
280
311
|
data = tomllib.load(f)
|
|
281
|
-
if
|
|
282
|
-
|
|
283
|
-
|
|
312
|
+
if spec in data:
|
|
313
|
+
matches.append((toml_file.stem, data[spec]))
|
|
314
|
+
if not matches:
|
|
315
|
+
return None
|
|
316
|
+
if len(matches) > 1:
|
|
317
|
+
stems = ", ".join(stem for stem, _ in matches)
|
|
318
|
+
print(
|
|
319
|
+
f" [ambiguous] {spec!r} is in {len(matches)} files ({stems}); "
|
|
320
|
+
f"using {matches[0][0]}. Pin one with '{matches[0][0]}:{spec}'.",
|
|
321
|
+
flush=True,
|
|
322
|
+
)
|
|
323
|
+
return matches[0][1]
|
|
284
324
|
|
|
285
325
|
|
|
286
326
|
def median_run(scenario: dict, runs: int) -> tuple[list[dict], dict]:
|
|
@@ -328,14 +368,10 @@ def median_run(scenario: dict, runs: int) -> tuple[list[dict], dict]:
|
|
|
328
368
|
IndexConfig(name=str(entry["name"]), url=str(entry["url"]))
|
|
329
369
|
for entry in raw_indexes
|
|
330
370
|
]
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
index=str(entry["index"]),
|
|
336
|
-
marker=entry.get("marker"),
|
|
337
|
-
)
|
|
338
|
-
for entry in raw_overrides
|
|
371
|
+
raw_routes = scenario.get("index_routes", [])
|
|
372
|
+
index_routes = [
|
|
373
|
+
IndexRoute(name=str(entry["name"]), index=str(entry["index"]))
|
|
374
|
+
for entry in raw_routes
|
|
339
375
|
]
|
|
340
376
|
raw_build_packages = scenario.get("build_packages", []) or []
|
|
341
377
|
build_policy_overrides = {
|
|
@@ -368,8 +404,10 @@ def median_run(scenario: dict, runs: int) -> tuple[list[dict], dict]:
|
|
|
368
404
|
else None
|
|
369
405
|
)
|
|
370
406
|
uploaded_prior_to = parse_datetime(datetime_str) if datetime_str else None
|
|
407
|
+
# See scenarios.py: trust pre-2.2 sdist PKG-INFO deps by default so the
|
|
408
|
+
# benchmark measures search, not strict PEP 643 sdist rejection.
|
|
371
409
|
trust_unverified_sdist_deps = bool(
|
|
372
|
-
scenario.get("trust_unverified_sdist_deps",
|
|
410
|
+
scenario.get("trust_unverified_sdist_deps", True)
|
|
373
411
|
)
|
|
374
412
|
|
|
375
413
|
runs_data: list[dict] = [
|
|
@@ -380,7 +418,7 @@ def median_run(scenario: dict, runs: int) -> tuple[list[dict], dict]:
|
|
|
380
418
|
constraints,
|
|
381
419
|
marker_environment=marker_environment or None,
|
|
382
420
|
indexes=indexes,
|
|
383
|
-
|
|
421
|
+
index_routes=index_routes or None,
|
|
384
422
|
build_policy_overrides=build_policy_overrides or None,
|
|
385
423
|
trust_unverified_sdist_deps=trust_unverified_sdist_deps,
|
|
386
424
|
)
|
|
@@ -395,6 +433,9 @@ def median_run(scenario: dict, runs: int) -> tuple[list[dict], dict]:
|
|
|
395
433
|
summary = {
|
|
396
434
|
"success_runs": f"{successes}/{len(runs_data)}",
|
|
397
435
|
"median_decisions": int(med("decisions")),
|
|
436
|
+
"median_distributions_seen": int(med("distributions_seen")),
|
|
437
|
+
"median_metadata_fetched": int(med("metadata_fetched")),
|
|
438
|
+
"median_packages": int(med("packages")),
|
|
398
439
|
"median_conflicts": int(med("conflicts")),
|
|
399
440
|
"median_backjumps": int(med("backjumps")),
|
|
400
441
|
"median_wall": round(med("wall_time_seconds"), 2),
|
|
@@ -433,29 +474,32 @@ def main() -> None:
|
|
|
433
474
|
f"{'scenario':<45} "
|
|
434
475
|
f"{'success':>9} "
|
|
435
476
|
f"{'med_dec':>8} "
|
|
477
|
+
f"{'med_dist':>10} "
|
|
436
478
|
f"{'med_wall':>10} "
|
|
437
479
|
f"{'min_dec':>8} "
|
|
438
480
|
f"{'max_dec':>8}"
|
|
439
481
|
)
|
|
440
|
-
print("-" *
|
|
482
|
+
print("-" * 110)
|
|
441
483
|
|
|
442
484
|
summary_all: dict[str, dict] = {}
|
|
443
485
|
for name in scenarios_to_run:
|
|
444
486
|
scenario = find_scenario(name)
|
|
487
|
+
label = name.split(":", 1)[-1]
|
|
445
488
|
if scenario is None:
|
|
446
|
-
print(f"{
|
|
489
|
+
print(f"{label:<45} NOT FOUND")
|
|
447
490
|
continue
|
|
448
491
|
runs_data, summary = median_run(scenario, args.runs)
|
|
449
|
-
summary_all[
|
|
492
|
+
summary_all[label] = {"runs": runs_data, "summary": summary}
|
|
450
493
|
|
|
451
494
|
if "skipped" in summary:
|
|
452
|
-
print(f"{
|
|
495
|
+
print(f"{label:<45} SKIPPED: {summary['skipped']}")
|
|
453
496
|
continue
|
|
454
497
|
|
|
455
498
|
print(
|
|
456
|
-
f"{
|
|
499
|
+
f"{label:<45} "
|
|
457
500
|
f"{summary['success_runs']:>9} "
|
|
458
501
|
f"{summary['median_decisions']:>8} "
|
|
502
|
+
f"{summary['median_distributions_seen']:>10} "
|
|
459
503
|
f"{summary['median_wall']:>10} "
|
|
460
504
|
f"{summary['min_decisions']:>8} "
|
|
461
505
|
f"{summary['max_decisions']:>8}"
|
|
@@ -38,7 +38,6 @@ STAT_LABELS = {
|
|
|
38
38
|
"look_ahead_rejections": "Look-ahead rejections",
|
|
39
39
|
"packages_resolved": "Packages resolved",
|
|
40
40
|
"wall_time_seconds": "Wall time (s)",
|
|
41
|
-
# legacy keys (older results before stats rework):
|
|
42
41
|
"listing_requests": "Listing requests (legacy)",
|
|
43
42
|
"metadata_requests": "Metadata requests (legacy)",
|
|
44
43
|
}
|
|
@@ -1530,8 +1530,8 @@ requirements = [
|
|
|
1530
1530
|
# Migrated from unsupported.toml (2026-04-27). These were filed against
|
|
1531
1531
|
# original tool-specific features (uv universal resolution, multi-index,
|
|
1532
1532
|
# --pre flag, project install) but the requirement list itself is a valid
|
|
1533
|
-
# single-platform PyPI input that nab can resolve.
|
|
1534
|
-
#
|
|
1533
|
+
# single-platform PyPI input that nab can resolve. Some need a
|
|
1534
|
+
# pre-release pin to find a candidate.
|
|
1535
1535
|
# ============================================================================
|
|
1536
1536
|
|
|
1537
1537
|
[uv-pyspark-resolution]
|
|
@@ -1624,12 +1624,11 @@ requirements = ["playwright"]
|
|
|
1624
1624
|
[uv-issue-11636-llvmlite-prerelease]
|
|
1625
1625
|
# https://github.com/astral-sh/uv/issues/11636
|
|
1626
1626
|
# llvmlite==0.44.0 only exists as a pre-release on PyPI at the chosen
|
|
1627
|
-
# date; needs
|
|
1627
|
+
# date; needs a pre-release pin to find a candidate.
|
|
1628
1628
|
resolution = "lowest-direct"
|
|
1629
1629
|
python_version = "3.13"
|
|
1630
1630
|
platform_system = "Linux"
|
|
1631
1631
|
datetime = "2025-02-19 20:01:16"
|
|
1632
|
-
allow_prereleases = true
|
|
1633
1632
|
requirements = ["llvmlite==0.44.0"]
|
|
1634
1633
|
|
|
1635
1634
|
[uv-tensorflow-macos]
|
|
@@ -1530,8 +1530,8 @@ requirements = [
|
|
|
1530
1530
|
# Migrated from unsupported.toml (2026-04-27). These were filed against
|
|
1531
1531
|
# original tool-specific features (uv universal resolution, multi-index,
|
|
1532
1532
|
# --pre flag, project install) but the requirement list itself is a valid
|
|
1533
|
-
# single-platform PyPI input that nab can resolve.
|
|
1534
|
-
#
|
|
1533
|
+
# single-platform PyPI input that nab can resolve. Some need a
|
|
1534
|
+
# pre-release pin to find a candidate.
|
|
1535
1535
|
# ============================================================================
|
|
1536
1536
|
|
|
1537
1537
|
[uv-pyspark-resolution]
|
|
@@ -1624,12 +1624,11 @@ requirements = ["playwright"]
|
|
|
1624
1624
|
[uv-issue-11636-llvmlite-prerelease]
|
|
1625
1625
|
# https://github.com/astral-sh/uv/issues/11636
|
|
1626
1626
|
# llvmlite==0.44.0 only exists as a pre-release on PyPI at the chosen
|
|
1627
|
-
# date; needs
|
|
1627
|
+
# date; needs a pre-release pin to find a candidate.
|
|
1628
1628
|
resolution = "lowest"
|
|
1629
1629
|
python_version = "3.13"
|
|
1630
1630
|
platform_system = "Linux"
|
|
1631
1631
|
datetime = "2025-02-19 20:01:16"
|
|
1632
|
-
allow_prereleases = true
|
|
1633
1632
|
requirements = ["llvmlite==0.44.0"]
|
|
1634
1633
|
|
|
1635
1634
|
[uv-tensorflow-macos]
|
|
@@ -1422,8 +1422,8 @@ requirements = [
|
|
|
1422
1422
|
# Migrated from unsupported.toml (2026-04-27). These were filed against
|
|
1423
1423
|
# original tool-specific features (uv universal resolution, multi-index,
|
|
1424
1424
|
# --pre flag, project install) but the requirement list itself is a valid
|
|
1425
|
-
# single-platform PyPI input that nab can resolve.
|
|
1426
|
-
#
|
|
1425
|
+
# single-platform PyPI input that nab can resolve. Some need a
|
|
1426
|
+
# pre-release pin to find a candidate.
|
|
1427
1427
|
# ============================================================================
|
|
1428
1428
|
|
|
1429
1429
|
[uv-pyspark-resolution]
|
|
@@ -1509,11 +1509,10 @@ requirements = ["playwright"]
|
|
|
1509
1509
|
[uv-issue-11636-llvmlite-prerelease]
|
|
1510
1510
|
# https://github.com/astral-sh/uv/issues/11636
|
|
1511
1511
|
# llvmlite==0.44.0 only exists as a pre-release on PyPI at the chosen
|
|
1512
|
-
# date; needs
|
|
1512
|
+
# date; needs a pre-release pin to find a candidate.
|
|
1513
1513
|
python_version = "3.13"
|
|
1514
1514
|
platform_system = "Linux"
|
|
1515
1515
|
datetime = "2025-02-19 20:01:16"
|
|
1516
|
-
allow_prereleases = true
|
|
1517
1516
|
requirements = ["llvmlite==0.44.0"]
|
|
1518
1517
|
|
|
1519
1518
|
[uv-tensorflow-macos]
|
|
@@ -35,11 +35,12 @@ from nab_python._vendor.packaging.markers import default_environment
|
|
|
35
35
|
from nab_python._vendor.packaging.ranges import VersionRange
|
|
36
36
|
from nab_python._vendor.packaging.requirements import Requirement
|
|
37
37
|
from nab_python._vendor.packaging.utils import canonicalize_name
|
|
38
|
+
from nab_python.config import PackageOverride
|
|
38
39
|
from nab_python.fetch import (
|
|
39
40
|
DEFAULT_INDEX_NAME,
|
|
40
41
|
DEFAULT_INDEX_URL,
|
|
41
42
|
FetchCoordinator,
|
|
42
|
-
|
|
43
|
+
IndexRoute,
|
|
43
44
|
)
|
|
44
45
|
from nab_python.provider import (
|
|
45
46
|
BuildPolicy,
|
|
@@ -137,7 +138,7 @@ def parse_requirements(
|
|
|
137
138
|
)
|
|
138
139
|
raise NotImplementedError(msg)
|
|
139
140
|
name = canonicalize_name(req.name)
|
|
140
|
-
reqs[name] = req.specifier.to_range()
|
|
141
|
+
reqs[name] = reqs.get(name, VersionRange.full()) & req.specifier.to_range()
|
|
141
142
|
for extra in req.extras:
|
|
142
143
|
reqs[f"{name}[{extra}]"] = VersionRange.full()
|
|
143
144
|
return reqs
|
|
@@ -212,7 +213,7 @@ def resolve_scenario( # noqa: PLR0913 - one wrapper per scenario knob
|
|
|
212
213
|
constraints: dict[str, VersionRange] | None = None,
|
|
213
214
|
marker_environment: dict[str, str] | None = None,
|
|
214
215
|
indexes: list[IndexConfig] | None = None,
|
|
215
|
-
|
|
216
|
+
index_routes: list[IndexRoute] | None = None,
|
|
216
217
|
build_policy_overrides: Mapping[str, BuildPolicy] | None = None,
|
|
217
218
|
resolution_strategy: ResolutionStrategy = ResolutionStrategy.HIGHEST,
|
|
218
219
|
*,
|
|
@@ -222,12 +223,20 @@ def resolve_scenario( # noqa: PLR0913 - one wrapper per scenario knob
|
|
|
222
223
|
direct_packages = frozenset(
|
|
223
224
|
name for name in requirements if split_extra(name)[1] is None
|
|
224
225
|
)
|
|
226
|
+
package_overrides = tuple(
|
|
227
|
+
PackageOverride(
|
|
228
|
+
requirement=Requirement(name),
|
|
229
|
+
name=canonicalize_name(name),
|
|
230
|
+
version_range=VersionRange.full(),
|
|
231
|
+
build_policy=policy,
|
|
232
|
+
)
|
|
233
|
+
for name, policy in (build_policy_overrides or {}).items()
|
|
234
|
+
)
|
|
225
235
|
with FetchCoordinator(
|
|
226
236
|
HttpxAsyncTransport(),
|
|
227
237
|
indexes=indexes,
|
|
228
238
|
cache_dir=CACHE_DIR,
|
|
229
|
-
|
|
230
|
-
marker_environment=marker_environment,
|
|
239
|
+
index_routes=index_routes,
|
|
231
240
|
) as coordinator:
|
|
232
241
|
provider = Provider(
|
|
233
242
|
coordinator,
|
|
@@ -236,7 +245,7 @@ def resolve_scenario( # noqa: PLR0913 - one wrapper per scenario knob
|
|
|
236
245
|
uploaded_prior_to=uploaded_prior_to,
|
|
237
246
|
dist_policy=DistPolicy.WHEEL_OR_SDIST,
|
|
238
247
|
build_policy=BuildPolicy.NEVER,
|
|
239
|
-
|
|
248
|
+
package_overrides=package_overrides,
|
|
240
249
|
trust_unverified_sdist_deps=trust_unverified_sdist_deps,
|
|
241
250
|
marker_environment=marker_environment,
|
|
242
251
|
resolution_strategy=resolution_strategy,
|
|
@@ -316,7 +325,7 @@ def _expected_input( # noqa: PLR0913 - assembling the JSON dump key
|
|
|
316
325
|
vcs_policy_str: str,
|
|
317
326
|
marker_environment: dict[str, str],
|
|
318
327
|
indexes: list[IndexConfig],
|
|
319
|
-
|
|
328
|
+
index_routes: list[IndexRoute],
|
|
320
329
|
build_packages: list[str] | None = None,
|
|
321
330
|
resolution_strategy: ResolutionStrategy = ResolutionStrategy.HIGHEST,
|
|
322
331
|
*,
|
|
@@ -346,14 +355,9 @@ def _expected_input( # noqa: PLR0913 - assembling the JSON dump key
|
|
|
346
355
|
expected_input["indexes"] = [
|
|
347
356
|
{"name": cfg.name, "url": cfg.url} for cfg in indexes
|
|
348
357
|
]
|
|
349
|
-
if
|
|
350
|
-
expected_input["
|
|
351
|
-
{
|
|
352
|
-
"name": o.name,
|
|
353
|
-
"index": o.index,
|
|
354
|
-
**({"marker": o.marker} if o.marker else {}),
|
|
355
|
-
}
|
|
356
|
-
for o in index_overrides
|
|
358
|
+
if index_routes:
|
|
359
|
+
expected_input["index_routes"] = [
|
|
360
|
+
{"name": o.name, "index": o.index} for o in index_routes
|
|
357
361
|
]
|
|
358
362
|
if build_packages:
|
|
359
363
|
expected_input["build_packages"] = sorted(build_packages)
|
|
@@ -364,30 +368,30 @@ def _expected_input( # noqa: PLR0913 - assembling the JSON dump key
|
|
|
364
368
|
return expected_input
|
|
365
369
|
|
|
366
370
|
|
|
367
|
-
def
|
|
371
|
+
def parse_index_routes(
|
|
368
372
|
scenario_name: str,
|
|
369
373
|
scenario: dict,
|
|
370
|
-
) -> list[
|
|
371
|
-
"""Read the ``
|
|
374
|
+
) -> list[IndexRoute]:
|
|
375
|
+
"""Read the ``index_routes`` array of records from a scenario.
|
|
372
376
|
|
|
373
377
|
Each entry is a TOML inline table with keys ``name`` (the package
|
|
374
|
-
name) and ``index`` (the *name* of an entry in ``indexes``)
|
|
375
|
-
|
|
376
|
-
so :func:`nab_python.fetch.
|
|
377
|
-
|
|
378
|
+
name) and ``index`` (the *name* of an entry in ``indexes``). A route
|
|
379
|
+
carries no version scope and no marker. Entries are returned in
|
|
380
|
+
declaration order so :func:`nab_python.fetch._resolve_routes` can
|
|
381
|
+
apply last-match-wins on duplicates.
|
|
378
382
|
"""
|
|
379
|
-
raw = scenario.get("
|
|
383
|
+
raw = scenario.get("index_routes", [])
|
|
380
384
|
if not isinstance(raw, list):
|
|
381
385
|
msg = (
|
|
382
|
-
f"{scenario_name}:
|
|
386
|
+
f"{scenario_name}: index_routes must be a TOML array of"
|
|
383
387
|
f" tables, got {type(raw).__name__}"
|
|
384
388
|
)
|
|
385
389
|
raise TypeError(msg)
|
|
386
|
-
out: list[
|
|
390
|
+
out: list[IndexRoute] = []
|
|
387
391
|
for entry in raw:
|
|
388
392
|
if not isinstance(entry, dict):
|
|
389
393
|
msg = (
|
|
390
|
-
f"{scenario_name}:
|
|
394
|
+
f"{scenario_name}: index_routes entries must be tables,"
|
|
391
395
|
f" got {type(entry).__name__}"
|
|
392
396
|
)
|
|
393
397
|
raise TypeError(msg)
|
|
@@ -396,12 +400,10 @@ def parse_index_overrides(
|
|
|
396
400
|
index = entry["index"]
|
|
397
401
|
except KeyError as missing:
|
|
398
402
|
msg = (
|
|
399
|
-
f"{scenario_name}:
|
|
400
|
-
f" key {missing!s}"
|
|
403
|
+
f"{scenario_name}: index_routes entry missing required key {missing!s}"
|
|
401
404
|
)
|
|
402
405
|
raise ValueError(msg) from None
|
|
403
|
-
|
|
404
|
-
out.append(IndexOverride(name=str(name), index=str(index), marker=marker))
|
|
406
|
+
out.append(IndexRoute(name=str(name), index=str(index)))
|
|
405
407
|
return out
|
|
406
408
|
|
|
407
409
|
|
|
@@ -513,14 +515,10 @@ def process_scenario(
|
|
|
513
515
|
constraint_strings: list[str] = scenario.get("constraints", [])
|
|
514
516
|
marker_environment = parse_marker_environment(scenario_name, scenario)
|
|
515
517
|
indexes = parse_indexes(scenario_name, scenario)
|
|
516
|
-
|
|
518
|
+
index_routes = parse_index_routes(scenario_name, scenario)
|
|
517
519
|
build_policy_overrides = parse_build_packages(scenario_name, scenario)
|
|
518
520
|
if marker_environment and build_policy_overrides:
|
|
519
|
-
#
|
|
520
|
-
# provider construction (host backend cannot reflect the
|
|
521
|
-
# impersonated target). Drop the per-package builds so the
|
|
522
|
-
# scenario still runs; if resolution now fails the override
|
|
523
|
-
# was load-bearing and the scenario needs an audit.
|
|
521
|
+
# BUILD_REMOTE + marker_environment is rejected at provider construction.
|
|
524
522
|
print(
|
|
525
523
|
f"\n [audit] {scenario_name}: dropping {len(build_policy_overrides)}"
|
|
526
524
|
" build_packages override(s) because the scenario uses a"
|
|
@@ -543,8 +541,13 @@ def process_scenario(
|
|
|
543
541
|
f" got {resolution_raw!r}"
|
|
544
542
|
)
|
|
545
543
|
raise ValueError(msg) from exc
|
|
544
|
+
# Trust a pre-2.2 sdist's PKG-INFO deps by default. The benchmark measures
|
|
545
|
+
# resolver search, and under BuildPolicy.NEVER the strict PEP 643 product
|
|
546
|
+
# default rejects every sdist-only pre-2.2 pin (UnsupportedSdistError),
|
|
547
|
+
# dropping in-window versions uv resolves by building. A scenario sets this
|
|
548
|
+
# false to exercise strict behavior.
|
|
546
549
|
trust_unverified_sdist_deps: bool = scenario.get(
|
|
547
|
-
"trust_unverified_sdist_deps",
|
|
550
|
+
"trust_unverified_sdist_deps", True
|
|
548
551
|
)
|
|
549
552
|
optional_dependencies: dict[str, list[str]] = scenario.get(
|
|
550
553
|
"optional_dependencies", {}
|
|
@@ -580,7 +583,7 @@ def process_scenario(
|
|
|
580
583
|
vcs_policy_str,
|
|
581
584
|
marker_environment,
|
|
582
585
|
indexes,
|
|
583
|
-
|
|
586
|
+
index_routes,
|
|
584
587
|
build_packages=sorted(build_policy_overrides),
|
|
585
588
|
resolution_strategy=resolution_strategy,
|
|
586
589
|
trust_unverified_sdist_deps=trust_unverified_sdist_deps,
|
|
@@ -615,7 +618,7 @@ def process_scenario(
|
|
|
615
618
|
constraints,
|
|
616
619
|
marker_environment=marker_environment or None,
|
|
617
620
|
indexes=indexes,
|
|
618
|
-
|
|
621
|
+
index_routes=index_routes or None,
|
|
619
622
|
build_policy_overrides=build_policy_overrides or None,
|
|
620
623
|
resolution_strategy=resolution_strategy,
|
|
621
624
|
trust_unverified_sdist_deps=trust_unverified_sdist_deps,
|