+
    2j                   t  a 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIH	t	 ^ RI
HtHtHt ^ RIHtHtHt ^ RIHt ^ RIHtHtHt ^ RIHt ^ RIt^ R	IHt ^ R
IHtHt ^ RIH t  ^ RI!H"t" ^ RI#H$t$ ^ RI%H&t& ^RI'H(t(H)t) ^RI*H+t+ ^RI,H-t- ^RI.H/t/ ^RI0H1t1 ^RI2H3t3H4t4 ^RI5H6t6H7t7 ^RI8H9t9 ^RI:H;t;H<t<H=t=H>t>H?t?H@t@HAtAHBtBHCtCHDtDHEtE ^RIFHGtGHHtHHItI ^RIJHKtK ^RILHMtMHNtNHOtOHPtPHQtQHRtRHStSHTtTHUtUHVtV ^RIWHXtXHYtYHZtZH[t[H\t\ ^RI]H^t^H_t_H`t`HataHbtbHctc ^RIdHeteHftfHgtgHhthHiti ]'       d   ^ RIjHktkHltl ^ RIjHmtn ^ R IoHptp ^R!IqHrtr . EROts]P                  ! R.4      tu]v! 0 ER m4      tw]v! R3R404      tx^tyR5tzR6t{]! R7R7R87       ! R9 R*4      4       t|]! R7R7R87       ! R: R(4      4       t} ! R; R%]P                  4      t ! R< R#]P                  4      t]! R7R7R87       ! R= R$4      4       t]! R7R7R87       ! R> R'4      4       tR? R@ ltRA RB lt]! R7R7R87       ! RC R"4      4       t]! R7R7R87       ! RD R-4      4       t]! R7R7R87       ! RE R)4      4       t^tER!RF RG llt]! R7R7R87       ! RH R+4      4       tRI RJ lt ! RK R&];4      t ! RL R,];4      tRM RN ltRO RP ltRQ RR ltRSR7RTRRUR/RV RW lltRXR/RY RZ lltR[ R\ ltR] R^ lt]EP*                  ! ]4      tR_ R` ltRa Rb ltRc Rd ltRe Rf ltRg Rh ltRi Rj ltRk Rl ltRm Rn ltRo Rp ltRq Rr ltRs Rt ltRu Rv ltRw Rx ltRy Rz ltR{ R| ltR} R~ ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R lt]v! RR04      tR R ltR R ltR R ltR R lt]v! 0 ER"m4      tR R ltR R ltR R ltER#tER$tER%tER&tR1RR2R/t]^EP                  ! 4        U Uu/ uF  w  rVR/,          VR0,          3V bK  	  upp tR]R&   R R ltR R ltR R lt]v! 0 ER'm4      tR R ltR R lt]v! 0 ER(m4      t]v! R04      ],          t]v! 0 ER)m4      t]v! 0 ER*m4      tER+tR R ltR R ltR R ltR R ltR R ltR R ltR R ltRR7/R R lltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R lt]v! 0 ER,m4      tR R ltR R lt]v! RR04      tR R lt]v! RR04      tR R ltR R ltR R ltR R ltR R ltR R lt^t] Uu/ uF  q"EP                  VbK  	  upt]v! RR04      tR R ltR R ltER-R R lltR R ltR R ltR R ltER  ER ltER ER lt^tER ER lt]v! 0 ER.m4      t]! ER	]v! ERER04      ER
]v! ER04      /4      tER]ER&   ER ER lEt ER ER lEtER ER lEtER ER lEtER ER lEtER ER lEt]v! 0 ER/m4      EtER ER lEtER ER lEtER0Et	ER ER lEt
R# u upp i u upi (1  a  Read ``[tool.nab]`` from a ``pyproject.toml`` into a typed config.

The CLI is intentionally narrow: anything that defines *what* gets
resolved lives in ``[tool.nab]``; anything about *how this run executes*
lives on the CLI.  This module owns the project side.
)annotationsN)defaultdict)	dataclassfieldreplace)datetime	timedeltatimezone)MappingProxyType)TYPE_CHECKINGAnycast)urlsplit)override)ArchiveRequestArchiveRequestError)is_file_url)IndexConfig)SimpleSerialization)subdirectory_escapes)
KIND_EXTRA
KIND_GROUP)parse_iso_datetime)tool_nab_section)known_vcs_schemes)Requirement)InvalidSpecifierSpecifierSet)InvalidNamecanonicalize_name)Version)ConfigErrorEffectiveValue
SourceKindSourceRootsbuild_cli_layerdiscover_layerspyproject_registry_keysread_env_layerreject_user_keys_in_pyprojectresolve_anchorresolve_config)DEFAULT_INDEX_NAMEDEFAULT_INDEX_URL
IndexRoute)resolve_path)
ArchiveSourceBuildPolicyDecisionOrder
DistPolicyLocalSourceResolutionStrategyResolveMode	VcsConfig	VcsPolicy	VcsSource)DEFAULT_LIBC
LIBC_MAJORLibcPlatformSpecplatform_kind)PLATFORM_MARKERSMatrixResolveTargetcheck_free_threadedhost_environmentpython_axis_environment)WorkspaceConfigdiscover_workspace_rootmerge_workspace_local_sourcesread_workspace_membersworkspace_local_sources)MappingSequence)Set)Path)VersionRangeConflictForkConflictKindConflictMemberConflictPolicyConflictSelectionErrorConflictSetEnvironmentConfigIndexOverrideMatrixConfigNabProjectConfigOverrideConflictErrorPackageOverridez	^P(\d+)D$sys_platformplatform_machineplatform_releaseplatform_versionpython_versionpython_full_versionrequires-pythonz[project] requires-pythonT)frozenslotsc                  Z    ] tR t^t$ RtR]R&   R]R&   RtR]R&   RtR	]R
&   RtR]R&   Rt	R# )rW   z3User-declared matrix axes for universal resolution.strpythontuple[PlatformSpec, ...]	platformsascpython_orderNzMapping[str, str] | Nonepython_patchestuple[str, ...]implementations cpython)
__name__
__module____qualname____firstlineno____doc____annotations__rj   rk   rm   __static_attributes__rn       \/home/user/billing-ledger-validation/.venv/lib/python3.14/site-packages/nab_python/config.pyrW   rW      s/    =K''L#/3N,3'3O_3rx   c                  F    ] tR t^t$ RtRtR]R&   RtR]R&   RtR]R&   Rt	R# )	rU   a  The single environment ``[tool.nab.environment]`` declares.

The axes a target is made of, the same ones a matrix entry carries.
An unset axis takes the host's value, so an empty table is the host
and a table naming only ``python`` is the host machine running
another Python.

``platform`` is the same :class:`~nab_python.tags.PlatformSpec` a
``matrix.platforms`` entry parses to, so the wheel-tag knobs (the libc
family, the libc and macOS the lock must run on, the kernel
marker values, the free-threaded build) are declarable here too.
N
str | Nonerf   zPlatformSpec | Noneplatformimplementationrn   )
rq   rr   rs   rt   ru   rf   rv   r|   r}   rw   rn   rx   ry   rU   rU      s(     FJ$(H!(!%NJ%rx   c                  &    ] tR t^tRtRtRtRtRtR# )rR   a  How exclusive the members of a :class:`ConflictSet` are.

Mirrors Gentoo's ``REQUIRED_USE`` group operators.  ``AT_MOST_ONE``
(``??``) is the default for a bare uv-style set: the members are
mutually exclusive but selecting none is fine, which suits opt-in
extras.  ``EXACTLY_ONE`` (``^^``) additionally requires one to be
chosen.  ``AT_LEAST_ONE`` (``||``) only forbids the empty
selection; it is rarely useful for extras and is included for
completeness.
zat-most-onezexactly-onezat-least-onern   N)	rq   rr   rs   rt   ru   AT_MOST_ONEEXACTLY_ONEAT_LEAST_ONErw   rn   rx   ry   rR   rR      s    	  KK!Lrx   c                  "    ] tR t^tRt]t]tRt	R# )rP   z<Whether a :class:`ConflictMember` names an extra or a group.rn   N)
rq   rr   rs   rt   ru   r   EXTRAr   GROUPrw   rn   rx   ry   rP   rP      s    FEErx   c                  F    ] tR t^t$ RtR]R&   R]R&   ]R R l4       tRtR	# )
rQ   a-  One side of a conflict: a named extra or dependency group.

``name`` is stored canonicalised (PEP 685 for extras, PEP 735 for
groups) so a selection compares equal regardless of how the user
spelled it.  An extra and a group sharing a name are distinct
members, matching uv's package-qualified model.
rP   kindre   namec                   V ^8  d   QhRR/#    returnre   rn   )formats   "ry   __annotate__ConflictMember.__annotate__   s     2 2 2rx   c                N    V P                   P                   RV P                  : 2# )z=Render as ``extra 'cpu'`` / ``group 'black22'`` for messages. r   valuer   )selfs   &ry   __str__ConflictMember.__str__   s"     ))//"!DII=11rx   rn   N)	rq   rr   rs   rt   ru   rv   r   r   rw   rn   rx   ry   rQ   rQ      s&     
I2 2rx   c                  ^    ] tR t^t$ RtR]R&   ]P                  tR]R&   ]	R R l4       t
RtR	# )
rT   z?A set of mutually-exclusive members with an exclusivity policy.tuple[ConflictMember, ...]membersrR   policyc                   V ^8  d   QhRR/# r   rn   )r   s   "ry   r   ConflictSet.__annotate__   s     1 1 1rx   c                ~    RP                  R V P                   4       4      pV P                  P                   RV R2# )zBRender as ``at-most-one (extra 'cpu', extra 'gpu')`` for messages., c              3  8   "   T F  p\        V4      x  K  	  R # 5iNre   .0ms   & ry   	<genexpr>&ConflictSet.__str__.<locals>.<genexpr>   s     8<a3q66<    ())joinr   r   r   )r   joineds   & ry   r   ConflictSet.__str__   s:     84<<88++##$Bvha00rx   rn   N)rq   rr   rs   rt   ru   rv   rR   r   r   r   r   rw   rn   rx   ry   rT   rT      s-    I''+77FN71 1rx   c                    V ^8  d   QhRRRR/# r   	conflictsSequence[ConflictSet]r   z&tuple[frozenset[tuple[str, str]], ...]rn   )r   s   "ry   r   r      s      $+rx   c                Z    \         ;QJ d    . R V  4       F  NK  	  5# ! R V  4       4      # )a  Project conflict sets to the neutral exclusion form the lockfile uses.

