B
    ê¹`•T  ã               @   sž   d dl mZ d dlZd dlZd dlZd dlZddlmZ ddlm	Z	m
Z
mZ dddœZed	ƒZG d
d„ dƒZG dd„ dƒZG dd„ deƒZG dd„ deƒZdS )é    )ÚdequeNé   )ÚReadOnlyFileBasedBuffer)Úbuild_http_dateÚloggerÚqueue_loggerÚCONTENT_LENGTHÚCONTENT_TYPE)r   r	   )Ú
connectionz
keep-alivezproxy-authenticatezproxy-authorizationÚteZtrailersztransfer-encodingÚupgradec               @   sR   e Zd ZdZdZdZeZeZdd„ Zdd„ Z	dd„ Z
d	d
„ Zdd„ Zddd„ZdS )ÚThreadedTaskDispatcherz6A Task Dispatcher that creates a thread for each task.r   c             C   s:   t ƒ | _tƒ | _t ¡ | _t | j¡| _t | j¡| _	d S )N)
ÚsetÚthreadsr   ÚqueueÚ	threadingÚLockÚlockÚ	ConditionÚqueue_cvÚthread_exit_cv)Úself© r   úU/home/kop/projects/devel/pgwui/test_venv/lib/python3.7/site-packages/waitress/task.pyÚ__init__3   s
    
zThreadedTaskDispatcher.__init__c             C   s*   t j|d |¡|fd}d|_| ¡  d S )Nzwaitress-{})ÚtargetÚnameÚargsT)r   ÚThreadÚformatÚdaemonÚstart)r   r   Ú	thread_noÚtr   r   r   Ústart_new_thread:   s    z'ThreadedTaskDispatcher.start_new_threadc          	   C   sÐ   xÊ| j Š x:| jsD| jdkrD|  jd8  _| j ¡  |  jd7  _qW | jdkr„|  jd8  _|  jd8  _| j |¡ | j 	¡  P | j 
¡ }W d Q R X y| ¡  W q tk
rÆ   | j d|¡ Y qX qW d S )Nr   r   zException when servicing %r)r   r   Ú
stop_countÚactive_countr   Úwaitr   Údiscardr   ÚnotifyÚpopleftÚserviceÚBaseExceptionr   Ú	exception)r   r"   Útaskr   r   r   Úhandler_threadA   s"    


z%ThreadedTaskDispatcher.handler_threadc          	   C   s¬   | j œ | j}d}t|ƒ| j }xX||k rxx||kr>|d }q,W | |¡ |d7 }|  | j|¡ |  jd7  _|d }q"W ||krž|  j|| 7  _| j 	¡  W d Q R X d S )Nr   r   )
r   r   Úlenr%   Úaddr$   r/   r&   r   Ú
notify_all)r   Úcountr   r"   Úrunningr   r   r   Úset_thread_countX   s    


z'ThreadedTaskDispatcher.set_thread_countc          	   C   sf   | j V | j |¡ | j ¡  t| jƒ}t| jƒ| j | j }||krX| j	 
d|| ¡ W d Q R X d S )NzTask queue depth is %d)r   r   Úappendr   r)   r0   r   r%   r&   r   Úwarning)r   r.   Z
queue_sizeZidle_threadsr   r   r   Úadd_taskk   s    

zThreadedTaskDispatcher.add_taskTé   c          	   C   s¸   |   d¡ | j}t ¡ | }| jŒ x4|rXt ¡ |krJ| j dt|ƒ¡ P | j d¡ q&W |rª| j	}t|ƒdkr‚| j dt|ƒ¡ x|rš| 
¡ }| ¡  q„W | j ¡  dS W d Q R X dS )Nr   z%d thread(s) still runninggš™™™™™¹?zCanceling %d pending task(s)TF)r5   r   Útimer   r   r7   r0   r   r'   r   r*   Úcancelr   r2   )r   Zcancel_pendingÚtimeoutr   Z
expirationr   r.   r   r   r   Úshutdownv   s&    

zThreadedTaskDispatcher.shutdownN)Tr9   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r%   r&   r   r   r   r$   r/   r5   r8   r=   r   r   r   r   r   +   s   r   c               @   s|   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZeZdd„ Zdd„ Zed	d
„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )ÚTaskFz200 OKr   Nc             C   s.   || _ || _g | _|j}|dkr$d}|| _d S )N)z1.0z1.1z1.0)ÚchannelÚrequestÚresponse_headersÚversion)r   rC   rD   rF   r   r   r   r   ›   s    zTask.__init__c             C   sH   y|   ¡  |  ¡  |  ¡  W n& tk
rB   d| _| jjjr>‚ Y nX d S )NT)r!   ÚexecuteÚfinishÚOSErrorÚclose_on_finishrC   ÚadjZlog_socket_errors)r   r   r   r   r+   ¥   s    
zTask.servicec             C   s&   | j  d¡p"| j  d¡p"| j  d¡ S )NÚ1Z204Z304)ÚstatusÚ
startswith)r   r   r   r   Úhas_body¯   s    zTask.has_bodyc                s  ˆj }ˆjj dd¡ ¡ }g ‰d }d }d }d ‰ xxˆjD ]n\}}d dd„ | d¡D ƒ¡}|dkrnˆjr6|}nq6|dkrz|}|dkr†|}|d	kr–| ¡ ‰ ˆ 	||f¡ q6W |d krØˆj
d k	rØˆjrØtˆj
ƒ}ˆ 	d|f¡ ‡ ‡‡fd
d„}|dkr|dkr|s
|ƒ  n
ˆ 	d¡ n|ƒ  nP|dkrf|dkr8|ƒ  |snˆjrVˆ 	d¡ dˆ_ˆjsn|ƒ  ntdƒ‚ˆjjjj}	|s–|	rªˆ 	d|	f¡ nˆ 	d|	p¤df¡ |sÄˆ 	dtˆjƒf¡ ˆˆ_dˆj ˆjf }
dd„ tˆjdd„ dD ƒ}|
g| }dd |¡ }| d¡S )NZ
CONNECTIONÚ ú-c             S   s   g | ]}|  ¡ ‘qS r   )Ú
capitalize)Ú.0Úxr   r   r   ú
<listcomp>Â   s    z.Task.build_response_header.<locals>.<listcomp>zContent-LengthÚDateÚServerÚ
Connectionc                  s   ˆ d krˆ  d¡ dˆ_d S )N)rX   ÚcloseT)r6   rJ   r   )Úconnection_close_headerrE   r   r   r   rJ   Ý   s    
z3Task.build_response_header.<locals>.close_on_finishz1.0z
keep-alive)rX   z
Keep-Alivez1.1rY   )zTransfer-EncodingÚchunkedTzneither HTTP/1.0 or HTTP/1.1ZViaZwaitressz
HTTP/%s %sc             S   s   g | ]}d | ‘qS )z%s: %sr   )rS   Zhvr   r   r   rU     s    c             S   s   | d S )Nr   r   )rT   r   r   r   Ú<lambda>  ó    z,Task.build_response_header.<locals>.<lambda>)Úkeyz%s

z
zlatin-1)rF   rD   ÚheadersÚgetÚlowerrE   ÚjoinÚsplitrO   r6   Úcontent_lengthÚstrÚchunked_responserJ   ÚAssertionErrorrC   ÚserverrK   Úidentr   Ú
start_timerM   ÚsortedÚencode)r   rF   r
   Zcontent_length_headerZdate_headerZserver_headerZ
headernameZ	headervalrJ   ri   Ú
first_lineZ
next_linesÚlinesÚresr   )rZ   rE   r   r   Úbuild_response_header·   sn    







zTask.build_response_headerc             C   s>   g }x.| j D ]$\}}| ¡ dkr"q| ||f¡ qW || _ d S )Nzcontent-length)rE   ra   r6   )r   rE   Úheader_nameÚheader_valuer   r   r   Úremove_content_length_header  s    z!Task.remove_content_length_headerc             C   s   t   ¡ | _d S )N)r:   rj   )r   r   r   r   r!   #  s    z
Task.startc             C   s&   | j s|  d¡ | jr"| j d¡ d S )Nr]   s   0

)Úwrote_headerÚwriterf   rC   Ú
write_soon)r   r   r   r   rH   &  s    
zTask.finishc             C   s  | j stdƒ‚| j}| js2|  ¡ }| |¡ d| _|rÜ| jrÜ|}| j}| jr|t	t
|ƒƒdd …  ¡  d¡d }||d 7 }nP|d k	rÌ|d || j … }|  jt
|ƒ7  _||krÌ| jsÌ| j d| ¡ d| _|rÚ| |¡ n8|r|  jt
|ƒ7  _| js| j d| j ¡ d| _d S )Nz1start_response was not called before body writtenTé   zlatin-1s   
z`application-written content exceeded the number of bytes specified by Content-Length header (%s)zfapplication-written content was ignored due to HTTP response that may not contain a message-body: (%s))ÚcompleteÚRuntimeErrorrC   rt   rp   rv   rO   rd   rf   Úhexr0   Úupperrl   Úcontent_bytes_writtenÚlogged_write_excessr   r7   Úlogged_write_no_bodyrM   )r   ÚdatarC   ZrhZtowriteÚclr   r   r   ru   -  s<    

