nab-python 0.0.7__tar.gz → 0.0.9__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.
Files changed (214) hide show
  1. {nab_python-0.0.7 → nab_python-0.0.9}/PKG-INFO +3 -3
  2. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/README.md +2 -2
  3. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/canary.py +17 -4
  4. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/ai-stack-lowest-direct.toml +2 -0
  5. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/ai-stack-lowest.toml +2 -0
  6. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/ai-stack.toml +2 -0
  7. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/forums-lowest-direct.toml +5 -0
  8. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/forums-lowest.toml +5 -0
  9. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/forums.toml +5 -0
  10. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pip-lowest-direct.toml +15 -3
  11. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pip-lowest.toml +19 -3
  12. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pip.toml +19 -3
  13. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios.py +18 -4
  14. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/strategy_sweep.py +1 -2
  15. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/universal_scenarios.py +45 -26
  16. {nab_python-0.0.7 → nab_python-0.0.9}/pyproject.toml +3 -3
  17. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_build/env.py +95 -47
  18. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_build/runner.py +7 -8
  19. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_conflict_kind.py +2 -2
  20. nab_python-0.0.9/src/nab_python/_iso8601.py +34 -0
  21. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_lockfile/builder.py +153 -54
  22. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_lockfile/disjointness.py +10 -3
  23. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_lockfile/pylock.py +242 -129
  24. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_lockfile/requirements.py +37 -33
  25. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_packaging_provider.py +24 -2
  26. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_provider/build_remote.py +1 -2
  27. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_provider/extras.py +34 -17
  28. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_provider/listing.py +258 -57
  29. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_provider/lookahead.py +5 -4
  30. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_provider/metadata_resolver.py +66 -30
  31. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_provider/sources.py +78 -59
  32. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_testing/coordinator_fake.py +34 -80
  33. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vcs_admission.py +59 -4
  34. nab_python-0.0.9/src/nab_python/_vendor/packaging/PROVENANCE.md +61 -0
  35. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/_manylinux.py +0 -2
  36. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/_musllinux.py +1 -1
  37. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/_ranges.py +17 -17
  38. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/dependency_groups.py +5 -4
  39. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/direct_url.py +17 -8
  40. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/markers.py +43 -4
  41. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/metadata.py +8 -2
  42. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/pylock.py +4 -1
  43. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/ranges.py +251 -57
  44. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/requirements.py +13 -2
  45. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/specifiers.py +6 -6
  46. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/tags.py +14 -5
  47. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/version.py +21 -5
  48. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/build_backend.py +43 -21
  49. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/config.py +890 -101
  50. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/config_sources.py +56 -4
  51. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/download.py +25 -22
  52. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/fetch.py +333 -160
  53. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/lockfile.py +70 -38
  54. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/provider.py +479 -161
  55. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/requirements_file.py +11 -56
  56. nab_python-0.0.9/src/nab_python/resolve.py +1360 -0
  57. nab_python-0.0.9/src/nab_python/tags.py +813 -0
  58. nab_python-0.0.9/src/nab_python/target.py +1116 -0
  59. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/workspace.py +138 -72
  60. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/strategies.py +7 -0
  61. {nab_python-0.0.7/tests/universal/property_universal → nab_python-0.0.9/tests/property_python}/test_alignment.py +70 -64
  62. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_build_policy_never.py +2 -1
  63. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_cached_client_equiv.py +5 -5
  64. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_conflict_fork_markers.py +22 -29
  65. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_download_hashes.py +11 -2
  66. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_extras_pep685.py +6 -1
  67. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_fetch_coordinator.py +59 -33
  68. nab_python-0.0.9/tests/property_python/test_from_bounds_snap_bounds.py +119 -0
  69. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_lockfile_pep751.py +113 -84
  70. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_marker_overlay.py +23 -21
  71. {nab_python-0.0.7/tests/universal/property_universal → nab_python-0.0.9/tests/property_python}/test_matrix.py +42 -39
  72. {nab_python-0.0.7/tests/universal/property_universal → nab_python-0.0.9/tests/property_python}/test_matrix_labels.py +83 -39
  73. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_prerelease_admission.py +3 -0
  74. {nab_python-0.0.7/tests/universal/property_universal → nab_python-0.0.9/tests/property_python}/test_provider_pep425.py +68 -87
  75. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_sdist_archive_safety.py +24 -4
  76. nab_python-0.0.7/tests/universal/property_universal/test_wheel_selection_differential.py → nab_python-0.0.9/tests/property_python/test_tags_differential.py +100 -33
  77. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_universal_faithfulness.py +27 -40
  78. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_vcs_admission.py +16 -2
  79. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_archive.py +378 -23
  80. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_async_transports.py +386 -4
  81. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_benchmark_parse_requirements.py +3 -1
  82. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_build_backend.py +32 -6
  83. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_build_runner.py +233 -18
  84. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_cache.py +79 -22
  85. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_cached_client.py +438 -7
  86. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_config.py +1197 -32
  87. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_config_sources.py +24 -4
  88. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_download.py +115 -64
  89. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_fetch.py +597 -112
  90. nab_python-0.0.9/tests/test_iso8601.py +73 -0
  91. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_local_index.py +218 -5
  92. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_lockfile.py +1417 -814
  93. nab_python-0.0.9/tests/test_matrix.py +344 -0
  94. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_multi_index.py +75 -1
  95. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_provider.py +1329 -517
  96. nab_python-0.0.9/tests/test_provider_declared_target.py +1208 -0
  97. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_requirements_file.py +54 -43
  98. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_resolve.py +1160 -498
  99. nab_python-0.0.9/tests/test_resolve_targets.py +1822 -0
  100. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_resolver_packaging.py +19 -13
  101. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_simple_client_malformed.py +17 -6
  102. nab_python-0.0.9/tests/test_simple_client_size.py +46 -0
  103. nab_python-0.0.9/tests/test_tags.py +1271 -0
  104. nab_python-0.0.9/tests/test_target.py +1030 -0
  105. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_vcs.py +267 -10
  106. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_vcs_admission.py +225 -1
  107. nab_python-0.0.9/tests/test_vendor_from_bounds_snap_bounds.py +214 -0
  108. nab_python-0.0.9/tests/test_widen_decision.py +272 -0
  109. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_workspace.py +107 -0
  110. {nab_python-0.0.7 → nab_python-0.0.9}/tests/universal/property_universal/strategies.py +7 -13
  111. nab_python-0.0.7/src/nab_python/_vendor/packaging/PROVENANCE.md +0 -92
  112. nab_python-0.0.7/src/nab_python/resolve.py +0 -1048
  113. nab_python-0.0.7/src/nab_python/universal/__init__.py +0 -1
  114. nab_python-0.0.7/src/nab_python/universal/matrix.py +0 -337
  115. nab_python-0.0.7/src/nab_python/universal/provider.py +0 -234
  116. nab_python-0.0.7/src/nab_python/universal/reresolve.py +0 -340
  117. nab_python-0.0.7/src/nab_python/universal/resolve.py +0 -781
  118. nab_python-0.0.7/src/nab_python/universal/validate.py +0 -554
  119. nab_python-0.0.7/src/nab_python/universal/wheel_selection.py +0 -431
  120. nab_python-0.0.7/tests/universal/property_universal/test_reresolve_fixed_point.py +0 -168
  121. nab_python-0.0.7/tests/universal/property_universal/test_validate.py +0 -143
  122. nab_python-0.0.7/tests/universal/property_universal/test_validate_mutations.py +0 -184
  123. nab_python-0.0.7/tests/universal/test_matrix.py +0 -529
  124. nab_python-0.0.7/tests/universal/test_reresolve.py +0 -488
  125. nab_python-0.0.7/tests/universal/test_resolve.py +0 -1584
  126. nab_python-0.0.7/tests/universal/test_universal_provider.py +0 -691
  127. nab_python-0.0.7/tests/universal/test_validate.py +0 -1443
  128. nab_python-0.0.7/tests/universal/test_wheel_selection.py +0 -598
  129. {nab_python-0.0.7 → nab_python-0.0.9}/.gitignore +0 -0
  130. {nab_python-0.0.7 → nab_python-0.0.9}/LICENSE +0 -0
  131. {nab_python-0.0.7 → nab_python-0.0.9}/README.md +0 -0
  132. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/_profile_runner.py +0 -0
  133. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/cache/.gitignore +0 -0
  134. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/canary_results/.gitignore +0 -0
  135. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/compare.py +0 -0
  136. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/results/.gitignore +0 -0
  137. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/airflow-lowest-direct.toml +0 -0
  138. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/airflow-lowest.toml +0 -0
  139. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/airflow.toml +0 -0
  140. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/big-packages-lowest-direct.toml +0 -0
  141. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/big-packages-lowest.toml +0 -0
  142. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/big-packages.toml +0 -0
  143. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/cross-tracker-lowest-direct.toml +0 -0
  144. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/cross-tracker-lowest.toml +0 -0
  145. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/cross-tracker.toml +0 -0
  146. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/ecosystem-lowest-direct.toml +0 -0
  147. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/ecosystem-lowest.toml +0 -0
  148. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/ecosystem.toml +0 -0
  149. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pdm-lowest-direct.toml +0 -0
  150. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pdm-lowest.toml +0 -0
  151. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pdm.toml +0 -0
  152. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/poetry-lowest-direct.toml +0 -0
  153. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/poetry-lowest.toml +0 -0
  154. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/poetry.toml +0 -0
  155. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pytorch-lowest-direct.toml +0 -0
  156. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pytorch-lowest.toml +0 -0
  157. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/pytorch.toml +0 -0
  158. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/quick-lowest-direct.toml +0 -0
  159. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/quick-lowest.toml +0 -0
  160. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/quick.toml +0 -0
  161. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/rip-lowest-direct.toml +0 -0
  162. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/rip-lowest.toml +0 -0
  163. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/rip.toml +0 -0
  164. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/universal.toml +0 -0
  165. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/unsupported-lowest-direct.toml +0 -0
  166. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/unsupported-lowest.toml +0 -0
  167. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/unsupported.toml +0 -0
  168. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/uv-lowest-direct.toml +0 -0
  169. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/uv-lowest.toml +0 -0
  170. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/scenarios/uv.toml +0 -0
  171. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/strategy_sweep_results/summary.json +0 -0
  172. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/strategy_sweep_summary.py +0 -0
  173. {nab_python-0.0.7 → nab_python-0.0.9}/benchmarks/universal_summary.py +0 -0
  174. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/__init__.py +0 -0
  175. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_build/__init__.py +0 -0
  176. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_build/errors.py +0 -0
  177. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_lockfile/__init__.py +0 -0
  178. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_provider/__init__.py +0 -0
  179. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_provider/priority.py +0 -0
  180. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_testing/__init__.py +0 -0
  181. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_testing/overrides.py +0 -0
  182. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_toml.py +0 -0
  183. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/__init__.py +0 -0
  184. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/LICENSE +0 -0
  185. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/LICENSE.APACHE +0 -0
  186. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/LICENSE.BSD +0 -0
  187. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/__init__.py +0 -0
  188. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/_elffile.py +0 -0
  189. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/_parser.py +0 -0
  190. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/_structures.py +0 -0
  191. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/_tokenizer.py +0 -0
  192. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/errors.py +0 -0
  193. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/licenses/__init__.py +0 -0
  194. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/licenses/_spdx.py +0 -0
  195. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/py.typed +0 -0
  196. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/_vendor/packaging/utils.py +0 -0
  197. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/metadata.py +0 -0
  198. {nab_python-0.0.7 → nab_python-0.0.9}/src/nab_python/py.typed +0 -0
  199. {nab_python-0.0.7 → nab_python-0.0.9}/tests/__init__.py +0 -0
  200. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/__init__.py +0 -0
  201. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_disjointness_differential.py +0 -0
  202. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_filename_differential.py +0 -0
  203. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_multi_index_contract.py +0 -0
  204. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_multi_index_pep503.py +0 -0
  205. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_override_overlap.py +0 -0
  206. {nab_python-0.0.7 → nab_python-0.0.9}/tests/property_python/test_resolver_pep440.py +0 -0
  207. {nab_python-0.0.7 → nab_python-0.0.9}/tests/ruff.toml +0 -0
  208. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_marker_evaluation.py +0 -0
  209. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_metadata.py +0 -0
  210. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_simple_client_filenames.py +0 -0
  211. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_simple_client_hashes.py +0 -0
  212. {nab_python-0.0.7 → nab_python-0.0.9}/tests/test_simple_client_upload_time.py +0 -0
  213. {nab_python-0.0.7 → nab_python-0.0.9}/tests/universal/__init__.py +0 -0
  214. {nab_python-0.0.7 → nab_python-0.0.9}/tests/universal/property_universal/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nab-python
