+
    2j                      R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIHtH	t	 ^ RI
HtHt ^ RIHt ^ RIHt ^ RIHtHtHtHt ^ RIHtHtHt ^ R	IHtHt ^ R
IHtH t  ^ RI!H"t"H#t#H$t$ ^ RI%H&t&H't' ^ RI(H)t) ^ RI*H+t+H,t, ^RI-Ht ]'       d   ^ RI.H/t/H0t0H1t1 ^ RI2H3t3 . R+Ot4Rt5Rt6^
t7R,t8]'       d   ^ RI9H:t: ^ RI*H;t; ]Px                  ! ]=4      t> ! R R]P~                  4      t@]! RRR7       ! R R4      4       tAR R  ltB]! RRR7       ! R! R4      4       tC] ! R" R4      4       tD] ! R# R$4      4       tER% R& ltFR' R( ltG ! R) R4      tH]C]I]C,          ,          R,          tJ ! R* R4      tKR# )-a  Channel-based async I/O coordinator for nab-python.

Mirrors uv's architecture: a sync resolver on the main thread sends
fetch requests through a queue to an async fetcher on a background
thread. An InMemoryIndex is shared state between both.

The cross-thread bridge is built from the standard library only:
the fetcher thread owns an ``asyncio.Queue`` and the sync side
schedules puts on the loop with ``call_soon_threadsafe``.
)annotationsN)	dataclassfield)TYPE_CHECKINGAny)urlsplit)canonicalize_name)CacheBackend	NullCacheOfflineErrorOnDiskCache)CachedAsyncSimpleClientParsedCacheStatsread_fresh_parsed_listing)	SdistFile	WheelFile)RangeCapabilityMemoRangeOutcome)LocalIndexClientis_file_urlparse_file_url)IndexConfigMultiIndexClient)SimpleSerialization)IDENTITY_HEADERSraise_unless_ok)CallableMappingSequence)SelfFetchCoordinator	FetchKindFetchRequestInMemoryIndex
IndexRouteWarmSyncStatspypizhttps://pypi.org/simple/)Path)AsyncHttpTransportc                  2    ] tR t^MtRtRtRtRtRtRt	Rt
RtR	# )
r!   z;Distinguishes the kinds of fetches the coordinator handles.listingmetadatazrange-metadatasdistzsdist-archivezdirect-archive N)__name__
__module____qualname____firstlineno____doc__LISTINGMETADATARANGE_METADATASDISTSDIST_ARCHIVEDIRECT_ARCHIVE__static_attributes__r-       [/home/user/billing-ledger-validation/.venv/lib/python3.14/site-packages/nab_python/fetch.pyr!   r!   M   s#    EGH%NE#M%Nr:   T)frozenslotsc                  0    ] tR t^Xt$ RtR]R&   R]R&   RtR# )r$   a  Per-package index routing rule (a strict pin to one index).

``name`` is the package name (canonicalised internally).  ``index``
is the *name* of an :class:`IndexConfig` declared in the
coordinator's ordered list.  Routing decides where to fetch a
package's listing before any version is known, so a route carries no
version scope and no marker; the override layer guarantees at most one
route per package.
strnameindexr-   N)r.   r/   r0   r1   r2   __annotations__r9   r-   r:   r;   r$   r$   X   s     IJr:   c                    V ^8  d   QhRRRR/# )   routeszlist[IndexRoute]returnzdict[str, str]r-   )formats   "r;   __annotate__rH   h   s     L L, L Lr:   c                l    V  Uu/ uF#  p\        VP                  4      VP                  bK%  	  up# u upi )zReduce routes to ``{canonical_name: index_name}``.

At most one route exists per package (the override layer rejects two
routes for one name at parse time), so this is a straight projection.
)r   r@   rA   )rE   entrys   & r;   _resolve_routesrK   h   s1     EKKF5ejj)5;;6FKKKs   )1c                  v    ] tR t^qt$ Rt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"   z@A single fetch request, carried across the sync->async boundary.r!   kindr?   packageN
str | Noneversionurltuple[str, str] | Nonemetadata_hashtuple[tuple[str, str], ...]sdist_hasheswheel_hashesr-   )r.   r/   r0   r1   r2   rB   rP   rQ   rS   rU   rV   r9   r-   r:   r;   r"   r"   q   sD    J
OLGZC,0M)002L-202L-2r:   c                  ~    ] tR t^~t$ Rt^ tR]R&   ^ tR]R&   ^ tR]R&   ^ t	R]R&   ^ t
R]R&   ^ tR]R&   ^ tR]R	&   R
tR# )r%   zCounters for the synchronous warm-hit listing path.

A sync hit bumps ``listing_hits``; a decline bumps ``listing_declines`` and
one reason sub-counter, then runs the async path. Written only from the main
resolver thread, so the counters need no lock.
intlisting_hitslisting_declinesdeclined_ineligibledeclined_no_policydeclined_stale_onlinedeclined_no_blobdeclined_small_blobr-   N)r.   r/   r0   r1   r2   rY   rB   rZ   r[   r\   r]   r^   r_   r9   r-   r:   r;   r%   r%   ~   sW     L#c  !"3" c  r:   c                  V    ] tR t^t$ ]! ]P                  R7      tR]R&   Rt	R]R&   Rt
R# )_Pending)default_factorythreading.EventeventNr   resultr-   )r.   r/   r0   r1   r   	threadingEventrd   rB   re   r9   r-   r:   r;   ra   ra      s    "9??CE?CFCr:   ra   c               (    V ^8  d   QhRRRRRRRR/# rD   rN   r?   rP   metadata_urlrO   rF   r-   )rG   s   "r;   rH   rH      s(     : :3 : :J :3 :r:   c                    RV  RV RV 2# )zReturn the pending key for one sidecar fetch.

The URL is in the key so two wheels of a version do not share a request:
a waiter is released by the artifact it asked for.
z	metadata::r-   )rN   rP   rj   s   &&&r;   _metadata_keyrm      s     wiq	<.99r:   c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   	wheel_urlrF   r-   )rG   s   "r;   rH   rH      s(     4 4 4c 4c 4c 4r:   c                    RV  RV RV 2# )a  Return the pending key for one range read.

The wheel URL is in the key so sibling sidecar-less wheels of a version do
not share a request: sibling wheels can declare different dependencies, so a
waiter is released by the wheel it asked for, matching the sidecar path.
zrange:rl   r-   )rN   rP   ro   s   &&&r;   
_range_keyrq      s     G9AgYa	{33r:   c                     ] tR t^tRtR R ltR R ltRRRR/R	 R
 lltR R ltR R lt	R R lt
R R ltR R ltR R ltR R ltRUR R lltRUR R lltRUR R lltR  R! ltRUR" R# lltRUR$ R% lltRUR& R' lltR( R) ltR* R+ ltR, R- ltR. R/ ltR0 R1 ltR2 R3 ltR4 R5 ltR6 R7 ltR8 R9 ltR: R; ltR< R= lt R> R? lt!R@ RA lt"RB RC lt#RD RE lt$RF RG lt%RH RI lt&RJ RK lt'RL RM lt(RN RO lt)RP RQ lt*RR RS lt+RTt,R# )Vr#   zgThread-safe storage for fetched package data.

The async fetcher writes here; the sync provider reads.
c                   V ^8  d   QhRR/# rD   rF   Noner-   )rG   s   "r;   rH   InMemoryIndex.__annotate__   s     0G 0G$ 0Gr:   c                x   \         P                  ! 4       V n        / V n        / V n        / V n        \        4       V n        \        4       V n        / V n	        / V n
        \        4       V n        \        4       V n        \        4       V n        / V n        / V n        / V n        / V n        / V n        / V n        / V n        R# )zCreate an empty index.N)rf   Lock_lock	_listings_listing_errors_listing_indexesset_offline_listing_misses_unreadable_only_listings	_metadata_metadata_errors_offline_metadata_misses_offline_metadata_warned_metadata_from_sdist_sdist_pyproject_sdist_archives_sdist_archive_errors_range_outcomes_pending_parsed_metadata_resolved_sdist_metadataselfs   &r;   __init__InMemoryIndex.__init__   s    ^^%
AC9;0214$365& IKRT DG5%25%% ;>%!CEDFKM"
 JL-/ IK EG%r:   c                    V ^8  d   QhRRRR/# rD   rN   r?   rF   z"list[WheelFile | SdistFile] | Noner-   )rG   s   "r;   rH   rv      s     / /3 /+M /r:   c                    V P                   ;_uu_ 4        V P                  P                  V4      uuRRR4       #   + '       g   i     R# ; i)z7Return the cached listing for ``package``, or ``None``.N)ry   rz   getr   rN   s   &&r;   get_listingInMemoryIndex.get_listing   s)    ZZZ>>%%g. ZZZ	   ;A	offline_missFunreadable_onlyc          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