The disjointness validator consumes a sequence of member sets, of
which at most one member may be active in any install context.
Only :attr:`ConflictPolicy.AT_MOST_ONE` and
:attr:`ConflictPolicy.EXACTLY_ONE` forbid co-selection, so only
those contribute; :attr:`ConflictPolicy.AT_LEAST_ONE` constrains the
empty selection, not co-selection, and is omitted.  Each member
becomes a ``(kind, canonical_name)`` pair.
c              3     "   T FA  pVP                   \        P                  Jg   K#  \        R  VP                   4       4      x  KC  	  R# 5i)c              3  d   "   T F&  qP                   P                  VP                  3x  K(  	  R # 5ir   r   r   s   & ry   r   6conflict_exclusion_groups.<locals>.<genexpr>.<genexpr>        =*Q66<<(*   .0N)r   rR   r   	frozensetr   r   css   & ry   r   ,conflict_exclusion_groups.<locals>.<genexpr>   s=      B99N777 	>	="**===s
    A$Atupler   s   &ry   conflict_exclusion_groupsr      s6     5 5 5   rx   c                    V ^8  d   QhRRRR/# r   rn   )r   s   "ry   r   r     s      $+rx   c                Z    \         ;QJ d    . R V  4       F  NK  	  5# ! R V  4       4      # )aV  Project every conflict set (any policy) to ``(kind, name)`` member sets.

Distinct from :func:`conflict_exclusion_groups`, which drops
:attr:`ConflictPolicy.AT_LEAST_ONE` because that policy permits
co-selection.  The disjointness validator uses this projection to
tell already-declared collisions from undeclared ones when shaping
the hint.
c              3  Z   "   T F!  p\        R  VP                   4       4      x  K#  	  R# 5i)c              3  d   "   T F&  qP                   P                  VP                  3x  K(  	  R # 5ir   r   r   s   & ry   r   3conflict_member_groups.<locals>.<genexpr>.<genexpr>  r   r   N)r   r   r   s   & ry   r   )conflict_member_groups.<locals>.<genexpr>  s%      HQ"	="**===	s   )+r   r   s   &ry   conflict_member_groupsr     s6     5 HQ5 5 HQ  rx   c                  H    ] tR tRt$ RtR]R&   R]R&   R]R&   R	tR]R&   R	tR
# )rO   i  a  One fork of a conflict-driven universal resolve.

``selection`` is the active conflicting members as ``(kind, name)``
pairs.  ``active_extras`` and ``active_groups`` are the selections
this fork resolves with, the non-conflicting ones plus its own chosen
members, and hold only names the project declares.  A name
``[tool.nab]`` configures is on ``active_configured`` instead.  An
unforked resolve is a single fork with an empty ``selection``.
ztuple[tuple[str, str], ...]	selectionrl   active_extrasactive_groupsactive_configuredrn   N)rq   rr   rs   rt   ru   rv   r   rw   rn   rx   ry   rO   rO     s+     +*"""")++*rx   c                      ] tR tRt$ RtR]R&   R]R&   R]R&   R	tR
]R&   R	tR]R&   R	tR]R&   R	t	R]R&   Rt
R]R&   R	tR]R&   R	tR]R&   R	tR]R&   R	tR]R&   ]! RRR7      tR]R&   RtR	# ) rZ   i+  a  One per-package override: a requirement plus a body.

Built from either ``[tool.nab.packages.<name>]`` (the name-keyed sugar
table) or a ``[[tool.nab.package-rules]]`` entry (one body across the
requirements in its ``match`` selector).  The selector is a single PEP
508 ``requirement`` (name plus an optional version specifier; no
extras, marker, or URL); ``name`` is its canonical package name and
``version_range`` its range, so a policy field applies only to
candidate versions inside it.  The *body* sets any combination of
``dist_policy`` (with ``dist_trust_unverified_deps`` folding in the
sdist-trust flag), ``build_policy``, the ``uploaded_prior_to`` cutoff
(or ``uploaded_prior_to_disabled`` for the ``false`` form), the
routing ``index``, and the metadata-override fields.  An entry that
sets ``index`` must use a bare-name requirement (full range), because
routing decides where to fetch a listing before any version is known.

The metadata-override fields ``dependencies``, ``requires_python``, and
``provides_extra`` substitute for what nab would parse from the
distribution, keyed to the matched version range (uv
``dependency-metadata`` parity).  Each replaces its field independently:
``dependencies`` becomes the whole runtime ``Requires-Dist`` list,
``requires_python`` the Python specifier, and ``provides_extra`` the
declared extras.  For every one, ``None`` means the entry does not set
it; a present-but-empty value (``()`` for the two tuples) is a distinct,
first-class value meaning "replace with nothing".
r   requirementre   r   rN   version_rangeNDistPolicy | Nonedist_policybool | Nonedist_trust_unverified_depsBuildPolicy | Nonebuild_policydatetime | Noneuploaded_prior_toFbooluploaded_prior_to_disabledr{   indextuple[Requirement, ...] | Nonedependenciesrequires_pythontuple[str, ...] | Noneprovides_extra )defaultcomparesource_labelrn   )rq   rr   rs   rt   ru   rv   r   r   r   r   r   r   r   r   r   r   r   rw   rn   rx   ry   rZ   rZ   +  s    6 
I%)K").22'+L$+)--',,E:37L07"&OZ&-1N*1
 b%8L#8rx   c                  p    ] tR tRt$ RtRtR]R&   RtR]R&   RtR]R	&   Rt	R
]R&   Rt
R]R&   RtR]R&   RtR# )rV   i[  a  One ``[tool.nab.index.<name>]`` entry: policy for an index.

Keyed by a declared index name.  The body sets any combination of
``dist_policy`` (with ``dist_trust_unverified_deps``),
``build_policy``, the ``uploaded_prior_to`` cutoff (or
``uploaded_prior_to_disabled`` for the ``false`` form), and
``assume_fresh_seconds``, a read-time freshness floor on the index's
Simple listing.  It applies to every package served from that index;
it carries no routing and no version scope.
Nr   r   r   r   r   r   r   r   Fr   r   
int | Noneassume_fresh_secondsrn   )rq   rr   rs   rt   ru   r   rv   r   r   r   r   r   rw   rn   rx   ry   rV   rV   [  sK    	 &*K").22'+L$+)--',,'+*+rx   c          
     ,    V ^8  d   QhRRRRRRRRRR/# )	r   selected_extrasSequence[str]selected_groupsr   r   configured_groupsr   zlist[ConflictFork]rn   )r   s   "ry   r   r   v  sA     R R"R"R %R %	R
 Rrx   c                z   V  Uu. uF  p\        V4      NK  	  ppV Uu. uF  p\        V4      NK  	  pp\        \        P                  R V 4       4      4      p\	        V4      p	\	        V4      p
\	        V4      V	,          p. p\	        4       p\	        4       pV F  pVP
                  \        P                  J d   K#  VP                   Uu. uF  p\        VW4      '       g   K  VNK  	  pp\        V4      \        8  d   Kh  VP                  V4       V F@  pVP                  \        P                  J d   TMTpVP!                  VP"                  4       KB  	  K  	  V'       g,   \%        R\'        V4      \'        V4      \'        V4      R7      .# V Uu. uF  qDV9  g   K  VNK  	  ppV Uu. uF  qfV9  g   K  VNK  	  ppV Uu. uF  qfV9  g   K  VNK  	  pp. p\(        P*                  ! V!   EF  pV Uu. uF/  pVP                  \        P                  J g   K#  VP"                  NK1  	  ppV Uu. uF/  pVP                  \        P,                  J g   K#  VP"                  NK1  	  ppV Uu. uF  qfV	9  g   K  VNK  	  ppV Uu. uF  qfV	9   g   K  VNK  	  ppVP                  \%        \'        \/        R V 4       4      4      \'        VV,           4      \'        VV,           4      \'        VV,           4      R7      4       EK  	  V# u upi u upi u upi u upi u upi u upi u upi u upi u upi u upi )a|  Split a selection into one fork per mutually-exclusive combination.

A conflict set is *engaged* when the selection activates two or more
of its members under an exclusivity policy (at-most-one or
exactly-one); only an engaged set forces a fork.  Each engaged set
contributes one chosen member per fork, and the forks are the
cartesian product across engaged sets.  Members of engaged sets are
dropped from the shared base; non-conflicting selections stay active
in every fork.  With no engaged set the result is a single unforked
fork carrying the whole selection.

A declared group is active when the selection names it.  A
``configured_groups`` name is active whenever it is set, since the
context it names is part of every resolve rather than something a run
asks for, so a set naming one engages on every run.  Those names come
back on :attr:`ConflictFork.active_configured` rather than
``active_groups``, which stays what the ``[dependency-groups]`` loader
can resolve.

Names compare and emit canonicalised; the extra and group loaders
normalise on lookup, so a canonical active set resolves the same
requirements the user's spelling would.
c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   r   )r   gs   & ry   r   !conflict_forks.<locals>.<genexpr>  s     #TBSQ$5a$8$8BSr   )r   r   r   r   c              3  d   "   T F&  qP                   P                  VP                  3x  K(  	  R # 5ir   r   r   s   & ry   r   r     s     &Mu!aff'=ur   rn   )r   listdictfromkeyssetr   rR   r   r   _member_activelen_MIN_ENGAGED_MEMBERSappendr   rP   r   addr   rO   r   	itertoolsproductr   sorted)r   r   r   r   ebase_extrasr   base_groups
configuredconfigured_set	extra_set	group_setengageddrop_extrasdrop_groupsconflict_setr   r   membertargetrest_extrasrest_groupsrest_configuredforkscombochosen_extraschosenchosen_groupschosen_configureds   &&&&                         ry   conflict_forksr  v  s   : 2AAA$Q'KA1@AA$Q'KAdmm#TBS#TTUJ_NK IK >1I +-GEKEK!."="==#++
+!~a/VAA+ 	 
 w<..wF$*KK<3E3E$E[;FJJv{{#  " #K0#K0"'
"3	
 	
 *Bkk-A11kKB)Bkk-A11kKB",E*Q0Dqq*OE "E""G,).OA!&&L<N<N2NO"'H%Q166\5G5G+G&!&&%H$*FFq~.EFF(.F1~2EQQF&Mu&M MN#K-$?@#K-$?@"':K(K"L		
 - Lk BA
* CBE PHFFsj   LLL$LL!L-L:LL$L$9 L)L)4 L.L./L3<L3L8L8c                  &   ] tR tRt$ Rt]P                  tR]R&   R7t	R]R&   R7t
R]R&   RtR	]R
&   RtR	]R&   RtR	]R&   ]tR]R&   RtR]R&   ]P$                  tR]R&   ]P*                  tR]R&   ^ tR]R&   RtR]R&   RtR]R&   ]! ]]4      3tR]R&   ]! ]R7      t R]R &   R7t!R!]R"&   R7t"R#]R$&   R7t#R%]R&&   Rt$R']R(&   ]%PL                  t'R)]R*&   ](PR                  t*R+]R,&   Rt+R-]R.&   R7t,R/]R0&   R7t-R1]R2&   ]! ].R7      t/R3]R4&   ]! ]0R7      t1R5]R6&   R7t2R# )8rX   i  zAEverything ``[tool.nab]`` says about how to resolve this project.r6   moderl   constraintsdefault_groupsNr{   
base_groupbuild_groupr   re   requires_python_sourcer   r   r3   r   r1   r   intbuild_requires_depthFr   trust_unverified_sdist_depsEnvironmentConfig | Noneenvironmenttuple[IndexConfig, ...]indexes)default_factoryr7   vcstuple[LocalSource, ...]local_sourcestuple[VcsSource, ...]vcs_sourcestuple[ArchiveSource, ...]archive_sourcesMatrixConfig | Nonematrixr5   
resolutionr2   decision_orderWorkspaceConfig | None	workspacetuple[ConflictSet, ...]r   tuple[PackageOverride, ...]package_overridesMapping[str, IndexOverride]index_overridesfrozenset[str]workspace_member_namesrn   )3rq   rr   rs   rt   ru   r6   SPECIFICr  rv   r  r  r  r  r   _TOOL_NAB_REQUIRES_PYTHONr  r   r3   WHEEL_OR_SDISTr   r1   BUILD_LOCALr   r  r  r  r   r,   r-   r  r   r7   r!  r#  r%  r'  r)  r5   HIGHESTr*  r2   ARRIVALr+  r-  r   r0  r   r2  r   r4  rw   rn   rx   ry   rX   rX     sg   K#,,D+,#%K%&(NO(!J
!"K" #'OZ& #<C;)--(77K7 + 7 7L+7 !"#!(-- -1K)0&(9:(G$  95C5-/M*/)+K&+13O.3"&F&%7%?%?J"?$1$9$9NM9(,I%,)+I&+ 6827 493NO0N
 .39-MNMrx   c                    V ^8  d   QhRRRR/# )r   configrX   r   rl   rn   )r   s   "ry   r   r     s     
 
#3 
 
rx   c                    \         ;QJ d*    . R V P                  V P                  3 4       F  NK  	  5# ! R V P                  V P                  3 4       4      # )a5  Return the group names active by configuration rather than by selection.

``base-group`` names the project's own dependencies and ``build-group``
its build requirements; neither is ever in a run's selection, so every
caller that has to treat them as active asks here rather than naming
the two fields itself.
c              3  0   "   T F  qf   K  Vx  K  	  R # 5ir   rn   r   r   s   & ry   r   )configured_group_names.<locals>.<genexpr>  s      @@s   
)r   r  r  )r<  s   &ry   configured_group_namesrA    sX     5  ++V-?-?@5 5  ++V-?-?@  rx   c                      ] tR tRtRtRtR# )rS   i  al  A requested extra/group selection violates a declared conflict.

Raised when one resolve cannot serve the selection: a project
resolving for a single environment cannot install two
mutually-exclusive members at once.  A declared matrix forks the
resolve instead of raising, and only raises when one fork still
reaches two members (through an umbrella extra, say).
rn   Nrq   rr   rs   rt   ru   rw   rn   rx   ry   rS   rS         rx   c                      ] tR tRtRtRtR# )rY   i  a  A per-package and a per-index override set the same field for one candidate.

Raised at resolve time when a candidate ``(package, version)`` served
from an index is governed by both a per-package override (whose range
contains the version) and a per-index override that each set the same
policy field.  The two surfaces are deliberately not ranked, so an
overlap is an error rather than a precedence call.
rn   NrC  rn   rx   ry   rY   rY     rD  rx   c               (    V ^8  d   QhRRRRRRRR/# )r   r  rQ   r   zAbstractSet[str]r   r   r   rn   )r   s   "ry   r   r   &  s0     ( ((#( $( 
	(rx   c                z    V P                   \        P                  J d   V P                  V9   # V P                  V9   # )z=Return True when ``member`` is in the selected extras/groups.r   rP   r   r   )r  r   r   s   &&&ry   r   r   &  s4     {{l((({{m++;;-''rx   c               (    V ^8  d   QhRRRRRRRR/# r   r   r   r   r   r   r   Nonern   )r   s   "ry   r   r   1  s0     "* "*$"*""* #"* 
	"*rx   c                h  a
a V Uu0 uF  p\        V4      kK  	  upo
V Uu0 uF  p\        V4      kK  	  upoV  F  p\        ;QJ d*    V
V3R lVP                   4       F  '       g   K   RM	  RM! V
V3R lVP                   4       4      pV'       d   K]  VP                  \        P
                  J d   K}  RP                  R VP                   4       4      pVP                  \        P                  J d   RMRpV RV R	VP                  P                   R
2p	\        V	4      h	  R# u upi u upi )aV  Raise when a require-one set has no active member.

Enforces only the "must select one" policies: an exactly-one set
and an at-least-one set each require at least one active member.
Names compare under canonicalisation.  Universal mode calls this to
apply the minimums without the co-selection rejection, which it
handles by forking instead.
c              3  >   <"   T F  p\        VSS4      x  K  	  R # 5ir   )r   )r   r   r   r   s   & ry   r   -validate_conflict_minimums.<locals>.<genexpr>A  s$      
) 1m];;)s   TFr   c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   r   r   s   & ry   r   rN  I  s     A,@qCFF,@r   zexactly onezat least onez of z must be selected: declared z in [tool.nab].conflictsN)
r   anyr   r   rR   r   r   r   r   rS   )r   r   r   r   r   r  
any_activer   
quantifiermsgr   r   s   &&&       @@ry   validate_conflict_minimumsrT  1  s     4CC?a&q)?CM3BC?a&q)?CM!S 
!))
SSS 
!))
 

 ."<"<<))AL,@,@AA ""n&@&@@  	 l$wi (##))**BD 	 %S))' " DCs
   D*D/c               (    V ^8  d   QhRRRRRRRR/# rJ  rn   )r   s   "ry   r   r   V  s0     . .$.". #. 
	.rx   c           	         V Uu0 uF  p\        V4      kK  	  ppV Uu0 uF  p\        V4      kK  	  pp\        P                  \        P                  0pV  F  pVP                   U	u. uF  p	\        WV4      '       g   K  V	NK  	  p
p	\        V
4      ^8  g   KD  VP                  V9   g   KW  RP                  R V
 4       4      pV RVP                  P                   R2p\        V4      h	  R# u upi u upi u up	i )a  Raise when a selection co-activates two members of an exclusive set.

An at-most-one or exactly-one set cannot have two active members at
once.  Names compare under canonicalisation.  Universal mode applies
this per fork, against the self-reference- and include-expanded
active set, to catch members an umbrella selection reaches only
transitively (one fork cannot serve two of them disjointly).
r   c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   r   r   s   & ry   r   /validate_conflict_exclusions.<locals>.<genexpr>m  s     6v!s1vvvr   z; cannot be selected together: declared mutually exclusive (z) in [tool.nab].conflictsN)r   rR   r   r   r   r   r   r   r   r   rS   )r   r   r   r   r   r   r   	exclusiver  r   activer  rS  s   &&&          ry   validate_conflict_exclusionsr[  V  s     4CC?a&q)?MC3BC?a&q)?MC++^-G-GHI! "))
)a> A) 	 

 v;?|22i?YY6v66F( +228899RT  )-- " DC
s   C1C6(C;C;discover_workspaceanchorcli_overridesc          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )r   pathrM   r\  r   r]  r   r^  zMapping[str, Any] | Noner   rX   rn   )r   s   "ry   r   r   u  sC     T T
T T 	T
 ,T Trx   c                  Vf%   \         P                  ! \        P                  4      pV P                  P                  4       p\        V 4       \        V 4      p\        WDV P                  ,          R7      p\        V4      ;_uu_ 4        \        V4      p\        T;'       g    / 4      p\        V\        / 4      V4      p	RRR4       \        X	VVVR7      p
\!        V	R,          V 4       \#        V	R,          V	R,          4       \%        V	R,          V	R,          V 4       V'       d)   \'        W
V	R,          P(                  P*                  R7      p
V
#   + '       g   i     L; i)aQ  Parse ``[tool.nab]`` from ``path`` into :class:`NabProjectConfig`.

Returns the default ``NabProjectConfig`` when the table is absent.
Unknown keys at the top level are rejected so typos fail loud.

When ``discover_workspace`` is true (the default), the merged
``workspace`` table drives discovery and its members resolve against
the project directory.  A project that declares no workspace of its
own walks up from ``path`` for the first ancestor project file that
declares one.  Either way every member is materialised as an
additional :class:`LocalSource` (explicit
``[[tool.nab.local-sources]]`` entries win on collision).  A workspace
does not change the effective ``build-policy``: a member with dynamic
metadata needs a build, and under ``never`` it is refused like any
other source.  Pass ``discover_workspace=False`` to skip discovery;
useful for tests or for callers that layer their own workspace logic
on top of a base config.

The ``[tool.nab]``-config portion is sourced from the registry merged
ladder (pyproject ``[tool.nab]`` plus a project-dir ``nab.toml``,
merged by :func:`config_sources.resolve_config` with its per-key merge,
cross-file conflict check, and category gate), so a project-dir
``nab.toml`` value configures the resolve exactly as the inspector
reports it.  The
cross-field transforms (mode/matrix, the build-policy host-build gate,
universal marker-environment ban, source-name uniqueness, declared
index references) then run on the merged config; workspace discovery
runs last.

``anchor`` is the timestamp ``P<n>D`` durations resolve against.
Defaults to ``datetime.now(UTC)`` when not supplied, which gives
fresh-resolve semantics.  The ``nab lock`` CLI passes the anchor
captured in any existing lockfile so re-locks reproduce the same
cutoff for relative durations.

``cli_overrides`` carries the ``--project-*`` overrides for the
PROJECT options that take a CLI flag, keyed by registry key.  They
layer as the highest-precedence source, so a flag wins over both
project files and an array flag appends after them.  ``None`` (the
default) is a file-only resolve, byte-identical to before.
N)project_dir	pyproject)r]  pyproject_dirproject_requires_python
base-groupbuild-groupr-  )declared_in)r   nowr	   utcparentresolve_reject_unknown_pyproject_keys_read_project_requires_pythonr$   r   r*   r&   r%   r+   r(   _config_from_effective_validate_base_group_is_free&_validate_build_group_has_a_base_group_validate_build_group_is_free_apply_workspace_discoveryoriginlabel)r`  r\  r]  r^  rd  re  rootslayers	cli_layer	effectiver<  s   &$$$       ry   read_pyproject_configrz  u  s'   ` ~hll+KK'')M"4(;DA MTYY=VWE
 
		 '#M$7$7R8	"6>"+=yI	 
  $# 7	F !<!8$?*- )L"9 "- )L"94 +i&<&C&C&I&I
 M+ 
 	s   	7EE!	re  c          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )r   ry  Mapping[str, EffectiveValue]r]  r   rd  rM   re  r{   r   rX   rn   )r   s   "ry   r   r     sC     J J+J J 	J
 (J Jrx   c               t   ?V R,          pV R,          pVP                   pVP                   pV\        P                  J d=   Vf9   VP                  P                  \
        P                  J d   RpMRp\        V4      hV\        P                  J d?   Ve;   VP                  P                  VP                  4      '       g   Rp\        V4      hRpV R,          P                   w  rV R,          P                   p\        R	 V 4       4      p. V R
,          P                   OV R,          P                   O5p\        V4       \        W4       V R,          P                   p\        W4       \        V 4      pVe   Ve   Rp\        V4      h\        W4      p\!        VV R,          P                   V R,          P                  P                  \
        P"                  JVVR7      pV R,          P                   p\$        pVf   Ve	   Tp\&        pV R,          P                   pV R,          P                   p\)        VVV R,          P                   4       \+        VV R,          P                   V R,          P                   4       V R,          P                   pV R,          P                   pV R,          P                   p\-        VVV4       V R,          P                   p\/        VV4       ?\1        R0/ RVbRV R,          P                   bRVbRV R,          P                   bRV R,          P                   bRVbRVbRV R ,          P                   bR!V	bR"VbR#V R$,          P                   bR%V
bR&VbRVbRVbR'VbR(VbR)VbRVbR*V R*,          P                   bR+V R,,          P                   bR-V R-,          P                   bRVbR.VbR/Vb # )1a4  Assemble :class:`NabProjectConfig` from the registry merged ladder.

Each ``[tool.nab]`` config key is taken from its effective (merged)
value; the registry has already applied the per-key merge, the
cross-file conflict rule, and the category gate.  The cross-field
transforms the single-key rows deliberately defer (mode/matrix mutual
requirement, declared-index references for routing and per-index
overrides, the cross-surface package-override overlap, the resolve-target
plan and the build-policy enforcement it drives, the
default-groups-vs-conflicts check, and source-name uniqueness) then run
here over the merged whole.  Workspace discovery is applied by the
caller afterwards.

``project_requires_python`` is ``[project].requires-python``, the
fallback source for the declaration when ``[tool.nab]`` sets none.
r  r)  Nz--project-mode universal needs a [tool.nab.matrix] table, but a matrix can only be declared in the project file (there is no --project-matrix flag). Add [tool.nab.matrix] to the project's pyproject.toml or nab.toml, or drop --project-mode universal.zTmode = 'universal' requires a [tool.nab.matrix] table declaring python and platformsz[tool.nab.matrix] is set but mode is 'specific'; set mode = 'universal' to resolve for every target the matrix declares, or remove the table. The multi-target lockfile format universal mode produces is experimental.dist-policyr  c              3  8   "   T F  qP                   x  K  	  R # 5ir   )r   )r   is   & ry   r   )_config_from_effective.<locals>.<genexpr>  s     $=WVVWr   packageszpackage-rulesr   z[tool.nab.matrix] and [tool.nab.environment] cannot both be set: the matrix declares one environment per tuple, so a single declared environment would contradict it.  Drop one.build-policytargetsr   build_policy_setr0  r2  ra   zdefault-groupsr   rf  rg  zlocal-sourceszvcs-sourceszarchive-sourcesr!  r  r  r  r  r   r  r   uploaded-prior-tor   r   r  zbuild-requires-depthr  r  r#  r%  r'  r*  r+  zdecision-orderr-  r0  r2  rn   )r   r6   	UNIVERSALrt  r   r#   CLIr!   r5  outranksr   _check_package_override_overlap_validate_routes_declared"_validate_index_overrides_declared_environment_from_effective_plan_targets enforce_build_policy_for_targetsDEFAULTr6  _PROJECT_REQUIRES_PYTHON*_validate_default_groups_against_conflicts"_validate_configured_conflict_sets_reject_duplicate_source_names_reject_vcs_sources_under_blockrX   )ry  r]  rd  re  
mode_valuematrix_valuer  r)  rS  r   trust_unverifiedr  declared_index_namesr0  r2  r  r  r   r   r  r  r   r#  r%  r'  
vcs_configs   &$$$                      ry   ro  ro    s   . 	6"JX&L"((D"."4"4F{$$$!!Z^^3 2  #{###(:  )),*=*=>>C  c"" $-m$<$B$B!K'0';'A'AG$$=W$==	:		$	$	?	#	)	) $$56/F3<W3E3K3KO&M-i8Kk5D 	
 #F0G3~.44">299>>!!"+'L   1288O6#:#F1!9/066N+&,,I.	9\#:#@#@ '9\*00)M2J2P2P o.44MM*00K 1288O"=+O5!''J#K< m,22 & \*00	
 m,22 (  6 $$78>>   " ''=>DD %5      $!"  #$ (%& '( \*00)* !!1288+, K(..-. /0 ,12 (3 rx   c               $    V ^8  d   QhRRRRRR/# )r   r0  r/  r  r3  r   rK  rn   )r   s   "ry   r   r   Y  s&     # #2#(# 
#rx   c                    V  FG  pVP                   pVf   K  W19  g   K  \        V4      pVP                   RV: RV: 2p\        V4      h	  R# )a?  Reject a routing override that names an index not in ``indexes``.

A per-package surface is parsed without the declared index set, so the
route-points-at-a-real-index check runs here, after the index list is
known.  The error names the surface the route was declared on
(``packages.'<name>'`` or ``package-rules[N]``).
Nz".index routes to undeclared index ; declared indexes are )r   r   r   r!   )r0  r  pkg_overrideroutevalidrS  s   &&    ry   r  r  Y  sc     *""!B/0E,,- .93E9>  c"" *rx   c               $    V ^8  d   QhRRRRRR/# )r   r2  r1  r  r3  r   rK  rn   )r   s   "ry   r   r   o  s&     # #0#(# 
#rx   c                j    V  F,  pW!9  g   K  \        V4      pRV RV: RV: 2p\        V4      h	  R# )zReject a ``[tool.nab.index.<name>]`` key naming an undeclared index.

The registry parses this surface with ``declared_index_names=None``, so
the cross-key check runs post-merge with the single-file message.
index.z names undeclared index r  N)r   r!   )r2  r  r   r  rS  s   &&   ry   r  r  o  sN      +/0E6th ?)).	3  c""  rx   c               (    V ^8  d   QhRRRRRRRR/# )r   r`  rM   r<  rX   rh  re   r   rn   )r   s   "ry   r   r     s,     % %
%(%:=%%rx   c                 a VP                   e<   \        VP                   P                  V P                  P	                  4       VR7      pM\        V 4      pVf   V# \        V4      pV'       g   V# \        VP                  V4      p\        WQP                  VP                  4       VP                   Uu0 uF  p\        VP                  4      kK  	  upo\        VV\        V3R lV 4       4      R7      # u upi )aq  Materialise the workspace members as local sources.

The project's own ``workspace`` table wins, whichever project file
declared it (``declared_in`` names that file), and its members
resolve against the project directory.  A project that declares none
walks up for an ancestor project file that does, so ``nab lock
<member>`` still resolves against the workspace root.
)root_dirrh  c              3     <"   T F6  p\        VP                  4      S9  g   K  \        VP                  4      x  K8  	  R # 5ir   )r   r   )r   srcexplicit_namess   & ry   r   -_apply_workspace_discovery.<locals>.<genexpr>  s8      )
! *.@ (chh''!s
   AA)r#  r4  )r-  rI   r   rk  rl  rF   rH   rG   r#  r  r%  r'  r   r   r   r   )r`  r<  rh  
discovered	root_filemergedr  r  s   &&$    @ry   rs  rs    s     #,$$[[((*#

 ,D1	M+I6
*6+?+?LF"6+=+=v?U?UV=C=Q=QR=Qc'1=QRN( )
!)
  
  Ss   5C7c                    V ^8  d   QhRRRR/# )r   r`  rM   r   rK  rn   )r   s   "ry   r   r     s     ! ! !$ !rx   c                    V P                  R4      ;_uu_ 4       p\        P                  ! V4      pRRR4       \        X4      p\        T\        4      '       g$   R\        T4      P                   2p\        T4      h\        T4       \        4       p\        \        T4      T,
          4      pT'       d   RT: R\        T4      : 2p\        T4      hR#   + '       g   i     L; i  \        \        P                  3 d   pT  RT 2p\        T4      ThRp?i\         d   pRT  RT 2p\        T4      ThRp?ii ; i)	a)  Reject a USER-scope or unknown key in pyproject ``[tool.nab]``.

Run before the registry merge so the resolve reports a typo'd
``[tool.nab]`` key and a USER-scope key set in pyproject with the
established messages.  A USER-scope option (``offline``, ``cache-dir``)
surfaces the category error; an unknown key fails loud rather than being
silently dropped.  Reads the pyproject raw directly; the registry merge
reads the same file again, and this keeps the unknown-key error a
``ConfigError`` on the pyproject surface for everything that is a known
key.
rbNz is not valid TOML: zcannot read : z [tool.nab] must be a table, got zunknown [tool.nab] keys: ; expected one of )opentomliloadUnicodeDecodeErrorTOMLDecodeErrorr!   OSErrorr   
isinstancer   typerq   r)   r'   r   r   )r`  fdataexcrS  rawknownunknowns   &       ry   rm  rm    s   (YYt__::a=D  4
 Cc4  0c1C1C0DE# "#&#%ESX%&G)'4Fve}FWX# % _ 5 56 (*3%0#C' (TF"SE*#C'(sE   C) CC) C&	!C) &C) )D>DD>$D>%D99D>c                    V ^8  d   QhRRRR/# )r   r<  rX   r   tuple[ResolveTarget, ...]rn   )r   s   "ry   r   r     s     " ") ".G "rx   c                "   \        V P                  V P                  4      pV P                  e)   \        V P                  V^ ,          P                  34       V F2  p\        V P                  VV P                  V P                  RJR7       K4  	  V# )a  Return every environment ``config`` resolves against, in matrix order.

The host is the target unless the project says otherwise: a declared
matrix expands to one target per tuple, ``[tool.nab.environment]``
names a single target (declared when it moves the platform axis, the
host machine on another Python when it names only ``python``), and a
project that declares neither resolves against the running interpreter,
like pip.

The ``requires-python`` declaration and the free-threaded floor are
checked here rather than at parse time because ``--python`` moves the
target after the config is read, and it is the flag that rescues a
project whose declaration excludes the host.

Every target is checked, matrix included: the lock records the
declaration at top level and the targets in ``environments``, so a
target the declaration excludes would be a lock that contradicts itself
and that a PEP 751 installer refuses.
N)sourcer)  )r  r)  r   _check_free_threaded_environmentr_   $_check_requires_python_admits_targetr   r  )r<  r  r  s   &  ry   plan_targetsr    s    ( FMM6+=+=>G%(!:!: <	
 ,""00==,		
  Nrx   c               $    V ^8  d   QhRRRRRR/# )r   r)  r(  r  r  r   r  rn   )r   s   "ry   r   r     s)     @ @@.F@@rx   c                   V e#   \        \        V 4      P                  4       4      # Vf   \        P                  ! 4       3# VP
                  e   \        V4      3# VP                  f   Q h\        P                  ! VP                  4      3# )zPlan the targets from the two declaring surfaces, pre-assembly.

Takes the pieces rather than a :class:`NabProjectConfig` so the config
parse can plan (and enforce the build policy) while it is still
assembling one.
)	r   matrix_from_configexpandrA   for_hostr|   _declared_targetrf   for_host_python)r)  r  s   &&ry   r  r    s     '/66899&&(**' -// )))))+*<*<=??rx   c                    V ^8  d   QhRRRR/# )r   r  rU   r   rA   rn   )r   s   "ry   r   r     s      "3  rx   c                   V P                   f   Q hV P                  ;'       g    \        4       R,          p\        V4      pV P                  ;'       g    Rp\        Y P                  '       d   VR,          3MR4       \        \        V4      P                  4      \        8  p\        P                  ! VR,          V P                   TV'       d   VR,          R7      # RR7      # )a(  Build the one target ``[tool.nab.environment]`` declares.

The platform is named, so the target's markers and wheel tags are
synthesized from it rather than read off the host.  An unset ``python``
takes the host's release, and an unset ``implementation`` is CPython,
matching the matrix default.
Nr`   rp   r_   )r_   specr}   r`   rn   )r|   rf   rC   rD   r}   r  r   r    release_PYTHON_MINOR_PARTSrA   for_declared)r  rf   axisr}   pinned_micros   &    ry   r  r    s     +++LL#3#56K#LF"6*D //<<9N$2D2D2Dd+,." wv../2EEL%%,-!!%;GD!67	  NR	 rx   c               $    V ^8  d   QhRRRRRR/# )r   r  rU   python_versionsr   r   rK  rn   )r   s   "ry   r   r   )  s$     ( ("(5B(	(rx   c                    V P                   f   R#  \        V P                   3V P                  ;'       g    R3VR7       R#   \         d   pRT 2p\	        T4      ThRp?ii ; i)a8  Hold ``[tool.nab.environment]`` to the free-threaded interpreter floor.

``python_versions`` is empty for a table that names no python, since
``--python`` can still move that axis after the parse.  The parse then
checks only the implementation, and :func:`plan_targets` checks the
python the target ended up on.
Nrp   )rh   rm   r  z invalid [tool.nab.environment]: )r|   rB   r}   
ValueErrorr!   )r  r  r  rS  s   &&  ry   r  r  )  sn     #("++-(77DD9F+	

  (06#C'(s   #A 
A A#AA#c                    V ^8  d   QhRRRR/# )r   r)  rW   r   r@   rn   )r   s   "ry   r   r   @  s     
 
| 
 
rx   c                    \        V P                  V P                  V P                  V P                  e   \        V P                  4      MRV P                  R7      # )zBBuild the expandable :class:`Matrix` from its parsed config table.Nrf   rh   rj   rk   rm   )r@   rf   rh   rj   rk   r   rm   )r)  s   &ry   r  r  @  sM    }}""((+1+@+@+LD&&'RV.. rx   c                    V ^8  d   QhRRRR/# )r   r  Sequence[ResolveTarget]r   r   rn   )r   s   "ry   r   r   M  s     G G"9 Gd Grx   c                j    \         ;QJ d    R V  4       F  '       g   K   R# 	  R# ! R V  4       4      # )zWhether any target impersonates a machine other than the host's.

A declared target (a matrix tuple, or an environment naming a platform
or implementation) carries a :class:`PlatformSpec`; the host and a
host-python retarget do not.
c              3  <   "   T F  qP                   R Jx  K  	  R # 5ir   )platform_specr   r  s   & ry   r   '_forbids_host_builds.<locals>.<genexpr>T  s     FgF##4/g   TF)rP  )r  s   &ry   _forbids_host_buildsr  M  s-     3FgF33F3F3FgFFFrx   c               0    V ^8  d   QhRRRRRRRRR	R
RR/# )r   r  r  r   r1   r  r   r0  Sequence[PackageOverride]r2  r1  r   rn   )r   s   "ry   r   r   W  sF     2 2$2 2 	2
 12 12 2rx   c                x   \        V 4      '       dH   \        VVVVR7      pV'       d!   RRP                  V4       R2p\        V4      h\        P
                  # \        ;QJ d    R V  4       F  '       d   K   RM	  RM! R V  4       4      '       g(   \        P                  RV ^ ,          P                  4       V# )	ai  Return the build policy the planned targets permit, or raise.

A PEP 517 backend only ever runs on the host interpreter, so what a
build reports is the host's metadata.  Two tiers follow:

* A target that moves the platform axis (a matrix, or an environment
  naming a ``platform`` or ``implementation``) forbids host builds:
  ``build-policy`` is forced to ``never`` and an explicit non-``never``
  value, global or in any override, is an error.  This matches pip,
  which requires ``--only-binary=:all:`` under ``--platform``.
* A python-axis-only retarget on the host machine warns and permits:
  the machine is still the host, so a build can run at all, and
  refusing every one of them would take the default case with it.  A
  deliberate deviation from pip.  Set ``build-policy = "never"`` to
  forbid it.

The host target permits, so the default case builds freely.
)r  r   r0  r2  zQa declared target cannot build on the host, so build-policy must be 'never'; got r   z.  A PEP 517 backend runs on the host and reports the host's metadata, not the target's.  Remove the setting (it defaults to 'never' for a declared target) or set it to 'never'.c              3  8   "   T F  qP                   x  K  	  R # 5ir   )host_faithfulr  s   & ry   r   3enforce_build_policy_for_targets.<locals>.<genexpr>  s     :'##'r   FTzthe resolve targets Python %s but a build would run on the host interpreter and report its metadata; set build-policy = 'never' to forbid builds)
r  _explicit_host_buildsr   r!   r1   NEVERall_loggerwarningr`   )r  r   r  r0  r2  	offendingrS  s   $$$$$  ry   r  r  W  s    4 G$$)-%/+	
	 ))-9)=(> ?HH  c""   3:':333:':::  AJ**		
 rx   c          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )r   r  r   r   r1   r0  r  r2  r1  r   z	list[str]rn   )r   s   "ry   r   r     s<        1	
 1 rx   c                    . pV '       d4   V\         P                  Jd    VP                  RVP                  : 24       V FW  pVP                  pVf   K  V\         P                  Jg   K+  VP                  RVP
                   RVP                  : 24       KY  	  VP                  4        FO  w  rxVP                  pVf   K  V\         P                  Jg   K-  VP                  RV RVP                  : 24       KQ  	  V# )zName every surface that explicitly asks for a non-``never`` build.

An unset global is not offending: ``build-policy`` defaults to
``never`` for a target that forbids host builds rather than failing a
project that never mentioned it.
zbuild-policy = 	packages.z build-policy = r  )r1   r  r   r   r   r   items)	r  r   r0  r2  r  pkgbpr   index_overrides	   $$$$     ry   r  r    s     IL0A0AA?<+=+=*@AB >b(9(99y(99I"((VW ! !0 5 5 7((>b(9(99vdV+;BHH<HI !8 rx   c               $    V ^8  d   QhRRRRRR/# )r   r<  rX   rf   r{   r   rn   )r   s   "ry   r   r     s$     2 22&022rx   c                   Vf   V # V P                   e   Rp\        V4      h \        V4       T P                  f   \        TR7      M\        T P                  TR7      p\        \        T P                   T4      T P                  RT P                  T P                  R7      p\        YTR7      p\        T4       T#   \         d   pRT: 2p\        T4      ThRp?ii ; i)aM  Return ``config`` with its resolve target moved onto ``python``.

The ``--python`` flag (and the ``python_version`` argument of
:func:`~nab_python.resolve.resolve_for_targets`) retargets the python
axis for one run, leaving any declared platform in place.  The
build-policy guard runs again over the new plan, so a runtime retarget
is held to the same rule as a declared one.  ``None`` is a no-op.

A matrix already declares the python axis for every target it names, so
retargeting one of them would resolve for a python the matrix does not
model and record it under that target's label.
Nz--python cannot retarget a resolve that declares [tool.nab.matrix]: the matrix names the python axis of every target.  Narrow matrix.python instead.z8--python must be a version like '3.12' or '3.12.4', got )rf   Tr  )r  r   )r)  r!   r    r  r  rU   r   r  r  r   r0  r2  r  )r<  rf   rS  r  r  r   
retargeteds   &&     ry   with_python_overrider    s     ~}} 6 	
 #( % 	(V''7  4fmm[9((  22..L |TJ/  (H
S#C'(s   B; ;CCCc          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )r   r   r{   r  rA   r  re   r)  r   r   rK  rn   )r   s   "ry   r   r     s:     / /// 	/
 / 
/rx   c                   V f   R# VP                  \        V 4      4      '       d   R# V RV : RVP                   RVP                   R2pV'       d   V R2pMV R2p\	        V4      h)a2  Reject a ``requires-python`` declaration that excludes the resolve target.

``requires-python`` declares the Python range the project supports; it
does not steer the resolve.  Resolving for a Python the project says it
does not support would produce a lock the project's own metadata
rejects, so it fails loud and names the knob that moves the target.

A minor-interval target is admitted when ``requires-python`` overlaps its
whole minor, so a micro floor like ``>= "3.11.4"`` admits the 3.11 minor
rather than excluding it at the synthetic ``.0`` floor.  Which knob the
error names depends on the target.  A matrix declares the python axis of
every target it expands, and both ``--python`` and ``[tool.nab.environment]``
are themselves errors alongside one, so a matrix target is moved by
``matrix.python`` instead.
Nz = z$ excludes the resolve target Python r   z).z  [tool.nab.matrix] declares the python axis of every target it expands: narrow matrix.python to drop the version, or widen requires-python.z  nab resolves for the host interpreter unless told otherwise; pass --python with a version the declaration admits, set [tool.nab.environment] python to one, or widen requires-python.)admits_requires_pythonr   r`   ru  r!   )r   r  r  r)  excludesrS  s   &&$$  ry   r  r    s    ,  $$\/%BCC(#o( )--.bb	B  j & & 	 j O O 	
 c
rx   c                    V ^8  d   QhRRRR/# )r   r   objectr   r6   rn   )r   s   "ry   r   r     s     	( 	(v 	(+ 	(rx   c                
   \        V \        4      '       g$   R \        V 4      P                   2p\	        V4      h \        V 4      #   \         d2   p\        R \
         4       4      pRT: RT : 2p\	        T4      ThRp?ii ; i)zmode must be a string, got c              3  8   "   T F  qP                   x  K  	  R # 5ir   r   r   s   & ry   r   _parse_mode.<locals>.<genexpr>  s     41wwr   zmode must be one of , got N)r  re   r  rq   r!   r6   r  r   )r   rS  r  r  s   &   ry   _parse_moder
    s    eS!!+DK,@,@+AB#(5!! (444$UIVE9=#C'(s   
A B,A==Bc               $    V ^8  d   QhRRRRRR/# )r   keyre   r   r  r   rl   rn   )r   s   "ry   r   r     s!     
 
C 
 
? 
rx   c                X   \        V\        4      '       g&   V  R \        V4      P                   2p\	        V4      h. p\        V4       FT  w  rE\        V\        4      '       g)   V  RV R\        V4      P                   2p\	        V4      hVP                  V4       KV  	  \        V4      # )z  must be a list of strings, got [] must be a string, got )	r  r   r  rq   r!   	enumeratere   r   r   )r  r   rS  outr  items   &&    ry   _parse_string_listr    s    eT""5d5k6J6J5KL#CU#$$$E1#5d4j6I6I5JKCc""

4	 $
 :rx   c               $    V ^8  d   QhRRRRRR/# )r   r  re   r  r   rK  rn   )r   s   "ry   r   r   '  s!      S   rx   c                &    \        V4      pVP                  P                  4        TP
                  '       d   T  RT 2p\	        T4      hTP                  e   T  RT 2p\	        T4      hR#   \         d   pT  RT 2p\	        T4      ThRp?ii ; i)zValidate one ``constraints`` entry's shape.

A constraint is a name with an optional specifier and marker; it bounds
versions but never pulls a package in, so extras and direct-reference
URLs are rejected here rather than only at resolve.
z is not a valid requirement: Nz cannot have extras: z% cannot be a direct reference (URL): )r   	specifierto_ranger  r!   extrasurl)r  r  reqr  rS  s   &&   ry   _require_constraintr  '  s    ($ 
 zzz*4&1#
ww:4&A#   (23%8#C'(s   %A- -B8BBc                    V ^8  d   QhRRRR/# r   r   r  r   rl   rn   )r   s   "ry   r   r   ?  s      f  rx   c                f    \        R V 4      p\        V4       F  w  r#\        RV R2V4       K  	  V# )r  zconstraints[])r  r  r  )r   r  r  r  s   &   ry   _parse_constraintsr   ?  s7    }e4EU#l1#Q/6 $Lrx   c               $    V ^8  d   QhRRRRRR/# )r   r  re   r  rl   r   rK  rn   )r   s   "ry   r   r   F  s!      C  D rx   c                    \        4       pV F-  pW29   d   V  R V: 2p\        V4      hVP                  V4       K/  	  R# )z has duplicate entry: N)r   r!   r   )r  r  seenr  rS  s   &&   ry   _reject_duplicatesr$  F  s?    UD<E/x8Cc""	 rx   c               $    V ^8  d   QhRRRRRR/# )r   r  re   r   r  r   rn   )r   s   "ry   r   r   O  s!      S  C rx   c                |    \        V\        4      '       g&   V  R \        V4      P                   2p\	        V4      hV# ) must be a string, got )r  re   r  rq   r!   )r  r   rS  s   && ry   _parse_string_valuer(  O  s;    eS!!,T%[-A-A,BC#Lrx   c                    V ^8  d   QhRRRR/# r   r   r  r   r{   rn   )r   s   "ry   r   r   V  s      V 
 rx   c                    \        RV 4      p \        VRR7      p\	        T4      #   \         d   pRT: RT 2p\        T4      ThRp?ii ; i)zParse ``[tool.nab].base-group`` as a PEP 735 group name.

Names the group a lock gives the project's own dependencies, so an
installer can ask for one group without them.  Unset leaves them
unconditional.
rf  Tvalidatezbase-group  is not a valid group name: Nr(  r   r   r!   re   r   r  	canonicalr   rS  s   &    ry   _parse_base_groupr2  V  s_     lE
2C&%cD9	 y>  &C7">qcB#A%&   & AAAc                    V ^8  d   QhRRRR/# r*  rn   )r   s   "ry   r   r   f  s      f  rx   c                    \        RV 4      p \        VRR7      p\	        T4      #   \         d   pRT: RT 2p\        T4      ThRp?ii ; i)a  Parse ``[tool.nab].build-group`` as a PEP 735 group name.

Names the group a lock gives ``[build-system].requires``, so one lock
can describe the environment the project is built in as well as the
one it runs in.  Unset, a lock says nothing about how it is built.
rg  Tr,  zbuild-group r.  Nr/  r0  s   &    ry   _parse_build_groupr6  f  s_     mU
3C&%cD9	 y>  &SG#?sC#A%&r3  c                    V ^8  d   QhRRRR/# r*  rn   )r   s   "ry   r   r   v  s      & Z rx   c                    \        RV 4      p \        V4      P                  4        V#   \         d   pRT: R2p\	        T4      ThRp?ii ; i)a:  Parse ``[tool.nab].requires-python`` as a PEP 440 specifier.

A declaration, not a target: it is recorded as the lock's top-level
``requires-python`` and checked against the resolve target, and the
target itself comes from ``[tool.nab.environment]`` (the host by
default).  Stored as the raw specifier string so the lockfile writer
can pass it straight to :class:`SpecifierSet`.  Raises
:class:`ConfigError` for invalid specifiers and for well-meaning bare
versions like ``"3.13"``; those are not valid specifiers and must be
written ``"==3.13"`` or ``">=3.13,<3.14"``.
ra   z1requires-python must be a PEP 440 specifier, got z(.  Did you mean ==X.Y or >=X.Y,<X.{Y+1}?N)r(  r   r  r  r!   )r   r  r  rS  s   &   ry   _parse_requires_pythonr9  v  sf     /
7C(S""$ J  (?w G8 9 	 #C'(s   ) AAAc               $    V ^8  d   QhRRRRRR/# )r   r  r"   r`  rM   r   rK  rn   )r   s   "ry   r   r     s!      ^ 4 D rx   c                  a	 V P                   o	S	f   R# VP                  R4      ;_uu_ 4       p\        P                  ! V4      pRRR4       XP	                  R4      p\        V\        4      '       g   R# \        V	3R lV 4       4      pV'       g   R# RP                  R V 4       4      pV P                  P                  \        P                  J d   RMRpV R	S	: R
V R2p\        V4      h  + '       g   i     L; i)a  Reject a ``base-group`` the project already declares as a group.

Both would emit ``'name' in dependency_groups`` and no marker could
say which was meant.  Checked as the file is read rather than at
emission, so it costs no resolve and holds for every output format.
Nr  dependency-groupsc              3  L   <"   T F  p\        V4      S8X  g   K  Vx  K  	  R # 5ir   r   r   declaredr   s   & ry   r   /_validate_base_group_is_free.<locals>.<genexpr>  s#      !'X+<X+F$+Ns   $
$r   c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   reprr   r?  s   & ry   r   r@         ;Ud8nnUr   --project-base-grouprf  r    and [dependency-groups] / are the same name; one marker cannot mean both)r   r  r  r  getr  r   r   r   rt  r   r#   r  r!   )
r  r`  r  r  groupstakennamesr  rS  r   s
   &&       @ry   rp  rp    s     "''D|	4Azz!} 
XX)*Ffd## !' E II;U;;E !!Z^^3 	  %q1% 9' 	'  c
) 
s   C//C?	c               $    V ^8  d   QhRRRRRR/# )r   r  r"   r  r   rK  rn   )r   s   "ry   r   r     s$      -;	rx   c                    V P                   e   VP                   e   R# V P                  P                  \        P                  J d   RMRpV RV P                   : R2p\        V4      h)a  Reject a ``build-group`` without a ``base-group`` to answer for the rest.

Unnamed, the project's own dependencies carry no marker and install
under every selection, so asking for the build group returns them too
and nothing can install the build requirements alone, which is the
reason to name them.  Naming both costs nothing: an install that wants
them together selects both groups.
N--project-build-grouprg  z is z, but base-group is unset, so the project's own dependencies carry no marker and install alongside every group; set base-group to name them, or drop build-group and use nab lock --build-requirements for a separate lock)r   rt  r   r#   r  r!   )r  r  r  rS  s   &&  ry   rq  rq    sw      J$4$4$@ ""jnn4 	   %tK%%( )A 	A  c
rx   c               (    V ^8  d   QhRRRRRRRR/# )r   r  r"   r  r`  rM   r   rK  rn   )r   s   "ry   r   r     s,     + ++-;+CG+	+rx   c                  a V P                   oSf   R# V P                  P                  \        P                  J d   RMRpSVP                   8X  dD   VP                  P                  \        P                  J d   RMRpV RV RS: R2p\        V4      hVP                  R	4      ;_uu_ 4       p\        P                  ! V4      pRRR4       XP                  R
4      p\        V\        4      '       g   R# \        V3R lV 4       4      p	V	'       g   R# RP                  R V	 4       4      p
V RS: RV
 R2p\        V4      h  + '       g   i     L; i)a  Reject a ``build-group`` some other group already answers to.

A declared ``[dependency-groups]`` name and ``base-group`` are both
already spoken for, and all three emit ``'name' in dependency_groups``.
Checked as the file is read, like :func:`_validate_base_group_is_free`.
NrO  rg  rF  rf   and z
 are both z; one marker cannot mean bothr  r<  c              3  |   <"   T F1  p\        V\        4      '       g   K  \        V4      S8X  g   K-  Vx  K3  	  R # 5ir   )r  re   r   r>  s   & ry   r   0_validate_build_group_is_free.<locals>.<genexpr>  s6      Hh$ 	):8)D)L 	s   <<
<r   c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   rB  rD  s   & ry   r   rT    rE  r   r   rG  rH  )r   rt  r   r#   r  r!   r  r  r  rI  r  r   r   r   )r  r  r`  r  otherrS  r  r  rJ  rK  rL  r   s   &&&        @ry   rr  rr    sE    #((D| ""jnn4 	  
 z   %%7 # 	
 U5'D83PQ#	4Azz!} 
XX)*Ffd##  E
 II;U;;E%q1% 9' 	'  c
# 
s   -EE	c                    V ^8  d   QhRRRR/# )r   r`  rM   r   r{   rn   )r   s   "ry   r   r     s     > > > >rx   c                   V P                  R4      ;_uu_ 4       p\        P                  ! V4      pRRR4       XP                  R4      p\	        V\
        4      '       d   RV9  d   R# \        VR,          4      #   + '       g   i     LR; i)aT  Read ``[project].requires-python``, the fallback declaration source.

``[tool.nab].requires-python`` (and ``--project-requires-python``) wins
when set; otherwise the project's own declaration is what the lock
records.  The file has already been parsed as TOML by
:func:`_reject_unknown_pyproject_keys`, so a decode error cannot reach
here.
r  Nprojectra   )r  r  r  rI  r  r   r9  )r`  r  r  rY  s   &   ry   rn  rn    sd     
4Azz!} 
hhy!Ggt$$(9(H!'*;"<== 
s   A;;B	c                    V ^8  d   QhRRRR/# )r   r<  rX   r   zlist[IndexRoute]rn   )r   s   "ry   r   r   
  s      %5 :J rx   c                    V P                    Uu. uF4  pVP                  f   K  \        VP                  VP                  R7      NK6  	  up# u upi )a  Project the routing package overrides into coordinator :class:`IndexRoute`s.

Each per-package override that sets ``index`` contributes one route,
keyed by its bare package name.  A routing entry always uses a
bare-name requirement (parse-time guarantee), and the parse-time
non-overlap check forbids two routes for one package, so the resulting
route map has at most one entry per name.
)r   r   )r0  r   r.   r   )r<  r   s   & ry   index_routes_from_configr\  
  sG     000H>> 	=
X^^<0  s
   A%Ac                    V ^8  d   QhRRRR/# )r   r<  rX   r   zdict[str, int]rn   )r   s   "ry   r   r     s      +;  rx   c                    V P                   P                  4        UUu/ uF!  w  rVP                  f   K  WP                  bK#  	  upp# u uppi )z>Project per-index cache-freshness floors, keyed by index name.)r2  r  r   )r<  r   r   s   &  ry   index_cache_floors_from_configr_    sN     %44::<<ND(( 	,+++<  s
   A	A	c               $    V ^8  d   QhRRRRRR/# )r   r   r  r]  r   r   rn   )r   s   "ry   r   r   #  s!     2 2F 2x 2H 2rx   c               ^   \        V \        4      '       d"   V P                  f   RV : 2p\        V4      hV # \        V \        4      '       g$   R\        V 4      P                   2p\        V4      h\        P                  V 4      pVe-    V\        \        VP                  ^4      4      R7      ,
          #  \        V 4      pTP                  f   RT : 2p\        T4      hT#   \        \        3 d    RT : 2p\        T4      Rhi ; i  \         d   pRT : 2p\        T4      ThRp?ii ; i)aN  Parse ``uploaded-prior-to`` (ISO datetime, TOML datetime, or ``P<n>D``).

Naive datetimes are rejected so lockfiles read identically across
timezones. ``P<n>D`` (a nab extension) is resolved against
``anchor`` so re-locks reproduce the same cutoff.  Callers only reach
here with a present value (the absent case is handled upstream).
Nzfuploaded-prior-to TOML datetime must have an explicit timezone offset (e.g. ``Z`` or ``+00:00``); got zwuploaded-prior-to must be a TOML offset-date-time, an ISO 8601 datetime string with timezone, or a 'PnD' duration; got )daysz)uploaded-prior-to duration is too large: zuploaded-prior-to must be an ISO 8601 datetime with timezone (e.g. '2026-05-01T00:00:00Z') or a 'PnD' duration (e.g. 'P4D'); got zduploaded-prior-to ISO datetime must include an explicit timezone offset (e.g. 'Z' or '+00:00'); got )r  r   tzinfor!   re   r  rq   _DURATION_PATTERNmatchr   r  groupOverflowErrorr  r   )r   r]  rS  duration_matchdtr  s   &$    ry   _parse_uploaded_prior_torj  #  sY    %""<<9 
 c""eS!!K(()+ 	
 #&,,U3N!	-I3~/C/CA/F+GHHH(& 
yyy 	
 #I' z* 	-=eYGCc",	-
  (++0)5 	
 #C'(s$   *C# 7D
 #$D
D,D''D,r   trust-unverified-depsc                    V ^8  d   QhRRRR/# )r   r   r  r   ztuple[DistPolicy, bool]rn   )r   s   "ry   r   r   [  s      V 0G rx   c                   \        V \        4      '       g#   \        RV \        \        P                  4      R3# \        \        V 4      \        ,
          4      pV'       d#   RV: R\        \        4      : 2p\        V4      hRV 9  d   Rp\        V4      h\        RV R,          \        \        P                  4      p\        RV P                  R	4      RR
7      pW43# )zParse the global ``dist-policy``: an enum string or a policy table.

The table form ``{ policy = "...", trust-unverified-deps = bool }``
folds the sdist-trust flag into the dist body.  Returns
``(policy, trust_unverified)``.
r~  Fz%dist-policy table has unknown key(s) ; expected r   z#dist-policy table must set 'policy'zdist-policy.policy!dist-policy.trust-unverified-depsrk  r   )r  r   _parse_enumr3   r7  r   r   _DIST_POLICY_TABLE_KEYSr!   _parse_boolrI  )r   r  rS  r   trusts   &    ry   _parse_dist_policy_globalru  [  s     eT""uj*:S:ST
 	
 SZ"99:G3G; ? 78;= 	 #u3#eHoz:;T;TF +		)*E
 ?rx   c               (    V ^8  d   QhRRRRRRRR/# )r   r  re   r   r  r   r   r   rn   )r   s   "ry   r   r   |  s(      S  T d rx   c                   Vf   V# \        V\        4      '       g&   V  R\        V4      P                   2p\	        V4      hV# )Nz must be a boolean, got )r  r   r  rq   r!   )r  r   r   rS  s   &&$ ry   rs  rs  |  sE    }eT""-d5k.B.B-CD#Lrx   c          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )r   r  re   r   r  enum_clsztype[enum.Enum]r   z	enum.Enumr   r   rn   )r   s   "ry   r   r     s:     ( (	(( ( 	(
 	(rx   c                   Vf   V# \        V\        4      '       g&   V  R\        V4      P                   2p\	        V4      h V! V4      #   \
         d0   p\        R T 4       4      pT  RT: RT: 2p\	        T4      ThR p?ii ; i)Nr'  c              3  8   "   T F  qP                   x  K  	  R # 5ir   r  r   s   & ry   r   _parse_enum.<locals>.<genexpr>  s     11wwr    must be one of r	  )r  re   r  rq   r!   r  r   )r  r   ry  r   rS  r  r  s   &&&&   ry   rq  rq    s     }eS!!,T%[-A-A,BC#( (111%eYfUI>#C'(s   A B*B  Bc                    V ^8  d   QhRRRR/# )r   r   r  r   zdict[str, str]rn   )r   s   "ry   r   r     s      V  rx   c                   \        V \        4      '       g$   R \        V 4      P                   2p\	        V4      h/ pV P                  4        F  w  r4\        V\        4      '       d   \        V\        4      '       g   RV: RV: 2p\	        V4      hV\        9  d%   \        \        4      pRV: RV: 2p\	        V4      hV\        9   d    \        V4       WBV&   K  	  V#   \         d   pRT RT: 2p\	        T4      ThRp?ii ; i)z<marker-environment must be a table of string -> string, got z9marker-environment entries must be string -> string, got r  z$unknown marker-environment variable z-; expected a PEP 508 marker variable, one of zmarker-environment.z  must be a PEP 440 version, got N)r  r   r  rq   r!   r  re   _PEP508_MARKER_VARIABLESr   _VERSION_MARKER_VARIABLESr    r  )r   rS  r  kvr  r  s   &      ry   _parse_marker_environmentr    s#   eT""K(()+ 	 #C!S!!As););KA5PRSTRWX  c"",,34E6qe <,,196  c""))0
 A' ( J	  0+A3.NqeT!#&C/0s   C""D-DDc                    V ^8  d   QhRRRR/# )r   r   r  r   dict[str, Any]rn   )r   s   "ry   r   r     s      f  rx   c           	        \        V \        4      '       g$   R\        V 4      P                   2p\	        V4      h\        \        V 4      \        ,
          4      pV'       d#   RV: R\        \        4      : 2p\	        V4      hV P                  4        UUu/ uF  w  r4TVR8X  d   TM\        RV 2V4      bK   	  ppp\        V4       V# u uppi )a  Parse ``[tool.nab.environment]``: the one environment to resolve for.

Kept as the raw table so the registry merges it sub-key by sub-key
across the config sources; :func:`_environment_from_effective` turns the
merged whole into an :class:`EnvironmentConfig`.  ``platform`` takes the
two shapes a ``matrix.platforms`` entry takes, a bare id or a table of
the wheel-tag knobs, so a dict value passes through here.
z,[tool.nab.environment] must be a table, got z%unknown [tool.nab.environment] keys: rn  r|   zenvironment.)r  r   r  rq   r!   r   r   _ENVIRONMENT_KEYSr  r(  _validate_environment_values)r   rS  r  r  r  r  s   &     ry   _parse_environmentr    s     eT""<T%[=Q=Q<RS#SZ"334G3G; ? 1257 	 #
 	 'IC 	*  <u!5t<	= '	   !%Js   $C
c                    V ^8  d   QhRRRR/# )r   r   r  r   r=   rn   )r   s   "ry   r   r     s      f  rx   c                    Rp\        V \        4      '       d   \        WR7      # \        V \        4      '       d   \	        V\        RV 4      4      # V R\        V 4      P                   2p\        V4      h)zBuild the :class:`PlatformSpec` ``[tool.nab.environment].platform`` names.

The same two shapes ``matrix.platforms`` entries take, parsed by the same
code: a bare id at the platform's default tag knobs, or a table declaring
them.
zenvironment.platformplatform_idr  ' must be a platform id or a table, got )	r  re   _platform_specr   _parse_platform_tabler   r  rq   r!   r   whererS  s   &  ry   _environment_platform_specr    sj     #E%e77%$UD1A5,IJJG:4;;O;O:P
QC
c
rx   c                    V ^8  d   QhRRRR/# )r   r  zMapping[str, Any]r   rK  rn   )r   s   "ry   r   r     s     " ".? "D "rx   c                   V P                  R4      pVe    \        V4       V P                  R4      pVeE   \	        V4      P
                  pV\        9  d%   \        \        4      pRV: RV: 2p\        V4      hV P                  R4      pVe2   V\        9  d%   \        \        4      pRV: RV: 2p\        V4      hR# R#   \         d   pRT: 2p\        T4      ThRp?ii ; i)	zValidate the value of every environment axis the table names.

Shared by the ``[tool.nab.environment]`` parse and the
``[tool.nab.marker-environment]`` translation, so both reject the
same bad values with one message.
rf   NzBenvironment.python must be a version like '3.12' or '3.12.4', got r|   zunknown environment.platform r  r}   z#unknown environment.implementation )
rI  r    r  r!   r  r  r?   r   _KNOWN_IMPLEMENTATIONSr   )r  rf   r  rS  r|   r  r  r}   s   &       ry   r  r    s    __X&F	,FO z*H0:FF..+,E/ ?$$)9.  c"" __%56N!n<R&R+,1.1C D  %y* 	 # 'S!#  	,""(-  c"+	,s   C C%C  C%platform-releaseplatform-versionzdict[tuple[str, str], str]_PLATFORM_ID_BY_MARKERSc                    V ^8  d   QhRRRR/# )r   marker_environmentMapping[str, str]r   r  rn   )r   s   "ry   r   r   !  s      Z Z)ZZrx   c                  a  \         P                  R4       0 \        m\        m\        m\
        m\        mp\        \        S 4      V,
          4      pV'       d$   RV: R\        \        4      : R2p\        V4      h/ p\         F  pVS 9   g   K  S V,          VR&    M	  \         F&  pVS 9   g   K  S V,          P                  4       VR&    M	  . \
        O\        O Uu. uF  pVS 9   g   K  VNK  	  ppV'       d[   \        ;QJ d#    V 3R l\         4       F  '       g   K   RM	  R	M! V 3R l\         4       4      '       g   R
V: R2p\        V4      h\        ;QJ d#    V 3R l\         4       F  '       g   K   RM	  R	M! V 3R l\         4       4      '       d   S P                  RR4      S P                  RR4      3p\        P                  V4      p	V	f&   \        \        4      p
RV: RV
: R2p\        V4      h\!        S V	4       RV	/\        P#                  4        UUu/ uF  w  r[VS 9   g   K  VS V,          bK  	  uppCVR&   \%        V4       V# u upi u uppi )a\  Translate the deprecated ``[tool.nab.marker-environment]`` overlay.

The overlay set PEP 508 marker variables one by one, which let a
partial declaration (``sys_platform`` alone) leave the rest of the
environment on the host and resolve for a machine that does not exist.
The replacement declares whole axes, so every overlay key must name one:
an unmappable ``(sys_platform, platform_machine)`` pair, or a key no
axis can carry, is an error rather than a silently-wrong resolve.  The
kernel markers name no axis of their own; they are knobs of the platform
the pair names, and translate into its table.
z[tool.nab.marker-environment] is deprecated and will be removed; declare [tool.nab.environment] with python/platform/implementation instead.  Translating the overlay for this run.z*[tool.nab.marker-environment] variable(s) z@ cannot be translated to [tool.nab.environment], whose axes are zZ.  The platform id carries the OS and machine markers; declare it as environment.platform.rf   r}   c              3  ,   <"   T F	  qS9   x  K  	  R # 5ir   rn   )r   r  r  s   & ry   r   7_environment_from_marker_environment.<locals>.<genexpr>V  s      ")>A)>   TF#[tool.nab.marker-environment] sets z without (sys_platform, platform_machine), which is the pair that names the machine.  Declare [tool.nab.environment] platform instead: half a machine would keep the other half of the host's.c              3  ,   <"   T F	  qS9   x  K  	  R # 5ir   rn   )r   r  r  s   & ry   r   r  a  s     
F0E$$0Er  r[   r   r\   zF[tool.nab.marker-environment] sets (sys_platform, platform_machine) = zX, which names no platform nab models.  Declare [tool.nab.environment] platform = one of ze; both markers must name one machine, because half a machine would keep the other half of the host's.idr|   )r  r  _MARKER_PYTHON_KEYS_MARKER_IMPLEMENTATION_KEYS_MARKER_PLATFORM_KEYS_MARKER_PLATFORM_IMPLIED_KEYS_MARKER_PLATFORM_KNOBSr   r   r  r!   lowerrP  rI  r  r?   _check_implied_platform_markersr  r  )r  translatableuntranslatablerS  r  r  r  needs_platformpairr  r  knobs   f           ry   $_environment_from_marker_environmentr  !  s    OO	;		$ 
 
'	
 
 L C 23lBCN88J K(), -KK 	 #"$K"$$$6s$;K! # +$$,>s,C,I,I,KK()	 + K0J3IJJA"" 	
J  
 cc ")>"ccc ")>"   2.1C DG G 	 #
s
F0E
Fsss
F0E
FFF"">26""#5r:
 .11$7+,E((,x 09 FF  c""'(:KH+#
 "8!=!=!?!?IC,, .(--!?#
J !-UFs   !	I/I)I!9I!c               $    V ^8  d   QhRRRRRR/# )r   r  r  r  re   r   rK  rn   )r   s   "ry   r   r   ~  s$      )8;	rx   c                   \         V,          p\         Uu/ uF)  pW09   g   K  W,          W#,          8w  g   K   W0V,          bK+  	  ppV'       d2   V Uu/ uF  q3W#,          bK  	  ppRV: RV: RV: R2p\        V4      hR# u upi u upi )zReject an overlay whose implied markers contradict the platform it names.

The platform id carries ``platform_system`` and ``os_name``, so an overlay
that repeats them is translatable; one that disagrees with them names two
machines at once.
r  z, which contradicts platform z, where they are z!.  One overlay names one machine.N)r?   r  r!   )r  r  r?  r  conflictingexpectedrS  s   &&     ry   r  r  ~  s      ,H 10C$ 	%);)@HM)Q 	%$$0  
 2=>+3&+>1+ A%%0O 4|<> 	
 #  ?s   BBBBc                    V ^8  d   QhRRRR/# )r   ry  r|  r   r  rn   )r   s   "ry   r   r     s     ' '+''rx   c                   V R,          P                   pV R,          P                   pV'       d!   V'       d   Rp\        V4      h\        V4      pV'       g   R# VP                  R4      p\	        VP                  R4      Vf   RM
\        V4      VP                  R4      R7      pVP                  e0   VP                  f"   \        \        4      pR	V: R
2p\        V4      hV# )a  Fold the environment surfaces into the one declared environment.

``[tool.nab.environment]`` is the surface;
``[tool.nab.marker-environment]`` is its deprecated predecessor and is
translated into it.  Declaring both is an error: the two would have to
agree, and a silent precedence between them is exactly the ambiguity the
replacement removes.  Returns ``None`` when neither is declared, which
is the host.
r  zmarker-environmentzx[tool.nab.environment] and the deprecated [tool.nab.marker-environment] are both set; drop the marker-environment table.Nr|   rf   r}   )rf   r|   r}   z[tool.nab.environment].implementation needs a platform: an interpreter is modelled on a declared machine, not on the host's.  Add platform = one of .)
r   r!   r  rI  rU   r  r}   r|   r   r?   )ry  r?  r  rS  r|   r  r  s   &      ry   r  r    s     #,M":"@"@H,56J,K,Q,Q- 
 c""78JK||J'H#||H%!)/I(/S||$45K
 !!-+2F2F2N'('',iq2 	
 #rx   r   r  c                    V ^8  d   QhRRRR/# )r   r   r  r   r  rn   )r   s   "ry   r   r     s     - -& -%< -rx   c           	        \        V \        4      '       g$   R \        V 4      P                   2p\	        V4      hV '       g   Rp\	        V4      h. p\        V 4       EFZ  w  r4\        V\        4      '       g'   RV R\        V4      P                   2p\	        V4      h\        \        V4      \        ,
          4      pV'       d&   RV RV: R\        \        4      : 2p\	        V4      h VR,          pVR,          p\        T\        4      '       d   \        T\        4      '       g   RT R2p\	        T4      hRT9   d'   \        T4      '       d   RT RT: R2p\	        T4      h\        RT R2TP                  R4      \        \        P                   4      p	TP#                  \%        YgT	R7      4       EK]  	  \'        V4       \)        V4      #   \         d   pRT R	T: 2p\	        T4      R
hR
p?ii ; i)z(indexes must be an array of tables, got z4indexes must contain at least one entry when presentzindexes[] must be a table, got zunknown indexes[] keys: rn  r   r  ] missing required key N] name and url must be stringsserializationz].serialization is not settable on a file:// index: a local index is read from disk with no Accept negotiation, so the pin would do nothing.  Drop it from index r  z].serialization)r   r  r  )r  r   r  rq   r!   r  r   r   r   _INDEX_KEYSKeyErrorre   r   rq  rI  r   	NEGOTIATEr   r   _check_index_name_uniquenessr   )
r   rS  r  r  entryr  r   r  missingr  s
   &         ry   _parse_indexesr    s   eT""8e9M9M8NO#D#Ce$%&&QC6tE{7K7K6LMCc""Uk12"1#Xg[ 9#K035  c""	-=D,C $$$JsC,@,@QC=>Cc""e#C(8(81# EEIHAO 
 c""#qc)IIo&))	
 	

;DOPC %D !%:+  	-QC6wkBCc",	-s   +GG6G11G6c                    V ^8  d   QhRRRR/# )r   r  zSequence[IndexConfig]r   rK  rn   )r   s   "ry   r   r     s      *? D rx   c                    \        4       pV  FJ  pVP                  V9   d   RVP                  : 2p\        V4      hVP                  VP                  4       KL  	  R# )z/Reject two indexes declared with the same name.zduplicate index name: N)r   r   r!   r   )r  r#  r   rS  s   &   ry   r  r    sJ    UD::*5::.9Cc""	 rx   re  c               $    V ^8  d   QhRRRRRR/# r   r   r  r]  r   r   list[PackageOverride]rn   )r   s   "ry   r   r   $  s(     0 00 0 	0rx   c          
     v   \        V \        4      '       d   Rp\        V4      h\        V \        4      '       g$   R\	        V 4      P
                   2p\        V4      h. pV P                  4        F  w  rERV: 2p\        WF4      p\        V\        4      '       g&   V R\	        V4      P
                   2p\        V4      h\        WV4       \        \        V4      \        ,
          4      pV'       d%   V RV: R\        \        4      : 2p\        V4      hVP                  \        V3VVVR7      4       K  	  V# )a;  Parse ``[tool.nab.packages.<name>]`` into per-package overrides.

Each key is a PEP 508 requirement (a bare name, or a name plus a
version specifier in a quoted key such as ``"numpy <= 1.21"``) and the
sub-table is the override body.  The key is the whole selector, so the
sugar form carries no inner selector key.
z[tool.nab.packages] is the name-keyed table form ([tool.nab.packages.<name>]); for one body across several requirements use [[tool.nab.package-rules]] with match = [...]z?[tool.nab.packages] must be a table keyed by package name, got r   must be a table, got : unknown override key(s) ; expected body keys r]  )r  r   r!   r   r  rq   r  _requirement_from_selector_reject_deferredr   r   _PACKAGE_OVERRIDE_BODY_KEYSextend_build_package_overrides)	r   r]  rS  r  r  bodyr  r   r  s	   &$       ry   _parse_packages_sugarr  $  s@    %N 	
 #eT""U$$%' 	 #!#C[[]	C7#0<$%%G1$t*2E2E1FGCc""%T%@@A'3G; ? ;<?A  c""

$		
 #, Jrx   c               $    V ^8  d   QhRRRRRR/# r  rn   )r   s   "ry   r   r   W  s(        	rx   c          	         \        V \        4      '       g$   R\        V 4      P                   2p\	        V4      h. p\        V 4       F!  w  rEVP                  \        WTVR7      4       K#  	  V# )a  Parse ``[[tool.nab.package-rules]]`` into per-package overrides.

Each entry's ``match`` selector lists PEP 508 requirements (name plus
an optional version specifier); the body applies to every one, so a
single rule can cover many packages (e.g. routing a namespace to one
index).
z[tool.nab.package-rules] must be an array of tables ([[tool.nab.package-rules]]); for per-package policy keyed by name use [tool.nab.packages.<name>].  Got r  )r  r   r  rq   r!   r  r  _parse_package_rule_entry)r   r]  rS  r  r  r  s   &$    ry   _parse_package_rulesr  W  sm     eT""::>u+:N:N9OQ 	
 #!#Ce$

,UfEF %Jrx   c               (    V ^8  d   QhRRRRRRRR/# )	r   r  r  r   r  r]  r   r   r  rn   )r   s   "ry   r   r   p  s6     N NNN 	N
 Nrx   c                  R V R2p\        V \        4      '       g&   V R\        V 4      P                   2p\	        V4      h\        W4       \        \        V 4      \        ,
          4      pV'       d%   V RV: R\        \        4      : 2p\	        V4      h\        V P                  R4      V4      pV'       g   V R2p\	        V4      hV P                  4        UUu/ uF  w  rxVR8w  g   K  WxbK  	  p	pp\        WiW2R7      # u uppi )zpackage-rules[r  r  r  z!; expected 'match' and body keys re  zG must carry a 'match' selector listing at least one PEP 508 requirementr  )r  r   r  rq   r!   r  r   r   _PACKAGE_RULE_KEYSr  _parse_matchrI  r  r  )
r  r   r]  r  rS  r  requirementsr  valr  s
   &&$       ry   r  r  p  s    UG1%EeT""-d5k.B.B-CD#U"SZ"445Gg/{ ;$%@ADF 	 #		' 2E:Lg # # 	 #%*[[]E]cWnHCH]DE#LMM Fs   D.Dc          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )r   r  tuple[Requirement, ...]r  r  r  re   r]  r   r   r  rn   )r   s   "ry   r   r     sA     L L)L
L L
 L Lrx   c                  \        VP                  R4      V4      w  rERV9   d+   \        V R2VR,          \        \        P                  4      MRp\        VP                  R4      VVRV9   R7      w  rx\        W4      p	\        VP                  R4      V4      p
\        VP                  R4      V4      p\        VP                  R	4      V4      pVRJ;'       gW    VRJ;'       gK    VRJ;'       g?    VRJ;'       g3    T;'       g)    V	RJ;'       g    V
RJ;'       g    VRJ;'       g    VRJpV'       g!   V R
\        \        4      : 2p\        V4      hV	eB   V  F;  p\        VP                  4      '       g   K   V R\        V4      : R2p\        V4      h	  V  Uu. uFF  p\        V\!        VP"                  4      VP                  P%                  4       VVVVVV	V
VVVR7      NKH  	  up# u upi )zETurn a validated selector and body into one override per requirement.r~  r  .build-policyNr  r]  presentr   ra   provides-extra3 sets no policy; an entry must set at least one of z.index routing requires bare-name requirements (no version specifier); routing decides where to fetch a listing before any version is known, but z is version-scoped)r   r   r   r   r   r   r   r   r   r   r   r   r   )_parse_override_distrI  rq  r1   r  !_parse_override_uploaded_prior_to_parse_override_index_parse_override_dependencies_parse_override_requires_python_parse_override_provides_extrar   r  r!   re   r  rZ   r   r   r  )r  r  r  r]  r   
dist_trustr   r   uploaded_disabledr  r   r   r   has_bodyrS  r   s   &&&$            ry   r  r    sp    3488M3JERK T! 	g]# 		
   ,M$%#t+	,( "$.E/0H%PL5"#UO 4DHH=M4NPUVN4 	& 	&T!	& 	&t#	& 	& D(	& 	& 		& 	&
 	& 	& t#	& 	& $&	& 	& %  g 2368 	 #'K;(())g  K(++=?  "#&& (4 (!  (K 	#";#3#34%//88:#'1%/'8%+)	
 (!  s   #AG2c               $    V ^8  d   QhRRRRRR/# )r   r  re   r  r   r   rn   )r   s   "ry   r   r     s!      C   rx   c                .    \        V 4      pVP                  P                  4        TP
                  '       g!   TP                  f   TP                  '       d   T RT : R2p\	        T4      hT#   \         d   pT RT : R2p\	        T4      ThRp?ii ; i)zParse one selector into a name-plus-optional-specifier requirement.

Extras, markers, and URLs are rejected: a selector carries only a
package name and an optional version specifier.
z entry z# is not a valid PEP 508 requirementNz} may carry only a name and an optional version specifier; extras, markers, and URLs are not supported on the override surface)r   r  r  r  r!   r  markerr  )r  r  r   r  rS  s   &&   ry   r  r    s    (!#&&&( [//;{gWSG $' ' 	
 #  (wsg%HI#C'(s   %A/ /B:BBc                    V ^8  d   QhRRRR/# )r   	overridesr/  r   rK  rn   )r   s   "ry   r   r     s     + +*+	+rx   c                   \          F  w  r\        \        4      pV  F7  p\        WB4      '       g   K  W4P                  ,          P                  V4       K9  	  VP                  4        F  w  rV\        P                  ! V^4       Fv  w  rxVP                  VP                  ,          P                  '       d   K4  RV: RV: R\        VP                  4      : R\        VP                  4      : R2	p	\        V	4      h	  K  	  K  	  R# )a  Reject two per-package entries setting one field for overlapping ranges.

For each (canonical name, policy field) the entries that set the field
must have pairwise-disjoint version ranges.  Two ranges overlap when
``not (range_a & range_b).is_empty``.  A bare-name requirement is the
full range, so it overlaps every range for that package; in
particular two routing entries for one package always conflict.
ztwo per-package overrides for z
 both set z for overlapping versions: rR  zJ.  Per-package overrides for one field must cover disjoint version ranges.N)_PACKAGE_POLICY_FIELDSr   r   _override_setsr   r   r  r   combinationsr   is_emptyre   r   r!   )
r  _fieldattrby_namer  r   entriesleftrightrS  s
   &         ry   r  r    s     /;Ft;LEe**

#**51  %]]_MD(55gqA**U-@-@@JJJ8 A": & 0 014 5 1 125 6II  &c**  B - /rx   c               $    V ^8  d   QhRRRRRR/# )r   r   rZ   r  re   r   r   rn   )r   s   "ry   r   r   	  s!     / /_ /C /D /rx   c                n    VR8X  d#   V P                   RJ;'       g    V P                  # \        W4      RJ# )zWhether ``override`` carries the policy field tracked by ``attr``.

uploaded-prior-to counts as set by either a cutoff datetime or the
``false`` disable form, so a cutoff entry and a disable entry for one
package with overlapping ranges still conflict.
r   N)r   r   getattr)r   r  s   &&ry   r  r  	  sE     ""))5 
 
//	
 8"$..rx   flat_metadata_advicec               (    V ^8  d   QhRRRRRRRR/# )	r   r  r  r  re   r  r   r   rK  rn   )r   s   "ry   r   r   	  s,      "%@D	rx   c                   \        \        V 4      \        ,          4      pV'       d-   V RV: R2pV'       d   RV9   d
   VR,          p\        V4      hR# )zReject override-body keys that are not supported.

``flat_metadata_advice`` gates the package-surface hint to set metadata
via the flat body keys; the index surface passes ``False`` since those
keys are rejected there too.
z	: key(s) z are not supportedmetadatazd; set metadata as the flat body keys 'dependencies', 'requires-python', and 'provides-extra' insteadN)r   r   _OVERRIDE_DEFERRED_KEYSr!   )r  r  r  deferredrS  s   &&$  ry   r  r  	  sZ     c%j#::;Hy,>?J($:CC # rx   c               $    V ^8  d   QhRRRRRR/# )r   r   r  r]  r   r   zdict[str, IndexOverride]rn   )r   s   "ry   r   r   2	  s(        	rx   c                   \        V \        4      '       g$   R\        V 4      P                   2p\	        V4      h/ pV P                  4        F  w  rERV 2p\        WVVR7      W4&   K  	  V# )a  Parse ``[tool.nab.index.<name>]`` into a name-keyed policy map.

Each key must name a declared ``[[tool.nab.indexes]]`` entry; that
cross-key check is a resolve-path concern run post-merge by
:func:`_validate_index_overrides_declared` (the surface is parsed in
isolation from the ``indexes`` row, so this parser does not see the
declared set).  The body sets policy fields only (no routing, no
version scope); the override applies to every package served from that
index.
z:[tool.nab.index] must be a table keyed by index name, got r  r  )r  r   r  rq   r!   r  _parse_index_override_body)r   r]  rS  r  r   r  r  s   &$     ry   _parse_index_overridesr  2	  st     eT""U$$%' 	 #$&Ckkm
.t6J	 $ Jrx   c               (    V ^8  d   QhRRRRRRRR/# )	r   r  r  r  re   r]  r   r   rV   rn   )r   s   "ry   r   r   N	  s,     8 8
88)188rx   c          	     4   \        V \        4      '       g&   V R \        V 4      P                   2p\	        V4      h\        WRR7       \        \        V 4      \        ,
          4      pV'       d&   V RV: R\        \        4      : R2p\	        V4      h\        V P                  R4      V4      w  rVRV 9   d+   \        V R2V R,          \        \        P                  4      MR	p\        V P                  R
4      VVR
V 9   R7      w  r\        V P                  R4      V4      p
VR	J;'       g3    VR	J;'       g'    VR	J;'       g    VR	J;'       g    T	;'       g    V
R	JpV'       g!   V R\        \        4      : 2p\	        V4      h\!        VVVVV	V
R7      # )r  F)r  r  r  z< (per-index overrides carry no routing and no version scope)r~  r  r  Nr  r  assume-fresh-secondsr  )r   r   r   r   r   r   )r  r   r  rq   r!   r  r   r   _INDEX_OVERRIDE_KEYSr  rI  rq  r1   r  r  _parse_index_assume_freshrV   )r  r  r]  rS  r  r   r  r   r   r  r   r  s   &&$         ry   r  r  N	  s    dD!!-d4j.A.A-BC#Tu=SY!556Gg/{ ;+,/ 0-- 	
 #2488M3JERK T! 	g]# 		
   ,M$%#t+	,( 5'(% 	4 	, 	,T!	, 	,t#	, 	, D(	, 	, 		, 	,
  t+  g +,/1 	 ##-!+#41 rx   c               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   r  rn   )r   s   "ry   r   r   	  s'     
U 
U 
Us 
U/F 
Urx   c                   a V f   R# \        S R2V 4      p\        ;QJ d    . V3R lV 4       F  NK  	  5# ! V3R lV 4       4      # )zParse a ``match`` selector into PEP 508 requirements.

Each entry is a requirement of name plus an optional version
specifier; extras, markers, and URLs are rejected.  A bare name means
all versions; a version specifier scopes the entry to matching ones.
.matchc              3  B   <"   T F  p\        VS R 24      x  K  	  R# 5i)r  N)r  )r   r  r  s   & ry   r   _parse_match.<locals>.<genexpr>	  s#     Tes+CE7&1ABBe   rn   )r  r   )r   r  rL  s   &f ry   r  r  	  sD     }	%/7E5TeT5T5TeTTTrx   c               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   z%tuple[DistPolicy | None, bool | None]rn   )r   s   "ry   r   r   	  s$     + +++*+rx   c                   V f   R# \        V \        4      '       d&   \        V R2V \        \        P                  4      R3# \        V \
        4      '       g&   V R\        V 4      P                   2p\        V4      h\        \        V 4      \        ,
          4      pV'       d%   V RV: R\        \        4      : 2p\        V4      hRV 9  d   V R2p\        V4      h\        V R2V R,          \        \        P                  4      pV P                  R	4      pVe'   \        V\        4      '       g   V R
2p\        V4      hWE3# )zParse the ``dist-policy`` body: an enum string or a policy table.

The table form ``{ policy = ..., trust-unverified-deps = bool }``
folds the sdist-trust flag into the dist body.
Nz.dist-policyzW.dist-policy must be a policy string or a table { policy, trust-unverified-deps }, got z .dist-policy has unknown key(s) rn  r   z$.dist-policy table must set 'policy'z.dist-policy.policyrk  z4.dist-policy.trust-unverified-deps must be a boolean)NN)r  re   rq  r3   r7  r   r  rq   r!   r   r   rr  rI  r   )r   r  rS  r  r   rt  s   &&    ry   r  r  	  sa    }%'&z:;T;T 	
 	
 eT""g 99=e9M9M8NP 	 #SZ"99:Gg5g[ A 78;= 	 #u;<#'$%h!!	F II-.EE4!8!8KL#?rx   c          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )r   r   r  r  re   r]  r   r  r   r   ztuple[datetime | None, bool]rn   )r   s   "ry   r   r   	  s4      *2=A!rx   c                   V'       g   R# V RJ d   R# V RJ d   V R2p\        V4      h \        WR7      pVR3#   \          d   pT RT 2p\        T4      ThRp?ii ; i)	zHParse the ``uploaded-prior-to`` body: ``false`` disables, else a cutoff.NFTz.uploaded-prior-to: ``true`` is not a valid value; use ``false`` to disable the cutoff or a datetime / 'PnD' duration to set a windowr  z.uploaded-prior-to: )NF)NT)r!   rj  )r   r  r]  r  rS  cutoffr  s   &&$$   ry   r  r  	  s     ~}g   	
 #()%? E?  (+C51#C'(s   : AAAc               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   r   rn   )r   s   "ry   r   r   	  s!     
 
V 
C 
J 
rx   c                    V f   R# \        V \        4      '       g   \        V \        4      '       d   V ^ 8:  d   V RV : 2p\        V4      hV # )zEParse ``assume-fresh-seconds``: a positive integer number of seconds.NzH.assume-fresh-seconds must be a positive integer number of seconds, got )r  r   r  r!   r  s   && ry   r  r  	  sT    }%j&<&<
g "I' 	 #Lrx   c               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   r{   rn   )r   s   "ry   r   r   	  s!     ( (6 (# (* (rx   c                r    V f   R#  \        V 4      #   \         d   pT RT 2p\        T4      ThRp?ii ; i)a  Parse a per-package ``requires-python`` override, naming the entry.

An absent key (``None``) means no override; a present value delegates
to :func:`_parse_requires_python` for PEP 440 validation, prefixing the
``where`` selector on failure so the message names the offending entry.
Nr  )r9  r!   )r   r  r  rS  s   &&  ry   r  r  	  sI     }(%e,, (q#C'(s   
 616c               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   r   rn   )r   s   "ry   r   r   	  s$     ) )))#)rx   c                   V f   R# \        V \        4      '       g&   V R\        V 4      P                   2p\	        V4      h. p\        V 4       Fz  w  rE\        V\        4      '       g)   V RV R\        V4      P                   2p\	        V4      h \        V4      pVP                  P                  4        TP                  T4       K|  	  \        V4      #   \         d   pT RT RT: 2p\	        T4      ThRp?ii ; i)a  Parse the ``dependencies`` body: PEP 508 strings that replace deps.

The list replaces a package's declared runtime dependencies for the
matched version range.  Each item is a full PEP 508 dependency
*value*, so extras, markers, and version specifiers are all legal
(unlike the override *key*, which :func:`_requirement_from_selector`
restricts to a name plus specifier).  A present-but-empty list is
stored as ``()`` (replace with zero deps), distinct from the key
being absent (``None``).
NzA.dependencies must be a list of PEP 508 requirement strings, got z.dependencies[r  z&] is not a valid PEP 508 requirement: )r  r   r  rq   r!   r  re   r   r  r  r  r   r   )r   r  rS  r  r  r  r   r  s   &&      ry   r  r  	  s    }eT""g !%[1124 	 #CU#$$$'s*B4:CVCVBWX  c""		,%d+K!!**, 	

;! $" :  	,'s +!!%*  c"+	,s   %CC?#C::C?c               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   r   rn   )r   s   "ry   r   r   %
  s"      &  AW rx   c                v   V f   R# \        V \        4      '       g&   V R\        V 4      P                   2p\	        V4      h. p\        V 4       F]  w  rE\        V\        4      '       g)   V RV R\        V4      P                   2p\	        V4      hVP                  \        V4      4       K_  	  \        V4      # )aF  Parse the ``provides-extra`` body: the extras the override declares.

A TOML array of extra names, each normalised per PEP 685 like a parsed
``Provides-Extra``, so an extra compares equal regardless of spelling. A
present-but-empty list is stored as ``()`` (declares no extras), distinct
from the key being absent (``None``).
Nz3.provides-extra must be a list of extra names, got z.provides-extra[r  )
r  r   r  rq   r!   r  re   r   r   r   )r   r  rS  r  r  r  s   &&    ry   r  r  %
  s     }eT""g U$$%' 	 #CU#$$$')! -J''(*  c""

$T*+ $ :rx   c               $    V ^8  d   QhRRRRRR/# )r   r  r  r  re   r   r{   rn   )r   s   "ry   r   r   C
  s!        
 rx   c                   V P                  R4      pVe<   \        V\        4      '       g&   V R\        V4      P                   2p\        V4      hRV 9  d   V# Vf   V R2p\        V4      hV R,          p\        V\        4      '       g&   V R\        V4      P                   2p\        V4      hV'       g   V R2p\        V4      hV# )a  Parse the routing ``index`` body and validate its ``strict`` flag.

The route is always a strict pin to one index, so ``strict`` only
accepts ``true``.  ``strict = false`` is rejected: fallthrough on a
miss is not cleanly wireable through the single-index-pin router this
release ships.

The route-names-a-declared-index check is a resolve-path concern run
post-merge by :func:`_validate_routes_declared`, since this parser sees
the override surface in isolation from the ``indexes`` row.
r   z.index must be a string, got strictz5.strict is only meaningful alongside an 'index' routez.strict must be a boolean, got zn.strict = false (fallthrough routing) is not supported in this release; the index route is always a strict pin)rI  r  re   r  rq   r!   r   )r  r  r  rS  r*  s   &&   ry   r  r  C
  s     IIgEE3!7!74T%[5I5I4JK#u}LM#8_Ffd##6tF|7L7L6MN#g D D 	 #Lrx   c                    V ^8  d   QhRRRR/# )r   r   r  r   r7   rn   )r   s   "ry   r   r   e
  s     " "f " "rx   c                   \        V \        4      '       g$   R \        V 4      P                   2p\	        V4      h\        0 Rm4      p\        \        V 4      \        V4      ,
          4      pV'       d   RV: RV: 2p\	        V4      h\        RV P                  R4      \        \        P                  4      p\        RV P                  R. 4      4      p\        \        V4      \        4       ,
          4      pV'       d'   R	V: R
\        \        4       4      : 2p\	        V4      h\        RV P                  R. 4      4      pV F  p\        V4       K  	  V P                  RR4      p	\        V	\        4      '       g$   R\        V	4      P                   2p\	        V4      h\        V\!        V4      \#        V4      V	R7      # )z$[tool.nab.vcs] must be a table, got r   allowed-schemesallowed-reposrequire-pinzunknown [tool.nab.vcs] keys: rn  z
vcs.policyzvcs.allowed-schemeszunknown vcs.allowed-schemes: z; nab recognises zvcs.allowed-reposTz'vcs.require-pin must be a boolean, got )r   allowed_schemesallowed_reposrequire_pin>   r   r/  r.  r-  )r  r   r  rq   r!   r   r   rq  rI  r8   BLOCKr  r   _validate_allowed_repor   r7   r   r   )
r   rS  allowedr  r   r0  unknown_schemesr1  reporequire_pin_raws
   &         ry   
_parse_vcsr9  e
  s   eT""4T%[5I5I4JK#RSGSZ#g,./G-g[G;O#uyy':IyWF(uyy):B?O S14E4GGHO+O+> ?(*+.0 	 #&UYY;M t$ iit4Oot,,7_8M8V8V7WX#!/2M*#	 rx   c                    V ^8  d   QhRRRR/# )r   r7  re   r   rK  rn   )r   s   "ry   r   r   
  s     
( 
( 
( 
(rx   c                n     \        V 4       R#   \         d   pRT : RT 2p\        T4      ThRp?ii ; i)zReject an ``allowed-repos`` entry whose authority does not parse.

:func:`urlsplit` raises ValueError on an authority it cannot parse,
such as an unterminated IPv6 bracket.
zvcs.allowed-repos entry  does not parse: N)r   r  r!   )r7  r  rS  s   &  ry   r4  r4  
  s>    ( ((0A#G#C'(s    4/4c               (    V ^8  d   QhRRRRRRRR/# )	r   r  r  r  r  rd  rM   r   r4   rn   )r   s   "ry   r   r   
  s(     0 0v 0# 0 0+ 0rx   c                  \        V \        4      '       g'   R V R\        V 4      P                   2p\	        V4      h\        \        V 4      \        ,
          4      pV'       d&   RV RV: R\        \        4      : 2p\	        V4      h V R,          pV R,          p\        T\        4      '       d   \        T\        4      '       g   R T R	2p\	        T4      hT P                  R
R4      p\        T\        4      '       g   R T R2p\	        T4      hT P                  R4      p	T	e(   \        T	\        4      '       g   R T R2p\	        T4      hT	e'   \        T	4      '       d   R T RT	: R2p\	        T4      h\        Y&4      p
T
f   R T RT: R2p\	        T4      h\        T\        T
4      TT	R7      #   \         d   pR T RT: 2p\	        T4      RhRp?ii ; i)zlocal-sources[r  zunknown local-sources[r  rn  r   r`  r  Nz] name and path must be stringseditableFz] editable must be a booleansubdirectoryz] subdirectory must be a stringz] subdirectory z escapes the source treez] path z  is not a usable filesystem path)r   r`  r?  r@  )r  r   r  rq   r!   r   r   _LOCAL_SOURCE_KEYSr  re   rI  r   r   r/   r4   )r  r  rd  rS  r  r   
path_valuer  r?  r@  resolveds   &&$        ry   _parse_local_sourcerD  
  s   eT""qc!8e9M9M8NO#SZ"445G$QCx{ ; 2368 	 #)V}6]
 dC  
:s(C(Cqc!@A#yyU+Hh%%qc!=>#99^,L
<(E(Eqc!@A#$8$F$FQC|.>>VW 	 #M6Hqc6VW#]!	 7  )qc!8D#D()s   
F4 4G?GGc               $    V ^8  d   QhRRRRRR/# )r   r   r  rd  rM   r   r"  rn   )r   s   "ry   r   r   
  s$     	 		%)		rx   c                  a \        V \        4      '       g$   R \        V 4      P                   2p\	        V4      h\
        ;QJ d     . V3R l\        V 4       4       F  NK  	  5# ! V3R l\        V 4       4       4      # )z.local-sources must be an array of tables, got c              3  B   <"   T F  w  r\        W!SR 7      x  K  	  R# 5i))rd  N)rD  )r   r  r  rd  s   &  ry   r   '_parse_local_sources.<locals>.<genexpr>
  s$      (HA 	EMBB(r  )r  r   r  rq   r!   r   r  )r   rd  rS  s   &d ry   _parse_local_sourcesrI  
  sp     eT"">tE{?S?S>TU#5 !%(5 5 !%(  rx   c                    V ^8  d   QhRRRR/# )r   r   r  r   r$  rn   )r   s   "ry   r   r   
  s      f )> rx   c           	        \        V \        4      '       g$   R \        V 4      P                   2p\	        V4      h. p\        V 4       F  w  r4\        V\        4      '       g'   RV R\        V4      P                   2p\	        V4      h\        \        V4      \        ,
          4      pV'       d&   RV RV: R\        \        4      : 2p\	        V4      h VR,          pVR,          p\        T\        4      '       d   \        T\        4      '       g   RT R
2p\	        T4      hTP                  \        YgR7      4       K  	  \        V4      #   \         d   pRT RT: 2p\	        T4      R	hR	p?ii ; i)z,vcs-sources must be an array of tables, got zvcs-sources[r  zunknown vcs-sources[r  rn  r   r  r  Nr  r   r  )r  r   r  rq   r!   r  r   r   r   _VCS_SOURCE_KEYSr  re   r   r9   r   	r   rS  r  r  r  r  r   r  r  s	   &        ry   _parse_vcs_sourcesrO  
  sd   eT""<T%[=Q=Q<RS#Ce$%&& #:4;;O;O:PQCc""U&667&qc' =#$458:  c""	-=D,C $$$JsC,@,@ #ABCc""

9$01) %* :  	- #:7+FCc",	-s   EE3E..E3c                    V ^8  d   QhRRRR/# )r   r   r  r   r&  rn   )r   s   "ry   r   r   
  s      & -F rx   c           	        \        V \        4      '       g$   R \        V 4      P                   2p\	        V4      h. p\        V 4       EF  w  r4\        V\        4      '       g'   RV R\        V4      P                   2p\	        V4      h\        \        V4      \        ,
          4      pV'       d&   RV RV: R\        \        4      : 2p\	        V4      h VR,          pVR,          p\        T\        4      '       d   \        T\        4      '       g   RT R
2p\	        T4      h\        Y74       TP                  \        YgR7      4       EK  	  \        V4      #   \         d   pRT RT: 2p\	        T4      R	hR	p?ii ; i)z0archive-sources must be an array of tables, got archive-sources[r  zunknown archive-sources[r  rn  r   r  r  Nr  rL  )r  r   r  rq   r!   r  r   r   r   _ARCHIVE_SOURCE_KEYSr  re   _validate_archive_urlr   r0   r   rN  s	   &        ry   _parse_archive_sourcesrU  
  sm   eT""@eAUAU@VW#!Ce$%&&$QC'>tE{?S?S>TUCc""U&::;*1#Xg[ A#$89<>  c""	-=D,C $$$JsC,@,@$QC'EFCc""a%

=d45+ %, :  	-$QC'>wkJCc",	-s   EF &E;;F c               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   rK  rn   )r   s   "ry   r   r     s!     " " "3 "4 "rx   c                    \         P                  ! V4      pTP                  '       g   RT  RT: R2p\        T4      h \        TP                  4      P                  pTP                  R4      '       g   RT  RT: R2p\        T4      hR#   \         d   pRT  RT 2p\        T4      ThRp?ii ; i  \         d   pRT  RT: RT 2p\        T4      ThRp?ii ; i)	a  Reject an archive URL that is malformed, has no hash, or is not a .tar.gz.

PEP 751 ``packages.archive.hashes`` is required, so nab requires the
hash in the URL fragment and verifies the download against it.  Only
``.tar.gz`` source archives are supported today; wheels and zips are
refused loudly rather than mis-handled.  :func:`urlsplit` raises
ValueError on an authority it cannot parse, such as an unterminated
IPv6 bracket, so that surfaces as a ConfigError here too.
rR  z] url: Nz] url zO has no hash; add a '#sha256=<hex>' fragment (PEP 751 requires an archive hash)r<  z.tar.gzzE is not a .tar.gz archive; only .tar.gz source archives are supported)
r   parser   r!   has_usable_hashr   r  r`  r  endswith)r   r  requestr  rS  r`  s   &&    ry   rT  rT    s   ( &&s+
 """ugVC7 3K K 	 #($))
 ==##ugVC7 3: : 	 # $#  ( wse4#C'(  ( vcW4EcUK#C'(s/   B  B4 B1B,,B14C?CCc               (    V ^8  d   QhRRRRRRRR/# )	r   r#  r"  r%  r$  r'  r&  r   rK  rn   )r   s   "ry   r   r   ?  s0     & &*&&& /& 
	&rx   c                    / p. V OVOVO FU  p\        VP                  4      pWS9   d*   RV: RW5,          : RVP                  : 2p\        V4      hVP                  W5&   KW  	  R# )zReject a canonical name claimed by more than one declared source.

The provider enforces this while indexing, but as a bare ValueError raised
after the resolve starts; raising ConfigError here surfaces it at parse
time like every other config error.
zV[tool.nab] local-sources/vcs-sources/archive-sources declare duplicate canonical name z via rR  N)r   r   r!   )r#  r%  r'  r#  r  r1  rS  s   &&&    ry   r  r  ?  sw     DBMBKB/B%fkk2	--6Mt>Q( 
 c"" ++ Crx   c               $    V ^8  d   QhRRRRRR/# )r   r%  r$  r  r7   r   rK  rn   )r   s   "ry   r   r   W  s&      & 
