
    qiH                        S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKrSSKrSSKrSSKrSSKJr  S r \
R,                  SS S:X  a  S rOSSKrS r  " S
 S5      r " S S\R:                  5      rSrS r S r!SS.S jr"SSSSS\RF                  RH                  SS4S jr%S r&/ r'Sr( " S S\)5      r*SS jr+g! \ a    SSKrSSKrS	 r Nzf = f)a  Extensions to unittest for web frameworks.

Use the :py:meth:`WebCase.getPage` method to request a page
from your HTTP server.

Framework Integration
=====================
If you have control over your server process, you can handle errors
in the server-side of the HTTP conversation a bit better. You must run
both the client (your :py:class:`WebCase` tests) and the server in the
same process (but in separate threads, obviously).
When an error occurs in the framework, call server_error. It will print
the traceback to stdout, and keep any assertions you have from running
(the assumption is that, if the server errors, the page output will not
be of further significance to your tests).
    N)always_iterablec                 "    U S:X  a  gU S:X  a  gU $ )zReturn an IP address for a client connection given the server host.

If the server is listening on '0.0.0.0' (INADDR_ANY)
or '::' (IN6ADDR_ANY), this will return the proper localhost.
z0.0.0.0	127.0.0.1z::z::1 )hosts    I/home/kali/flask_env/lib/python3.13/site-packages/cheroot/test/webtest.py	interfacer	   %   s     yt|K       javac                  @    [         R                  R                  S5      $ Get a key press.   )sysstdinreadr   r
   r   getcharr   8   s     99>>!$$r
   c                  ,    [         R                  " 5       $ )r   )msvcrtgetchr   r
   r   r   r   @   s    <<>!r
   c                     [         R                  R                  5       n [        R                  " U 5      n [
        R                  " [         R                  R                  5       5        [         R                  R                  S5      n[        R                  " U [        R                  U5        U$ ! [        R                  " U [        R                  U5        f = fr   )
r   r   filenotermios	tcgetattrttysetrawr   	tcsetattr	TCSADRAIN)fdold_settingschs      r   r   r   H   s    YY((,	CJJsyy'')*"Bb'"3"3\B	 b'"3"3\Bs   AB/ /(Cc                   (    \ rS rSrSrS rSS jrSrg)NonDataPropertyU   zNon-data property decorator.c                 R    Uc   S5       e[        U5      (       d   S5       eXl        g)zInitialize a non-data property.Nzfget cannot be nonezfget must be callable)callablefget)selfr(   s     r   __init__NonDataProperty.__init__X   s-    6!66~~666~	r
   Nc                 .    Uc  U $ U R                  U5      $ )zReturn a class property.r(   )r)   objobjtypes      r   __get__NonDataProperty.__get__^   s    ;Kyy~r
   r-   N)__name__
__module____qualname____firstlineno____doc__r*   r0   __static_attributes__r   r
   r   r$   r$   U   s    &r
   r$   c                   v   \ rS rSrSrSrSr\R                  R                  r
SrSrSrSrSrSrSrSrSr\S	 5       rS S
 jrS!S jr\S 5       r\R2                  S 5       rS r     S"S jr\S 5       rSrS r\S 5       r S r!S#S jr"S$S jr#S#S jr$S#S jr%S#S jr&S#S jr'S#S jr(S#S jr)S#S jr*S%S jr+Sr,g)&WebCasee   zHelper web test suite base.r   @  HTTP/1.1httpNutf-8c                 p    U R                   R                  5        S3n[        [        R                  U5      $ )zeReturn HTTPConnection or HTTPSConnection based on self.scheme.

* from :py:mod:`python:http.client`.

Connection)schemeuppergetattrr>   client)r)   cls_names     r   _ConnWebCase._Conny   s/     kk'')**5t{{H--r
   c                     U R                  U R                  5       U R                  5      nXl        UR	                  5         U$ )z'Return a connection to our HTTP server.)rG   r	   PORT	auto_openconnect)r)   rK   conns      r   get_connWebCase.get_conn   s0    zz$..*DII6"r
   c                    [         R                  " [        [        5         U R                  R                  5         SSS5        U(       a  U R                  US9U l        gU R                  U l        g! , (       d  f       N<= f)a)  Make our HTTP_CONN persistent (or not).

If the 'on' argument is True (the default), then self.HTTP_CONN
will be set to an instance of HTTP(S)?Connection
to persist across requests.
As this class only allows for a single open connection, if
self already has an open connection, it will be closed.
N)rK   )
contextlibsuppress	TypeErrorAttributeError	HTTP_CONNcloserN   rG   )r)   onrK   s      r   set_persistentWebCase.set_persistent   sY       N;NN  " < 35DMMIM. 	:>** 	 <;s   A11
A?c                 .    [        U R                  S5      $ )z+Presence of the persistent HTTP connection.	__class__)hasattrrU   r)   s    r   
persistentWebCase.persistent   s     t~~{33r
   c                 &    U R                  U5        g r2   )rX   )r)   rW   s     r   r^   r_      s    Br
   c                 ,    [        U R                  5      $ )zReturn an IP address for a client connection.