rD   rN   r?   dataSequence[WheelFile | SdistFile]r   boolr   rF   ru   r-   )rG   s   "r;   rH   rv      s<          . 
     
 r:   c                  RV 2p\        V4      pV P                  ;_uu_ 4        W`P                  V&   V'       d   V P                  P	                  V4       V'       d   V P
                  P	                  V4       V P                  P                  V4      pRRR4       Xe#   Wgn        VP                  P                  4        R# R#   + '       g   i     L8; i)a  Cache the listing for ``package`` and unblock any waiter.

``data`` is accepted as a Sequence (covariant) so callers can pass
homogeneous ``list[WheelFile]`` lists; it is materialised into the
internal ``list[WheelFile | SdistFile]`` cache.

``offline_miss`` marks the empty listing as an index skipped offline
rather than one that served no files.  ``unreadable_only`` marks it
as a page whose every file is in a format nab does not read.
listing:N)listry   rz   r~   addr   r   r   re   rd   r}   )r   rN   r   r   r   keymaterialisedpendings   &&&$$   r;   store_listingInMemoryIndex.store_listing   s    $ 	"DzZZZ&2NN7#,,009..227;mm'',G  )NMM  Zs   9C6CC	c                    V ^8  d   QhRRRR/# rD   rN   r?   rF   r   r-   )rG   s   "r;   rH   rv     s     ; ;s ;t ;r:   c                    V P                   ;_uu_ 4        WP                  9   uuRRR4       #   + '       g   i     R# ; i)zBWhether ``package``'s empty listing is an offline cold-cache miss.N)ry   r~   r   s   &&r;   is_offline_listing_miss%InMemoryIndex.is_offline_listing_miss  s#    ZZZ::: ZZZ   .?	c                    V ^8  d   QhRRRR/# r   r-   )rG   s   "r;   rH   rv     s     = =# =$ =r:   c                    V P                   ;_uu_ 4        WP                  9   uuRRR4       #   + '       g   i     R# ; i)zAWhether ``package``'s empty listing held only unreadable formats.N)ry   r   r   s   &&r;   is_unreadable_only_listing(InMemoryIndex.is_unreadable_only_listing  s#    ZZZ<<< ZZZr   c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   errorBaseExceptionrF   ru   r-   )rG   s   "r;   rH   rv     s!        3  }    r:   c                   RV 2pV P                   ;_uu_ 4        W P                  V&   V P                  P                  V4      pRRR4       Xe   VP                  P                  4        R# R#   + '       g   i     L2; i)a+  Record a failed listing fetch and unblock any waiter.

Distinct from ``store_listing([])``: an empty listing means the
index served nothing nab could read, while an error means the fetch
itself failed. ``fetch_versions`` re-raises the error instead of
reporting the package as having no candidates.
r   N)ry   r{   r   r   rd   r}   )r   rN   r   r   r   s   &&&  r;   store_listing_error!InMemoryIndex.store_listing_error  se     	"ZZZ,1  )mm'',G  MM  Zs   *A..A>	c                    V ^8  d   QhRRRR/# )rD   rN   r?   rF   BaseException | Noner-   )rG   s   "r;   rH   rv      s     5 5 51E 5r:   c                    V P                   ;_uu_ 4        V P                  P                  V4      uuRRR4       #   + '       g   i     R# ; i)zEReturn the recorded listing fetch error for ``package``, or ``None``.N)ry   r{   r   r   s   &&r;   get_listing_errorInMemoryIndex.get_listing_error   s+    ZZZ''++G4 ZZZr   c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   
index_namerF   ru   r-   )rG   s   "r;   rH   rv   %  s!     8 83 8C 8D 8r:   c                    V P                   ;_uu_ 4        W P                  V&   RRR4       R#   + '       g   i     R# ; i)z1Record which configured index served ``package``.N)ry   r|   )r   rN   r   s   &&&r;   store_listing_index!InMemoryIndex.store_listing_index%  s%    ZZZ-7!!'* ZZZs   .?	c                    V ^8  d   QhRRRR/# )rD   rN   r?   rF   rO   r-   )rG   s   "r;   rH   rv   *  s     6 6 6 6r:   c                    V P                   ;_uu_ 4        V P                  P                  V4      uuRRR4       #   + '       g   i     R# ; i)zFReturn the configured index name that served ``package``, or ``None``.N)ry   r|   r   r   s   &&r;   get_listing_indexInMemoryIndex.get_listing_index*  s+    ZZZ((,,W5 ZZZr   c               (    V ^8  d   QhRRRRRRRR/# rD   rN   r?   rP   rj   rO   rF   ztuple[str | None, bool]r-   )rG   s   "r;   rH   rv   /  s2     P PP%(P8BP	 Pr:   c                    VeE   WV3pW@P                   9   d   V P                   V,          pVe   VR3# MW3V P                  9   d   R# V P                   P                  WR34      pWaV3V P                  9   3# )a  Return the text answering for ``metadata_url`` and its origin.

Caller holds the lock.  The artifact's own slot wins, then the
version-level one.  An sdist's PKG-INFO answers for an artifact whose
own read returned nothing, but not for one nobody has read yet:
lending it there would give a wheel that declares its own dependencies
the sdist's.  An injected override has no artifact behind it and
answers for any.
NF)NF)r   r   r   )r   rN   rP   rj   slottextversion_levels   &&&&   r;   _read_metadataInMemoryIndex._read_metadata/  s     #l3D~~%~~d+# %=( $#t'@'@@$$**Gd+CD1T5N5NNOOr:   Nc               (    V ^8  d   QhRRRRRRRR/# ri   r-   )rG   s   "r;   rH   rv   F  s2     J JJ%(J8BJ	Jr:   c                    V P                   ;_uu_ 4        V P                  WV4      ^ ,          uuRRR4       #   + '       g   i     R# ; i)z;Return cached metadata text, or ``None`` if not yet stored.Nry   r   r   rN   rP   rj   s   &&&&r;   get_metadataInMemoryIndex.get_metadataF  s.     ZZZ&&wFqI ZZZs	   9A
	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   rj   rO   rF   r   r-   )rG   s   "r;   rH   rv   M  s,      %(8B	r:   c                   V P                   ;_uu_ 4        Ve   WV3V P                  9   d    RRR4       R# WR3V P                  9   ;'       d    VRJ ;'       g    W3V P                  9  uuRRR4       #   + '       g   i     R# ; i)a  Return ``True`` once a fetch answering for ``metadata_url`` resolved.

Any value counts, including the ``None`` of a sidecar that was not
served.  It tracks :meth:`_read_metadata`, so a fetch skipped on the
strength of it leaves the reader the same text a fetch would have.
NT)ry   r   r   r   s   &&&&r;   has_metadataInMemoryIndex.has_metadataM  s|     ZZZ(|4F Z d+t~~=  $ G G%T-F-FF ZZZs   A7A7A7A77B	c               (    V ^8  d   QhRRRRRRRR/# r   r-   )rG   s   "r;   rH   rv   a  s2     
G 
G
G%(
G8B
G	 
Gr:   c                    V P                   ;_uu_ 4        V P                  WV4      uuRRR4       #   + '       g   i     R# ; i)a  Return the metadata text for ``metadata_url`` and its sdist origin.

A wheel's METADATA and an sdist's PKG-INFO can both stand for one
version, and only sdist text goes through the :pep:`643` dynamic-deps
gate, so text and origin are read together under one lock.
Nr   r   s   &&&&r;   get_metadata_with_origin&InMemoryIndex.get_metadata_with_origina  s)     ZZZ&&wF ZZZs	   2A	c               (    V ^8  d   QhRRRRRRRR/# )	rD   r   ztuple[str, str, str | None]r   rO   
from_sdistr   rF   ru   r-   )rG   s   "r;   rH   rv   m  s2     $ $)$ $
 $ 
$r:   c               0   Vw  rEpVf   V P                   P                  V4      V8w  d   V P                  P                  WE3R4       V'       d   V P                  P                  WE34       MV P                  P                  WE34       W P                   V&   R# )zWrite one metadata slot. Caller holds the lock.

Reconciled sdist metadata is derived from the version-level text, so
replacing that text drops it.  The parsed cache carries the text it
parsed and needs no eviction.
N)r   r   r   popr   r   discard)r   r   r   r   rN   rP   rj   s   &&&$   r;   _write_metadata_slot"InMemoryIndex._write_metadata_slotm  s     *.&,~~!!$'4/--1172DdK))--w.@A))1172DE#tr:   c          
     ,    V ^8  d   QhRRRRRRRRRR/# )	rD   rN   r?   rP   r   rO   rj   rF   ru   r-   )rG   s   "r;   rH   rv     s<            	 
 !  
 r:   c                .   \        WV4      pWV3pV P                  ;_uu_ 4        V P                  WcRR7       V P                  P	                  V4      pRRR4       Xe#   W7n        VP                  P                  4        R# R#   + '       g   i     L8; i)a  Cache metadata text (or ``None`` for a failed fetch).

``metadata_url`` is the sidecar the text came from; ``None`` stores the
text as standing for the version rather than for one artifact.

A ``data`` of ``None`` means no PEP 658 sidecar arrived and readers
fall back to the sdist.  It lands in the sidecar's own slot, so it
cannot erase sdist PKG-INFO the version-level slot already holds.
Fr   N)rm   ry   r   r   r   re   rd   r}   )r   rN   rP   r   rj   r   r   r   s   &&&&&   r;   store_metadataInMemoryIndex.store_metadata  sy      Gl;,/ZZZ%%dU%Cmm'',G  !NMM  Zs   /BB	c          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
rD   rN   r?   rP   r   r   rj   rO   rF   ru   r-   )rG   s   "r;   rH   rv     s<            	 
 !  
 r:   c                   \        WV4      pV P                  ;_uu_ 4        W0P                  WV3&   V P                  P	                  V4      pRRR4       Xe   VP
                  P                  4        R# R#   + '       g   i     L2; i)a2  Record a failed metadata fetch and unblock waiters.

Distinct from ``store_metadata(None)``: ``None`` means no PEP 658
sidecar arrived and the resolver may fall back to the sdist; an error
means an advertised sidecar could not be fetched or failed its published
hash, so the resolve must not fall through.
N)rm   ry   r   r   r   rd   r}   )r   rN   rP   r   rj   r   r   s   &&&&&  r;   store_metadata_error"InMemoryIndex.store_metadata_error  sj     Gl;ZZZFK!!7\"BCmm'',G  MM  Z   ,A77B	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   rj   rO   rF   r   r-   )rG   s   "r;   rH   rv     s2     G GG%(G8BG	Gr:   c                   V P                   ;_uu_ 4        Ve.   V P                  P                  WV34      pVe   VuuRRR4       # V P                  P                  WR34      uuRRR4       #   + '       g   i     R# ; i)zoReturn a recorded metadata fetch error, or ``None``.

The artifact's own error wins, then a version-level one.
N)ry   r   r   )r   rN   rP   rj   r   s   &&&& r;   get_metadata_error InMemoryIndex.get_metadata_error  se     ZZZ'--117\2RS$ 	 Z
 ((,,g-EF ZZZs   'A.A..A?	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   rQ   rF   ru   r-   )rG   s   "r;   rH   rv     s2     
G 
G
G%(
G/2
G	
Gr:   c                    V P                   ;_uu_ 4        V P                  P                  WV34       RRR4       R#   + '       g   i     R# ; i)a  Mark the metadata fetch at ``url`` as one offline mode skipped.

The skip writes the same empty slot a metadata-less artifact writes, so
without the mark the two read alike.  ``url`` keys it to one rung of the
ladder: a rung skipped is no claim about an artifact a later rung read.
N)ry   r   r   r   rN   rP   rQ   s   &&&&r;   record_offline_metadata_miss*InMemoryIndex.record_offline_metadata_miss  s2     ZZZ))--w.EF ZZZs	   =A	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   rQ   rO   rF   r   r-   )rG   s   "r;   rH   rv     s2     L LL%(L/9L	Lr:   c                    V P                   ;_uu_ 4        WV3V P                  9   uuRRR4       #   + '       g   i     R# ; i)z:Whether the metadata fetch at ``url`` was skipped offline.N)ry   r   r   s   &&&&r;   is_offline_metadata_miss&InMemoryIndex.is_offline_metadata_miss  s,     ZZZc*d.K.KK ZZZs	   1A	c                    V ^8  d   QhRRRR/# r   r-   )rG   s   "r;   rH   rv     s      c d r:   c                    V P                   ;_uu_ 4        WP                  9   d    RRR4       R# V P                  P                  V4        RRR4       R#   + '       g   i     R# ; i)a  Whether the caller owns ``package``'s one offline-skip warning.

True for the first caller only.  The targets of a run share this index
but each builds its own :class:`~nab_python.provider.Provider`, so the
state lives here to hold the report to one per package.
NFT)ry   r   r   r   s   &&r;   claim_offline_metadata_warning,InMemoryIndex.claim_offline_metadata_warning  sH     ZZZ777 Z ))--g6	 ZZZs   AAA(	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   r   rO   rF   ru   r-   )rG   s   "r;   rH   rv     s,         %( 0: 	 r:   c                $   RV RV 2pV P                   ;_uu_ 4        V P                  WR3VRR7       V P                  P                  V4      pRRR4       Xe#   W5n        VP
                  P                  4        R# R#   + '       g   i     L8; i)a  Store sdist-derived PKG-INFO in the version-level metadata slot.

PKG-INFO is core-metadata-equivalent, so it stands for the version
rather than for one artifact and answers a read that names no
artifact.  The pending key differs from a wheel's so an sdist request
can run in parallel with (or after) a failed wheel metadata request.
:meth:`metadata_from_sdist` reports which kind the version-level slot
holds.
sdist:rl   NTr   )ry   r   r   r   re   rd   r}   r   rN   rP   r   r   r   s   &&&&  r;   store_sdist_metadata"InMemoryIndex.store_sdist_metadata  s}     wiq	*ZZZ%%w&>QU%Vmm'',G  !NMM  Zs   2A??B	c               (    V ^8  d   QhRRRRRRRR/# rD   rN   r?   rP   r   r   rF   ru   r-   )rG   s   "r;   rH   rv     ,         %( 1> 	 r:   c                   RV RV 2pV P                   ;_uu_ 4        W0P                  WR3&   V P                  P                  V4      pRRR4       Xe   VP                  P                  4        R# R#   + '       g   i     L2; i)a  Record a failed sdist fetch and unblock the sdist waiter.

Distinct from ``store_sdist_metadata(None)``: ``None`` means the archive
yielded no PKG-INFO; an error means the archive could not be fetched or
failed its published hash, so the resolve must abort rather than fall
through.
r   rl   N)ry   r   r   r   rd   r}   r   rN   rP   r   r   r   s   &&&&  r;   store_sdist_metadata_error(InMemoryIndex.store_sdist_metadata_error  sp     wiq	*ZZZ>C!!7T":;mm'',G  MM  Zs   ,A33B	c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   rP   rF   r   r-   )rG   s   "r;   rH   rv     s&     C C3 C C Cr:   c                    V P                   ;_uu_ 4        W3V P                  9   uuRRR4       #   + '       g   i     R# ; i)a   Return ``True`` when the version-level slot was written from an sdist.

The slot itself cannot distinguish wheel METADATA from sdist
PKG-INFO; readers that apply the :pep:`643` dynamic-deps gate
only to sdist values ask here for the current text's origin.
N)ry   r   r   rN   rP   s   &&&r;   metadata_from_sdist!InMemoryIndex.metadata_from_sdist  s*     ZZZ%)B)BB ZZZs	   0A	c          
     ,    V ^8  d   QhRRRRRRRRRR/# )rD   rN   r?   rP   ro   r   rF   ru   r-   )rG   s   "r;   rH   rv     s4         %( 58 @C 	 r:   c                ,   \        WV4      pV P                  ;_uu_ 4        V P                  WV3VRR7       V P                  P	                  V4      pRRR4       Xe#   WFn        VP                  P                  4        R# R#   + '       g   i     L8; i)a  Store range-recovered wheel METADATA in the wheel's own slot.

The text is authoritative wheel METADATA, so it lands in the
``(package, version, wheel_url)`` slot with ``from_sdist=False`` and
stays off the :pep:`643` dynamic-deps gate.  Keying by the wheel URL,
like the sidecar path, keeps sibling sidecar-less wheels of one version
independent: a matrix target that picks one wheel never reads another
wheel's dependencies.  Firing the ``range:`` pending releases the
provider thread blocked on rung 4.
Fr   N)rq   ry   r   r   r   re   rd   r}   )r   rN   rP   ro   r   r   r   s   &&&&&  r;   store_range_metadata"InMemoryIndex.store_range_metadata  s}     95ZZZ%%9-t &  mm'',G	 
 !NMM  Zs   2BB	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   ro   rF   ru   r-   )rG   s   "r;   rH   rv   &  s)        #      PT  r:   c                    \        WV4      pV P                  ;_uu_ 4        V P                  P                  V4      pRRR4       Xe   VP                  P                  4        R# R#   + '       g   i     L2; i)aQ  Release a rung-4 waiter without writing a metadata slot.

A range read that yielded no METADATA (ranges unsupported, no matching
dist-info, an offline cold miss, a dead fetcher loop) is a rung miss,
not an error: the pending fires so the provider reads ``None`` and steps
to the sdist rung, which can still write the version-level slot.
N)rq   ry   r   r   rd   r}   )r   rN   rP   ro   r   r   s   &&&&  r;   store_range_absent InMemoryIndex.store_range_absent&  sU     95ZZZmm'',G MM  Zs   A''A7	c          
     ,    V ^8  d   QhRRRRRRRRRR/# )	rD   rN   r?   rP   ro   r   r   rF   ru   r-   )rG   s   "r;   rH   rv   4  s4         %( 58 AN 	 r:   c                   \        WV4      pV P                  ;_uu_ 4        W@P                  WV3&   V P                  P	                  V4      pRRR4       Xe   VP
                  P                  4        R# R#   + '       g   i     L2; i)a  Record a failed range read as a per-wheel error and unblock rung 4.

Distinct from :meth:`store_range_absent`: a malformed-UTF-8 METADATA
blob, or a wheel URL the index advertised and then could not serve,
fails the resolve rather than falling through to the sdist, mirroring
:meth:`store_metadata_error` for an advertised sidecar.  The error
lands in the ``(package, version, wheel_url)`` slot the provider reads
for that wheel.  The ``range:`` pending fires so the waiter unblocks.
N)rq   ry   r   r   r   rd   r}   )r   rN   rP   ro   r   r   r   s   &&&&&  r;   store_range_errorInMemoryIndex.store_range_error4  sj     95ZZZCH!!7Y"?@mm'',G  MM  Zr   c          
     ,    V ^8  d   QhRRRRRRRRRR/# )	rD   rN   r?   rP   ro   outcomer   rF   ru   r-   )rG   s   "r;   rH   rv   G  s;     J JJ%(J58JCOJ	Jr:   c                    V P                   ;_uu_ 4        W@P                  WV3&   RRR4       R#   + '       g   i     R# ; i)zBRecord the mechanical outcome of a range read for tier accounting.N)ry   r   )r   rN   rP   ro   r  s   &&&&&r;   store_range_outcome!InMemoryIndex.store_range_outcomeG  s,     ZZZBI  'I!>? ZZZs	   0A	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   ro   rF   zRangeOutcome | Noner-   )rG   s   "r;   rH   rv   N  s2     K KK%(K58K	Kr:   c                    V P                   ;_uu_ 4        V P                  P                  WV34      uuRRR4       #   + '       g   i     R# ; i)z@Return the recorded range-read outcome, or ``None`` if none ran.N)ry   r   r   )r   rN   rP   ro   s   &&&&r;   get_range_outcomeInMemoryIndex.get_range_outcomeN  s2     ZZZ''++Wy,IJ ZZZs	   =A	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   r   rF   ru   r-   )rG   s   "r;   rH   rv   U  s(     
= 
=S 
=3 
=c 
=d 
=r:   c                    V P                   ;_uu_ 4        W0P                  W3&   RRR4       R#   + '       g   i     R# ; i)a]  Store sdist-derived pyproject.toml text for static-metadata fallback.

The fetcher writes both PKG-INFO and pyproject.toml when an
sdist is downloaded. Provider code reads this slot when
PKG-INFO marks dependencies as :pep:`643` Dynamic.  No
``None`` slot is written: missing pyproject.toml is
indistinguishable from never-fetched at the read path.
N)ry   r   )r   rN   rP   r   s   &&&&r;   store_sdist_pyproject#InMemoryIndex.store_sdist_pyprojectU  s*     ZZZ8<!!7"45 ZZZ	   /A 	c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   rP   rF   rO   r-   )rG   s   "r;   rH   rv   a  s&     A A3 A A Ar:   c                    V P                   ;_uu_ 4        V P                  P                  W34      uuRRR4       #   + '       g   i     R# ; i)zDReturn sdist pyproject.toml text or ``None`` if absent or unfetched.N)ry   r   r   r  s   &&&r;   get_sdist_pyproject!InMemoryIndex.get_sdist_pyprojecta  s.    ZZZ((,,g-?@ ZZZ	   <A	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   r   bytes | NonerF   ru   r-   )rG   s   "r;   rH   rv   f  s,     
  
 
 %(
 0<
 	
 r:   c                   RV RV 2pV P                   ;_uu_ 4        W0P                  W3&   V P                  P                  V4      pRRR4       Xe#   W5n        VP
                  P                  4        R# R#   + '       g   i     L8; i)z;Cache sdist archive bytes (or ``None`` for a failed fetch).sdist-archive:rl   N)ry   r   r   r   re   rd   r}   r   s   &&&&  r;   store_sdist_archive!InMemoryIndex.store_sdist_archivef  ss     wiq	2ZZZ7;  '!34mm'',G  !NMM  Zs   +A88B	c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   rP   rF   r/  r-   )rG   s   "r;   rH   rv   r  s&     @ @ @s @| @r:   c                    V P                   ;_uu_ 4        V P                  P                  W34      uuRRR4       #   + '       g   i     R# ; i)zCReturn cached sdist archive bytes, or ``None`` if absent or failed.N)ry   r   r   r  s   &&&r;   get_sdist_archiveInMemoryIndex.get_sdist_archiver  s.    ZZZ''++W,>? ZZZr-  c               (    V ^8  d   QhRRRRRRRR/# r  r-   )rG   s   "r;   rH   rv   w  r  r:   c                
   RV RV 2pV P                   ;_uu_ 4        W0P                  W3&   V P                  P                  V4      pRRR4       Xe   VP                  P                  4        R# R#   + '       g   i     L2; i)a  Record a failed sdist-archive fetch and unblock the waiter.

Kept in its own slot rather than ``store_sdist_archive(None)`` so the
``BUILD_REMOTE`` path can tell an archive the index never offered (skip
the version) from one it advertised and then failed to serve (abort the
resolve).
r1  rl   N)ry   r   r   r   rd   r}   r  s   &&&&  r;   store_sdist_archive_error'InMemoryIndex.store_sdist_archive_errorw  sn     wiq	2ZZZ=B&&'9:mm'',G  MM  Zs   +A22B	c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   rP   rF   r   r-   )rG   s   "r;   rH   rv     s)     F FF%(F	Fr:   c                    V P                   ;_uu_ 4        V P                  P                  W34      uuRRR4       #   + '       g   i     R# ; i)z9Return a recorded sdist-archive fetch error, or ``None``.N)ry   r   r   r  s   &&&r;   get_sdist_archive_error%InMemoryIndex.get_sdist_archive_error  s0     ZZZ--1172DE ZZZr-  c                    V ^8  d   QhRRRR/# )rD   r   r?   rF   ztuple[_Pending, bool]r-   )rG   s   "r;   rH   rv     s     " " "1F "r:   c                    V P                   ;_uu_ 4        WP                  9   d    V P                  V,          R3uuRRR4       # \        4       pW P                  V&   VR3uuRRR4       #   + '       g   i     R# ; i)z"Return (pending, already_existed).TNF)ry   r   ra   )r   r   r   s   && r;   get_or_create_pending#InMemoryIndex.get_or_create_pending  sU    ZZZmm#}}S)4/ Z jG!(MM#E> ZZZs   %A+A++A<	c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   source_textrF   
Any | Noner-   )rG   s   "r;   rH   rv     s,      %(7:	r:   c                    V P                   ;_uu_ 4        V P                  P                  W34      pVe   V^ ,          V8w  d    RRR4       R# V^,          uuRRR4       #   + '       g   i     R# ; i)a  Return the cached parse of ``source_text``, or ``None``.

Unlike :meth:`get_metadata` (which returns the raw text), this
returns the already-parsed dataclass.  A parse of any other text is
a miss: wheel METADATA and sdist PKG-INFO share one
``(package, version)`` slot and either can replace the other
mid-resolve, so a hit on the key alone could hand back the deps of
the artifact the caller is not holding.
N)ry   r   r   )r   rN   rP   rE  rJ   s   &&&& r;   get_parsed_metadata!InMemoryIndex.get_parsed_metadata  sU     ZZZ))--w.@AE}aK 7 Z 8	 ZZZs   0A"A""A3	c          
     ,    V ^8  d   QhRRRRRRRRRR/# )	rD   rN   r?   rP   r+   r   rE  rF   ru   r-   )rG   s   "r;   rH   rv     s;     
P 
P
P%(
P47
PFI
P	
Pr:   c                    V P                   ;_uu_ 4        WC3V P                  W3&   RRR4       R#   + '       g   i     R# ; i)zCache the parse of ``source_text`` for future tuple lookups.

Safe across tuples because the parsed object is read-only and
a pure function of ``source_text``.  Per-tuple classification
(marker eval, extras admission) happens above this cache.
N)ry   r   )r   rN   rP   r+   rE  s   &&&&&r;   store_parsed_metadata#InMemoryIndex.store_parsed_metadata  s/     ZZZ9D8OD!!7"45 ZZZs	   1A	c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   rP   rF   rF  r-   )rG   s   "r;   rH   rv     s&     I I3 I I Ir:   c                    V P                   ;_uu_ 4        V P                  P                  W34      uuRRR4       #   + '       g   i     R# ; i)a  Return cached post-reconciliation sdist metadata or ``None``.

The cached value is the result of
:func:`nab_python._provider.metadata_resolver.resolve_dynamic_sdist`:
either a :pep:`621` pyproject augmentation or a PEP 517 backend
invocation.  Both branches are deterministic functions of the
sdist content under nab's build inputs, so the value is shared
across universal-mode tuples to avoid duplicate work.
N)ry   r   r   r  s   &&&r;   get_resolved_sdist_metadata)InMemoryIndex.get_resolved_sdist_metadata  s0     ZZZ0044g5GH ZZZr-  c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   r+   r   rF   ru   r-   )rG   s   "r;   rH   rv     s2     I II%(I47I	Ir:   c                    V P                   ;_uu_ 4        W0P                  W3&   RRR4       R#   + '       g   i     R# ; i)z6Cache reconciled sdist metadata for cross-tuple reuse.N)ry   r   )r   rN   rP   r+   s   &&&&r;   store_resolved_sdist_metadata+InMemoryIndex.store_resolved_sdist_metadata  s*     ZZZ@H))7*<= ZZZr(  )r{   r|   rz   ry   r   r   r   r~   r   r   r   r   r   r   r   r   r   r   N)-r.   r/   r0   r1   r2   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&  r+  r2  r6  r:  r>  rB  rH  rL  rP  rT  r9   r-   r:   r;   r#   r#      s    
0Gd/
 
 #  !& >;
=
 5
8
6
P.J(
G$. 2 *G
GL ( "C .  &JK
=A

 @
 "F"$
PII Ir:   c                  L   ] tR tRtRt^
tRRR^2RRRRRR	R
RRRRR/R R llt]R R l4       tR R lt	R R lt
]R R l4       t]R R l4       tR R ltR R ltR R ltR R  ltR! R" ltR# R$ ltR% R& ltR' R( ltR) R* ltR+R	/R, R- lltR]R. R/ lltR^R0 R1 lltR^R2 R3 lltR^R4 R5 lltR6 R7 ltR8 R9 ltR: R; ltR< R= ltR> R? ltR@ RA lt RB RC lt!RD RE lt"RF RG lt#RH RI lt$RJ RK lt%RL RM lt&RN RO lt'RP RQ lt(RR RS lt)RT RU lt*RV RW lt+RX RY lt,RZ R[ lt-R\t.R# )_r    i  a  Bridges the sync provider and the async fetcher.

Cross-thread communication uses an ``asyncio.Queue`` that lives
in the fetcher thread's event loop. Sync callers schedule puts
on the loop via ``loop.call_soon_threadsafe``. Batch submissions
(lists) guarantee all items arrive together for concurrent
processing.

Use as a context manager:
    with FetchCoordinator(transport) as coordinator:
        ...
indexesNmax_concurrency	cache_dircache_backendofflineFindex_routesindex_cache_floorson_fetchc               @    V ^8  d   QhRRRRRRRRR	R
RRRRRRRRRR/
# )rD   	transportr(   rX  zlist[IndexConfig] | NonerY  rX   rZ  zPath | Noner[  zCacheBackend | Noner\  r   r]  zlist[IndexRoute] | Noner^  zMapping[str, int] | Noner_  zCallable[[], None] | NonerF   ru   r-   )rG   s   "r;   rH   FetchCoordinator.__annotate__  sz     n. n.%n. *	n.
 n. n. +n. n. .n. 5n. ,n. 
n.r:   c                  Vf   \        \        \        4      .pV'       g   Rp
\        V
4      hV Uu. uF  qP                  NK  	  pp\        V4      \        \        V4      4      8w  dC   \        V Uu0 uF  qP                  V4      ^8  g   K  VkK  	  up4      pRV 2p
\        V
4      h\        V4      V n
        Wn        W0n        W`n        Ve   \        V4      ^8  d   Rp
