+
    4jG(                    \   R t ^ RIHt ^ RIt^ RIt^ RIHt ^RIHtH	t	 ]'       d   ^ RI
Ht ^RIHt . R'Ot^ t^t^ t^t^t^t^ t^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 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# )(a  Codec for the parsed-listing cache: records <-> opaque cache blob.

Stores the post-:func:`nab_index.client._parse_files` records so a warm
resolve skips ``json.loads`` and wheel/sdist filename parsing. This module
owns the record<->bytes translation; :class:`~nab_index.cache.OnDiskCache`
treats the blob as opaque and knows nothing about record shapes.

Wire form (UTF-8 JSON of ``[header, rows]``):

* header ``[format, codec, key_scheme, body_digest]`` is checked before
  anything is trusted. A reader on a different ``format``, ``codec``, or
  ``key_scheme`` treats the entry as a miss and rebuilds, so a cache written by
  an older build self-heals instead of misdecoding. ``body_digest`` binds the
  blob to the raw body it was parsed from; :func:`decode` rejects a blob whose
  digest does not equal the policy's, so a raw-body update invalidates the
  derived form.
* rows hold one entry per surviving record, in the order the wire parse
  returned them, so a downstream stable-sort tie-break stays identical. Each
  row is a flat list tagged wheel or sdist by its first element. Every field is
  type-checked on the way back, and ``requires_python`` and hash-algorithm
  names are re-interned via ``sys.intern`` so the round trip reproduces the
  dedup the wire parse builds.

The blob is portable: one entry serves every interpreter that shares the cache,
and a body this module will not parse is a miss, never an exception reaching
the caller.
)annotationsN)TYPE_CHECKING)	SdistFile	WheelFile)Sequence)CachePolicyc                      ] tR t^=tRtRtR# )_BadRowErrorzEA row whose tag, arity, or field types are not what this codec wrote. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r
       j/home/user/pdf2html-billing-ledger-validate/.venv/lib/python3.14/site-packages/nab_index/parsed_listing.pyr	   r	   =   s    Or   r	   c               $    V ^8  d   QhRRRRRR/# )   fileslist[WheelFile | SdistFile]body_digeststrreturnbytesr
   )formats   "r   __annotate__r   A   s"     * *- *C *E *r   c                t   . pV  F  p\        V\        4      '       d|   VP                  \        VP                  VP
                  VP                  VP                  VP                  VP                  VP                  VP                  VP                  .
4       K  VP                  \        VP                  VP
                  VP                  VP                  VP                  VP                  VP                  .4       K  	  \        \        \         V.p\"        P$                  ! WB.RRR7      P'                  4       # )a|  Encode parsed listing ``files`` into a cache blob bound to ``body_digest``.

``body_digest`` is the sha256 hex of the raw body the records were parsed
from; :func:`decode` rehydrates only when it matches the policy's digest.
``local_path`` is not stored (a parsed-cache entry always comes from a
remote body) and ``metadata_url`` is a derived property, so neither rides
the wire.
F)ensure_ascii
separators),:)
isinstancer   append
_TAG_WHEELfilenameurlversionrequires_pythonhas_metadataupload_timehashessizemetadata_hash
_TAG_SDISTFORMAT_VERSIONCODEC
KEY_SCHEMEjsondumpsencode)r   r   rowsrecordheaders   &&   r   r4   r4   A   s      "Dfi((KKOOJJNN**''&&MMKK(( KKOOJJNN**&&MMKK	# : eZ=F::	Uzfhr   c               $    V ^8  d   QhRRRRRR/# )r   blobr   policyr   r   z"list[WheelFile | SdistFile] | Noner
   )r   s   "r   r   r   n   s"     ! ! ! !0R !r   c                    \         P                  ! V 4      p\        T\        4      '       d   \        T4      \        8X  g   R# Tw  r4\        T\        4      '       d   \        T4      \        8X  g   R# Tw  rVrxT\        8w  g5   T\        8w  g*   T\        8w  g   TP                  e   YP                  8w  d   R#  \        T4      #   \         d     R# i ; i  \        \        3 d     R# i ; i)a  Decode a cache blob back to parsed records, or ``None`` to force a miss.

