U
    n5{i<Q  ã                   @   sþ   d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ eeef edœdd„Zeedœdd„ZG dd„ dƒZG dd„ dƒZG dd„ dƒZeeƒG dd„ dƒƒZdgZ dS )zo
An implementation of
U{Python Web Server Gateway Interface v1.0.1<http://www.python.org/dev/peps/pep-3333/>}.
é    )ÚSequence)Úexc_info)ÚListÚUnion)Úwarn)Úimplementer)ÚblockingCallFromThread)ÚLogger)ÚFailure)ÚINTERNAL_SERVER_ERROR)Ú	IResource)ÚNOT_DONE_YET)ÚstringÚreturnc                 C   s(   t | tƒr|  d¡ d¡S |  d¡S dS )aW  
    Convert C{string} to a WSGI "bytes-as-unicode" string.

    If it's a byte string, decode as ISO-8859-1. If it's a Unicode string,
    round-trip it to bytes and back using ISO-8859-1 as the encoding.

    @type string: C{str} or C{bytes}
    @rtype: C{str}

    @raise UnicodeEncodeError: If C{string} contains non-ISO-8859-1 chars.
    ú
iso-8859-1N)Ú
isinstanceÚstrÚencodeÚdecode©r   © r   ú4/tmp/pip-unpacked-wheel-mnhg7r0q/twisted/web/wsgi.pyÚ_wsgiString%   s    
r   c                 C   s
   |   d¡S )zÞ
    Convert C{string} from a WSGI "bytes-as-unicode" string to an
    ISO-8859-1 byte string.

    @type string: C{str}
    @rtype: C{bytes}

    @raise UnicodeEncodeError: If C{string} contains non-ISO-8859-1 chars.
    r   )r   r   r   r   r   Ú_wsgiStringToBytes7   s    
r   c                   @   sB   e Zd ZdZeƒ Zeddœdd„Zee ddœdd„Z	d	d
„ Z
dS )Ú_ErrorStreama·  
    File-like object instances of which are used as the value for the
    C{'wsgi.errors'} key in the C{environ} dictionary passed to the application
    object.

    This simply passes writes on to L{logging<twisted.logger>} system as
    error events from the C{'wsgi'} system.  In the future, it may be desirable
    to expose more information in the events it logs, such as the application
    object which generated the message.
    N)Údatar   c                 C   s:   t |tƒs td|t|ƒjf ƒ‚| jj|dd|fd� dS )a  
        Generate an event for the logging system with the given bytes as the
        message.

        This is called in a WSGI application thread, not the I/O thread.

        @type data: str

        @raise TypeError: if C{data} is not a native string.
        z)write() argument must be str, not %r (%s)ZwsgiT)ÚsystemZisErrorÚmessageN)r   r   Ú	TypeErrorÚtypeÚ__name__Ú_logÚerror)Úselfr   r   r   r   ÚwriteR   s    
ÿÿz_ErrorStream.write)Úiovecr   c                 C   s   |   d |¡¡ dS )aZ  
        Join the given lines and pass them to C{write} to be handled in the
        usual way.

        This is called in a WSGI application thread, not the I/O thread.

        @param iovec: A C{list} of C{'\n'}-terminated C{str} which will be
            logged.

        @raise TypeError: if C{iovec} contains any non-native strings.
        Ú N)r$   Újoin)r#   r%   r   r   r   Ú
writelinesg   s    z_ErrorStream.writelinesc                 C   s   dS )zÈ
        Nothing is buffered, so flushing does nothing.  This method is required
        to exist by PEP 333, though.

        This is called in a WSGI application thread, not the I/O thread.
        Nr   ©r#   r   r   r   Úflushu   s    z_ErrorStream.flush)r    Ú
__module__Ú__qualname__Ú__doc__r	   r!   r   r$   r   r(   r*   r   r   r   r   r   D   s
   r   c                   @   s>   e Zd ZdZdd„ Zddd„Zddd„Zdd	d
„Zdd„ ZdS )Ú_InputStreamaˆ  
    File-like object instances of which are used as the value for the
    C{'wsgi.input'} key in the C{environ} dictionary passed to the application
    object.

    This only exists to make the handling of C{readline(-1)} consistent across
    different possible underlying file-like object implementations.  The other
    supported methods pass through directly to the wrapped object.
    c                 C   s
   || _ dS )zt
        Initialize the instance.

        This is called in the I/O thread, not a WSGI application thread.
        N)Ú_wrapped)r#   Úinputr   r   r   Ú__init__‰   s    z_InputStream.__init__Nc                 C   s   |dkr| j  ¡ S | j  |¡S )zƒ
        Pass through to the underlying C{read}.

        This is called in a WSGI application thread, not the I/O thread.
        N)r/   Úread©r#   Úsizer   r   r   r2   ‘   s    