\        V
4      hVeH   \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   Rp
\        V
4      hVe   WPn        MHVe6   \!        WB^ ,          P"                  V^ ,          P$                  R	7      V n        M\'        4       V n        W@n        \        T;'       g    . 4      V n        \-        T;'       g    / 4      V n        \        V P                  4      ^8H  ;'       dg    V P*                  '       * ;'       dN    \1        V P                  ^ ,          P"                  4      '       * ;'       d    \3        V P                  \         4      V n        Wn        \9        4       V n        \=        4       V n        \A        4       V n!        \E        4       V n#        \H        V n%        RV n&        RV n'        RV n(        RV n)        RV n*        RV n+        \X        PZ                  ! 4       V n.        R# u upi u upi )
a,  Create a coordinator that wraps ``transport``.

``indexes`` is the ordered list of :class:`IndexConfig` records;
order is significant (presence-based first-index walks them
left-to-right).  When omitted, defaults to
``[IndexConfig("pypi", "https://pypi.org/simple/")]``.  Each
index name must be unique across the list.

``index_routes`` adds per-package routing rules; an entry's
``index`` field names one of the configured indexes and pins that
package's listing fetch to it.

``index_cache_floors`` maps an index name to a read-time
freshness floor in seconds, passed to that index's cached client
as ``min_fresh_seconds``.  Indexes absent from the map, and the
``file://`` local client, get no floor.