rx   c                    V '       dG   VP                   \        P                  J d'   RVP                   P                  : R2p\	        V4      hR# R# )a  Reject vcs-sources declared while the VCS policy blocks cloning.

Cloning is opt-in, so a ``[[tool.nab.vcs-sources]]`` entry under the
default ``policy = "block"`` is contradictory. Raising ConfigError here
fails at parse time and names the token to set.

``policy = "allow"`` opens the gate but does not on its own admit a
URL: ``allowed-schemes`` and ``allowed-repos`` are empty by default
and each denies every URL until an entry is added, so the message
points at the whole gate rather than promising that one key is enough.
zB[[tool.nab.vcs-sources]] is declared but [tool.nab.vcs].policy is z, which refuses every clone; remove the sources, or set [tool.nab.vcs].policy = "allow" and open the rest of the gate (vcs.allowed-schemes and vcs.allowed-repos are empty by default and each denies every URL)N)r   r8   r3  r   r!   )r%  r  rS  s   && ry   r  r  W  sR     z((IOO;!!''* +;; 	 # <{rx   c                    V ^8  d   QhRRRR/# )r   r   r  r   zdict[str, str] | Nonern   )r   s   "ry   r   r   q  s       ,A rx   c                @   V f   R # \        V \        4      '       g$   R\        V 4      P                   2p\	        V4      h/ pV P                  4        F  w  r4\        V\        4      '       d   \        V\        4      '       g   RV: RV: 2p\	        V4      h \        V4      p\        V4      pTP                  R,          TP                  R,          8w  d   RT: RT: 2p\	        T4      hYBT&   K  	  V#   \         d   pRT: RT: 2p\	        T4      ThR p?ii ; i)NzDmatrix.python-patches must be a table of minor -> full version, got z<matrix.python-patches entries must be string -> string, got r  z3matrix.python-patches expects version strings, got :Nr   Nzmatrix.python-patches value z is not a patch release of )
r  r   r  rq   r!   r  re   r    r  r  )r   rS  r  r  r  minorfullr  s   &       ry   _parse_python_patchesrd  q  s,   }eT""U$$%' 	
 #C!S!!As););**+b7  c""	,AJE1:D
 <<u}}R0005PQRPUVCc""A# $ J  	,GuBqeTCc"+	,s   C77DDDc                    V ^8  d   QhRRRR/# )r   r   r  r   r,  rn   )r   s   "ry   r   r     s     , ,F ,'= ,rx   c                L   \        V \        4      '       g$   R\        V 4      P                   2p\	        V4      hR0p\        \        V 4      V,
          4      pV'       d   RV: R\        V4      : 2p\	        V4      h\        RV P                  R. 4      4      p\        VR7      # )aU  Parse the optional ``[tool.nab.workspace]`` table.