Returns ``None`` (treat as a cache miss and rebuild from the raw body) when
the blob does not decode, is the wrong shape, was written by a different
build (``format`` / ``codec`` / ``key_scheme``), or is not bound to
``policy``'s body (``body_digest``).  Otherwise rehydrates the records,
re-interning ``requires_python`` and hash-algorithm names so string identity
matches a fresh parse.
N)r2   loads
ValueErrorr"   listlen_TOP_LEN_HEADER_LENr/   r0   r1   r   _decode_rows	TypeError)	r9   r:   loadedr7   r5   format_codec
key_schemer   s	   &&       r   decoderH   n   s    D! vt$$V)@LFvt$$V)C.4+GJ>!E>#%,,,D!!'  ( 	" s#   C ;
C CCC-,C-c                    V ^8  d   QhRRRR/# )r   r9   r   r   
str | Noner
   )r   s   "r   r   r      s      E j r   c                    \         P                  ! V 4      p\        T\        4      '       d   \        T4      \        8X  g   R# Tw  r#\        T\        4      '       d   \        T4      \        8X  g   R# Tw  rErgT\        8w  g   T\        8w  g   T\        8w  d   R#  \        T4       R#   \         d     R# i ; i  \        \        3 d     R# i ; i)an  Return a reason if ``blob`` is structurally corrupt, else ``None``.

Distinguishes genuine corruption (garbage or truncated bytes, or a
same-build blob whose rows are the wrong shape) from a benign miss, where
the header names a different build or binds a different body. The read path
warns only on the former. The row check runs only once the header names this
exact build, since a foreign build may have written a shape this one never
did; checking it earlier would misreport version skew as corruption. This is
a second pass used only to gate that warning; :func:`decode` returns ``None``
for every miss reason alike.
znot valid JSONzunexpected top-level shapezunexpected header shapeNzunexpected row shape)r2   r<   r=   r"   r>   r?   r@   rA   r/   r0   r1   rB   rC   )r9   rD   r7   r5   rE   rF   rG   _body_digests   &       r   corruption_reasonrM      s     D! vt$$V)@+LFvt$$V)C(/5,GJ. EUNjJ6N &T #     	" &%&s#   B* B< *B98B9<CCc                    V ^8  d   QhRRRR/# )r   r5   objectr   r   r
   )r   s   "r   r   r      s     . .v ."= .r   c                z    \        V \        4      '       g   \        hV  Uu. uF  p\        V4      NK  	  up# u upi )zHRehydrate every row, raising :class:`_BadRowError` on the first bad one.)r"   r>   r	   _decode_row)r5   rows   & r   rB   rB      s2    dD!!(,-K---s   8c                    V ^8  d   QhRRRR/# )r   rR   rO   r   zWheelFile | SdistFiler
   )r   s   "r   r   r      s      V  5 r   c                    \        V \        4      '       d	   V '       g   \        hV ^ ,          p\        V4      \        Jd   \        hV\
        8X  d   \        V 4      # V\        8X  d   \        V 4      # \        h)zDRehydrate one row, dispatching on the tag its first element carries.)	r"   r>   r	   typeintr$   _decode_wheelr.   _decode_sdist)rR   tags   & r   rQ   rQ      s^    c4  
a&CCy
jS!!
jS!!
r   c                    V ^8  d   QhRRRR/# )r   rR   Sequence[object]r   r   r
   )r   s   "r   r   r      s      ' I r   c                    V w
  ppppppppp	p
\        \        V4      \        V4      \        V4      \        V4      \        V4      \	        V4      \        V4      \        V	4      \        V
4      R 7	      # ))	r%   r&   r'   r(   r)   r*   r+   r,   r-   )r   _text_interned_or_none_flag_text_or_none_hashes_count_or_none_pair_or_none)rR   _r%   r&   r'   r(   r)   r*   r+   r,   r-   s   &          r   rW   rW      s{     		x#Jg)/:<(!+.vD!#M2
 