``cache_backend`` wins over ``cache_dir`` if both are given;
otherwise ``cache_dir`` enables a per-index :class:`OnDiskCache`
and ``None`` falls back to a :class:`NullCache`.  Passing an
explicit ``cache_backend`` together with more than one entry in
``indexes``, or with an index that pins its ``serialization``, is
rejected: each of those needs its own cache.
Nz-indexes must contain at least one IndexConfigzduplicate index names: zqexplicit cache_backend is incompatible with more than one index: pass cache_dir so each index gets its own cache.c              3  X   "   T F   qP                   \        P                  Jx  K"  	  R # 5irV  )serializationr   	NEGOTIATE).0idxs   & r;   	<genexpr>,FetchCoordinator.__init__.<locals>.<genexpr>  s#      -
NUs%8%B%BBgs   (*TFzexplicit cache_backend is incompatible with a pinned serialization: pass cache_dir so the pinned index gets a cache of its own.re  )/r   DEFAULT_INDEX_NAMEDEFAULT_INDEX_URL
ValueErrorr@   lenr}   sortedcountr   rX  
_transport_max_concurrency_offlineany_cacher   rQ   re  r
   
_cache_dir_index_routesdict_index_cache_floorsr   
isinstance_sync_listing_enabled	_on_fetchr#   rA   r   _range_memor   _parsed_cache_statsr%   _warm_sync_stats_WARM_SYNC_MIN_BLOB_BYTES_warm_sync_min_blob_bytes_thread_started_crashed_crash_error_loop_async_qrf   rg   _queue_ready)r   ra  rX  rY  rZ  r[  r\  r]  r^  r_  msgrh  namesn
duplicatess   &&$$$$$$$$     r;   r   FetchCoordinator.__init__  s   J ?"#57HIJGACS/!%,-WcW-u:SZ(E HEq[[^a5GE HIJ+J<8CS/!G}# /$W)9K  S/!$ -
NU-
 -