If the server is listening on '0.0.0.0' (INADDR_ANY)
or '::' (IN6ADDR_ANY), this will return the proper localhost.
)r	   HOSTr]   s    r   r	   WebCase.interface   s     ##r
   c                    S[         l        [        U[        5      (       a  UR	                  S5      n[        U[        5      (       a  UR	                  S5      nU=(       d    SnXl        SU l        [        R                  " 5       n[        UUUUU R                  U R                  U R                  U=(       d    U R                  UU R                  S9
n[        R                  " 5       U-
  U l        Uu  U l        U l        U l        U R                   V	V
s/ s H  u  pU	R!                  5       S:X  d  M  SU
4PM!     sn
n	U l        [         R                  (       a  [         eU$ s  sn
n	f )a  Open the url with debugging support.

Return status, headers, body.

url should be the identifier passed to the server, typically a
server-absolute path and query string (sent between method and
protocol), and should only be an absolute URI if proxy support is
enabled in the server.

If the application under test generates absolute URIs, be sure
to wrap them first with :py:func:`strip_netloc`::

    >>> class MyAppWebCase(WebCase):
    ...     def getPage(url, *args, **kwargs):
    ...         super(MyAppWebCase, self).getPage(
    ...             cheroot.test.webtest.strip_netloc(url),
    ...             *args, **kwargs
    ...         )

``raise_subcls`` is passed through to :py:func:`openURL`.
Fr?   r   N)raise_subclsssl_contextz
set-cookieCookie)ServerErrorrW   
isinstancestrencodeurltimeopenURLrb   rJ   rU   PROTOCOLrf   statusheadersbodylowercookies)r)   rl   rq   methodrr   protocolre   startresultkvs              r   getPageWebCase.getPage   s   < c3**W%CdC  ;;w'D $)r			IIIINN%%((
 IIK%'	/5,T\49 '+ll
&2daaggi<6OMXqMl
 >>
s   E1Ec                     [         R                  R                  SS5      n[        [        R
                  " UR                  5       5      5      nU(       a  [        R                  " S[        SS9  U$ )zDetermine whether tests are run in interactive mode.

Load interactivity setting from environment, where
the value can be numeric or a string like true or
False or 1 or 0.
WEBTEST_INTERACTIVETruezhInteractive test failure interceptor support via WEBTEST_INTERACTIVE environment variable is deprecated.r   )
stacklevel)
osenvirongetbooljsonloadsrs   warningswarnDeprecationWarning)r)   env_stris_interactives      r   interactiveWebCase.interactive   sU     **..!6?djj9:MMJ"	 r
      c                    [        5         [        SU-  5        U R                  (       d  U R                  U5      eSn[        R                  R                  U5        [        R                  R                  5          [        5       R                  5       n[        U[        5      (       d  UR                  S5      nUS;  a  MG  [        UR                  5       5        US:X  a  [        U R                  R                  5       5       H  u  pEUS-   U R                  -  S:X  a^  [        R                  R                  S5        [        5       R!                  5       n[        R                  R                  S	5        US
:X  a    O[        U5        M     OUS:X  a!  ["        R"                  " U R$                  5        OqUS:X  a  [        U R&                  5        OUUS:X  a  [        U R(                  5        O9US:X  a  g US:X  a  U R                  U5      eUS:X  a  [        R*                  " 5         [        R                  R                  U5        [        R                  R                  5         GM  )Nz    ERROR: %szO    Show: [B]ody [H]eaders [S]tatus [U]RL; [I]gnore, [R]aise, or sys.e[X]it >> asciiBHSUIRXBr   r   z<-- More -->z            qHSUIRX)printr   failureExceptionr   stdoutwriteflushr   rC   ri   rj   decode	enumeraterr   
splitlinesconsole_heightrs   pprintrq   rp   rl   exit)r)   msgpixlinems          r   _handlewebErrorWebCase._handlewebError  s   o#$'',,3 	

 	



	!Aa%%HHW%	!!'')Cx()=)=)?@GAA!4!449

(()9:#IOO-

(()9:8!$K  A cdll+cdkk"cdhhcc++C00c
JJQJJA r
   c                 2    [        U R                  SS 5      $ )zInteger HTTP status code.N   )intrp   r]   s    r   status_codeWebCase.status_code3  s     4;;r?##r
   c                 d    [        U[        5      (       a  U R                  OU R                  nX:H  $ )z-Check whether actual status matches expected.)ri   r   r   rp   )r)   expectedactuals      r   status_matchesWebCase.status_matches8  s(    %/#%>%>!!DKK!!r
   c                     [        [        U R                  [        U5      5      5      (       a  gSU R                   SU 3nU R                  U=(       d    U5        g)zwFail if self.status != status.

status may be integer code, exact string status, or
iterable of allowed possibilities.
NzStatus z does not match )anymapr   r   rp   r   )r)   rp   r   tmpls       r   assertStatusWebCase.assertStatus=  sM     s4&&(?@AA%5fX>S[D)r
   c                     UR                  5       nU R                   H1  u  pVUR                  5       U:X  d  M  Ub  [        U5      U:X  d  M/  Us  $    Uc  Uc  SU-  nO
U< SU< S3nU R                  U5        g)z+Fail if (key, [value]) not in self.headers.Nz%r not in headers:z not in headers)rs   rq   rj   r   )r)   keyvaluer   lowkeyry   rz   s          r   assertHeaderWebCase.assertHeaderI  sp    LLDAwwyF"=CJ!OH !
 ;})C/03U;S!r
   c                 "   UR                  5       nU R                   HI  u  pVUR                  5       U:X  d  M  U Vs/ s H  n[        U5      U:X  d  M  UPM     nnU(       d  MG  Us  $    Uc  S[        5       -  nU R	                  U5        gs  snf )z?Fail if header indicated by key doesn't have one of the values.Nz%(key)r not in %(values)r)rs   rq   rj   varsr   )	r)   r   valuesr   r   ry   rz   r   matchess	            r   assertHeaderInWebCase.assertHeaderInY  s}    LLDAwwyF".4HfUE
a5fH7"N	 ! ;-6CS! Is   BBc                     U R                  XS9n[        [        R                  UR	                  S5      5      nX%;   a  U$ Uc	  U< SU< 3nU R                  U5        g)z8Fail if the header does not contain the specified value.)r   ,Nz not in )r   r   rj   stripsplitr   )r)   r   r   r   actual_valueheader_valuess         r   assertHeaderItemValueWebCase.assertHeaderItemValueg  s[    (((6CII|'9'9#'>?!L;$)=9CS!r
   c                     UR                  5       nU R                   VVs/ s H  u  pEUR                  5       U:X  d  M  UPM     nnnU(       a  Uc  SU-  nU R                  U5        ggs  snnf )zFail if key in self.headers.Nz%r in headersrs   rq   r   )r)   r   r   r   ry   rz   r   s          r   assertNoHeaderWebCase.assertNoHeaders  s_    !%Ef1D1E{%+  %  Fs
   A)A)c                     UR                  5       nU R                  nU VVs/ s H$  u  pgUR                  5       U:X  d  M  Xr:X  d  M"  UPM&     nnnU(       a"  Uc  U< SU< SU< 3nU R                  U5        ggs  snnf )z0Fail if the header contains the specified value.Nr   z in r   )	r)   r   r   r   r   hdrsry   rz   r   s	            r   assertNoHeaderItemValueWebCase.assertNoHeaderItemValue|  sl    ||!%Lf)<11L{'*E48  %  Ms   A: A:A:c                     [        U[        5      (       a  UR                  U R                  5      nXR                  :w  a)  Uc  SU< SU R                  < 3nU R                  U5        gg)zFail if value != self.body.Nzexpected body:
z

actual body:
ri   rj   rk   encodingrr   r   r)   r   r   s      r   
assertBodyWebCase.assertBody  sV    eS!!LL/EII{II   % r
   c                     [        U[        5      (       a  UR                  U R                  5      nXR                  ;  a(  Uc  U< SU R                  < 3nU R                  U5        gg)zFail if value not in self.body.Nz not in body: r   r   s      r   assertInBodyWebCase.assertInBody  sQ    eS!!LL/E		!{.3TYY?  % "r
   c                     [        U[        5      (       a  UR                  U R                  5      nXR                  ;   a  Uc  SU-  nU R                  U5        gg)zFail if value in self.body.Nz%r found in bodyr   r   s      r   assertNotInBodyWebCase.assertNotInBody  sM    eS!!LL/EII{(50  % r
   c                     [        U[        5      (       a  UR                  U R                  5      n[        R
                  " XR                  U5      c  Uc  SU-  nU R                  U5        gg)z4Fail if value (a regex pattern) is not in self.body.NzNo match for %r in body)ri   rj   rk   r   researchrr   r   )r)   patternr   flagss       r   assertMatchesBodyWebCase.assertMatchesBody  sX    gs##nnT]]3G99Wii/7{/'9  % 8r
   )rU   rr   rt   rq   rp   rm   rl   )F)TF)NGETNNr   r2   )NN)Nr   )-r3   r4   r5   r6   r7   rb   rJ   r>   rE   HTTPConnectionrU   ro   rB   rl   rf   rp   rq   rr   r   rm   propertyrG   rN   rX   r^   setterr	   r{   r$   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r8   r   r
   r   r:   r:   e   s   %DD**IHF
CKFGDHD. .
  4 4    $ AF  $ N.` $ $"

* 
&&
&&&&r
   r:   )POSTPUTPATCHc           	         U c  / n SnU  H  u  pgUR                  5       S:X  d  M  Sn  O   U(       d4  US:X  a  U R                  SU45        OU R                  SU< SU< 345        U[        ;   ak  SnU  H  u  pgUR                  5       S:X  d  M  Sn  O   U(       d?  U R                  S5        U R                  S	[        [	        U=(       d    S
5      5      45        U $ )zAReturn request headers, with required headers added (if missing).Fr   TP   Hostr   zcontent-type)zContent-Typez!application/x-www-form-urlencodedzContent-Length )rs   appendmethods_with_bodiesrj   len)rq   ru   rr   r   portfoundry   _vs           r   cleanHeadersr     s     E779E  2:NNFD>*NNFtT$:;<$$EAwwyN*  NNE NN,c#djb/.BCDNr
   c                 |    U R                   < SU R                  < 3nXR                  5       U R                  5       4$ )z=Return status, headers, body the way we like from a response. )rp   reason
getheadersr   )responseresp_status_lines     r   shbr    s/    "*//8??C002HMMOCCr
   r   )re   c                    ^  [         R                  " [        /UQ70 UD6nU 4S jn[        R                   R	                  USU[
        R                  S9$ )z
Open a URL, retrying when it fails.

Specify ``raise_subcls`` (class or tuple of classes) to exclude
those socket.error subclasses from being suppressed and retried.
c                     > [         R                  " 5       S   n [        U T5      (       a  U e[        R                  " S5        g )Nr   g      ?)r   exc_infori   rm   sleep)excre   s    r   on_exceptionopenURL.<locals>.on_exception  s0    llnQc<((I

3r
   	   )retriescleanuptrap)	functoolspartial_open_url_oncejaraco
retry_callsocketerror)re   argskwargsopenerr  s   `    r   rn   rn     sT     ~???F &&\\	 '  r
   r   r   r<   r=   c	           	         [        XX4U5      n[        US5      (       a  Un	O 0 n
U(       a  XS'   U" [        U5      U40 U
D6n	Xyl        [	        SR                  U Vs/ s H  oR                  5       (       d  M  UPM     sn5      5      U	l        [        U [        5      (       a  U R                  5       n U	R                  UR                  5       U SSS9  U H%  u  pU	R                  XR                  S5      5        M'     U	R                  5         Ub  U	R!                  U5        U	R#                  5       n[%        U5      u  nnn[        US5      (       d  U	R'                  5         UUU4$ s  snf )zBOpen the given HTTP resource and return status, headers, and body.r   contextr   T)	skip_hostskip_accept_encodingzLatin-1)r   r\   r	   _http_vsn_strr   joinisdigit	_http_vsnri   bytesr   
putrequestrC   	putheaderrk   
endheaderssendgetresponser  rV   )rl   rq   ru   rr   r   r   	http_connrv   rf   rM   kwr   r   r   r  shbs                     r   r  r    s7    7D=G y&!!'yM4$5"5!X!EX!X!EFGDN#ujjlOO!	   
sLL34 OO		$!H(mGAq!9f%%

a7N) "Fs   E'8E'c                     [         R                  R                  U 5      nUu  p#pEpgSSXEUS4n[         R                  R                  U5      $ )a  Return absolute-URI path from URL.

Strip the scheme and host from the URL, returning the
server-absolute portion.

Useful for wrapping an absolute-URI for which only the
path is expected (such as in calls to :py:meth:`WebCase.getPage`).

.. testsetup::

   from cheroot.test.webtest import strip_netloc

>>> strip_netloc('https://google.com/foo/bar?bing#baz')
'/foo/bar?bing'

>>> strip_netloc('//google.com/foo/bar?bing#baz')
'/foo/bar?bing'

>>> strip_netloc('/foo/bar?bing#baz')
'/foo/bar?bing'
r   )urllibparseurlparse
urlunparse)	rl   parsed_scheme_netlocpathparamsquery	_fragmentstrippeds	            r   strip_netlocr;     sI    , \\""3'F7=4GdE2tUB.H<<""8,,r
   Fc                       \ rS rSrSrSrSrg)rh   iF  z&Exception for signalling server error.Fr   N)r3   r4   r5   r6   r7   rW   r8   r   r
   r   rh   rh   F  s
    0	Br
   rh   c                     U c  [         R                  " 5       n [        (       d  U S   [        ;   a  gS[        l        [        5         [        SR                  [        R                  " U 6 5      5        g)zServer debug hook.

Return True if exception handled, False if ignored.
You probably want to wrap this, so you can still handle an error using
your framework when it's ignored.
r   FTr   )
r   r  
ignore_allignored_exceptionsrh   rW   r   r   	tracebackformat_exception)r
  s    r   server_errorrB  L  sS     {llnzSV11KN	G	"''),,c2
34r
   r2   ),r7   rQ   r  http.clientr>   r   r   r   r   r  r   rm   r@  unittesturllib.parser/  r   jaraco.functoolsr  more_itertools.morer   r	   platformr   r   ImportErrorr   r   r$   TestCaser:   r   r   r  rn   rE   r   r  r;  r?  r>  	Exceptionrh   rB  r   r
   r   <module>rL     s  "     	  	  
       /
||BQ6!	% 		"*  F&h F&R
 / DD !# 4 			kk((+\-<  
 
) S  	s   	C  C C#"C#