r   c                    V ^8  d   QhRRRR/# )r   rR   r[   r   r   r
   )r   s   "r   r   r      s     
 
' 
I 
r   c                    V w  rr4rVrx\        \        V4      \        V4      \        V4      \        V4      \        V4      \	        V4      \        V4      R 7      # ))r%   r&   r'   r(   r*   r+   r,   )r   r]   r^   r`   ra   rb   )	rR   rd   r%   r&   r'   r(   r*   r+   r,   s	   &        r   rX   rX      sQ    LOIAVx#Jg)/:!+.vD! r   c                    V ^8  d   QhRRRR/# )r   valuerO   r   r   r
   )r   s   "r   r   r      s       C r   c                8    \        V 4      \        Jd   \        hV # N)rU   r   r	   rh   s   &r   r]   r]      s    E{#Lr   c                    V ^8  d   QhRRRR/# r   rh   rO   r   rJ   r
   )r   s   "r   r   r      s     3 3 3J 3r   c                $    V f   R # \        V 4      # rj   )r]   rk   s   &r   r`   r`          =42eEl2r   c                    V ^8  d   QhRRRR/# rm   r
   )r   s   "r   r   r      s     ? ?V ?
 ?r   c                L    V f   R # \         P                  ! \        V 4      4      # rj   )sysinternr]   rk   s   &r   r^   r^      s      =4>cjju&>>r   c                    V ^8  d   QhRRRR/# )r   rh   rO   r   boolr
   )r   s   "r   r   r     s       D r   c                8    \        V 4      \        Jd   \        hV # rj   )rU   ru   r	   rk   s   &r   r_   r_     s    E{$Lr   c                    V ^8  d   QhRRRR/# )r   rh   rO   r   z
int | Noner
   )r   s   "r   r   r     s      & Z r   c                D    V f   R # \        V 4      \        Jd   \        hV # rj   )rU   rV   r	   rk   s   &r   rb   rb     s!    }E{#Lr   c                    V ^8  d   QhRRRR/# )r   rh   rO   r   ztuple[str, str]r
   )r   s   "r   r   r     s     . . .O .r   c                    \        V \        4      '       d   \        V 4      \        8w  d   \        h\        V ^ ,          4      \        V ^,          4      3# )    )r"   r>   r?   	_PAIR_LENr	   r]   rk   s   &r   _pairr}     s;    eT""c%jI&=%(OU58_--r   c                    V ^8  d   QhRRRR/# )r   rh   rO   r   ztuple[str, str] | Noner
   )r   s   "r   r   r     s     3 3 3$: 3r   c                $    V f   R # \        V 4      # rj   )r}   rk   s   &r   rc   rc     ro   r   c                    V ^8  d   QhRRRR/# )r   rh   rO   r   ztuple[tuple[str, str], ...]r
   )r   s   "r   r   r     s     S S6 S9 Sr   c                    \        V \        4      '       g   \        h\        ;QJ d"    . R \	        \
        V 4       4       F  NK  	  5# ! R \	        \
        V 4       4       4      # )z4Return the hash pairs with algorithm names interned.c              3  V   "   T F  w  r\         P                  ! V4      V3x  K!  	  R # 5irj   )rr   rs   ).0algodigests   &  r   	<genexpr>_hashes.<locals>.<genexpr>!  s"     R@Q#**T"F+@Qs   '))r"   r>   r	   tuplemapr}   rk   s   &r   ra   ra     sE    eT""5RE5@QR5R5RE5@QRRRr   )rM   rH   r4   )(r   
__future__r   r2   rr   typingr   clientr   r   collections.abcr   cacher   __all__r/   r0   r1   r@   rA   r|   r$   r.   r=   r	   r4   rH   rM   rB   rQ   rW   rX   r]   r`   r^   r_   rb   r}   rc   ra   r
   r   r   <module>r      s   8 #  
   (("
3  	
 
	

P: P*Z!HD.4
"3?.3Sr   