NU-
 *
 *
% 
 S/!$(5K" &1:>>9Q9QDK $+DK#!,"4"4"5#'(:(@(@b#A  " 5 5&&&5 5Q 3 3445 5 4;;4	 	" ""_
 /0 $4#5  -)B&04267;
:>%OO-I . Hs   K&4K+K+c                   V ^8  d   QhRR/# )rD   rF   r   r-   )rG   s   "r;   rH   rb  P  s       r:   c                    V P                   # )z<Whether this run may read the cache only, never the network.)rt  r   s   &r;   r\  FetchCoordinator.offlineO  s     }}r:   c                   V ^8  d   QhRR/# )rD   rF   r   r-   )rG   s   "r;   rH   rb  T  s      4 r:   c                &    V P                  4        V # )z)Start the fetcher thread and return self.)startr   s   &r;   	__enter__FetchCoordinator.__enter__T  s    

r:   c                    V ^8  d   QhRRRR/# )rD   argsobjectrF   ru   r-   )rG   s   "r;   rH   rb  Y  s      f  r:   c                &    V P                  4        R# )z-Shut the fetcher thread down on context exit.N)shutdown)r   r  s   &*r;   __exit__FetchCoordinator.__exit__Y  s    r:   c                   V ^8  d   QhRR/# )rD   rF   r   r-   )rG   s   "r;   rH   rb  ^  s     ( ($4 (r:   c                    V P                   # )zParsed-listing cache counters for this run, shared by every index client.

Read after a run to confirm a warm resolve serves parsed blobs. The sink
is rebuilt at the start of each fetcher loop, so the counts reflect the
most recent run.
)r  r   s   &r;   parsed_cache_stats#FetchCoordinator.parsed_cache_stats]  s     '''r:   c                   V ^8  d   QhRR/# )rD   rF   r%   r-   )rG   s   "r;   rH   rb  h  s     % % %r:   c                    V P                   # )zASynchronous warm-hit listing counters, reset at each ``start()``.)r  r   s   &r;   warm_sync_stats FetchCoordinator.warm_sync_statsg  s     $$$r:   c                   V ^8  d   QhRR/# rt   r-   )rG   s   "r;   rH   rb  l  s     ! !t !r:   c                   V P                   '       d   R# RV n         \        4       V n        \        P                  ! V P
                  RRR7      V n        V P                  P                  4        V P                  P                  4        R# )z&Start the fetcher thread (idempotent).NTznab-fetcher)targetdaemonr@   )
r  r%   r  rf   Thread	_run_loopr  r  r  waitr   s   &r;   r  FetchCoordinator.startl  sb    === - ''>>

 	 r:   c                   V ^8  d   QhRR/# rt   r-   )rG   s   "r;   rH   rb  z  s     " "$ "r:   c                    V P                   f   R# V P                  R4       V P                   P                  \        R7       RV n         RV n        RV n        RV n        V P                  P                  4        R# )z.Signal the fetcher thread to exit and join it.N)timeoutF)	r  _submitjoin!_COORDINATOR_JOIN_TIMEOUT_SECONDSr  r  r  r  clearr   s   &r;   r  FetchCoordinator.shutdownz  sa    <<T"CD 
!r:   c                    V ^8  d   QhRRRR/# rD   item
_QueueItemrF   ru   r-   )rG   s   "r;   rH   rb    s      J 4 r:   c                    V P                   pV P                  pVe   Vf   V P                  V4       R#  VP                  VP                  V4       R#   \
         d    T P                  T4        R# i ; i)zSchedule ``item`` on the fetcher loop's queue from any thread.

Requests the loop cannot take are recorded as failures so their
waiters unblock instead of hanging.
N)r  r  _refusecall_soon_threadsafe
put_nowaitRuntimeError)r   r  loopqueues   &&  r;   r  FetchCoordinator._submit  sd     zz<5=LL	%%e&6&6= 	LL	s   A A32A3c               $    V ^8  d   QhRRRRRR/# )rD   callbackzCallable[..., object]r  r  rF   r   r-   )rG   s   "r;   rH   rb    s"      &; F t r:   c                x    V P                   pVf   R#  VP                  ! V.VO5!   R#   \         d     R# i ; i)zHand ``callback`` to the fetcher loop from any thread.

Returns ``False`` when there is no live loop (never started, or closed
between the read and the post) so the caller can run the work inline.
FT)r  r  r  )r   r  r  r  s   &&* r;   _post_to_loopFetchCoordinator._post_to_loop  sF     zz<	%%h66   		s   * 99c                    V ^8  d   QhRRRR/# r  r-   )rG   s   "r;   rH   rb    s     V VJ V4 Vr:   c                   Vf   R# \        V\        4      '       d   TMV.pV EF  p\        R4      pVP                  \        P
                  J d)   V P                  P                  VP                  V4       KU  VP                  f   Q hVP                  \        P                  J d>   V P                  P                  VP                  VP                  WCP                  4       K  VP                  \        P                  J dO   VP                  f   Q hV P                  P                  VP                  VP                  VP                  4       EK,  VP                  \        P                  J d5   V P                  P!                  VP                  VP                  V4       EK~  V P                  P#                  VP                  VP                  V4       EK  	  R# )zBRecord a failure for each request in ``item``, unblocking waiters.Nz,Fetcher loop is not running, request refused)r{  r   r  rM   r!   r3   rA   r   rN   rP   r4   r   rQ   r5   r  r6   r  r:  )r   r  requestsreqr   s   &&   r;   r  FetchCoordinator._refuse  s?    <%dD114vC !OPExx9,,,

