+
    i:  c                   s,   R t R.t^ RIt^ RIt^ RIt]P
                  ! R4      t]P
                  ! R4      t ! R R]4      t	R t
R tR	 t ! R
 R4      t ! R R4      t ! R R4      t ! R R4      t ! R R4      tR tR tR tR tR tR tR tR tR# )a&  
Middleware to check for obedience to the WSGI specification.

Some of the things this checks:

* Signature of the application and start_response (including that
  keyword arguments are not used).

* Environment checks:

  - Environment is a dictionary (and not a subclass).

  - That all the required keys are in the environment: REQUEST_METHOD,
    SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors,
    wsgi.multithread, wsgi.multiprocess, wsgi.run_once

  - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the
    environment (these headers should appear as CONTENT_LENGTH and
    CONTENT_TYPE).

  - Warns if QUERY_STRING is missing, as the cgi module acts
    unpredictably in that case.

  - That CGI-style variables (that don't contain a .) have
    (non-unicode) string values

  - That wsgi.version is a tuple

  - That wsgi.url_scheme is 'http' or 'https' (@@: is this too
    restrictive?)

  - Warns if the REQUEST_METHOD is not known (@@: probably too
    restrictive).

  - That SCRIPT_NAME and PATH_INFO are empty or start with /

  - That at least one of SCRIPT_NAME or PATH_INFO are set.

  - That CONTENT_LENGTH is a positive integer.

  - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should
    be '/').

  - That wsgi.input has the methods read, readline, readlines, and
    __iter__

  - That wsgi.errors has the methods flush, write, writelines

* The status is a string, contains a space, starts with an integer,
  and that integer is in range (> 100).

* That the headers is a list (not a subclass, not another kind of
  sequence).

* That the items of the headers are tuples of strings.

* That there is no 'status' header (that is used in CGI, but not in
  WSGI).

* That the headers don't contain newlines or colons, end in _ or -, or
  contain characters codes below 037.

* That Content-Type is given if there is content (CGI often has a
  default content type, but WSGI does not).

* That no Content-Type is given when there is no content (@@: is this
  too restrictive?)

* That the exc_info argument to start_response is a tuple or None.

* That all calls to the writer are with strings, and no other methods
  on the writer are accessed.

* That wsgi.input is used properly:

  - .read() is called with exactly one argument

  - That it returns a string

  - That readline, readlines, and __iter__ return strings

  - That .close() is not called

  - No other methods are provided

* That wsgi.errors is used properly:

  - .write() and .writelines() is called with a string

  - That .close() is not called, and no other methods are provided.

* The response iterator:

  - That it is not a string (it should be a list of a single string; a
    string will work, but perform horribly).

  - That .__next__() returns a string

  - That the iterator is not iterated over until start_response has
    been called (that can signal either a server or application
    error).

  - That .close() is called (doesn't raise exception, only prints to
    sys.stderr, because we only know it isn't called when the object
    is garbage collected).
	validatorNz^[a-zA-Z][a-zA-Z0-9\-_]*$z[\000-\037]c                   s    ] tR t^ytRtRtR# )WSGIWarningz2
Raised in response to WSGI-spec-related warnings
 N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       )/usr/lib64/python3.14/wsgiref/validate.pyr   r   y   s    r	   r   c                 s(    V '       g
   \        V!  hR # N)AssertionError)Zcondargss   &*r
   assert_r   ~   s    d## r	   c                 st    \        V 4      \        J d   V # \        R P                  V\	        V 4      4      4      h)z!{0} must be of type str (got {1}))typestrr   ZformatZrepr)valueZtitle   &&r
   check_string_typer      s6    U|s
+225$u+FH Hr	   c                s   a  V 3R lpV# )a  
When applied between a WSGI server and a WSGI application, this
middleware will check for WSGI compliance on a number of levels.
This middleware does not modify the request or response in any
way, but will raise an AssertionError if anything seems off
(except for a failure to close the application iterator, which
will be printed to stderr -- there's no way to raise an exception
at that point).
c                  sT  <aa \        \        V 4      ^8H  R4       \        V'       * R4       V w  po\        V4       . oVV3R lp\        VR,          4      VR&   \	        VR,          4      VR&   S! W#4      p\        VRJ;'       d    VR8g  R4       \        V4       \        VS4      # )	   zTwo arguments requiredNo keyword arguments allowedc                  s~  < \        \        V 4      ^8H  ;'       g    \        V 4      ^8H  RV : 24       \        V'       * R4       V ^ ,          pV ^,          p\        V 4      ^8X  d   V ^,          pMRp\        V4       \        V4       \	        W#4       \        V4       SP                  R4       \        S! V !  4      # )r   zInvalid number of arguments: r   N)r   lencheck_statuscheck_headerscheck_content_typecheck_exc_infoZappendWriteWrapper)r   kwstatusheadersexc_infostart_responsestart_response_starteds   *,   r
   start_response_wrapperZ;validator.<locals>.lint_app.<locals>.start_response_wrapper   s    CIN44c$i1n59;>F:;!WF1gG4yA~7 '"v/8$"))$/ 566r	   
wsgi.inputwsgi.errorsNFz>The application must return an iterator, if only an empty list)r   r   check_environInputWrapperErrorWrappercheck_iteratorIteratorWrapper)r   r   environr"   iteratorr    r!   applications   *,   @@r
   lint_appZvalidator.<locals>.lint_app   s    D	Q 89B67"&g "$	7& !-W\-B C!-gm.D!Ew?$::U):L	N 	x x)?@@r	   r   )r,   r-   s   f r
   r    r       s    'AR Or	   c                   sD   a  ] tR t^t o R tR tR tR tR tR t	Rt