Schema today is a single ``members`` field listing literal paths.
Globs and member-existence checks happen in
:func:`nab_python.workspace.workspace_local_sources`; this layer only
validates the table shape so typos like ``member = ...`` (missing
the ``s``) fail loud at config-parse time.
z*[tool.nab.workspace] must be a table, got r   z#unknown [tool.nab.workspace] keys: rn  zworkspace.members)r   )
r  r   r  rq   r!   r   r   r  rI  rE   )r   rS  r5  r  r   s   &    ry   _parse_workspacerg    s     eT"":4;;O;O:PQ#kGSZ')*G1' =+- 	 # !4eii	26NOG7++rx   r   c                    V ^8  d   QhRRRR/# )r   r   r  r   r.  rn   )r   s   "ry   r   r     s      F '> rx   c                
   \        V \        4      '       g$   R\        V 4      P                   2p\	        V4      h\
        ;QJ d    . R \        V 4       4       F  NK  	  5M! R \        V 4       4       4      p\        V4       V# )a{  Parse the optional ``[tool.nab].conflicts`` array.

Each item is either a bare array of members (uv-compatible; the
members are mutually exclusive under the default at-most-one
policy) or a table ``{ members = [...], policy = "..." }`` whose
``policy`` value is ``at-most-one`` / ``exactly-one`` /
``at-least-one``.  A member is ``{ extra = "NAME" }`` or
``{ group = "NAME" }``.
z1conflicts must be an array of conflict sets, got c              3  <   "   T F  w  r\        W!4      x  K  	  R # 5ir   )_parse_conflict_set)r   r  r  s   &  ry   r   #_parse_conflicts.<locals>.<genexpr>  s     N=M'!$T--=Mr  )r  r   r  rq   r!   r   r  !_check_conflict_member_uniqueness)r   rS  setss   &  ry   _parse_conflictsro    sh     eT""A$u+BVBVAWX#5NYu=MN55NYu=MNND%d+Krx   c                    V ^8  d   QhRRRR/# )r   rn  r   r   rK  rn   )r   s   "ry   r   r     s      ,A d rx   c                    \        4       pV  F>  pVP                   F+  pW19   d   RV R2p\        V4      hVP                  V4       K-  	  K@  	  R# )z7Reject a member declared in more than one conflict set.zconflicts declares zF in more than one set; a member may belong to at most one conflict setN)r   r   r!   r   )rn  r#  r  r  rS  s   &    ry   rm  rm    sY     #D"**F~)& 2G G  "#&&HHV + rx   c               (    V ^8  d   QhRRRRRRRR/# )	r   r  r   r   r   r  r{   r   rK  rn   )r   s   "ry   r   r     s0     . .!.$. . 
	.rx   c                  a	a
 Vf   RM
