+
    2j5"                       R t ^ RIHt ^ RIt^ RIt^ RIHt ^ RIHt ^ RI	H
t
HtHt ^ RIHt . R"OtRtR	tR
tRtRtRtRt]! RRR7       ! R R4      4       tR R lt ! R R]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# )#zPEP 503 HTML project-page reading.

:pep:`691` allows an index to answer a JSON request with the HTML
serialization, so the ``file://`` index reader and the remote Simple-API
client both have to read the same anchor-tag shape.
)annotationsN)	dataclass)
HTMLParser)unquoteurljoinurlsplit)overrideAnchorzdata-requires-pythonzdata-yankedzdata-core-metadatazdata-dist-info-metadatazdata-upload-timezpypi:repository-versionz	
 T)frozenslotsc                  N    ] tR t^%t$ RtR]R&   R]R&   R]R&   R]R&   R]R	&   R
tR# )r	   a  One ``<a>`` link on a project page.

``metadata`` is the :pep:`714` ``data-core-metadata`` value, falling back
to the legacy ``data-dist-info-metadata`` when only that is set, and
``None`` when the anchor declares neither.

``upload_time`` is the ``data-upload-time`` value. No specification
covers it (:pep:`700` defines ``upload-time`` for the JSON serialization
only), so an index is free to omit it, and PyPI and download.pytorch.org
both do. It is read because it is the only upload time an HTML page can
carry.
strhref
str | Nonerequires_pythonmetadataboolyankedupload_time N)__name__
__module____qualname____firstlineno____doc____annotations____static_attributes__r       \/home/user/billing-ledger-validation/.venv/lib/python3.14/site-packages/nab_index/_pep503.pyr	   r	   %   s%     ILr   c                    V ^8  d   QhRRRR/# )   attrslist[tuple[str, str | None]]returnzAnchor | Noner   )formats   "r   __annotate__r%   ;   s      / M r   c                8   RpRpRpRpRpRpV  F[  w  rxVR8X  d   TpK  V\         8X  d   TpK  V\        8X  d   RpK.  V\        8X  d   TpK=  V\        8X  d   TpKL  V\        8X  g   KY  TpK]  	  Vf   R# Ve   TMTp	\        VP                  \        4      W)W64      # )zJBuild an :class:`Anchor` from a tag's attributes, or ``None`` if hrefless.NFr   T)_REQUIRES_PYTHON_ATTR_YANKED_ATTR_CORE_METADATA_ATTR_LEGACY_METADATA_ATTR_UPLOAD_TIME_ATTRr	   strip_HTML_WHITESPACE)
r!   r   r   r   core_metadatalegacy_metadatar   namevaluer   s
   &         r   _anchorr2   ;   s    D"&OF $M"&O"K6>D**#O\!F((!M**#O&&K  | - 9}H

#$o r   c                  H   a  ] tR t^[tRtR V 3R llt]R R l4       tRtV ;t	# )_ProjectPageParserzCollect a project page's anchors and its first ``<base href>``.

Also records whether the page declares the :pep:`629` repository version.
c                   V ^8  d   QhRR/# )r    r#   Noner   )r$   s   "r   r%   _ProjectPageParser.__annotate__a   s     1 1$ 1r   c                	N   < \         SV `  4        . V n        R V n        RV n        R # )NF)super__init__anchors	base_hrefdeclares_repository_version)self	__class__s   &r   r:   _ProjectPageParser.__init__a   s$    %'%)+0(r   c               $    V ^8  d   QhRRRRRR/# )r    tagr   r!   r"   r#   r6   r   )r$   s   "r   r%   r7   h   s#     ( (3 (/K (PT (r   c                	8   VR 8X  d,   V F#  w  r4VR8X  g   K  V\         8X  g   K  RV n         R# 	  R# VR8X  d,   V P                  f   V F  w  r4VR8X  g   K  W@n         R# 	  R# VR8w  d   R# \        V4      pVe   V P                  P                  V4       R# R# )metar0   TNbaser   a)_REPOSITORY_VERSION_METAr=   r<   r2   r;   append)r>   rB   r!   r0   r1   anchors   &&&   r   handle_starttag"_ProjectPageParser.handle_starttagg   s    &=$6>e/G&G7;D4	  % &=~~%#(KDv~).	 $) #:LL' r   )r;   r<   r=   )
r   r   r   r   r   r:   r   rJ   r   __classcell__)r?   s   @r   r4   r4   [   s&    
1 1 ( (r   r4   c                    V ^8  d   QhRRRR/# )r    textr   r#   r4   r   )r$   s   "r   r%   r%      s       + r   c                <    \        4       pVP                  V 4       V# )z"Run the page parser over ``text``.)r4   feedrN   parsers   & r   _parserS      s    !F
KKMr   c                    V ^8  d   QhRRRR/# )r    rN   r   r#   ztuple[list[Anchor], str | None]r   )r$   s   "r   r%   r%      s     . .C .; .r   c                H    \        V 4      pVP                  VP                  3# )zReturn a project page's anchors and its ``<base href>``, if it has one.

Relative anchors resolve against the base href rather than the page
directory, matching how pip and uv read a Simple-repository page.
)rS   r;   r<   rQ   s   & r   	read_pagerV      s"     D\FNNF,,--r   c                    V ^8  d   QhRRRR/# )r    r1   r   r#   zbool | dict[str, str] | Noner   )r$   s   "r   r%   r%      s      
 /K r   c                    V f   R# V R8X  d   R# V P                  R4      w  rpV'       d   V'       d   V'       d   W/# R# )zTranslate a metadata-sidecar attribute value into its PEP 691 JSON form.

:pep:`658`/:pep:`714` set the value to ``true`` (sidecar exists, no
published hash) or ``<algo>=<hexdigest>``.  Anything else declares no
sidecar and yields ``None``.
NtrueT=)	partition)r1   algosepdigests   &   r   metadata_declarationr_      s;     },Dv
t~r   c                    V ^8  d   QhRRRR/# )r    fragmentr   r#   ztuple[tuple[str, str], ...]r   )r$   s   "r   r%   r%      s      C $? r   c                &   . pV P                  R4       Fp  pVP                  R4      w  r4pV'       d	   V'       g   K)  VP                  4       pV\        P                  9   g   KP  VP                  W5P                  4       34       Kr  	  \        V4      # )a  Read a URL fragment's hash declarations into the ``hashes`` tuple shape.