..s{{EB;;***xx9---

//KKeWW Y555 ww***

--ckk3;;PY__,

55ckk3;;PUV

44S[[#++uU% r:   c                    V ^8  d   QhRRRR/# )rD   r   r   rF   ru   r-   )rG   s   "r;   rH   rb    s      = T r:   c                     Wn         RV n        R# )z2Record the failure that killed the fetcher thread.TN)r  r  )r   r   s   &&r;   _record_crashFetchCoordinator._record_crash  s    !r:   c                   V ^8  d   QhRR/# rt   r-   )rG   s   "r;   rH   rb    s        d  r:   c                	^    V P                   '       g   R # RV P                   2p\        V4      h)NzFetcher thread crashed: )r  r  r  )r   r  s   & r;   _check_aliveFetchCoordinator._check_alive  s,    }}}():):(;<3r:   c                    V ^8  d   QhRRRR/# r   r-   )rG   s   "r;   rH   rb    s       1S r:   c                   V P                   pV P                  '       g   V;P                  ^,          un        R# \        V P                  WP
                  R7      pVe   V# V P                  P                  V4      pVf   V;P                  ^,          un        R# VP                  4       '       g.   V P
                  '       g   V;P                  ^,          un	        R# V;P                  ^,          un
        R# )a  Read a fresh parsed listing on the caller's thread, or ``None``.

``read_fresh_parsed_listing`` never raises, so the caller's pending is
never stranded. On a decline the policy is re-read to attribute a reason
counter rather than threading it out of the pure helper.
Nr\  )r  r|  r[   r   rv  rt  get_simple_policyr\   is_freshr]   r^   )r   rN   statsrecordspolicys   &&   r;   _try_listing_sync"FetchCoordinator._try_listing_sync  s     %%)))%%*%+DKK--XN..w7>$$)$
 	 //##t}}}''1,'  ""a'"r:   c                    V ^8  d   QhRRRR/# r   r-   )rG   s   "r;   rH   rb    s     6 6C 6D 6r:   c                    V P                   '       g   R# V P                  P                  V4      pVf   R# W P                  8  # )a  Whether a warm listing may be served inline, or must go async.

A parsed blob below ``_WARM_SYNC_MIN_BLOB_BYTES`` declines to the async
path. A blob whose size cannot be stat'd, or a run where the sync path is
disabled, is admitted and left to ``_try_listing_sync`` to classify.
T)r|  rv  get_simple_parsed_sizer  )r   rN   sizes   && r;   _overlap_gate_admits%FetchCoordinator._overlap_gate_admits  s>     ))){{11':<5555r:   speculativec               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   r  r   rF   rc   r-   )rG   s   "r;   rH   rb    s$     ) )),0)	)r:   c                  V P                  4        V P                  P                  V4      e(   \        P                  ! 4       pVP                  4        V# RV 2pV P                  P                  V4      w  rVV'       d   VP                  # V'       Eg'   V P                  V4      '       d   V P                  V4      pVe   V P                  P                  WP                  ^ ,          P                  4       V P                  P                  W4       V P                  ;P                  ^,          un        V P!                  V P"                  W4      '       g   V P#                  W4       VP                  # M#V P                  ;P$                  ^,          un        V P                  ;P&                  ^,          un        V P)                  \+        \,        P.                  VR7      4       VP                  # )a=  Request a listing fetch; return an event set when the result lands.

The single-flight pending is claimed first: an existing pending means
another party owns fulfillment, so its event is joined and the cache is
never probed. Only the pending's creator probes; a fresh parsed hit is
served inline, and every other outcome declines to the async fetch, which
owns every cache write and self-heal.

``speculative`` callers skip the sync probe and dispatch async, so their
read work overlaps resolver CPU on the fetcher thread; only blocking
critical-path callers serve inline.
r   )rM   rN   )r  rA   r   rf   rg   r}   rB  rd   r  r  r   rX  r@   r   r  rY   r  _run_listing_tailr_   rZ   r  r"   r!   r3   )r   rN   r  doner   r   existedr  s   &&$     r;   request_listing FetchCoordinator.request_listing  so    	::!!'*6??$DHHJK	"::;;C@== {((11009& JJ227LLO<P<PQJJ,,W>))66!;6--d.D.DgWW..w@"==( ' %%99Q>9!!22a72\y'8'8'JK}}r:   c          
     ,    V ^8  d   QhRRRRRRRRRR/# )	rD   rN   r?   rP   rQ   rS   rR   rF   rc   r-   )rG   s   "r;   rH   rb    s<        	
 . 
r:   c           
        V P                  4        V P                  P                  WV4      '       d(   \        P                  ! 4       pVP                  4        V# \        WV4      pV P                  P                  V4      w  rxV'       g.   V P                  \        \        P                  VVVVR7      4       VP                  # )zJRequest the sidecar at ``url`` as the metadata for ``(package, version)``.rM   rN   rP   rQ   rS   )r  rA   r   rf   rg   r}   rm   rB  r  r"   r!   r4   rd   )	r   rN   rP   rQ   rS   r  r   r   r  s	   &&&&&    r;   request_metadata!FetchCoordinator.request_metadata  s     	::""7S99??$DHHJKGc2::;;C@LL"++##"/ }}r:   c          
     ,    V ^8  d   QhRRRRRRRRRR/# )	rD   rN   r?   rP   ro   rV   rT   rF   rc   r-   )rG   s   "r;   rH   rb  :  s<        	
 2 
r:   c           
         V P                  4        \        WV4      pV P                  P                  V4      w  rgV'       g.   V P	                  \        \        P                  VVVVR7      4       VP                  # )af  Request a sidecar-less wheel's METADATA over an HTTP range read.

This is rung 4: the ``range:`` pending key is per
``(package, version, wheel_url)``, so two provider threads asking for the
same wheel enqueue a single read, while sibling sidecar-less wheels of
one version (which a matrix picks per target and which can declare
different dependencies) each get their own read, matching the sidecar
path.  A warm cache hit is served inside the client, so there is no early
cache check here.  ``wheel_hashes`` are the wheel's published digests; a
full-body read is verified against them before its METADATA is used.
)rM   rN   rP   rQ   rV   )	r  rq   rA   rB  r  r"   r!   r5   rd   )r   rN   rP   ro   rV   r   r   r  s   &&&&&   r;   request_range_metadata'FetchCoordinator.request_range_metadata:  sk    $ 	95::;;C@LL"11##!!- }}r:   c          
     ,    V ^8  d   QhRRRRRRRRRR/# 	rD   rN   r?   rP   rQ   rU   rT   rF   rc   r-   )rG   s   "r;   rH   rb  [  s<        	
 2 
r:   c           
         V P                  4        RV RV 2pV P                  P                  V4      w  rgV'       g.   V P                  \	        \
        P                  VVVVR7      4       VP                  # )a  Request sdist PKG-INFO extraction.

Uses a separate ``sdist:`` pending key so it can fire even
when a prior wheel metadata fetch already cached ``None``
for the same ``(package, version)`` slot. The fetcher verifies the
downloaded archive against ``sdist_hashes`` before extraction.
r   rl   rM   rN   rP   rQ   rU   )r  rA   rB  r  r"   r!   r6   rd   r   rN   rP   rQ   rU   r   r   r  s   &&&&&   r;   request_sdistFetchCoordinator.request_sdist[  so     	wiq	*::;;C@LL"##!- }}r:   c          
     ,    V ^8  d   QhRRRRRRRRRR/# r  r-   )rG   s   "r;   rH   rb  x  s<        	
 2 
r:   c           
         V P                  4        RV RV 2pV P                  P                  V4      w  rgV'       g.   V P                  \	        \
        P                  VVVVR7      4       VP                  # )a  Request the raw bytes of an sdist archive.

Used by the :class:`~nab_python.provider.BuildPolicy.BUILD_REMOTE`
path; the bytes are extracted to a temp dir and handed to a
PEP 517 backend.  Stored under a separate pending key so it can
run concurrently with a PKG-INFO fetch for the same version. The
fetcher verifies the downloaded archive against ``sdist_hashes``
before storing the bytes.
r1  rl   r  )r  rA   rB  r  r"   r!   r7   rd   r  s   &&&&&   r;   request_sdist_archive&FetchCoordinator.request_sdist_archivex  sq      	wiq	2::;;C@LL"00##!- }}r:   c               (    V ^8  d   QhRRRRRRRR/# )rD   rN   r?   rP   rQ   rF   rc   r-   )rG   s   "r;   rH   rb    s2        	
 
r:   c           	         V P                  4        RV RV 2pV P                  P                  V4      w  rVV'       g-   V P                  \	        \
        P                  VVVR7      4       VP                  # )aJ  Request the bytes of an archive named by URL rather than by an index.

Used by ``[[tool.nab.archive-sources]]``, whose URL is declared
independently of every index, so the URL's own scheme decides how it is
read.  The bytes land unverified in the same slot as
:meth:`request_sdist_archive`; the caller checks the declared hashes.
r1  rl   )rM   rN   rP   rQ   )r  rA   rB  r  r"   r!   r8   rd   )r   rN   rP   rQ   r   r   r  s   &&&&   r;   request_direct_archive'FetchCoordinator.request_direct_archive  sn     	wiq	2::;;C@LL"11##	 }}r:   c                    V ^8  d   QhRRRR/# )rD   itemsz2list[tuple[str, str, str, tuple[str, str] | None]]rF   z&list[tuple[str, str, threading.Event]]r-   )rG   s   "r;   rH   rb    s     ! !G!	/!r:   c                &   V P                  4        . p. pV F  w  rErgV P                  P                  WEV4      '       d;   \        P                  ! 4       pVP                  4        VP                  WEV34       Kb  \        WEV4      p	V P                  P                  V	4      w  rV'       g.   VP                  \        \        P                  VVVVR7      4       VP                  WEV
P                  34       K  	  V'       d   V P                  V4       V# )zSubmit a batch of metadata requests as a single queue item.

Each item is ``(package, version, url, metadata_hash)``.  All
requests in the batch reach the fetcher together so they are
processed concurrently.
r  )r  rA   r   rf   rg   r}   appendrm   rB  r"   r!   r4   rd   r  )r   r  resultsbatchrN   rP   rQ   rS   r  r   r   r  s   &&          r;   request_metadata_batch'FetchCoordinator.request_metadata_batch  s     	:<$&490Gczz&&w== (
$78#6C#zz??DG &// ' '&3 NNGgmm<=% 5:& LLr:   c                   V ^8  d   QhRR/# rt   r-   )rG   s   "r;   rH   rb    s      4 r:   c                	     \         P                  ! V P                  4       4       R#   \         dI   pT P	                  T4       \
        P                  R 4       \        T\        4      '       g   h  Rp?R# Rp?ii ; i)zFetcher thread crashedN)	asynciorun_async_fetcherr   r  logger	exceptionr{  	Exception)r   excs   & r;   r  FetchCoordinator._run_loop  s^    	KK++-. 	s#56c9-- .		s   $( A;=A66A;c                   V ^8  d   QhRR/# )rD   rF   =CachedAsyncSimpleClient | LocalIndexClient | MultiIndexClientr-   )rG   s   "r;   rH   rb    s     
 
	F
r:   c                   \        V P                  4      p\        V P                  4      ^8X  d+   V'       g#   V P	                  V P                  ^ ,          4      # / pV P                   F   pV P	                  V4      W#P
                  &   K"  	  V P                   Uu. uF  q3P
                  NK  	  pp\        VVV4      # u upi )aE  Return the index client for this run.