V tR# )	r&   c                    Wn         R # r   input)self
wsgi_inputr   r
   __init__ZInputWrapper.__init__   s    
r	   c                s    \        \        V4      ^8H  4       V P                  P                  ! V!  p\        \	        V4      \
        J 4       V# i   )r   r   r0   readr   bytesr1   r   v   &* r
   r5   ZInputWrapper.read   s:    D	QJJOOT"Q5 !r	   c                s    \        \        V4      ^8*  4       V P                  P                  ! V!  p\        \	        V4      \
        J 4       V# r4   )r   r   r0   readliner   r6   r7   r9   r
   r:   ZInputWrapper.readline   s<    D	QJJ&Q5 !r	   c                s    \        \        V4      ^8*  4       V P                  P                  ! V!  p\        \	        V4      \
        J 4       V F  p\        \	        V4      \        J 4       K  	  V# r4   )r   r   r0   	readlinesr   listr6   )r1   r   Zlineslines   &*  r
   r;   ZInputWrapper.readlines   sW    D	Q

$$d+Ut#$DDJ%'( r	   c              #  sJ   "   V P                  4       ;p'       d   Vx  K  R # 5ir   )r:   )r1   r=      & r
   __iter__ZInputWrapper.__iter__   s      mmo%d%J &s   ##c                    \        ^ R4       R# )    z input.close() must not be calledNr   r1      &r
   closeZInputWrapper.close   s    56r	   r/   N)r   r   r   r   r3   r5   r:   r;   r?   rE   r   __classdictcell__Z__classdict__   @r
   r&   r&      s(      7 7r	   r&   c                   s>   a  ] tR t^t o R tR tR tR tR tRt	V t
R# )r'   c                r.   r   errors)r1   wsgi_errorsr   r
   r3   ZErrorWrapper.__init__       !r	   c                sp    \        \        V4      \        J 4       V P                  P	                  V4       R # r   )r   r   r   rJ   writer1   Zsr   r
   rM   ZErrorWrapper.write   s$    Q3!r	   c                s:    V P                   P                  4        R # r   )rJ   flushrC   rD   r
   rO   ZErrorWrapper.flush   s    r	   c                s:    V F  pV P                  V4       K  	  R # r   )rM   )r1   Zseqr=   s   && r
   
writelinesZErrorWrapper.writelines   s    DJJt r	   c                r@   )rA   z!errors.close() must not be calledNrB   rC   rD   r
   rE   ZErrorWrapper.close   s    67r	   rI   N)r   r   r   r   r3   rM   rO   rP   rE   r   rF   rG   rH   r
   r'   r'      s#     "8 8r	   r'   c                   s,   a  ] tR t^t o R tR tRtV tR# )r   c                r.   r   writer)r1   Zwsgi_writerr   r
   r3   ZWriteWrapper.__init__   rL   r	   c                s\    \        \        V4      \        J 4       V P                  V4       R # r   )r   r   r6   rR   rN   r   r
   __call__ZWriteWrapper.__call__   s    Q5 !Ar	   rQ   N)r   r   r   r   r3   rS   r   rF   rG   rH   r
   r   r      s     " r	   r   c                   s,   a  ] tR t^t o R tR tRtV tR# )PartialIteratorWrapperc                r.   r   r+   )r1   wsgi_iteratorr   r
   r3   ZPartialIteratorWrapper.__init__   s    %r	   c                s.    \        V P                  R 4      # r   )r)   r+   rC   rD   r
   r?   ZPartialIteratorWrapper.__iter__   s    t}}d33r	   rU   N)r   r   r   r   r3   r?   r   rF   rG   rH   r
   rT   rT      s     &4 4r	   rT   c                   s>   a  ] tR tRt o R tR tR tR tR tRt	V t