:pep:`503` carries the artefact's hash in the URL fragment; it is the only
place the hash appears when the index has not opted into :pep:`691` JSON.
The fragment is a ``&``-separated list of ``key=value`` parts, so a hash
can sit beside ``egg`` or ``subdirectory`` in any order.  A part keyed by
a ``hashlib`` algorithm and carrying a digest is a hash; anything else is
not.
&rZ   )splitr[   lowerhashlibalgorithms_guaranteedrH   tuple)ra   hashespartr\   r]   r^   s   &     r   hash_fragmentrk      sq     %'Fs# NN3/6&zz|7000MM401 $ =r   c               $    V ^8  d   QhRRRRRR/# )r    rI   r	   base_urlr   r#   zdict[str, object] | Noner   )r$   s   "r   r%   r%      s"          #  2J  r   c                     \        WP                  4      P                  R4      w  r#p\        \	        V4      P
                  P                  R^4      R,          4      pT'       g   R# RTRT/pT P                  e   T P                  TR&   \        \        T4      4      pT'       d   YvR&   \        T P                  4      pTe   YR&   T P                  e   T P                  TR	&   T P                  '       d   R
TR&   T#   \         d     R# i ; i)a  Render one anchor as a PEP 691 file entry, or ``None`` if it names no file.

An href with a malformed authority (an unterminated IPv6 bracket) makes
both the join and the split raise, so it is dropped like an href that
names no file rather than failing the whole listing.
#/Nfilenameurlzrequires-pythonri   zcore-metadatazupload-timeTr   )r   r   r[   r   r   pathrsplit
ValueErrorr   dictrk   r_   r   r   r   )	rI   rm   rr   _ra   rq   entryri   r   s	   &&       r   _file_entryrz      s    "8[[9CCCH8C=--44S!<R@A  *HeSAE)#)#9#9 -)*F h#FOO4H!)o%%11m}}}hL-  s   AC> >DDc               $    V ^8  d   QhRRRRRR/# )r    rN   r   page_urlr#   bytesr   )r$   s   "r   r%   r%      s!     $8 $8s $8c $8e $8r   c                  a
 \        V 4      pVP                  VP                  rCV'       g    VP                  '       g   Rp\	        V4      hVo
Ve    \        W4      o
V
3R lV 4       pV Uu. uF
  qf   K  VNK  	  p	p\        P                  ! RV	/4      P                  R4      #   \         d   pRT: RT 2p\	        T4      ThRp?ii ; iu upi )a  Re-serialize a PEP 503 project page as a PEP 691 JSON listing body.

Hrefs are resolved here, against the page's ``<base href>`` when it has
one and otherwise against ``page_url``, so the cached body stands on its
own.

Raises :class:`ValueError` when the page's ``<base href>`` cannot be
parsed. Every relative anchor resolves against it, so the whole page's
targets are unknown; the caller maps this to its own malformed-listing
error. A single unparseable anchor is dropped instead.

Also raises :class:`ValueError` for a page carrying neither a link nor
the :pep:`629` ``pypi:repository-version`` marker, since nothing in it
says it is a project page. An empty listing means "package absent" to
the multi-index router (see :func:`nab_index.client._parse_files`), so a
site error page served with a 200 would otherwise fall through to a
lower-priority index and risk pinning a different version.
zWbody has no links and no PEP 629 repository-version marker, so it is not a project pageNzunparseable <base href> z: c              3  <   <"   T F  p\        VS4      x  K  	  R # 5i)N)rz   ).0rI   rm   s   & r   	<genexpr>json_listing.<locals>.<genexpr>   s     C7{68,,7s   fileszutf-8)	rS   r;   r<   r=   rv   r   jsondumpsencode)rN   r|   rR   r;   r<   msgexcentriesry   r   rm   s   &&        @r   json_listingr      s    & D\F)9)9Y6===* 	 oH	+x3H D7CG '=uUUE=::w&'..w77  	+,YMC5ACS/s*	+ >s$   B& -C7C&C1CC)r	   rk   r   r_   rV   ) r   
__future__r   rf   r   dataclassesr   html.parserr   urllib.parser   r   r   typing_extensionsr   __all__r'   r(   r)   r*   r+   rG   r-   r	   r2   r4   rS   rV   r_   rk   rz   r   r   r   r   <module>r      s    #   ! " 3 3 & / * 1 & 4    $d#  $*@!( !(H.". F$8r   