+
    2j                      a  0 t $ R t^ RIHt ^ RIt^ RIt^ RIHtHt ^ RI	H
t
HtHtHt ^RIHt ^RIHt ]
'       d   ^ RIHt . R1OtR R lt]! 4       tR]R
&   RRR]/tR]R&   RR/tR]R	&   RtR]R&   RtR]R&   ]! ^^04      tR]R&   ]! RR04      tR ]R!&    ! R" R]4      t ! R# R]4      t  ! R$ R]!4      t"R% R& lt#R' R( lt$R) R* lt% ! R+ R]4      t& ! R, R]4      t'R- R. lt(R/ R0 lt)R# )2zHTTP transport abstractions for nab-index.

Defines minimal protocols for async HTTP GET requests.
Implementations can use any async HTTP library (httpx, or urllib3
wrapped in to_thread, etc.).
)annotationsN)PackageNotFoundErrorversion)TYPE_CHECKINGAnyFinalProtocol)IndexAccessError)RETRY_STATUSES)MappingDEFAULT_HEADERSIDENTITY_HEADERS
USER_AGENTAsyncHttpTransportContentDecodingError	HttpErrorHttpResponseUnserveableUrlErrorc                   V ^8  d   QhRR/#    returnstr )formats   "^/home/user/billing-ledger-validation/.venv/lib/python3.14/site-packages/nab_index/transport.py__annotate__r   %   s     ) )S )    c                 D     R\        R4       2#   \         d     R# i ; i)zFReturn the ``nab-index/<version>`` name PyPI's API guidelines ask for.z
nab-index/z	nab-indexznab-index/0.0.0+unknown)r   r   r   r   r   _user_agentr   %   s,    )GK0122 )()s    z
Final[str]zAccept-Encodinggzipz
User-AgentzFinal[dict[str, str]]identityi  r   _HTTP_BAD_REQUESTi  _HTTP_SERVER_ERRORzFinal[frozenset[int]]_CONTENT_STATUSESzx-gzipzFinal[frozenset[str]]_GZIP_CODINGSc                      ] tR t^@tRtRtR# )r   zA request failed, or answered with a status the caller cannot use.

Transports raise this from ``get`` and ``raise_for_status`` so callers
can handle index failures without importing a specific HTTP backend.
r   N__name__
__module____qualname____firstlineno____doc____static_attributes__r   r   r   r   r   @   s    r   c                      ] tR t^HtRtRtR# )r   a  The index reached a verdict that it will not serve this URL.

Raised for a client-error status the retry policy does not treat as a
blip, so not a 408 or a 429: a 404 on an advertised PEP 658 sidecar, a
403, a 410.  The status is a property of the URL, so asking again gets
the same answer, and a caller may treat the artifact as unavailable.

A 5xx that outlived the retry budget, and a connection that failed,
stay a bare :class:`HttpError`.  Those say nothing about the URL, so a
caller must not read them as a verdict.
r   Nr'   r   r   r   r   r   H   s    
r   c                      ] tR t^VtRtRtR# )r   z@A response body did not decode as its Content-Encoding promised.r   Nr'   r   r   r   r   r   V   s    Jr   c                    V ^8  d   QhRRRR/# )r   paramsr   r   floatr   )r   s   "r   r   r   Z   s      S U r   c                    V P                  R4       FH  pVP                  R4      w  r#pVP                  4       P                  4       R8X  g   K<   \	        V4      u # 	  R#   \
         d      R# i ; i)zzReturn an Accept-Encoding entry's ``q`` value, 1.0 when it carries none.

A ``q`` that does not parse reads as a refusal.
;=qg        g      ?)split	partitionstriplowerr2   
ValueError)r1   paramkey_values   &    r   _qualityr@   Z   sh    
 c",99;#%U|#	 #   s   