\        V4      o
V  Uu0 uF  p\        V4      kK  	  upo	S
e   S	P                  S
4       \        V4       F  p\        V	3R lV 4       4      p\	        V4      \
        8  d   K.  S
V9   d'   RP                  V
3R lV 4       4      pRV RV: R2pMRP                  R V 4       4      pRV R	2p\        V4      h	  R# u upi )
aX  Reject a default install that co-activates an exclusive conflict set.

A default install activates every default group with no user
selection, but the emit-time disjointness validator prunes any
context that activates two members of an exclusive set, so it never
enumerates that install.  Two members co-active by default would
silently violate the declared conflict; catch it at parse time.

``base_group`` counts as a default: PEP 751 seeds ``dependency_groups``
from ``default-groups``, and the lock puts that name there so an
install asking for nothing still gets the project's own dependencies.
Nc              3     <"   T F3  w  rV\         P                  P                  8X  g   K&  VS9   g   K/  Vx  K5  	  R # 5ir   )rP   r   r   )r   r   r   rZ  s   &  ry   r   =_validate_default_groups_against_conflicts.<locals>.<genexpr>  s<      
#
|))/// 48FN D#s   #>>
>r   c              3  J   <"   T F  qS8w  g   K  \        V4      x  K  	  R # 5ir   rB  )r   r   r   s   & ry   r   ru    s     Vid:CUztDzzis   ##zdefault-groups activates z, and base-group z names the project's own dependencies, which every default install activates too; they are declared mutually exclusive in [tool.nab].conflicts, so an installer given no selection would install neitherc              3  8   "   T F  p\        V4      x  K  	  R # 5ir   rB  r?  s   & ry   r   ru    s     @idtDzzir   z?, which are declared mutually exclusive in [tool.nab].conflicts)r   r   r   r   r   r   r   r!   )r  r   r  r   rf  	co_activeothersrS  r   rZ  r   s   &&&      @@ry   r  r    s    " $+1B:1NJ,:;Nq"N;F