3
- Version: 0.0.7
3
+ Version: 0.0.9
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.7
24
- Requires-Dist: nab-resolver==0.0.7
23
+ Requires-Dist: nab-index==0.0.9
24
+ Requires-Dist: nab-resolver==0.0.9
25
25
  Requires-Dist: pyproject-hooks>=1.2
26
26
  Requires-Dist: tomli-w>=1.2
27
27
  Requires-Dist: tomli>=2.0
@@ -1,7 +1,7 @@
1
1
  # Benchmarks
2
2
 
3
- nab ships two benchmark suites that exercise the single-environment
4
- and the universal resolver against real-world scenarios.
3
+ nab ships two benchmark suites that exercise single-environment and
4
+ universal resolves against real-world scenarios.
5
5
 
6
6
  ## Single-environment scenarios
7
7
 
@@ -53,6 +53,7 @@ from nab_python.provider import (
53
53
  VcsPolicy,
54
54
  split_extra,
55
55
  )
56
+ from nab_python.target import ResolveTarget
56
57
  from nab_resolver.resolver import Resolver
57
58
 
58
59
  BENCHMARKS_DIR = Path(__file__).parent
@@ -155,9 +156,14 @@ def parse_requirements(
155
156
  )
156
157
  raise NotImplementedError(msg)
