+
    2j                        R t ^ RIHt ^ RIHt ^RIHt ^RIHt RR.t	 ! R R]
4      t]! RRR	7       ! R
 R4      4       tR R ltR# )a  Direct-URL archive requirement parsing for nab-index.

Parses a pip-style archive URL such as
``https://example.com/foo-1.0.tar.gz#sha256=<hex>&subdirectory=pkg`` into
its bare URL, the declared hashes, and any subdirectory.

The download happens in the fetch coordinator, which reads the URL by its
own scheme; which archives are permitted is a policy decision in
:mod:`nab_python.config`.
)annotations)	dataclass)ACCEPTED_HASH_ALGORITHMS)subdirectory_escapesArchiveRequestArchiveRequestErrorc                      ] tR t^tRtRtR# )r   z,Raised when an archive URL cannot be parsed. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r	       \/home/user/billing-ledger-validation/.venv/lib/python3.14/site-packages/nab_index/archive.pyr   r      s    6r   T)frozenslotsc                  j    ] tR t^t$ RtR]R&   R]R&   RtR]R&   ]R R	 l4       t]	R
 R l4       t
RtR# )r   a/  Parsed representation of a direct-URL archive requirement.

``url`` is the archive URL with the ``#`` fragment stripped.
``hashes`` is the tuple of ``(algorithm, hex-digest)`` pairs read
from the fragment.  ``subdirectory`` is the project root inside the
extracted tree, or ``""`` for the archive root.
strurlztuple[tuple[str, str], ...]hashes subdirectoryc                   V ^8  d   QhRR/# )   returnboolr	   )formats   "r   __annotate__ArchiveRequest.__annotate__,   s     N N Nr   c                    \        V P                  4      ;'       dI    \        ;QJ d&    R V P                   4       F  '       d   K   R# 	  R# ! R V P                   4       4      # )zWhether every declared hash carries a non-empty digest.

PEP 751 requires an archive hash, so a URL with no hash fragment or a
present algorithm with an empty digest (``#sha256=``) has none.
c              3  *   "   T F	  w  rVx  K  	  R # 5i)Nr	   ).0_digests   &  r   	<genexpr>1ArchiveRequest.has_usable_hash.<locals>.<genexpr>2   s     (MIAs   FT)r   r   all)selfs   &r   has_usable_hashArchiveRequest.has_usable_hash+   sF     DKK MMSS(M(MSSMSMS(M(M%MMr   c                    V ^8  d   QhRRRR/# )r   raw_urlr   r   r   r	   )r   s   "r   r   r    5   s     !M !MC !MN !Mr   c           	        VP                  R4      w  r#p. pRpVP                  R4       F  pV'       g   K  VP                  R4      w  rp
V	'       g   RV: RV: 2p\        V4      hVR8X  d   T
pKI  V\        9   d#   VP	                  WP                  4       34       Kv  RV: RV: R	R
P                  \        4       R2p\        V4      h	  \        Wa4       V ! V\        V4      VR7      # )aU  Split ``raw_url`` into its URL, hashes, and subdirectory.

The fragment holds ``&``-separated ``key=value`` parts: a
recognised hash algorithm (see :data:`ACCEPTED_HASH_ALGORITHMS`)
or ``subdirectory``.  Any other key raises
:class:`ArchiveRequestError`; requiring a hash is left to the
config layer so the error names the offending source.
#r   &=zmalformed archive URL fragment  in r   z!unknown archive URL fragment key z; expected one of z, z or subdirectory)r   r   r   )		partitionsplitr   r   appendlowerjoin_reject_unsafe_subdirectorytuple)clsr-   r   r$   fragmentr   r   partkeysepvaluemsgs   &&          r   parseArchiveRequest.parse4   s     #,,S1(*NN3'D"nnS1OCe7xtG;O)#..n$$00sKKM23 8wd7+ N((,		2J(K'L&' 
 *#..# (& 	$L:s5=|LLr   r	   N)r
   r   r   r   r   __annotations__r   propertyr*   classmethodrA   r   r	   r   r   r   r      sH     
H''L#N N !M !Mr   c               $    V ^8  d   QhRRRRRR/# )r   r   r   r-   r   Noner	   )r   s   "r   r   r   Y   s!     ' 'c 'C 'D 'r   c                R    \        V 4      '       d   RV : RV: 2p\        V4      hR# )z6Refuse a subdirectory that escapes the extracted tree.zunsafe archive subdirectory r2   N)r   r   )r   r-   r@   s   && r   r8   r8   Y   s0    L)),\,<DL!#&& *r   N)r   
__future__r   dataclassesr   clientr   subdirr   __all__	Exceptionr   r   r8   r	   r   r   <module>rO      s\   	 # ! , ( 7) 7 $d#8M 8M $8Mv'r   