A  A0/A0c                    V ^8  d   QhRRRR/# )r   request_headersMapping[str, str]r   boolr   )r   s   "r   r   r   i   s      "3  r   c                ^   V P                  4        UUu/ uF  w  rVP                  4       VbK  	  pppVP                  RR4      P                  R4       FO  pVP	                  R4      w  rVpVP                  4       P                  4       R8X  g   K<  \        V4      ^ 8  g   KN   R# 	  R# u uppi )aJ  Whether ``request_headers`` asked the server for gzip.

A static file server derives Content-Encoding from the filename, so it
serves a ``.tar.gz`` as its own untouched bytes under
``Content-Encoding: gzip``. Decoding that yields a bare tar, which no
published digest covers, so only a coding the request asked for may be
undone.
zaccept-encoding ,r4   r    TF)itemsr:   getr7   r8   r9   r@   )rB   namer?   foldedentrycodingr>   r1   s   &       r   accepts_gziprN   i   s     6E5J5J5LM5LkddjjlE!5LFM-r288=!OOC06<<>!V+0@10D >  Ns   B)c               $    V ^8  d   QhRRRRRR/# )r   bodybytescontent_encodingz
str | Noner   r   )r   s   "r   r   r   z   s!     1 1e 1z 1e 1r   c                $   V '       d   Vf   V # VP                  4       P                  4       \        9  d   V #  \        P                  ! V 4      #   \
        \        P                  \        P                  3 d   pRT 2p\        T4      ThRp?ii ; i)aC  Return ``body`` decoded per ``content_encoding``.

Transports fetch bodies undecoded and decode them here: the HTTP
libraries' own gzip decoders accept a stream cut before its trailer
and hand back a silent prefix under a 200, while :func:`gzip.decompress`
checks the trailer (CRC and length) and turns the truncation into
:class:`ContentDecodingError`.

Only gzip is handled, the one coding the transports advertise; any
other coding passes through untouched. An empty body also passes
through: a bodiless response (a 304) may still carry the
representation's Content-Encoding.
Nz,gzip response body is truncated or corrupt: )
r9   r:   r%   r    
decompressEOFErrorzliberrorBadGzipFiler   )rP   rR   excmsgs   &&  r   decode_bodyr[   z   s     #+%%'}<1t$$djj$"2"23 1<SEB"3'S01s   A *B9B

Bc                      ] tR t^tRt]R R l4       t]R R l4       t]R R l4       t]R R	 l4       t	]R
 R l4       t
R R ltR R ltRtR# )r   zAMinimal HTTP response shape, shared by sync and async transports.c                   V ^8  d   QhRR/# )r   r   intr   )r   s   "r   r   HttpResponse.__annotate__   s      S r   c                    R# )z&HTTP status code (e.g. 200, 304, 404).Nr   selfs   &r   status_codeHttpResponse.status_code        	r   c                   V ^8  d   QhRR/# r   r   )r   s   "r   r   r_      s      S r   c                    R# )zAbsolute URL the body was retrieved from, after any redirect.

RFC 3986 section 5.1.3: this, not the requested URL, is the base a
relative URL inside the body resolves against.
Nr   ra   s   &r   urlHttpResponse.url   s     	r   c                   V ^8  d   QhRR/# )r   r   rC   r   )r   s   "r   r   r_      s      * r   c                    R# )z<Response headers, case-insensitive lookup by lowercased key.Nr   ra   s   &r   headersHttpResponse.headers   re   r   c                   V ^8  d   QhRR/# )r   r   rQ   r   )r   s   "r   r   r_      s       r   c                    R# )zResponse body as bytes.Nr   ra   s   &r   contentHttpResponse.content   re   r   c                   V ^8  d   QhRR/# r   r   )r   s   "r   r   r_            c r   c                    R# )zResponse body as text.Nr   ra   s   &r   textHttpResponse.text   re   r   c                   V ^8  d   QhRR/# )r   r   r   r   )r   s   "r   r   r_      rs   r   c                    R# )zResponse body parsed as JSON.Nr   ra   s   &r   jsonHttpResponse.json   s    r   c                   V ^8  d   QhRR/# r   r   Noner   )r   s   "r   r   r_      s      $ r   c                    R# )znRaise :class:`HttpError` for 4xx/5xx responses.