157
158
  name = canonicalize_name(req.name)
158
- reqs[name] = reqs.get(name, VersionRange.full()) & req.specifier.to_range()
159
+ term = (
160
+ req.specifier.to_range()
161
+ if req.specifier
162
+ else VersionRange.full(admit_arbitrary=False)
163
+ )
164
+ reqs[name] = reqs.get(name, VersionRange.full()) & term
159
165
  for extra in req.extras:
160
- reqs[f"{name}[{extra}]"] = VersionRange.full()
166
+ reqs[f"{name}[{extra}]"] = VersionRange.full(admit_arbitrary=False)
161
167
  return reqs
162
168
 
163
169
 
@@ -173,6 +179,14 @@ def _full_marker_environment(
173
179
  _PYTHON_VERSION_PARTS = 2
174
180
 
175
181
 
182
+ def _resolve_target(
183
+ python_version: str,
184
+ marker_environment: dict[str, str] | None,
185
+ ) -> ResolveTarget:
186
+ target = ResolveTarget.for_host_python(python_version)
187
+ return target.with_marker_overrides(marker_environment or {})
188
+
189
+
176
190
  def _scenario_marker_env(
177
191
  python_version: str,
178
192
  overlay: dict[str, str],
@@ -235,14 +249,13 @@ def run_one( # noqa: PLR0913 - one wrapper per scenario knob
235
249
  ) as coordinator:
236
250
  provider = Provider(
237
251
  coordinator,
238
- python_version=python_version,
252
+ target=_resolve_target(python_version, marker_environment),
239
253
  root_requirements=requirements,
240
254
  uploaded_prior_to=uploaded_prior_to,
241
255
  dist_policy=DistPolicy.WHEEL_OR_SDIST,
242
256
  build_policy=BuildPolicy.NEVER,
243
257
  package_overrides=package_overrides,
244
258
  trust_unverified_sdist_deps=trust_unverified_sdist_deps,
245
- marker_environment=marker_environment,
246
259
  )
247
260
  resolver = Resolver(
248
261
  provider,
@@ -463,6 +463,8 @@ requirements = ["llama-index-readers-confluence>=0.3,<0.4"]
463
463
  # https://github.com/run-llama/llama_index/issues/19167
464
464
  # docling 1.20 pins deepsearch-glm<0.23, not on PyPI, -> backtrack.
465
465
  resolution = "lowest-direct"
466
+ # Impossible by design: deepsearch-glm 0.21.1, the only version docling's
467
+ # range admits, ships cp39 to cp312 and no sdist, so 3.13 cannot install it.
466
468
  python_version = "3.13"
467
469
  platform_system = "Linux"
468
470
  datetime = "2025-06-21 10:33:57"
@@ -463,6 +463,8 @@ requirements = ["llama-index-readers-confluence>=0.3,<0.4"]
463
463
  # https://github.com/run-llama/llama_index/issues/19167
464
464
  # docling 1.20 pins deepsearch-glm<0.23, not on PyPI, -> backtrack.
465
465
  resolution = "lowest"
466
+ # Impossible by design: deepsearch-glm 0.21.1, the only version docling's
467
+ # range admits, ships cp39 to cp312 and no sdist, so 3.13 cannot install it.
466
468
  python_version = "3.13"
467
469
  platform_system = "Linux"
468
470
  datetime = "2025-06-21 10:33:57"
@@ -436,6 +436,8 @@ requirements = ["llama-index-readers-confluence>=0.3,<0.4"]
436
436
  [llama-index-docling]
437
437
  # https://github.com/run-llama/llama_index/issues/19167
438
438
  # docling 1.20 pins deepsearch-glm<0.23, not on PyPI, -> backtrack.
439
+ # Impossible by design: deepsearch-glm 0.21.1, the only version docling's
440
+ # range admits, ships cp39 to cp312 and no sdist, so 3.13 cannot install it.
439
441
  python_version = "3.13"
440
442
  platform_system = "Linux"
441
443
  datetime = "2025-06-21 10:33:57"
@@ -370,6 +370,9 @@ requirements = ["jupyter-server", "jupyter-core"]
370
370
  # https://stackoverflow.com/q/77664987
371
371
  # teachable-machine pulls tensorflow with no upper bound on Python 3.12.
372
372
  resolution = "lowest-direct"
373
+ # Impossible by design: tensorflow's first cp312 wheel is 2.16 (March 2024),
374
+ # after this cutoff, so every teachable-machine version is walked and none
375
+ # can be installed. That walk is the pip report this reproduces.
373
376
  python_version = "3.12"
374
377
  platform_system = "Linux"
375
378
  datetime = "2023-12-15 08:09:01"
@@ -1020,6 +1023,8 @@ requirements = ["django-mailgun"]
1020
1023
  # https://stackoverflow.com/q/77252186
1021
1024
  # Paddle stack (without git dep): paddlepaddle + paddleocr + paddlenlp
1022
1025
  resolution = "lowest-direct"
1026
+ # Impossible by design: paddlepaddle ships no cp310 wheel and no sdist
1027
+ # before this cutoff, which is the install failure the question reports.
1023
1028
  python_version = "3.10"
1024
1029
  platform_system = "Linux"
1025
1030
  datetime = "2023-10-08 14:00:00"
@@ -370,6 +370,9 @@ requirements = ["jupyter-server", "jupyter-core"]
370
370
  # https://stackoverflow.com/q/77664987
371
371
  # teachable-machine pulls tensorflow with no upper bound on Python 3.12.
372
372
  resolution = "lowest"
373
+ # Impossible by design: tensorflow's first cp312 wheel is 2.16 (March 2024),
374
+ # after this cutoff, so every teachable-machine version is walked and none
375
+ # can be installed. That walk is the pip report this reproduces.
373
376
  python_version = "3.12"
374
377
  platform_system = "Linux"
375
378
  datetime = "2023-12-15 08:09:01"
@@ -1020,6 +1023,8 @@ requirements = ["django-mailgun"]
1020
1023
  # https://stackoverflow.com/q/77252186
1021
1024
  # Paddle stack (without git dep): paddlepaddle + paddleocr + paddlenlp
1022
1025
  resolution = "lowest"
1026
+ # Impossible by design: paddlepaddle ships no cp310 wheel and no sdist
1027
+ # before this cutoff, which is the install failure the question reports.
1023
1028
  python_version = "3.10"
1024
1029
  platform_system = "Linux"
1025
1030
  datetime = "2023-10-08 14:00:00"
@@ -343,6 +343,9 @@ requirements = ["jupyter-server", "jupyter-core"]
343
343
  [so-teachable-machine-77664987]
344
344
  # https://stackoverflow.com/q/77664987
345
345
  # teachable-machine pulls tensorflow with no upper bound on Python 3.12.
346
+ # Impossible by design: tensorflow's first cp312 wheel is 2.16 (March 2024),
347
+ # after this cutoff, so every teachable-machine version is walked and none
348
+ # can be installed. That walk is the pip report this reproduces.
346
349
  python_version = "3.12"
347
350
  platform_system = "Linux"
348
351
  datetime = "2023-12-15 08:09:01"
@@ -946,6 +949,8 @@ requirements = ["django-mailgun"]
946
949
  [so-paddleocr-cli-77252186-clone]
947
950
  # https://stackoverflow.com/q/77252186
948
951
  # Paddle stack (without git dep): paddlepaddle + paddleocr + paddlenlp
952
+ # Impossible by design: paddlepaddle ships no cp310 wheel and no sdist
953
+ # before this cutoff, which is the install failure the question reports.
949
954
  python_version = "3.10"
950
955
  platform_system = "Linux"
951
956
  datetime = "2023-10-08 14:00:00"
@@ -186,6 +186,8 @@ requirements = ["trustllm"]
186
186
  [metagpt]
187
187
  # https://github.com/FoundationAgents/MetaGPT/issues/1825
188
188
  # ResolutionImpossible (not too-deep), kept as a regression check.
189
+ # Impossible by design: metagpt pins faiss-cpu==1.7.4, whose newest wheel is
190
+ # cp311, and it publishes no sdist, so 3.12 cannot install it.
189
191
  resolution = "lowest-direct"
190
192
  python_version = "3.12"
191
193
  platform_system = "Linux"
@@ -203,8 +205,14 @@ requirements = ["mem0ai[graph,extras]"]
203
205
 
204
206
  [langchain-ml-course]
205
207
  # https://github.com/pypa/pip/issues/13281#issuecomment-3813389543
208
+ # Reported on 3.14, but no solution exists there at this cutoff:
209
+ # langchain-chroma pulls chromadb, which requires onnxruntime, and
210
+ # onnxruntime publishes no sdist and no cp314 wheel until 2026-02-05.
211
+ # pip refuses it too. Targeted at 3.13, where onnxruntime does ship
212
+ # wheels, so the scenario still exercises the backtracking it was added
213
+ # for instead of measuring an impossible resolve.
206
214
  resolution = "lowest-direct"
207
- python_version = "3.14"
215
+ python_version = "3.13"
208
216
  platform_system = "Linux"
209
217
  datetime = "2026-01-28 19:21:17"
210
218
  requirements = [
@@ -786,8 +794,10 @@ requirements = ["trustllm"]
786
794
  # https://github.com/pypa/pip/issues/13281#issuecomment-3813389543
787
795
  # Near-duplicate of [langchain-ml-course] but on Darwin with a slightly different
788
796
  # datetime, capturing the repeated report from a different user environment.
797
+ # Targeted at 3.13 for the same reason: onnxruntime ships no cp314 wheel before
798
+ # the cutoff and no sdist, so 3.14 has no solution here.
789
799
  resolution = "lowest-direct"
790
- python_version = "3.14"
800
+ python_version = "3.13"
791
801
  platform_system = "Darwin"
792
802
  datetime = "2026-01-28 19:21:17"
793
803
  requirements = [
@@ -1656,7 +1666,9 @@ requirements = [
1656
1666
  # Re-run of pip-12275-old-pypi-date but in 2023. Useful as a historical
1657
1667
  # point: even in 2023 a 2019 PyPI cutoff sees heavy backtracking.
1658
1668
  resolution = "lowest-direct"
1659
- python_version = "3.9"
1669
+ # Python 3.9 did not exist at this cutoff (released 2020-10-05), so no
1670
+ # cp39 wheel could: 3.8 is the interpreter of the day.
1671
+ python_version = "3.8"
1660
1672
  platform_system = "Linux"
1661
1673
  datetime = "2020-06-01 00:00:00"
1662
1674
  requirements = [
@@ -186,6 +186,8 @@ requirements = ["trustllm"]
186
186
  [metagpt]
187
187
  # https://github.com/FoundationAgents/MetaGPT/issues/1825
188
188
  # ResolutionImpossible (not too-deep), kept as a regression check.
189
+ # Impossible by design: metagpt pins faiss-cpu==1.7.4, whose newest wheel is
190
+ # cp311, and it publishes no sdist, so 3.12 cannot install it.
189
191
  resolution = "lowest"
190
192
  python_version = "3.12"
191
193
  platform_system = "Linux"
@@ -203,8 +205,14 @@ requirements = ["mem0ai[graph,extras]"]
203
205
 
204
206
  [langchain-ml-course]
205
207
  # https://github.com/pypa/pip/issues/13281#issuecomment-3813389543
208
+ # Reported on 3.14, but no solution exists there at this cutoff:
209
+ # langchain-chroma pulls chromadb, which requires onnxruntime, and
210
+ # onnxruntime publishes no sdist and no cp314 wheel until 2026-02-05.
211
+ # pip refuses it too. Targeted at 3.13, where onnxruntime does ship
212
+ # wheels, so the scenario still exercises the backtracking it was added
213
+ # for instead of measuring an impossible resolve.
206
214
  resolution = "lowest"
207
- python_version = "3.14"
215
+ python_version = "3.13"
208
216
  platform_system = "Linux"
209
217
  datetime = "2026-01-28 19:21:17"
210
218
  requirements = [
@@ -784,10 +792,16 @@ requirements = ["trustllm"]
784
792
 
785
793
  [langchain-ml-course-macos]
786
794
  # https://github.com/pypa/pip/issues/13281#issuecomment-3813389543
795
+ # Reported on 3.14, but no solution exists there at this cutoff:
796
+ # langchain-chroma pulls chromadb, which requires onnxruntime, and
797
+ # onnxruntime publishes no sdist and no cp314 wheel until 2026-02-05.
798
+ # pip refuses it too. Targeted at 3.13, where onnxruntime does ship
799
+ # wheels, so the scenario still exercises the backtracking it was added
800
+ # for instead of measuring an impossible resolve.
787
801
  # Near-duplicate of [langchain-ml-course] but on Darwin with a slightly different
788
802
  # datetime, capturing the repeated report from a different user environment.
789
803
  resolution = "lowest"
790
- python_version = "3.14"
804
+ python_version = "3.13"
791
805
  platform_system = "Darwin"
792
806
  datetime = "2026-01-28 19:21:17"
793
807
  requirements = [
@@ -1656,7 +1670,9 @@ requirements = [
1656
1670
  # Re-run of pip-12275-old-pypi-date but in 2023. Useful as a historical
1657
1671
  # point: even in 2023 a 2019 PyPI cutoff sees heavy backtracking.
1658
1672
  resolution = "lowest"
1659
- python_version = "3.9"
1673
+ # Python 3.9 did not exist at this cutoff (released 2020-10-05), so no
1674
+ # cp39 wheel could: 3.8 is the interpreter of the day.
1675
+ python_version = "3.8"
1660
1676
  platform_system = "Linux"
1661
1677
  datetime = "2020-06-01 00:00:00"
1662
1678
  requirements = [
@@ -170,6 +170,8 @@ requirements = ["trustllm"]
170
170
  [metagpt]
171
171
  # https://github.com/FoundationAgents/MetaGPT/issues/1825
172
172
  # ResolutionImpossible (not too-deep), kept as a regression check.
173
+ # Impossible by design: metagpt pins faiss-cpu==1.7.4, whose newest wheel is
174
+ # cp311, and it publishes no sdist, so 3.12 cannot install it.
173
175
  python_version = "3.12"
174
176
  platform_system = "Linux"
175
177
  datetime = "2025-05-11 06:38:41"
@@ -185,7 +187,13 @@ requirements = ["mem0ai[graph,extras]"]
185
187
 
186
188
  [langchain-ml-course]
187
189
  # https://github.com/pypa/pip/issues/13281#issuecomment-3813389543
188
- python_version = "3.14"
190
+ # Reported on 3.14, but no solution exists there at this cutoff:
191
+ # langchain-chroma pulls chromadb, which requires onnxruntime, and
192
+ # onnxruntime publishes no sdist and no cp314 wheel until 2026-02-05.
193
+ # pip refuses it too. Targeted at 3.13, where onnxruntime does ship
194
+ # wheels, so the scenario still exercises the backtracking it was added
195
+ # for instead of measuring an impossible resolve.
196
+ python_version = "3.13"
189
197
  platform_system = "Linux"
190
198
  datetime = "2026-01-28 19:21:17"
191
199
  requirements = [
@@ -743,9 +751,15 @@ requirements = ["trustllm"]
743
751
 
744
752
  [langchain-ml-course-macos]
745
753
  # https://github.com/pypa/pip/issues/13281#issuecomment-3813389543
754
+ # Reported on 3.14, but no solution exists there at this cutoff:
755
+ # langchain-chroma pulls chromadb, which requires onnxruntime, and
756
+ # onnxruntime publishes no sdist and no cp314 wheel until 2026-02-05.
757
+ # pip refuses it too. Targeted at 3.13, where onnxruntime does ship
758
+ # wheels, so the scenario still exercises the backtracking it was added
759
+ # for instead of measuring an impossible resolve.
746
760
  # Near-duplicate of [langchain-ml-course] but on Darwin with a slightly different
747
761
  # datetime, capturing the repeated report from a different user environment.
748
- python_version = "3.14"
762
+ python_version = "3.13"
749
763
  platform_system = "Darwin"
750
764
  datetime = "2026-01-28 19:21:17"
751
765
  requirements = [
@@ -1579,7 +1593,9 @@ requirements = [
1579
1593
  # https://github.com/pypa/pip/issues/12275
1580
1594
  # Re-run of pip-12275-old-pypi-date but in 2023. Useful as a historical
1581
1595
  # point: even in 2023 a 2019 PyPI cutoff sees heavy backtracking.
1582
- python_version = "3.9"
1596
+ # Python 3.9 did not exist at this cutoff (released 2020-10-05), so no
1597
+ # cp39 wheel could: 3.8 is the interpreter of the day.
1598
+ python_version = "3.8"
1583
1599
  platform_system = "Linux"
1584
1600
  datetime = "2020-06-01 00:00:00"
1585
1601
  requirements = [
@@ -51,6 +51,7 @@ from nab_python.provider import (
51
51
  VcsPolicy,
52
52
  split_extra,
53
53
  )
54
+ from nab_python.target import ResolveTarget
54
55
  from nab_resolver.resolver import Resolver
55
56
 
56
57
  BENCHMARKS_DIR = Path(__file__).parent
@@ -138,9 +139,14 @@ def parse_requirements(
138
139
  )
139
140
  raise NotImplementedError(msg)
140
141
  name = canonicalize_name(req.name)
141
- reqs[name] = reqs.get(name, VersionRange.full()) & req.specifier.to_range()
142
+ term = (
143
+ req.specifier.to_range()
144
+ if req.specifier
145
+ else VersionRange.full(admit_arbitrary=False)
146
+ )
147
+ reqs[name] = reqs.get(name, VersionRange.full()) & term
142
148
  for extra in req.extras:
143
- reqs[f"{name}[{extra}]"] = VersionRange.full()
149
+ reqs[f"{name}[{extra}]"] = VersionRange.full(admit_arbitrary=False)
144
150
  return reqs
145
151
 
146
152
 
@@ -179,6 +185,15 @@ def scenario_marker_env(
179
185
  return env
180
186
 
181
187
 
188
+ def resolve_target(
189
+ python_version: str,
190
+ marker_environment: dict[str, str] | None,
191
+ ) -> ResolveTarget:
192
+ """Build the scenario's resolve target: host machine, scenario Python."""
193
+ target = ResolveTarget.for_host_python(python_version)
194
+ return target.with_marker_overrides(marker_environment or {})
195
+
196
+
182
197
  def parse_datetime(value: str) -> datetime:
183
198
  """Parse an ISO 8601 datetime string to a timezone-aware datetime."""
184
199
  dt = datetime.fromisoformat(value)
@@ -240,14 +255,13 @@ def resolve_scenario( # noqa: PLR0913 - one wrapper per scenario knob
240
255
  ) as coordinator:
241
256
  provider = Provider(
242
257
  coordinator,
243
- python_version=python_version,
258
+ target=resolve_target(python_version, marker_environment),
244
259
  root_requirements=requirements,
245
260
  uploaded_prior_to=uploaded_prior_to,
246
261
  dist_policy=DistPolicy.WHEEL_OR_SDIST,
247
262
  build_policy=BuildPolicy.NEVER,
248
263
  package_overrides=package_overrides,
249
264
  trust_unverified_sdist_deps=trust_unverified_sdist_deps,
250
- marker_environment=marker_environment,
251
265
  resolution_strategy=resolution_strategy,
252
266
  direct_packages=direct_packages,
253
267
  )
@@ -105,13 +105,12 @@ def _resolve_one( # noqa: PLR0913 - one kwarg per knob; bundling hides the surf
105
105
  ) as coordinator:
106
106
  provider = Provider(
107
107
  coordinator,
108
- python_version=python_version,
108
+ target=_scenarios.resolve_target(python_version, marker_environment),
109
109
  root_requirements=requirements,
110
110
  uploaded_prior_to=uploaded_prior_to,
111
111
  dist_policy=DistPolicy.WHEEL_OR_SDIST,
112
112
  build_policy=BuildPolicy.NEVER,
113
113
  package_overrides=package_overrides,
114
- marker_environment=marker_environment,
115
114
  resolution_strategy=strategy,
116
115
  direct_packages=direct_packages,
117
116
  extras_mode=extras_mode,
@@ -1,7 +1,7 @@
1
- """Run universal-resolution benchmark scenarios against nab_python.universal.
1
+ """Run universal-resolution benchmark scenarios against nab_python.
2
2
 
3
3
  Reads scenarios from ``scenarios/universal.toml`` and resolves each
4
- via ``nab_python.universal.resolve_universal``, sharing a single
4
+ via ``nab_python.resolve.resolve_with_coordinator``, sharing a single
5
5
  ``FetchCoordinator`` per scenario for metadata reuse across tuples.
6
6
 
7
7
  Output mirrors ``scenarios.py`` but with a ``per_tuple`` array so the
@@ -31,14 +31,20 @@ else:
31
31
  # nab pins py>=3.10 but the import fallback matches scenarios.py
32
32
  import tomli as tomllib # type: ignore[no-redef] # pragma: no cover
33
33
 
34
+ from nab_index.urllib3_async_transport import Urllib3AsyncTransport
34
35
  from nab_python._lockfile.pylock import build_pylock
36
+ from nab_python._vendor.packaging.requirements import Requirement
35
37
  from nab_python._vendor.packaging.utils import canonicalize_name
36
- from nab_python.universal.matrix import Matrix
37
- from nab_python.universal.resolve import (
38
- UniversalResult,
39
- merge_universal_lock_inputs,
40
- resolve_universal,
38
+ from nab_python.config import NabProjectConfig
39
+ from nab_python.fetch import FetchCoordinator
40
+ from nab_python.provider import ResolutionStrategy
41
+ from nab_python.resolve import (
42
+ ResolveResult,
43
+ build_lock_input,
44
+ resolve_with_coordinator,
41
45
  )
46
+ from nab_python.tags import PlatformSpec
47
+ from nab_python.target import Matrix
42
48
 
43
49
  BENCHMARKS_DIR = Path(__file__).parent
44
50
  SCENARIOS_DIR = BENCHMARKS_DIR / "scenarios"
@@ -86,7 +92,7 @@ def parse_datetime(value: str) -> datetime:
86
92
  return dt
87
93
 
88
94
 
89
- def check_lock_consistency(result: UniversalResult) -> tuple[bool, list[str]]:
95
+ def check_lock_consistency(result: ResolveResult) -> tuple[bool, list[str]]:
90
96
  """Verify the marker-gated lock reproduces each tuple's solution.
91
97
 
92
98
  Builds the real PEP 751 lock and, for each tuple, projects every
@@ -99,20 +105,20 @@ def check_lock_consistency(result: UniversalResult) -> tuple[bool, list[str]]:
99
105
 
100
106
  Call only when ``result.success`` so the lock covers every tuple.
101
107
  """
102
- lock_input = merge_universal_lock_inputs(result)
108
+ lock_input = build_lock_input(result)
103
109
  try:
104
110
  pylock = build_pylock(lock_input)
105
111
  except Exception as exc:
106
112
  return False, [f"build_pylock raised {type(exc).__name__}: {exc}"[:200]]
107
113
 
108
114
  problems: list[str] = []
109
- for tr in result.tuple_results:
115
+ for tr in result.target_results:
110
116
  expected = {canonicalize_name(n): str(v) for n, v in tr.pins.items()}
111
117
  selected: dict[str, str | None] = {}
112
118
  duplicates: set[str] = set()
113
119
  for pkg in pylock.packages:
114
120
  marker = pkg.marker
115
- if marker is not None and not marker.evaluate(tr.tuple_.environment):
121
+ if marker is not None and not marker.evaluate(tr.target.marker_env):
116
122
  continue
117
123
  name = canonicalize_name(str(pkg.name))
118
124
  if name in selected:
@@ -127,7 +133,7 @@ def check_lock_consistency(result: UniversalResult) -> tuple[bool, list[str]]:
127
133
  if expected[k] != selected[k]
128
134
  )
129
135
  problems.append(
130
- f"{tr.tuple_.label}: missing={missing} extra={extra} "
136
+ f"{tr.target.label}: missing={missing} extra={extra} "
131
137
  f"mismatch={mismatch} duplicate={sorted(duplicates)}"
132
138
  )
133
139
  return not problems, problems
@@ -177,30 +183,43 @@ def process_scenario(
177
183
  return
178
184
 
179
185
  print(f" {scenario_name} ", end="", flush=True)
180
- matrix = Matrix(python=python_spec, platforms=platforms, python_order=python_order)
186
+ matrix = Matrix(
187
+ python=python_spec,
188
+ platforms=tuple(PlatformSpec(p) for p in platforms),
189
+ python_order=python_order,
190
+ )
181
191
 
182
192
  previous_handler = signal.signal(signal.SIGALRM, _alarm_handler)
183
193
  signal.alarm(SCENARIO_WALL_TIMEOUT_SECONDS)
184
194
  start = time.monotonic()
185
195
  timed_out = False
186
196
  try:
187
- result = resolve_universal(
188
- matrix=matrix,
189
- requirements=requirement_strings,
190
- constraints=constraint_strings or None,
191
- cache_dir=CACHE_DIR,
197
+ config = NabProjectConfig(
198
+ constraints=tuple(constraint_strings),
192
199
  uploaded_prior_to=uploaded_prior_to,
193
- resolution_strategy=resolution_strategy,
194
- align_across_tuples=align,
195
200
  )
201
+ with FetchCoordinator(
202
+ Urllib3AsyncTransport(),
203
+ indexes=list(config.indexes),
204
+ cache_dir=CACHE_DIR,
205
+ ) as coordinator:
206
+ result = resolve_with_coordinator(
207
+ coordinator,
208
+ matrix.expand(),
209
+ [Requirement(text) for text in requirement_strings],
210
+ config=config,
211
+ cache_dir=CACHE_DIR,
212
+ resolution_strategy=ResolutionStrategy(resolution_strategy),
213
+ align_across_targets=align,
214
+ )
196
215
  elapsed = time.monotonic() - start
197
216
  per_tuple = [
198
217
  {
199
- "label": tr.tuple_.label,
200
- "python_version": tr.tuple_.python_version,
201
- "platform_id": tr.tuple_.platform_id,
218
+ "label": tr.target.label,
219
+ "python_version": tr.target.python_version,
220
+ "platform_id": tr.target.platform_id,
202
221
  "success": tr.success,
203
- "error": tr.error,
222
+ "error": str(tr.error) if tr.error is not None else None,
204
223
  "decisions": tr.decisions,
205
224
  "rounds": tr.rounds,
206
225
  "conflicts": tr.conflicts,
@@ -210,9 +229,9 @@ def process_scenario(
210
229
  "wall_time_seconds": round(tr.wall_time, 3),
211
230
  "package_count": len(tr.pins),
212
231
  }
213
- for tr in result.tuple_results
232
+ for tr in result.target_results
214
233
  ]
215
- merged = result.merged_lock()
234
+ merged = result.merged_pins()
216
235
  diverging_packages = sum(
217
236
  1 for pins in merged.values() if len({version for version, _ in pins}) > 1
218
237
  )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nab-python"
3
- version = "0.0.7"
3
+ version = "0.0.9"
4
4
  description = "Index-backed provider, lockfile emitter, and downloader for nab"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -19,8 +19,8 @@ classifiers = [
19
19
  "Typing :: Typed",
20
20
  ]
21
21
  dependencies = [
22
- "nab-resolver==0.0.7",
23
- "nab-index==0.0.7",
22
+ "nab-resolver==0.0.9",
23
+ "nab-index==0.0.9",
24
24
  "tomli>=2.0",
25
25
  "tomli_w>=1.2",
26
26
  "build>=1.2",