z_InputStream.readc                 C   s&   |dks|dkr| j  ¡ S | j  |¡S )zÅ
        Pass through to the underlying C{readline}, with a size of C{-1} replaced
        with a size of L{None}.

        This is called in a WSGI application thread, not the I/O thread.
        éÿÿÿÿN)r/   Úreadliner3   r   r   r   r6   œ   s    	
z_InputStream.readlinec                 C   s   |dkr| j  ¡ S | j  |¡S )zˆ
        Pass through to the underlying C{readlines}.

        This is called in a WSGI application thread, not the I/O thread.
        N)r/   Ú	readlinesr3   r   r   r   r7   ©   s    
z_InputStream.readlinesc                 C   s
   t | jƒS )z‡
        Pass through to the underlying C{__iter__}.

        This is called in a WSGI application thread, not the I/O thread.
        )Úiterr/   r)   r   r   r   Ú__iter__´   s    z_InputStream.__iter__)N)N)N)	r    r+   r,   r-   r1   r2   r6   r7   r9   r   r   r   r   r.   ~   s   



r.   c                   @   sT   e Zd ZdZdZeƒ Zdd„ Zdd„ Zddd	„Z	d
d„ Z
dd„ Zdd„ Zdd„ ZdS )Ú_WSGIResponsea$  
    Helper for L{WSGIResource} which drives the WSGI application using a
    threadpool and hooks it up to the L{http.Request}.

    @ivar started: A L{bool} indicating whether or not the response status and
        headers have been written to the request yet.  This may only be read or
        written in the WSGI application thread.

    @ivar reactor: An L{IReactorThreads} provider which is used to call methods
        on the request in the I/O thread.

    @ivar threadpool: A L{ThreadPool} which is used to call the WSGI
        application object in a non-I/O thread.

    @ivar application: The WSGI application object.

    @ivar request: The L{http.Request} upon which the WSGI environment is
        based and to which the application's output will be sent.

    @ivar environ: The WSGI environment L{dict}.

    @ivar status: The HTTP response status L{str} supplied to the WSGI
        I{start_response} callable by the application.

    @ivar headers: A list of HTTP response headers supplied to the WSGI
        I{start_response} callable by the application.

    @ivar _requestFinished: A flag which indicates whether it is possible to
        generate more response data or not.  This is L{False} until
        L{http.Request.notifyFinish} tells us the request is done,
        then L{True}.
    Fc                 C   s   d| _ || _|| _|| _|| _| j ¡  | j¡ |jrHdd 	|j¡ }nd}|j