Not a gate on reading the body; see :func:`raise_unless_ok`.
Nr   ra   s   &r   raise_for_statusHttpResponse.raise_for_status   s    
 	r   r   N)r(   r)   r*   r+   r,   propertyrc   rh   rl   rp   ru   ry   r   r-   r   r   r   r   r      sv    K          r   c                  :    ] tR t^tRtRR/R R lltR R ltRtR# )	r   zMinimal async HTTP transport for Simple API access.

Implementations are responsible for connection pooling and
HTTP version negotiation. Concurrency limits are managed by
the caller (e.g. via asyncio.Semaphore).
rl   Nc               $    V ^8  d   QhRRRRRR/# )r   rh   r   rl   zdict[str, str] | Noner   r   r   )r   s   "r   r   AsyncHttpTransport.__annotate__   s$     
 

$9
	
r   c                  "   R# 5i)zSend a GET request and return the response.

An implementation must not decode a coding ``headers`` did not ask
for; see :func:`accepts_gzip`.

Raises :class:`HttpError` on a connection or transport failure.
Nr   )rb   rh   rl   s   &&$r   rI   AsyncHttpTransport.get   s
      	   c                   V ^8  d   QhRR/# r|   r   )r   s   "r   r   r      s      d r   c                   "   R# 5i)zRelease resources.Nr   ra   s   &r   acloseAsyncHttpTransport.aclose   s     r   r   )r(   r)   r*   r+   r,   rI   r   r-   r   r   r   r   r      s    
<@
 r   c               $    V ^8  d   QhRRRRRR/# )r   statusr^   rh   r   r   r}   r   )r   s   "r   r   r      s!      3 S T r   c                    V \         8  d   R# RV  RV 2pV \        8  d   V \        9  d   \        V4      h\	        V4      h)a  Raise :class:`HttpError` for a 4xx/5xx ``status``.

A client error outside :data:`~nab_index.retry.RETRY_STATUSES` raises the
:class:`UnserveableUrlError` subclass: the retry policy calls those the
index's answer rather than a blip, so they name the URL, not the moment.
NHTTP  for )r"   r#   r
   r   r   )r   rh   rZ   s   && r   raise_for_error_statusr      sG     !!&se
$C""v^'C!#&&
C.r   c               $    V ^8  d   QhRRRRRR/# )r   responser   rh   r   r   r}   r   )r   s   "r   r   r      s!      l   r   c                    V P                  4        V P                  \        9  d   RV P                   RV R2p\        V4      hR# )ax  Raise :class:`HttpError` unless ``response`` carries the requested content.

:meth:`HttpResponse.raise_for_status` clears everything under 400, but a
204 has no content (RFC 9110 section 15.3.5) and a 3xx a transport did not
follow names another resource (section 15.4). A 203 passes with the 200:
its body is the representation a transforming proxy rewrote (section
15.3.4).
r   r   z is not the requested contentN)r   rc   r$   r   )r   rh   rZ   s   && r   raise_unless_okr      sJ     #44h**+55RSn 5r   )r   r   r   r   r   r   r   r   rN   r[   r   r   )*__conditional_annotations__r,   
__future__r   r    rV   importlib.metadatar   r   typingr   r   r   r   errorsr	   retryr
   collections.abcr   __all__r   r   __annotations__r   r   r"   r#   	frozensetr$   r%   r   r   	Exceptionr   r@   rN   r[   r   r   r   r   )r   s   @r   <module>r      s   #   < 6 6 $ !' ) %
J & v**&  ,=j*I ' I 5  E +4c3Z+@ ( @ (1&(1C'D$ D  ) K9 K"12)8 )X 2r   