:*95 
#
 
	
 y>00"YYViVVF+F8 4> "<<  YY@i@@F+F8 4> >  #1 6	 <s   Cc               (    V ^8  d   QhRRRRRRRR/# )r   r   r   r  r{   r  r   rK  rn   )r   s   "ry   r   r     s0     =# =#$=#=# =# 
	=#rx   c                  aa W3 Uu0 uF  pVf   K	  \        V4      kK  	  upoV  EF  pVP                  pVP                  \        P                  J dI   \        V3R lV 4       4      pV'       d*   RP                  R V 4       4      pRV R2p\        V4      hKv  Vf   K|  \        V4      o\        ;QJ d    V3R lV 4       F  '       g   K   RM	  R	M! V3R lV 4       4      p	\        R
 V 4       4      p
V	'       g   K  V
'       g   K  RP                  R V
 4       4      pRV: RV R2p\        V4      h	  R# u upi )a  Reject the conflict sets a configured group name cannot mean.

A configured member is active on every run, so an at-least-one set
holding one can never fail and decides nothing.  A declaration that
decides nothing reads as one that took effect, so it is refused
rather than left to sit.

An exclusive set pairing ``base-group`` with an extra is worse than
inert.  A PEP 621 extra installs on top of the project's own
dependencies, and the extras axis never deselects a default group, so
the fork that chooses the extra describes an install context no
installer can produce.  ``build-group`` pairs with an extra fine: the
project's dependencies stay in every fork of that set.
Nc              3     <"   T FD  pVP                   \        P                  J g   K#  VP                  S9   g   K6  VP                  x  KF  	  R # 5ir   r   rP   r   r   )r   r  rL  s   & ry   r   5_validate_configured_conflict_sets.<locals>.<genexpr>  sA      %F;;,"4"44 9?9M %s    AAAr   c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   rB  r?  s   & ry   r   r~  #  s     "@%$4::%r   z[tool.nab].conflicts declares z in an at-least-one set, but a group named by base-group or build-group is active on every run, so the set can never fail and decides nothingc              3     <"   T F8  pVP                   \        P                  J ;'       d    VP                  S8H  x  K:  	  R # 5ir   r}  )r   r  canonical_bases   & ry   r   r~  0  s;      
! KK<---OO&++2OO!s
   'AATFc              3  x   "   T F0  qP                   \        P                  J g   K"  VP                  x  K2  	  R # 5ir   rH  )r   r  s   & ry   r   r~  4  s(      