"
z
Task.write)r>   r?   r@   rJ   rM   rt   rj   rd   r|   r}   r~   rx   rf   r   r   r+   ÚpropertyrO   rp   rs   r!   rH   ru   r   r   r   r   rB   Ž   s&   

b
rB   c               @   s   e Zd ZdZdZdd„ ZdS )Ú	ErrorTaskz(An error task produces an error responseTc             C   sX   | j j}| ¡ \}}}|| _| j |¡ | j d¡ d| _t|ƒ| _	|  
| d¡¡ d S )N)rX   rY   Tzlatin-1)rD   ÚerrorZto_responserM   rE   Úextendr6   rJ   r0   rd   ru   rl   )r   ÚerM   r_   Úbodyr   r   r   rG   [  s    
zErrorTask.executeN)r>   r?   r@   rA   rx   rG   r   r   r   r   r‚   V  s   r‚   c               @   s$   e Zd ZdZdZdd„ Zdd„ ZdS )ÚWSGITaskz8A WSGI task produces a response from a WSGI application.Nc       
   	      sP  ˆ   ¡ }d‡ fdd„	}ˆ jj ||¡}d}z|jtkrˆˆ j}| |¡}|rˆ||krj|d k	rdˆ  ¡  |ˆ _ˆ  	d¡ ˆ j 