Single-index configurations return a plain
:class:`CachedAsyncSimpleClient` (or a :class:`LocalIndexClient`
for a ``file:`` URL).  Multi-index configurations wire up a
:class:`MultiIndexClient` whose underlying clients share the
coordinator's transport but get their own per-URL cache.
)rK   rx  ro  rX  _build_index_clientr@   r   )r   override_mapclients_by_namecfgorders   &    r;   _build_clientFetchCoordinator._build_client  s     't'9'9:t||!,++DLLO<<QS<<C(,(@(@(EOHH%  %)\\2\c\2
 	
 3s   B=c                    V ^8  d   QhRRRR/# )rD   r  r   rF   z*CachedAsyncSimpleClient | LocalIndexClientr-   )rG   s   "r;   rH   rb    s      
  
 
 
4 
r:   c                   \        VP                  4      '       d   \        VP                  4      # V P                  e.   \	        V P                  VP                  VP
                  R7      pMV P                  p\        V P                  VVP                  V P                  V P                  VP
                  V P                  P                  VP                  4      V P                  R7      # )ap  Build a single index client for ``cfg``.

A ``file:`` URL in either RFC 8089 spelling goes to
:class:`LocalIndexClient` (no caching; the filesystem is the
cache).  Everything else goes to :class:`CachedAsyncSimpleClient`
with a per-URL :class:`OnDiskCache` when ``cache_dir`` is set.
Any freshness floor registered for ``cfg.name`` is passed as
``min_fresh_seconds``.
rk  )r\  
range_memore  min_fresh_secondsparsed_stats)r   rQ   r   rw  r   re  rv  r   rr  rt  r~  rz  r   r@   r  )r   r  backends   && r;   r  $FetchCoordinator._build_index_client  s     sww#CGG,, ??&!8I8IG kkG&OOGGMM''++"66::388D11	
 		
r:   c                   V ^8  d   QhRR/# rt   r-   )rG   s   "r;   rH   rb    s     6+ 6+d 6+r:   c                	t  "   \        4       V n        \        4       V n        \        P
                  ! 4       p\        P                  ! V P                  4      p\        4       p V P                  4       p\        P                  ! 4       V n        Wn         T P                  P                  4         RpT'       gu   TP!                  4       G R j  xL
 pTf   MWT P#                  YtY#4       TP%                  4       '       d   KO   TP'                  4       pTf   RpKh  T P#                  YY#4       KE  T'       d   \        P*                  ! TRR/ G R j  xL
  TP-                  4       G R j  xL
  T P.                  P-                  4       G R j  xL
  R #   \         d   pT P                  T4       h R p?ii ; i  T P                  P                  4        i ; i EL  \        P(                   d     EK>  i ; i L L Ln  TP-                  4       G R j  xL 
  T P.                  P-                  4       G R j  xL 
  i ; i5i)NFTreturn_exceptions)r   r~  r   r  r  Queue	Semaphorers  r}   r  get_running_loopr  r  r   r  r  r   	_dispatchempty
get_nowait
QueueEmptygatheracloserr  )	r   r  semtasksclientr  stoppingr  extras	   &        r;   r  FetchCoordinator._async_fetcher  s     /0 $4#5 +2==? 5 56#&5
	$'')F 113DJ!M !!#	+H"YY[(<tS8  ++-- % 0 0 2 } $(NN5#=nneDtDDD--/!! //((***M  	s#	 !!#
 ) #--  E! +	 --/!! //((***s   AH8!0F H8-	G7 7G7 
G.G7 ?G #G7 3G7 G1G7 H8$G3%!H8G5H8F/F**F//F2 2GH8G7 G.)G7 -G..G7 3H85H87H5H"H5.H1/H55H8c          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )rD   r  z!FetchRequest | list[FetchRequest]r5  r  r3  asyncio.Semaphorer4  zset[asyncio.Task]rF   ru   r-   )rG   s   "r;   rH   rb  Q  s=     2 2/2 N2 	2
 !2 
2r:   c                   \        V\        4      '       d^   V FU  p\        P                  ! V P	                  W%V4      4      pVP                  V4       VP                  VP                  4       KW  	  R# \        P                  ! V P	                  W!V4      4      pVP                  V4       VP                  VP                  4       R# )z3Create async tasks for a single request or a batch.N)r{  r   r  create_task_handler   add_done_callbackr   )r   r  r5  r3  r4  r  tasks   &&&&&  r;   r-  FetchCoordinator._dispatchQ  s     dD!!**4<<S+IJ		$&&u}}5 
 &&t||F#'FGDIIdO""5==1r:   c               (    V ^8  d   QhRRRRRRRR/# )	rD   r5  r  r  r"   r3  r:  rF   ru   r-   )rG   s   "r;   rH   rb  c  s2     = =M= = 	=
 
=r:   c           	     	  "   T;_uu_4       GR j  xL
   VP                   \        P                  J d   V P                  W4      G R j  xL
  MVP                   \        P                  J d   V P                  W4      G R j  xL
  MVP                   \        P                  J d   V P                  W4      G R j  xL
  MVP                   \        P                  J d   V P                  W4      G R j  xL
  MRVP                   \        P                  J d   V P                  W4      G R j  xL
  MV P                  V4      G R j  xL
   R R R 4      GR j  xL
  R #  ELJ EL L L Ls L= L%  \         dS   p\        P                  RTP                   P                   TP"                  T4       T P%                  YT4        R p?LzR p?i\&         dS   p\        P)                  RTP                   P                   TP"                  T4       T P%                  YT4        R p?LR p?ii ; i L  + GR j  xL 
 '       g   i     R # ; i5i)NzFetch failed: %s %s: %s)rM   r!   r3   _fetch_listingr4   _fetch_metadatar6   _fetch_sdistr7   _fetch_sdist_archiver5   _fetch_range_metadata_fetch_direct_archiver   r  debugvaluerN   _record_fetch_failurer  warning)r   r5  r  r3  r  s   &&&& r;   r=  FetchCoordinator._handlec  s     33=88y000--f:::XX!3!33..v;;;XX0++F888XX!8!8833F@@@XX!9!9944VAAA44S999 33 ;;8@A9 =-sxx~~s{{C **6<< =-sxx~~s{{C **6<<	=) 333s5  IEIH(2E+	E