rddd 	|j
¡ }nd}|j dd¡}t|ƒdkrˆd}n|d }| ¡ }	t|jƒt|	jƒtt|	jƒƒt|ƒt|ƒt|ƒt| d¡pÔdƒt| d¡pädƒt| ¡ ƒtt| ¡ jƒƒt|jƒd	œ| _d | j_|j ¡ D ]D\}
}d
t|
ƒ ¡  dd¡ }
d 	dd„ |D ƒ¡ dd¡| j|
< �q"| j d| ¡ �r€d�p‚ddddt ƒ t!|j"ƒdœ¡ d S )NFó   /ó    ó   ?é   s   content-typer&   s   content-length)ÚREQUEST_METHODZREMOTE_ADDRZREMOTE_PORTZSCRIPT_NAMEZ	PATH_INFOÚQUERY_STRINGÚCONTENT_TYPEÚCONTENT_LENGTHZSERVER_NAMEZSERVER_PORTZSERVER_PROTOCOLZHTTP_ú-Ú_ú,c                 s   s   | ]}t |ƒV  qd S ©N)r   )Ú.0Úvr   r   r   Ú	<genexpr>  s     z)_WSGIResponse.__init__.<locals>.<genexpr>Ú
ú )r>   r   ÚhttpsÚhttpT)zwsgi.versionzwsgi.url_schemezwsgi.run_oncezwsgi.multithreadzwsgi.multiprocesszwsgi.errorsz
wsgi.input)#ÚstartedÚreactorÚ
threadpoolÚapplicationÚrequestZnotifyFinishZaddBothÚ	_finishedZprepathr'   ZpostpathÚuriÚsplitÚlenZgetClientAddressr   ÚmethodÚhostr   ÚportZ	getHeaderZgetRequestHostnameZgetHostZclientprotoÚenvironZdefaultContentTypeZrequestHeadersZgetAllRawHeadersÚupperÚreplaceÚupdateZisSecurer   r.   Úcontent)r#   rO   rP   rQ   rR   Z
scriptNameZpathInfoÚpartsZqueryStringZ
remotePeerÚnameÚvaluesr   r   r   r1   â   s\    
õ ÿëÿz_WSGIResponse.__init__c                 C   s
   d| _ dS )zc
        Record the end of the response generation for the request being
        serviced.
        TN)Ú_requestFinished)r#   Zignoredr   r   r   rS   2  s    z_WSGIResponse._finishedNc                 C   s(  | j r |dk	r |d  |d ¡‚t|tƒs@td |t|ƒj¡ƒ‚t|tƒrLn<t|t	ƒrrt
d|t|ƒjf td� ntd|t|ƒjf ƒ‚|D ]ˆ}t|tƒrœn<t|t	ƒrÂt
d|t|ƒjf td� ntd	|t|ƒjf ƒ‚t|ƒdkròtd
|›�ƒ‚|D ]}t|tƒsötd|›�ƒ‚qöqŒ|| _|| _| jS )z¼
        The WSGI I{start_response} callable.  The given values are saved until
        they are needed to generate the response.

        This will be called in a non-I/O thread.
        Nr>   é   z!status must be str, not {!r} ({})z%headers should be a list, not %r (%s))Úcategoryz#headers must be a list, not %r (%s)z0header should be a (str, str) tuple, not %r (%s)z.header must be a (str, str) tuple, not %r (%s)z'header must be a (str, str) tuple, not z%header must be (str, str) tuple, not )rN   Úwith_tracebackr   r   r   Úformatr   r    Úlistr   r   ÚRuntimeWarningÚtuplerV   ÚstatusÚheadersr$   )r#   rj   rk   ZexcInfoÚheaderÚelemr   r   r   ÚstartResponse9  s\    
 ÿÿ	

ÿýÿÿ

ÿýÿÿ
z_WSGIResponse.startResponsec                    s0   ‡ ‡fdd„}ztˆj|ˆj ƒW ¢S dˆ_ X dS )a   
        The WSGI I{write} callable returned by the I{start_response} callable.
        The given bytes will be written to the response body, possibly flushing
        the status and headers first.

        This will be called in a non-I/O thread.
        c                    s   | sˆ  ¡  ˆj ˆ ¡ d S rF   )Ú_sendResponseHeadersrR   r$   ©rN   ©r   r#   r   r   Ú	wsgiWriteŸ  s    z&_WSGIResponse.write.<locals>.wsgiWriteTN)rN   r   rO   )r#   r   rr   r   rq   r   r$   ~  s    !z_WSGIResponse.writec                 C   sd   | j  dd¡\}}t|ƒ}| j |t|ƒ¡ | jD ],\}}| ¡ dkr2| jj 	t|ƒt|ƒ¡ q2dS )a,  
        Set the response code and response headers on the request object, but
        do not flush them.  The caller is responsible for doing a write in
        order for anything to actually be written out in response to the
        request.

        This must be called in the I/O thread.
        Nr>   )ÚserverÚdate)
rj   rU   ÚintrR   ÚsetResponseCoder   rk   ÚlowerZresponseHeadersZaddRawHeader)r#   Úcoder   r`   Úvaluer   r   r   ro   ©  s    	 ÿz"_WSGIResponse._sendResponseHeadersc                 C   s   | j  | j¡ dS )zo
        Start the WSGI application in the threadpool.

        This must be called in the I/O thread.
        N)rP   ZcallInThreadÚrunr)   r   r   r   Ústart½  s    z_WSGIResponse.startc                    s°   zPˆ   ˆ jˆ j¡}|D ]}|r(ˆ  |¡ ˆ jr q4qt|ddƒ}|dk	rN|ƒ  W n8 tk