|¡ d}d S d }xX|D ]P}|d krÔt|ƒ}ˆ jd krÔd }	t|dƒrÆt|ƒ}	|	dkrÔ|ˆ _|r’ˆ  	|¡ q’W ˆ j}|d k	r,ˆ j|kr,dˆ _ˆ jjdkr,ˆ j d	ˆ j|f ¡ W d |rJt|d
ƒrJ| ¡  X d S )Nc                s4  ˆ j r|stdƒ‚|r8zˆ jr(|d ‚ng ˆ _W d d }X dˆ _ | jtk	rTtd|  ƒ‚d| ksdd| krltdƒ‚| ˆ _x®|D ]¦\}}|jtk	ržtd|||ff ƒ‚|jtk	r¼td	|||ff ƒ‚d|ksÌd|krÔtd
ƒ‚d|ksäd|krìtdƒ‚| ¡ }|dkr
t	|ƒˆ _
qx|tkrxtd| ƒ‚qxW ˆ j |¡ ˆ jS )Nz?start_response called a second time without providing exc_info.r   Tzstatus %s is not a stringÚ
úz5carriage return/line feed character present in statusz$Header name %r is not a string in %rz%Header value %r is not a string in %rz;carriage return/line feed character present in header valuez:carriage return/line feed character present in header namezcontent-lengthzS%s is a "hop-by-hop" header; it cannot be used by a WSGI application (see PEP 3333))rx   rg   rt   rE   Ú	__class__re   Ú
ValueErrorrM   ra   Úintrd   Ú
hop_by_hopr„   ru   )rM   r_   Úexc_infoÚkÚvÚkl)r   r   r   Ústart_responseq  sL    






z(WSGITask.execute.<locals>.start_responseTr]   FÚ__len__r   ÚHEADzVapplication returned too few bytes (%s) for specified Content-Length (%s) via app_iterrY   )N)Úget_environmentrC   rh   ZapplicationrŠ   r   rd   Úpreparers   ru   rv   r0   Úhasattrr|   rJ   rD   Úcommandr   r7   rY   )
r   Úenvironr’   Zapp_iterZcan_close_app_iterr€   ÚsizeZfirst_chunk_lenÚchunkZapp_iter_lenr   )r   r   rG   n  sN    A






zWSGITask.executec             C   sL  | j }|dk	r|S | j}|j}| j}|j}|jj}| d¡rJd| d¡ }|r~||kr\d}n"|d }| |¡r~|t	|ƒd… }|j
d |j
d t|j
d ƒ|j ¡ t|jƒ|j|jjd| j |||j|jdtjdd	d	| ¡ tdd
œ}xPt|jƒ ¡ D ]>\}}	|	 ¡ }	t |d¡}
|
dkr"d| }
|
|krô|	||
< qôW | jj|d< || _ |S )zReturns a WSGI environment.Nú/rP   r   r   zHTTP/%s)r   r   TF)ZREMOTE_ADDRZREMOTE_HOSTZREMOTE_PORTÚREQUEST_METHODZSERVER_PORTZSERVER_NAMEÚSERVER_SOFTWAREZSERVER_PROTOCOLZSCRIPT_NAMEZ	PATH_INFOÚQUERY_STRINGzwsgi.url_schemezwsgi.versionzwsgi.errorszwsgi.multithreadzwsgi.multiprocesszwsgi.run_oncez
wsgi.inputzwsgi.file_wrapperzwsgi.input_terminatedZHTTP_zwaitress.client_disconnected)r™   rD   ÚpathrC   rh   rK   Ú
url_prefixrN   Úlstripr0   Úaddrre   r˜   r{   Zeffective_portZserver_nameri   rF   ÚqueryÚ
url_schemeÚsysÚstderrZget_body_streamr   Údictr_   ÚitemsÚstripÚrename_headersr`   Zcheck_client_disconnected)r   r™   rD   r    rC   rh   r¡   Zurl_prefix_with_trailing_slashr^   ÚvalueZmykeyr   r   r   r•   ë  s\    


zWSGITask.get_environment)r>   r?   r@   rA   r™   rG   r•   r   r   r   r   r‡   i  s   }r‡   )Úcollectionsr   Úsocketr¦   r   r:   Úbuffersr   Z	utilitiesr   r   r   r«   Ú	frozensetr   r   rB   r‚   r‡   r   r   r   r   Ú<module>   s   c I