E+H(2E+E!E+H(2E+9E#:E+>H(?2E+1E%2E+6H(72E+)E'*E+.H(/E+E)E+H(	IH&IE+!E+#E+%E+'E+)E++H#6AG>H(H#H#AHH(H##H(&I(I	.H1/
I	:I	<	Ic               (    V ^8  d   QhRRRRRRRR/# )	rD   r5  r  r  r"   r  r  rF   ru   r-   )rG   s   "r;   rH   rb    s8     B BMB B 	B
 
Br:   c                   \        V\        4      pVP                  \        P                  J d   V'       dF   V P                  WP                  4       V P                  P                  VP                  . RR7       R# V P                  P                  VP                  4      f'   V P                  P                  VP                  V4       R# VP                  f   Q hV P                  W#VR7       R# )aC  Record a failed fetch so any waiter unblocks (else a deadlock).

Offline with a cold cache is the one deliberate degradation: the
artifact is recorded absent and the resolver works with what the cache
holds. Any other failure is recorded as an error, because a file the
listing advertised and the index then failed to serve is not the same as
a file that does not exist.

A listing that is already stored keeps it: the fetch succeeded, and the
work that raised ran after the waiter woke, so recording an error would
make the outcome depend on which thread reads the index first.
T)r   Nr  )r{  r   rM   r!   r3   _record_serving_indexrN   rA   r   r   r   rP   _record_versioned_failure)r   r5  r  r  r\  s   &&&& r;   rK  &FetchCoordinator._record_fetch_failure  s    $ S,/88y((( **6;;?

((bt(L  ''4<

..s{{C@{{&&&&&s&Ar:   c               (    V ^8  d   QhRRRRRRRR/# )	rD   r  r"   r  r  r\  r   rF   ru   r-   )rG   s   "r;   rH   rb    s2     3P 3P3P&/3P=A3P	3Pr:   c                  VP                   f   Q hVP                  \        P                  J d   V'       d   VP                  f   Q hV P
                  P                  VP                  VP                   VP                  4       V P
                  P                  VP                  VP                   RVP                  4       R# V P
                  P                  VP                  VP                   W!P                  4       R# VP                  \        P                  J d   VP                  f   Q hV'       dy   V P
                  P                  VP                  VP                   VP                  4       V P
                  P                  VP                  VP                   VP                  4       R# V P
                  P                  VP                  VP                   VP                  V4       R# VP                  \        P                  J d   V'       d   VP                  f   Q hV P
                  P                  VP                  VP                   VP                  4       V P
                  P                  VP                  VP                   R4       R# V P
                  P                  VP                  VP                   V4       R# V'       dR   VP                  \        P                   J d4   V P
                  P#                  VP                  VP                   R4       R# V P
                  P%                  VP                  VP                   V4       R# )an  Record the failure of a version-scoped fetch, unblocking its waiter.

Offline is the one deliberate degradation: the artifact is recorded
absent so the resolver works with what the cache holds.  Any other
failure is recorded as an error, because a file the listing advertised
and the index then failed to serve is not one that does not exist.

A declared archive is the exception: it is the package's only
candidate, so there is nothing to degrade to and an offline miss is
recorded as an error.

A metadata rung marks the skip before it stores, so a waiter released
by the store reads the mark and not a bare empty slot.
N)rP   rM   r!   r4   rQ   rA   r   rN   r   r   r5   r  r  r6   r  r  r7   r2  r:  )r   r  r  r\  s   &&&$r;   rQ  *FetchCoordinator._record_versioned_failure  s   " {{&&&88y)))ww***

77KKcgg 

))#++s{{D#''R

//S[[#wwWXX11177&&&

77KKcgg 

--ckk3;;P 

,,S[[#++swwPSTXX(ww***

77KKcgg 

//S[[$O

55ckk3;;PSTY%<%<<JJ**3;;TJJJ00ckk3Or:   c               $    V ^8  d   QhRRRRRR/# rD   r5  r  r  r"   rF   ru   r-   )rG   s   "r;   rH   rb    s-     B BMB B 
	Br:   c                	  "   VP                  VP                  4      G R j  xL
 pV P                  WP                  4       V P                  P	                  VP                  VVP                  VP                  4      R7       \        P                  RVP                  \        V4      4       V P                  e   V P                  4        V P                  VP                  V4       R #  L5i)N)r   zfetched listing: %s (%d files))	get_filesrN   rP  rA   r   served_unreadable_onlyr  rI  ro  r}   _prefetch_metadata_after_listing)r   r5  r  filess   &&& r;   rC  FetchCoordinator._fetch_listing  s     
 &&s{{33
 	""6;;7

  KK"99#++F 	! 	

 	5s{{CJO>>%NN--ckk5A 4s   C*C(CC*c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   r\  r   rF   ru   r-   )rG   s   "r;   rH   rb    s)     L LL#BL	Lr:   c                |   / pV FK  p\        V\        4      '       g   K  VP                  '       g   K/  VP                  VP                  V4       KM  	  \        VP                  4       4      V P                  ) R pV F;  pVP                  pVf   Q hV P                  WP                  WvP                  4       K=  	  R# )zEnqueue metadata for the newest candidates of a stored listing.

Files are oldest-first. One wheel per version: the first with a sidecar
is the one the provider picks for that version's metadata.
N)r{  r   r   
setdefaultrP   r   valuesPREFETCH_METADATA_COUNTrj   r  rS   )r   rN   r\  first_wheelfnewestwrQ   s   &&&     r;   r[  1FetchCoordinator._prefetch_metadata_after_listing  s     -/A!Y''ANNN&&qyy!4  k((*+T-I-I,I,KLA..C?"?!!'99c??K r:   c               $    V ^8  d   QhRRRRRR/# )rD   rN   r?   r  r   rF   ru   r-   )rG   s   "r;   rH   rb    s)     Q QQ%DQ	Qr:   c                     V P                   e   V P                  4        V P                  W4       R#   \         d"   p\        P	                  RY4        Rp?R# Rp?ii ; i)a  Run the post-listing tail on the fetcher loop: tick then prefetch.

Mirrors the tail of the async ``_fetch_listing``. A failure is swallowed
rather than turned into a listing error: the pending has already fired,
so the served listing must not be overwritten.
Nz$listing prefetch tail failed: %s: %s)r}  r[  r  r  rL  )r   rN   r  r  s   &&& r;   r  "FetchCoordinator._run_listing_tail  sN    	Q~~) 11'C 	QNNA7PP	Qs   /3 AAAc               $    V ^8  d   QhRRRRRR/# )rD   r5  r  rN   r?   rF   ru   r-   )rG   s   "r;   rH   rb    s(     6 6M6 6 
	6r:   c                   \        V\        4      '       d6   VP                  V4      pVe   TMV P                  ^ ,          P                  pMV P                  ^ ,          P                  pV P
                  P                  W$4       R# )ad  Record which configured index served ``package``'s listing.

Single-client configurations always serve from the lone
configured index.  Multi-client configurations consult the
router's per-package route cache; an empty cache (e.g. an
index returned no listing on every walk) falls back to the
first configured index name so consumers always see
something.
N)r{  r   	route_forrX  r@   rA   r   )r   r5  rN   routedr@   s   &&&  r;   rP  &FetchCoordinator._record_serving_index  sa     f.//%%g.F#/6T\\!_5I5ID<<?''D

&&w5r:   c               $    V ^8  d   QhRRRRRR/# rW  r-   )rG   s   "r;   rH   rb  &  s-     J JMJ J 
	Jr:   c                	  "   VP                   f   Q hVP                  f4   V P                  P                  VP                  VP                   R 4       R # VP                  VP                  VP                   VP                  VP                  4      G R j  xL
 pV P                  P                  VP                  VP                   W2P                  4       \        P                  RVP                  VP                   4       R #  Ll5i)Nzfetched metadata: %s %s)	rP   rQ   rA   r   rN   get_metadata_textrS   r  rI  )r   r5  r  r   s   &&& r;   rD   FetchCoordinator._fetch_metadata&  s     
 {{&&&77?JJ%%ckk3;;E--KKcggs/@/@
 
 	

!!#++s{{D''J.S[[I	
s   BDD A-Dc               $    V ^8  d   QhRRRRRR/# rW  r-   )rG   s   "r;   rH   rb  5  s(     $
 $
M$
 $
 
	$
r:   c                0  "   VP                   f   Q hVP                  f   Q hVP                  VP                  VP                   VP                  \	        VP                  4      VP
                  4      G Rj  xL
 pV P                  P                  VP                  VP                   VP                  VP                  4       VP                  f=   V P                  P                  VP                  VP                   VP                  4       MFV P                  P                  VP                  VP                   VP                  VP                  4       \        P                  RVP                  VP                   VP                  P                  4       R#  EL5i)a  Recover a sidecar-less wheel's METADATA over an HTTP range read.

A read that returns text stores it in the wheel's own slot; a read
that returns none (ranges unsupported, no METADATA member) records the
outcome and fires the waiter with no slot, so the provider steps to the
sdist rung.  A malformed blob or an unserveable wheel URL raises out of
the client and is caught by :meth:`_handle` as a fetch failure.
Nzrange metadata: %s %s (%s))rP   rQ   get_range_metadatarN   canonicalize_name_boundaryrV   rA   r  r  r   r  r  r  rI  rJ  )r   r5  r  re   s   &&& r;   rG  &FetchCoordinator._fetch_range_metadata5  s     {{&&&ww"""00KKKKGG&s{{3
 
 	

&&KKcggv~~	
 ;;JJ))#++s{{CGGLJJ++S[[#''6;; 	(KKKKNN  		
!
s   A4F6F7DFc               $    V ^8  d   QhRRRRRR/# rW  r-   )rG   s   "r;   rH   rb  [  s-     L LML L 
	Lr:   c                	  "   VP                   f   Q hVP                  f   Q hVP                  VP                  VP                   VP                  VP                  4      G R j  xL
 w  r4Ve2   V P
                  P                  VP                  VP                   V4       V P
                  P                  VP                  VP                   V4       R #  Ln5irV  )rP   rQ   get_sdist_filesrN   rU   rA   r&  r  )r   r5  r  pkg_info	pyprojects   &&&  r;   rE  FetchCoordinator._fetch_sdist[  s     
 {{&&&ww"""$*$:$:KKcggs/?/?%
 
  JJ,,S[[#++yQ

''S[[(K
s   A C"C#A/Cc               $    V ^8  d   QhRRRRRR/# rW  r-   )rG   s   "r;   rH   rb  l  s-     G GMG G 
	Gr:   c                	  "   VP                   f   Q hVP                  f4   V P                  P                  VP                  VP                   R 4       R # VP                  VP                  VP                   VP                  VP                  4      G R j  xL
 pV P                  P                  VP                  VP                   V4       R #  L75irV  )rP   rQ   rA   r2  rN   r6  rU   )r   r5  r  r   s   &&& r;   rF  %FetchCoordinator._fetch_sdist_archivel  s     
 {{&&&77?JJ**3;;TJ--KKcggs/?/?
 
 	

&&s{{CKKF
s   BCC8Cc                    V ^8  d   QhRRRR/# )rD   r  r"   rF   ru   r-   )rG   s   "r;   rH   rb  z  s     G G| G Gr:   c                F  "   VP                   f   Q hVP                  f   Q h\        VP                  4      P                  R8X  d%   \	        VP                  4      P                  4       pMV P                  '       d   RVP                   R2p\        V4      hV P                  P                  VP                  \        R7      G Rj  xL
 p\        WAP                  4       VP                  pV P                  P                  VP                  VP                   V4       R#  LX5i)z:Read an archive declared by URL, by that URL's own scheme.Nfilez+archive fetch unavailable in offline mode ())headers)rP   rQ   r   schemer   
read_bytesrt  r   rr  r   r   r   contentrA   r2  rN   )r   r  r   r  responses   &&   r;   rH  &FetchCoordinator._fetch_direct_archivez  s     {{&&&ww"""CGG##v-!#''*557D}}}CCGG9AN"3''!__00BR0SSHHgg.##D

&&s{{CKKF	 Ts   A:D!=A	D!DAD!)r  rv  rw  r  r  rz  rx  r  rs  rt  r}  r  r  r~  r  r|  r  rr  r  r  rA   rX  rV  )r-   )/r.   r/   r0   r1   r2   rb  r   propertyr\  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=  rK  rQ  rC  r[  r  rP  rD  rG  rE  rF  rH  r9   r-   r:   r;   r    r      sz    !n. -1	n.
  "n. "&n. .2n. n. 15n. 8<n. /3n.`  
 ( ( % %!"" V6
 .6)38)V6B:>6!F
0 
D6+p2$=@BB3PjB*L&Q 6*J$
LL"GG Gr:   )rl  rm  r    r!   r"   r#   r$   r%   i   )Lr2   
__future__r   r  enumloggingrf   dataclassesr   r   typingr   r   urllib.parser   packaging.utilsr   rw  nab_index.cacher	   r
   r   r   nab_index.cached_clientr   r   r   nab_index.clientr   r   nab_index.lazy_wheelr   r   nab_index.local_indexr   r   r   nab_index.multi_indexr   r   nab_index.serializationr   nab_index.transportr   r   _vendor.packaging.utilscollections.abcr   r   r   typing_extensionsr   __all__rl  rm  r  r  pathlibr'   r(   	getLoggerr.   r  Enumr!   r$   rK   r"   r%   ra   rm   rq   r#   r   r  r    r-   r:   r;   <module>r     s`  	 #     ( % ! K N N 
 2 B O O ? 7 A 6;;&	  .  %' ! & 6			8	$&		 & $d#  $L $d#	3 	3 $	3 ! ! !&   
:4]I ]IB D..5
zG zGr:   