&-F@R@R1RKFKKgs   ::c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   rB  r?  s   & ry   r   r~  8  s     =fdtDzzfr   z)[tool.nab].conflicts declares base-group z# mutually exclusive with the extra z~, but an extra installs on top of the project's own dependencies and never deselects them, so nothing could install that extra)	r   r   r   rR   r   r   r   r!   rP  )r   r  r  r   r  r   inertr   rS  
holds_mainr  r  rL  s   &&&        @@ry   r  r    sZ   *  --D 	 $-E
 "&&."="== % E
 "@%"@@4VH =' '  "#&&*:6S 
!
SSS 
!
 

  
&-
 
 :&&YY=f==F;J>5fX >GG  c""K "s
   D?D?c               $    V ^8  d   QhRRRRRR/# )r   r  r  r   r  r   rT   rn   )r   s   "ry   r   r   B  s!      f S [ rx   c                :   R V R2p\        V \        4      '       d%   \        \        W4      \        P
                  R7      # \        V \        4      '       d   \        \        V 4      \        ,
          4      pV'       d(   \        \        4      pV RV: RV: R2p\        V4      hRV 9  d   V R2p\        V4      h\        V P                  R4      V4      p\        \        V R,          V R	24      VR7      # V R
\        V 4      P                   2p\        V4      h)z
conflicts[r  )r   r   z: unknown conflict-set key(s) zJ; expected a table { members = [...], policy = '...' } with policy one of z, or a bare array of membersr   z): a conflict-set table must set 'members'r   z.membersz: must be an array of members or a conflict-set table, got )r  r   rT   _parse_conflict_membersrR   r   r   r   r   _CONFLICT_SET_KEYS_CONFLICT_POLICY_VALUESr!   _parse_conflict_policyrI  r  rq   )r  r   r  r  r  rS  r   s   &&     ry   rk  rk  B  s*   q!E$+D8!--
 	
 $T%77823E'7{ C98: 
 c""D GDECc""'(:EB+DOwh=OP
 	

 ' J 	"  c