R# )	r)   i  c                sL    Wn         \        V4      V n        R V n        W n        R# )FN)original_iteratorZiterr+   closedcheck_start_response)r1   rV   rY   s   &&&r
   r3   ZIteratorWrapper.__init__  s!    !.]+$8!r	   c                s    V # r   r   rC   rD   r
   r?   ZIteratorWrapper.__iter__  s    r	   c                s   \        V P                  '       * R 4       \        V P                  4      p\	        V4      \
        Jd   \        RRV: R24       V P                  e   \        V P                  R4       RV n        V# )zIterator read after closedFz!Iterator yielded non-bytestring ()NzjThe application returns and we started iterating over its body, but start_response has not yet been called)r   rX   Znextr+   r   r6   rY   )r1   r8   r>   r
   __next__ZIteratorWrapper.__next__  si    DKK(	*7%EQHI$$0D--|~(,D%r	   c                s    R V n         \        V P                  R4      '       d   V P                  P                  4        R# R# )TrE   N)rX   hasattrrW   rE   rC   rD   r
   rE   ZIteratorWrapper.close  s3    4))733""((* 4r	   c                s    V P                   '       g    \        P                  P                  R 4       \	        V P                   R 4       R# )z/Iterator garbage collected without being closedN)rX   sysZstderrrM   r   rC   rD   r
   __del__ZIteratorWrapper.__del__   s2    {{{JJAC=	?r	   )rY   rX   r+   rW   N)r   r   r   r   r3   r?   r[   rE   r^   r   rF   rG   rH   r
   r)   r)     s#     9
+
? ?r	   r)   c                 s   \        \        V 4      \        J R \        V 4      : RV : R24       R  F  p\        W9   RV: 24       K  	  R! F!  p\        W9  RV: R	VR
,          : R24       K#  	  RV 9  d   \        P                  ! R\
        4       V P                  4        FO  pRV9   d   K  \        \        W,          4      \        J RV: R\        W,          4      : RW,          : R24       KQ  	  \        \        V R,          4      \        J RV R,          : R24       \        V R,          R"9   RV R,          ,          4       \        V R,          4       \        V R,          4       V R,          R#9  d*   \        P                  ! RV R,          ,          \
        4       \        V P                  R4      '       * ;'       g    V R,          P                  R4      RV R,          ,          4       \        V P                  R4      '       * ;'       g    V R,          P                  R4      RV R,          ,          4       V P                  R4      '       d.   \        \        V R,          4      ^ 8  RV R,          ,          4       V P                  R4      '       g   \        RV 9   R4       \        V P                  R4      R8g  R4       R# )$z&Environment is not of the right type: z (environment: rZ   REQUEST_METHODwsgi.versionr#   r$   z"Environment missing required key: z%Environment should not have the key: z (use :i   NNz	 instead)ZQUERY_STRINGzQUERY_STRING is not in the WSGI environment; the cgi module will use sys.argv when this variable is missing, so application errors are more likelyZ.zEnvironmental variable z is not a string: z	 (value: z wsgi.version should be a tuple (zwsgi.url_schemezwsgi.url_scheme unknown: %rzUnknown REQUEST_METHOD: %rZSCRIPT_NAMEZ/z$SCRIPT_NAME doesn't start with /: %rZ	PATH_INFOz"PATH_INFO doesn't start with /: %rZCONTENT_LENGTHzInvalid CONTENT_LENGTH: %rzgOne of SCRIPT_NAME or PATH_INFO are required (PATH_INFO should at least be '/' if SCRIPT_NAME is empty)zOSCRIPT_NAME cannot be '/'; it should instead be '', and PATH_INFO should be '/'N)	r_   ZSERVER_NAMEZSERVER_PORTr`   r#   r$   zwsgi.multithreadzwsgi.multiprocesszwsgi.run_once)ZHTTP_CONTENT_TYPEZHTTP_CONTENT_LENGTH)ZhttpZhttps)ZGETZHEADZPOSTZOPTIONSZPATCHZPUTZDELETEZTRACE)r   r   Zdictwarningswarnr   Zkeysr   tuplecheck_inputcheck_errorsZgetZ
startswithint)r*   Zkeyr>   r
   r%   r%   '  sy   DMT!='	#$! 	69;	=	! <""%s2ww0	1 <
 W$4 		 ||~#:W\"c)D&6	7	  D()U2181H1HJLG%&*;;%0A(BBD %&'(   )M M(73C+DD	 M** 6 6}%005.1GGI K(( 4 4{#..s3,w{/CCE {{#$$G,-.!3(73C+DD	F ;;}%%w&>	? GKK&#-	"#r	   c                 R    R F   p\        \        W4      RV : RV: 24       K"  	  R# )r5   zwsgi.input () doesn't have the attribute N)r5   r:   r;   r?   r   r\   )r2   attrr>   r
   rd   rd   h  s%    =
)4!	" >r	   c                 rg   )rO   zwsgi.errors (rh   N)rO   rM   rP   ri   )rK   rj   r>   r
   re   re   n  s%    0*D"	# 1r	   c                 sT   \        V R 4      p V P                  R^4      ^ ,          p\        \        V4      ^8H  RV,          4       \	        V4      p\        V^d8  RV,          4       \        V 4      ^8  g   V ^,          R8w  d%   \
        P                  ! RV ,          \        4       R# R# )StatusNz)Status codes must be three characters: %rzStatus code is invalid: %rZ zjThe status string (%r) should be a three-digit integer followed by a single space and a status explanation)r   splitr   r   rf   ra   rb   r   )r   Zstatus_codeZ
status_ints   &  r
   r   r   t  s    vx0F,,tQ'*KC!3kAC[!JJ#;jHI
6{Q&)s*B!	# +r	   c           
      s@   \        \        V 4      \        J R V : R\        V 4      : 24       V  EFj  p\        \        V4      \        J RV: R\        V4      : 24       \        \	        V4      ^8H  4       Vw  r#\        VR4      p\        VR4      p\        VP                  4       R8g  RV,          4       \        RV9  ;'       d    R	V9  R
V,          4       \        \        P                  V4      RV,          4       \        VP                  R4      '       * ;'       d    VP                  R4      '       * RV,          4       \        P                  V4      '       g   EK3  \        ^ RV: R\        P                  V4      P                  ^ 4      : R24       EKm  	  R# )z	Headers (z) must be of type list: zIndividual headers (z) must be of type tuple: Header namezHeader valuer   zyThe Status header cannot be used; it conflicts with CGI script, and HTTP status is not given through headers (value: %r).Z
Z:z,Header names may not contain ':' or '\n': %rzBad header name: %rZ-Z_z#Names may not end in '-' or '_': %rzBad header value: z (bad char: rZ   N)r   r   r<   rc   r   r   lower	header_reZsearchZendswithbad_header_value_reZgroup)r   Zitemnamer   s   &   r
   r   r     sT   DMT!DM	#$ T
e#T$Z!	" 	D	Q }5!%8

("#	$ 	D 44S_;dB	D	  &(=(DEDMM#&&AAt}}S/A+A1D8	:%%e,,A)007==a@B C% r	   c                 s0   \        V R 4      p \        V P                  R^4      ^ ,          4      pRpV FD  w  rE\        VR4      pVP                  4       R8X  g   K(  W#9  d    R# \	        ^ RV,          4       KF  	  W#9  d   \	        ^ RV,          4       R# R# )rk   Nrm   zcontent-typezJContent-Type header found in a %s response, which must not return content.z,No Content-Type header found in headers (%s))i   i0  )r   rf   rl   rn   r   )r   r   ZcodeZNO_MESSAGE_BODYrq   r   s   &&    r
   r   r     s    vx0Fv||D!$Q'(D !O }5::<>)*A 9<@A B  "AGKL #r	   c           	      sv    \        V R J ;'       g    \        V 4      \        J RV : R\        V 4      : 24       R # )Nz
exc_info (z) is not a tuple: )r   r   rc   )r   rD   r
   r   r     s0    H77X% 7.6XGIr	   c                 sP    \        \        V \        \        34      '       * R 4       R# )zwYou should not return a string as your application iterator, instead return a single-item list containing a bytestring.N)r   Z
isinstancer   r6   rU   rD   r
   r(   r(     s#     
8c5\22	EFr	   )r   Z__all__Zrer]   ra   Zcompilero   rp   ZWarningr   r   r   r    r&   r'   r   rT   r)   r%   rd   re   r   r   r   r   r(   r   r	   r
   <module>rr      s   
iT - 
 
 JJ34	jj0 ' 
$H5n7 7@8 8& 4 4!? !?F?#B"##C2M I
Fr	   