rˆ   ‡ fdd„}ˆ jj|ˆ j	ft
ƒ žŽ  Y nX ‡ fdd„}ˆ j |ˆ j	¡ dˆ _	dS )z°
        Call the WSGI application object, iterate it, and handle its output.

        This must be called in a non-I/O thread (ie, a WSGI application
        thread).
        ÚcloseNc                    sB   ˆ j jdt|||ƒd� | r(ˆ j ¡  nˆ j t¡ ˆ j ¡  d S )NzWSGI application error)Úfailure)r!   r}   r
   rR   ZloseConnectionrv   r   Úfinish)rN   r   ry   Ú	tracebackr)   r   r   Ú	wsgiErrorØ  s     
ÿz$_WSGIResponse.run.<locals>.wsgiErrorc                    s    ˆ j s| sˆ  ¡  ˆ j ¡  d S rF   )rb   ro   rR   r~   rp   r)   r   r   Ú
wsgiFinishå  s    z%_WSGIResponse.run.<locals>.wsgiFinishT)rQ   rZ   rn   r$   rb   ÚgetattrÚBaseExceptionrO   ZcallFromThreadrN   r   )r#   ZappIteratorrm   r|   r€   r�   r   r)   r   rz   Å  s     


z_WSGIResponse.run)N)r    r+   r,   r-   rb   r	   r!   r1   rS   rn   r$   ro   r{   rz   r   r   r   r   r:   ½   s   !P
E+r:   c                   @   s4   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ ZdS )ÚWSGIResourceaW  
    An L{IResource} implementation which delegates responsibility for all
    resources hierarchically inferior to it to a WSGI application.

    The C{environ} argument passed to the application, includes the
    C{REMOTE_PORT} key to complement the C{REMOTE_ADDR} key.

    @ivar _reactor: An L{IReactorThreads} provider which will be passed on to
        L{_WSGIResponse} to schedule calls in the I/O thread.

    @ivar _threadpool: A L{ThreadPool} which will be passed on to
        L{_WSGIResponse} to run the WSGI application object.

    @ivar _application: The WSGI application object.
    Tc                 C   s   || _ || _|| _d S rF   )Ú_reactorÚ_threadpoolÚ_application)r#   rO   rP   rQ   r   r   r   r1     s    zWSGIResource.__init__c                 C   s    t | j| j| j|ƒ}| ¡  tS )a¾  
        Turn the request into the appropriate C{environ} C{dict} suitable to be
        passed to the WSGI application object and then pass it on.

        The WSGI application object is given almost complete control of the
        rendering process.  C{NOT_DONE_YET} will always be returned in order
        and response completion will be dictated by the application object, as
        will the status, headers, and the response body.
        )r:   r…   r†   r‡   r{   r   )r#   rR   Úresponser   r   r   Úrender
  s    
   ÿzWSGIResource.renderc                 C   s   t dƒ‚dS )z»
        Reject attempts to retrieve a child resource.  All path segments beyond
        the one which refers to this resource are handled by the WSGI
        application object.
        z/Cannot get IResource children from WSGIResourceN©ÚRuntimeError)r#   r`   rR   r   r   r   ÚgetChildWithDefault  s    z WSGIResource.getChildWithDefaultc                 C   s   t dƒ‚dS )zÖ
        Reject attempts to add a child resource to this resource.  The WSGI
        application object handles all path segments beneath this resource, so
        L{IResource} children can never be found.
        z0Cannot put IResource children under WSGIResourceNrŠ   )r#   ÚpathÚchildr   r   r   ÚputChild"  s    zWSGIResource.putChildN)	r    r+   r,   r-   ZisLeafr1   r‰   rŒ   r�   r   r   r   r   r„   ï  s   r„   N)!r-   Úcollections.abcr   Úsysr   Útypingr   r   Úwarningsr   Zzope.interfacer   Ztwisted.internet.threadsr   Ztwisted.loggerr	   Ztwisted.python.failurer
   Ztwisted.web.httpr   Ztwisted.web.resourcer   Ztwisted.web.serverr   r   Úbytesr   r   r   r.   r:   r„   Ú__all__r   r   r   r   Ú<module>   s*   :?  4;