rx   c               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   rR   rn   )r   s   "ry   r   r   b  s!      &   rx   c                "   V f   \         P                  # \        V \        4      '       g&   V R\	        V 4      P
                   2p\        V4      h\        P                  V 4      pVf'   \        \        4      pV RV: RV : 2p\        V4      hV# )zHParse the ``policy`` value of a conflict-set table; default at-most-one.z.policy must be a string, got z.policy must be one of r	  )
rR   r   r  re   r  rq   r!   r  rI  r   )r   r  rS  r   r  s   &&   ry   r  r  b  s    })))eS!!5d5k6J6J5KL#$((/F~./.uiveYG#Mrx   c               $    V ^8  d   QhRRRRRR/# )r   r   r  r  re   r   r   rn   )r   s   "ry   r   r   q  s"      6 # :T rx   c                  a \        V \        4      '       g&   S R \        V 4      P                   2p\	        V4      h\
        ;QJ d     . V3R l\        V 4       4       F  NK  	  5M! V3R l\        V 4       4       4      p\        V4      \        8  d#   S R\         R\        V4       2p\	        V4      h\        \        V4      4      \        V4      8w  d   S R2p\	        V4      hV# )z" must be an array of members, got c              3  L   <"   T F  w  r\        VS R V R24      x  K  	  R# 5i)r  r  N)_parse_conflict_member)r   r  r  r  s   &  ry   r   *_parse_conflict_members.<locals>.<genexpr>u  s.      EU'!twas!_55EUs   !$z must list at least z members to be a conflict; got z lists a member more than once)
r  r   r  rq   r!   r   r  r   _MIN_CONFLICT_MEMBERSr   )r   r  rS  r   s   &f  ry   r  r  q  s    eT""9$u+:N:N9OP#e ENuEUee ENuEU G 7|++g)*?)@ A  #G~/ 	 #
3w<CL(56#Nrx   c               $    V ^8  d   QhRRRRRR/# )r   r  r  r  re   r   rQ   rn   )r   s   "ry   r   r     s!     5 5 5 5 5rx   c           	     L   \        V \        4      '       g&   V R \        V 4      P                   2p\	        V4      h\
         Uu0 uF  q3P                  kK  	  pp\        \        V 4      V,
          4      pV'       d!   V RV: R\        V4      : 2p\	        V4      h\        \        V 4      V,          4      p\        V4      ^8w  d!   V R\        V4      : RV: 2p\	        V4      h\        V^ ,          4      pW^ ,          ,          p\        V\        4      '       d	   V'       g!   V RVP                   RV: 2p\	        V4      h \        VRR7      p	\        YyR7      # u upi   \         d3    \        T4      p	T RTP                   R	T: R
T	: R2p\	        T4      Rhi ; i)z9 must be a table { extra = ... } or { group = ... }, got z: unknown member key(s) rn  z must name exactly one of r	  r  z! must be a non-empty string, got Tr,  z" is not a valid extra/group name: z (canonicalises to r   N)r   r   )r  r   r  rq   r!   rP   r   r   r   r   re   r   r   rQ   )
r  r  rS  r  kindsr  r  r   r   r1  s
   &&        ry   r  r    s   dD!!g J''(* 	 #*+lWWlE+SY&'G/{+fUmEVW#SY&'G
7|q1&-1B&T#
#D
DdC  q$EdXN#)%dT:	 t44/ ,   )%d+	gQtzzl"DTH!)a1 	 #D()s   E!E& &=F#c                    V ^8  d   QhRRRR/# )r   r  re   r   rK  rn   )r   s   "ry   r   r     s      #  ##  #$  #rx   c                    \        V 4      pT F  p \        TP                  P                  R4      4      pTP                  ^ 8g  TP                  RJTP                  RJTP                  RJTP                  RJ3p\        TP                  4      \        8  g   \        T4      '       g   K  RT R2p\        T4      h	  R#   \         d   pRT : 2p\        T4      ThRp?ii ; i  \         d   pRT R2p\        T4      ThRp?ii ; i)zReject a matrix.python axis finer than major.minor.

The axis lists language (minor) Python versions; patch pins belong in
[tool.nab.matrix.python-patches].
z/matrix.python must be a PEP 440 specifier, got Nz.*zmatrix.python clause z is not a valid versionz7matrix.python axis is a language (minor) version only; zS is finer than major.minor. Put patch versions in [tool.nab.matrix.python-patches].)r   r   r!   r    versionremovesuffixr  epochprepostdevlocalr   r  _MINOR_RELEASE_PARTSrP  )r  specifier_setr  rS  clauser  finers   &      ry   _validate_matrix_pythonr    s   ($T*  	,fnn99$?@G MMQKKt#LL$KKt#MM%
 w"66#e**I( 44 
 c""+    (?xH#C'(  	,)&1HICc"+	,s.   C $C&C#CC#&D1DDlibcruns-on-libcruns-on-macoslinuxmacoszMapping[str, frozenset[str]]_PLATFORM_KNOB_OWNERc                    V ^8  d   QhRRRR/# )r   r   r  r   rg   rn   )r   s   "ry   r   r     s      6 .F rx   c                   \        V \        4      '       g$   R\        V 4      P                   2p\	        V4      h. p\        V 4       F  w  r4RV R2p\        V\        4      '       d   VP                  \        WTR7      4       K>  \        V\        4      '       d   VP                  \        WT4      4       Kp  V R\        V4      P                   2p\	        V4      h	  \        V4      # )aC  Parse ``matrix.platforms``: bare ids, tables, or a mix of both.

A bare id takes the platform's default tag knobs; the table form declares
them (libc family, the libc and macOS the lock must run on, kernel
marker values, free-threaded build).  Both become a :class:`PlatformSpec`,
so everything downstream reads one shape.
z%matrix.platforms must be a list, got zmatrix.platforms[r  r  r  )r  r   r  rq   r!   r  re   r   r  r   r  r   )r   rS  rh   r  r  r  s   &     ry   _parse_matrix_platformsr    s     eT""5d5k6J6J5KL#$&IU##A3a(dC  ^EDEd##25?@GB4:CVCVBWXCc"" $ rx   c               $    V ^8  d   QhRRRRRR/# )r   r  re   knobsr   r   r=   rn   )r   s   "ry   r   r     s!     ( (# ( ( (rx   c                h     \        R/ VB #   \         d   pRT  RT 2p\        T4      ThRp?ii ; i)zJBuild a :class:`PlatformSpec`, reporting its knob check as a config error.zinvalid r  Nrn   )r=   r  r!   )r  r  r  rS  s   &,  ry   r  r    sD    ($e$$ (r#'#C'(s   
 1,1c               $    V ^8  d   QhRRRRRR/# )r   r  re   r   r  r   r=   rn   )r   s   "ry   r   r      s!     # # #^ # #rx   c                   \        \        V4      \        ,
          4      pV'       d&   RV  RV: R\        \        4      : 2p\        V4      hRV9  d   V  R2p\        V4      h\	        V  R2VR,          4      p\        WV4       \        V V\        V  R2VP                  R4      4      \        V  R	2VP                  R
4      4      \        V  R2VP                  R4      4      \	        V  R2VP                  RR4      4      \	        V  R2VP                  RR4      4      \        V  R2VP                  R4      RR7      R7      # )zHParse one ``matrix.platforms`` table entry into a :class:`PlatformSpec`.zunknown z keys: rn  r  z missing required key 'id'z.idz.libcr  z.runs-on-libcr  z.runs-on-macosr  z.platform-releaser  r   z.platform-versionr  z.free-threadedfree-threadedFrp  )r  r  runs_on_libcruns_on_macosr]   r^   free_threaded)r   r   _PLATFORM_TABLE_KEYSr!   r(  _reject_foreign_knobsr  _parse_libcrI  _parse_major_minorrs  )r  r   r  rS  r  s   &&   ry   r  r     s]   SZ"667GugWWK 0 458: 	 #512#%smU4[AK%4E7%%))F*;<'g]#UYY~%>
 )g^$eii&@
 -g&'3Er)J
 -g&'3Er)J
 "g^$eii&@%
! rx   c               (    V ^8  d   QhRRRRRRRR/# )r   r  re   r   r  r  r   rK  rn   )r   s   "ry   r   r   &  s)     # # #^ ## #RV #rx   c                    \        V4      pVf   R# \        P                  4        FJ  w  rEW48X  d   K  \        V\	        V4      ,          4      pV'       g   K2  V  RV: RV RV: 2p\        V4      h	  R# )am  Reject a knob key the declared platform's kind cannot read.

:class:`PlatformSpec` refuses a knob whose *value* moves a platform that
ignores it, but it cannot see a key written at its own default.  The
table can, and a key that selects no wheel is a mistake either way.  An
unknown ``platform_id`` is left to the matrix, which names the whole
unknown set at once.
Nz
 declares z, which only a z platform reads, but its id is )r>   r  r  r   r   r!   )r  r   r  r   ownerkeysforeignrS  s   &&&     ry   r  r  &  s~     %D|+113=E
*+7'G;oeW E))49  c"" 4rx   c               $    V ^8  d   QhRRRRRR/# )r   r  re   r   r  r   r<   rn   )r   s   "ry   r   r   >  s!      S  D rx   c                    Vf   \         # \        W4      pV\        9  d%   V  R\        \        4      : RV: 2p\	        V4      h\        RV4      # )zAParse a libc family name; an absent key takes the default family.r}  r	  r<   )r:   r(  r;   r   r!   r   )r  r   textrS  s   &&  ry   r  r  >  sT    }s*D:%fZ&8%;6$J#rx   c               $    V ^8  d   QhRRRRRR/# )r   r  re   r   r  r   ztuple[int, int] | Nonern   )r   s   "ry   r   r   I  s"     $ $C $ $3I $rx   c                f   Vf   R# \        W4      p \        V4      pTP                  p\        T4      \        8H  pT'       d$   \        T4      T^ ,           RT^,           28w  d   T  RT: 2p\        T4      hT^ ,          T^,          3#   \         d   pT  RT: 2p\        T4      ThRp?ii ; i)zDParse a ``major.minor`` string into a pair; ``None`` passes through.Nz& must be a 'major.minor' version, got r  z$ must be exactly 'major.minor', got )r(  r    r  r!   r  r   r  re   )r  r   r  r  r  rS  r  two_parts   &&      ry   r  r  I  s    }s*D($- ooG7|33H s7|'!*Qwqzl'CC9$B#AJ
##  (;D8D#C'(s   B B0B++B0c                    V ^8  d   QhRRRR/# )r   r   r  r   r(  rn   )r   s   "ry   r   r   h  s     - - -$7 -rx   c                   \        V \        4      '       g$   R \        V 4      P                   2p\	        V4      h\        \        V 4      \        ,
          4      pV'       d#   RV: R\        \        4      : 2p\	        V4      h V R,          pV R,          p\        T\        4      '       g   Rp\	        T4      h\        T4       \        T4      pT'       g   Rp\	        T4      h\        R	\        ;QJ d    . R
 T 4       F  NK  	  5M! R
 T 4       4      4       \        RT P                  RR4      4      pTR9  d   RT: 2p\	        T4      h\!        T P                  R4      4      p\#        T P                  R4      4      p	\%        TTTTT	R7      p
\'        T
4       T
#   \         d   pRT: 2p\	        T4      RhRp?ii ; i)z'[tool.nab.matrix] must be a table, got z unknown [tool.nab.matrix] keys: rn  rf   rh   z'[tool.nab.matrix] missing required key Nz0matrix.python must be a string PEP 440 specifierz3matrix.platforms must list at least one platform idzmatrix.platformsc              3  8   "   T F  qP                   x  K  	  R # 5ir   r  )r   ps   & ry   r    _parse_matrix.<locals>.<genexpr>  s     0R	1	r   zmatrix.python-orderpython-orderri   z1matrix.python-order must be 'asc' or 'desc', got python-patchesrm   r  >   ri   desc)r  r   r  rq   r!   r   r   _MATRIX_KEYSr  re   r  r  r$  r   r(  rI  rd  _parse_implementationsrW   _validate_matrix_axes)r   rS  r  rf   platforms_rawr  rh   rj   patchesrm   r<  s   &          ry   _parse_matrixr  h  s   eT""7U8L8L7MN#SZ,./G.wk :-02 	 #)xk* fc""@#F#'6IC# )550R	0R550R	0R+RS&uyy?L ?*A,AQR##EII.>$?@G,UYY7H-IJO!'F &!M?  )7{C#D()s   F G*F<<Gc                    V ^8  d   QhRRRR/# )r   r<  rW   r   rK  rn   )r   s   "ry   r   r     s     ( (, (4 (rx   c                    \        V 4      p VP                  4        R#   \         d   pRT 2p\        T4      ThRp?ii ; i)z:Expand the matrix eagerly to catch bad axes at parse time.zinvalid [tool.nab.matrix]: N)r  r  r  r!   )r<  r)  r  rS  s   &   ry   r  r    sC    'F( (+C51#C'(s    A ;A c                    V ^8  d   QhRRRR/# r  rn   )r   s   "ry   r   r     s      & _ rx   c                   V f   R# \        RV 4      pV'       g   Rp\        V4      h\        RV4       \        \	        V4      \	        \
        4      ,
          4      pV'       d#   RV: R\        \
        4      : 2p\        V4      hV# )Nzmatrix.implementationsz<matrix.implementations must list at least one implementationz unknown matrix.implementations: rn  ro   )r  r!   r$  r   r   r  r   )r   implsrS  r  s   &   ry   r  r    s    }7?EL#/7SZ#&<"==>G.wk :3479 	 #Lrx   )r!   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r6   rA  r   r  r   r  r_  r\  r  r  rz  r[  rT  r  >   os_namer[   r_   platform_systemr\   r]   r^   implementation_namer`   implementation_versionplatform_python_implementation)rn   >   rf   r|   r}   )r`   r_   )r  r  )r[   r\   )r  r  >   r  r   r  >   r   r*  r   r~  r  r  ra   r  >   r~  r  r  r  >   r!  r  r  r	  r*  prereleases))r~  r   )ro  r   )r  r   )r  r   )r   r   )r   r   )ra   r   )r  r   >   r   r`  r?  r@  r   >   r  r  r  r  r  r  r  >   rf   rh   rm   r  r  )rp   pypy(  __conditional_annotations__ru   
__future__r   enumr   loggingrecollectionsr   dataclassesr   r   r   r   r   r	   typesr
   typingr   r   r   urllib.parser   r  typing_extensionsr   nab_index.archiver   r   nab_index.local_indexr   nab_index.multi_indexr   nab_index.serializationr   nab_index.subdirr   _conflict_kindr   r   _iso8601r   _tomlr   _vcs_admissionr   _vendor.packaging.requirementsr   _vendor.packaging.specifiersr   r   _vendor.packaging.utilsr   r   _vendor.packaging.versionr    config_sourcesr!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   fetchr,   r-   r.   pathsr/   providerr0   r1   r2   r3   r4   r5   r6   r7   r8   r9   tagsr:   r;   r<   r=   r>   r  r?   r@   rA   rB   rC   rD   r-  rE   rF   rG   rH   rI   collections.abcrJ   rK   rL   AbstractSetpathlibrM   _vendor.packaging.rangesrN   __all__compilerd  r   r  r  r  r6  r  rW   rU   EnumrR   rP   rQ   rT   r   r   rO   rZ   rV   r   r  rX   rA  rS   rY   r   rT  r[  rz  ro  r  r  	getLoggerrq   r  rs  rm  r  r  r  r  r  r  r  r  r  r  r
  r  r  r   r$  r(  r2  r6  r9  rp  rq  rr  rn  r\  r_  rj  rr  ru  rs  rq  r  r  r  r  r  r  r  r  r  r  r  r  rv   r  r  r  r  r  r  r  r  r  r
  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r9  r4  rA  rD  rI  rM  rO  rS  rU  rT  r  r  rd  rg  r  r   r  r  ro  rm  r  r  rk  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  )r  markersr  r  s   000@ry   <module>r     s   #    	 # 1 1 2 2 " + + !  & A - - 7 1 2 ( # - 7 H C .    E D    N M   126> JJ|,  % " &'79N&OP   
 . 6  $d#4 4 $4 $d#& & $&&"TYY ""499  $d#2 2 $2$ $d#
1 
1 $
1(  $d#* * $*( $d#,9 ,9 $,9^ $d#, , $,.  R Rj $d#4N 4N $4Nn
[ K ("*J.>T  $T #	T
 /3TnJ
 +/JZ#,#& 

H
%%P!H"J@*<(.
G2j62j/d	(
0  2B6+\>" 2j $X/F$GH B(&> FG : "N @ W <  !?  **  !1 6 6 87 8 ^g&89:KG 87 3 Zz2'T 89-` (	  y),GG  P 
 $H 	 0f2N:L^.+:/GK(88v
U+\.
(")X<D"J
( KL 0f	 fe_- : !&%1 <"J&04@,6  /=>~!77A:~> 	845 $. .b=#@@&5B   #F !
  6FFN34O,-6 2  0( (# #L# #0 $ $( - -`( ( -  U47d$ ?s   X/6X5