o
    ߥi3                     @   s  d dl 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 d dl	m
Z d dlmZmZmZmZmZmZmZmZmZmZmZ d dlmZ d dlmZmZ d dlmZmZ d d	l m!Z!m"Z"m#Z#m$Z$ d d
l%m&Z&m'Z'm(Z( edd dd eD Z)G dd de!Z*edZ+G dd de*e j,ee+ Z-G dd de-ee.e/f  Z0G dd de0Z1G dd de-e Z2G dd de*Z3G dd de*e j,ee+ Z4G dd de4e. Z5G d d! d!e4e' Z6G d"d# d#e*e"Z7dS )$    N)
HTTPStatus)
guess_type)choices)AnyDict	GeneratorGenericIterableMappingOptionalSequenceTupleTypeVarUnion)ThreadPoolExecutor)URLdefaultdict)MalformedRangeHeaderRangeNotSatisfiable)BaseResponseFileResponseMixinbuild_bytes_from_sse
iri_to_uri)EnvironServerSentEventStartResponsec                 C   s
   |  dS )Nz Unknown Status Code )statusr   r   H/home/ubuntu/.local/lib/python3.10/site-packages/baize/wsgi/responses.py<lambda>#   s   
 r   c                 C   s"   i | ]}t || d |j qS ) )intphrase).0r   r   r   r   
<dictcomp>$   s   " r$   c                   @   s*   e Zd ZdZdededee fddZdS )Responsezh
    The parent class of all responses, whose objects can be used directly as WSGI
    application.
    environstart_responsereturnc                 C   s&   d| j d< |t| j | jdd dS )N0content-lengthFas_bytes)    )headersStatusStringMappingstatus_codelist_headersselfr&   r'   r   r   r   __call__.   s
   
zResponse.__call__N)	__name__
__module____qualname____doc__r   r   r	   bytesr4   r   r   r   r   r%   (   s    r%   _ContentTypec                       s   e Zd ZU dZdZeed< dZeed< 				dded	e	d
e
eeef  de
e de
e ddf fddZejdedefddZdededee fddZ  ZS )SmallResponsez9
    Abstract base class for small response objects.
     
media_typeutf-8charset   Ncontentr0   r.   r(   c                    s0   t  || || _|p| j| _|p| j| _d S N)super__init__rA   r=   r?   )r3   rA   r0   r.   r=   r?   	__class__r   r   rD   C   s   zSmallResponse.__init__c                 C   s   t rB   NotImplementedErrorr3   rA   r   r   r   renderP   s   zSmallResponse.renderr&   r'   c                 c   s    |  | j}|rd| jvrtt|}|| jd< | j}|r4d| jvr4|dr/|d| j 7 }|| jd< |t| j	 | j
dd |V  d S )Nr*   content-typeztext/
; charset=Fr+   )rJ   rA   r.   strlenr=   
startswithr?   r/   r0   r1   )r3   r&   r'   bodycontent_lengthcontent_typer   r   r   r4   T   s   



zSmallResponse.__call__)r@   NNN)r5   r6   r7   r8   r=   rM   __annotations__r?   r:   r!   r   r
   rD   abcabstractmethodr9   rJ   r   r   r	   r4   __classcell__r   r   rE   r   r;   ;   s<   
 r;   c                   @   s*   e Zd ZdZdeeef defddZdS )PlainTextResponsez
text/plainrA   r(   c                 C   s   t |tr|| jS |S rB   )
isinstancerM   encoder?   rI   r   r   r   rJ   i   s   zPlainTextResponse.renderN)r5   r6   r7   r=   r   r9   rM   rJ   r   r   r   r   rW   f   s    rW   c                   @   s   e Zd ZdZdS )HTMLResponsez	text/htmlN)r5   r6   r7   r=   r   r   r   r   rZ   m   s    rZ   c                       s^   e Zd ZdZdZ		ddededeee	e	f  ded	df
 fd
dZ
ded	efddZ  ZS )JSONResponsezW
    `**kwargs` is used to accept all the parameters that `json.loads` can accept.
    zapplication/jsonr@   NrA   r0   r.   kwargsr(   c                    s:   ddd dd d| _ | j jdi | t j|||d d S )NF),:)ensure_ascii	allow_nanindent
separatorsdefaultr0   r.   r   )json_kwargsupdaterC   rD   )r3   rA   r0   r.   r\   rE   r   r   rD   x   s   zJSONResponse.__init__c                 C   s   t j|fi | j| jS rB   )jsondumpsre   rY   r?   rI   r   r   r   rJ      s   zJSONResponse.renderr@   N)r5   r6   r7   r8   r=   r   r!   r   r
   rM   rD   r9   rJ   rV   r   r   rE   r   r[   q   s"    r[   c                
       sH   e Zd Z		d	deeef dedeeeef  ddf fddZ	  Z
S )
RedirectResponse3  Nurlr0   r.   r(   c                    s&   t  j||d tt|| jd< d S )Nrd   location)rC   rD   r   rM   r.   )r3   rl   r0   r.   rE   r   r   rD      s   zRedirectResponse.__init__)rk   N)r5   r6   r7   r   rM   r   r!   r   r
   rD   rV   r   r   rE   r   rj      s    
rj   c                
       s|   e Zd Z		ddee dedeeeef  ddf fddZ	e
jdeeddf fd	d
Zdededee fddZ  ZS )StreamingResponser@   Niterabler0   r.   r(   c                    s   t  || || _d| _d S )NF)rC   rD   ro   _client_closed)r3   ro   r0   r.   rE   r   r   rD      s   
zStreamingResponse.__init__c                 c   s    t rB   rG   r3   r   r   r   render_stream   s   zStreamingResponse.render_streamr&   r'   c                 c   s,    |t | j | jdd |  E d H  d S )NFr+   )r/   r0   r1   rr   r2   r   r   r   r4      s
   zStreamingResponse.__call__ri   )r5   r6   r7   r	   r:   r!   r   r
   rM   rD   rT   rU   r   r9   rr   r   r   r4   rV   r   r   rE   r   rn      s*    
rn   c                       sb   e Zd Z			ddee dedeeeef  deddf
 fd	d
Z	de
eddf fddZ  ZS )StreamResponser@   Napplication/octet-streamro   r0   r.   rR   r(   c                    s   t  ||| || jd< d S )NContent-Type)rC   rD   r.   )r3   ro   r0   r.   rR   rE   r   r   rD      s   zStreamResponse.__init__c                 c   s    | j E d H  d S rB   )ro   rq   r   r   r   rr      s   zStreamResponse.render_stream)r@   Nrt   )r5   r6   r7   r	   r9   r!   r   r
   rM   rD   r   rr   rV   r   r   rE   r   rs      s      
rs   c                       s   e Zd ZdZedddZdddZ			dd
dddee de	de
eeef  dededd	f fddZdeed	d	f fddZ  ZS )SendEventResponsea|  
    Server-sent events response.

    When the cilent closes the connection, the generator will be closed.
    Use `try-finally` to clean up resources.

    ```python
    def generator():
        try:
            while True:
                yield ServerSentEvent()
        finally:
            print("generator closed")

    response = SendEventResponse(generator())
    ```
    
   
SendEvent_)max_workersthread_name_prefixzno-cacheztext/event-stream)zCache-Controlru   r@   N   r>   )ping_intervalr?   ro   r0   r.   r|   r?   r(   c                   sT   |r
i | j |}nt| j }|d  d| 7  < t ||| || _|| _d S )Nru   rL   )required_headersdictrC   rD   r|   r?   )r3   ro   r0   r.   r|   r?   rE   r   r   rD      s   	

zSendEventResponse.__init__c                 #   s   t jdd dd
 fdd}j|}zU| r!  sMz jjd}|d u r/W nt|j	V  W n t j
yD   dV  Y nw | r!  r!W d	  s\     rT| sj| }|d url|d S d S d	  s|     rt| s| }|d ur|w )N   )maxsizeFr(   c               	      s   z4t j} sz	 t|  W n ty   dY nw rW  d  j}t|dr3|  d S d S  d  j}t|drG|  w w )NTclose)iterro   putnextStopIterationhasattrr   )igqr3   should_stopr   r   push   s(   





z-SendEventResponse.render_stream.<locals>.push)timeouts   : ping

T)r(   N)queueQueuethread_poolsubmitdoneemptygetr|   r   r?   Empty
get_nowaitcancel	exception)r3   r   push_futureeventexcr   r   r   rr      sF   
	zSendEventResponse.render_streamri   )r5   r6   r7   r8   r   r   r}   r	   r   r!   r   r
   rM   floatrD   r   r9   rr   rV   r   r   rE   r   rv      s2     rv   c                       s  e Zd ZdZ					ddedeeeef  dee dee deej d	e	d
df fddZ
dede	ded
eeddf fddZdede	dede	de	d
eeddf fddZdede	dedeee	e	f  d
eeddf f
ddZdeded
ee fddZ  ZS )FileResponsez
    File response.

    It will automatically determine whether to send only headers
    and the range of files that need to be sent.
    N   filepathr.   rR   download_namestat_result
chunk_sizer(   c                    s   t  j|d || _|pt|ptj|d pd| _|| _|p$t	|| _
t	| j
jr4t| d|| _| j| | j| j| j| j
 d S )N)r.   r   rt   z is a directory)rC   rD   r   r   ospathbasenamerR   r   statr   S_ISDIRst_modeIsADirectoryErrorr   r.   rf   generate_common_headers)r3   r   r.   rR   r   r   r   rE   r   r   rD   "  s"   	zFileResponse.__init__send_header_only	file_sizer'   c                 c   s    t | j| jd< t || jd< |td | jdd |r"dV  d S t| jd}td|| jD ]	}|	| jV  q0W d    d S 1 sEw   Y  d S )	NrK   r*   r@   Fr+   r-   rbr   )
rM   rR   r.   r/   r1   openr   ranger   read)r3   r   r   r'   file_r   r   r   
handle_all=  s   "zFileResponse.handle_allstartendc                 c   s    d| d|d  d| | j d< t| j| j d< t|| | j d< |td | jd	d
 |r4dV  d S t| jd$}|| t||| j	D ]}|
t| j	|| V  qGW d    d S 1 saw   Y  d S )Nzbytes -r   /zcontent-rangerK   r*      Fr+   r-   r   )r.   rM   rR   r/   r1   r   r   seekr   r   r   min)r3   r   r   r'   r   r   r   herer   r   r   handle_single_rangeO  s    
"z FileResponse.handle_single_rangerangesc              	   c   s   d tddd}d| | jd< | |||| j\}}t|| jd< |td | jd	d
 |r6dV  d S t| j	d>}|D ](\}	}
|
|	 ||	|
V  t|	|
| jD ]}|t| j|
| V  qUdV  q?d| ddV  W d    d S 1 s}w   Y  d S )Nr<   $abcdefghijklmnopqrstuvwxyz0123456789   )kzmultipart/byteranges; boundary=rK   r*   r   Fr+   r-   r      
z--z--
ascii)joinrandom_choicesr.   generate_multipartrR   rM   r/   r1   r   r   r   r   r   r   r   rY   )r3   r   r   r'   r   boundaryrQ   generate_headersr   r   r   r   r   r   r   handle_several_rangesd  s(   

"z"FileResponse.handle_several_rangesr&   c           
   
   c   s   |d dk}| j }|j}d|vsd|v r)| |d |s)| |||E d H  d S z
| |d |}W n2 ttfye } z$|t|j g |j	pGi 
  |jd u rSdn|jdV  W Y d }~d S d }~ww t|dkr|d \}}	| |||||	E d H  d S | ||||E d H  d S )	NREQUEST_METHODHEAD
HTTP_RANGEHTTP_IF_RANGEr-   utf8r   r   )r   st_sizejudge_if_ranger   parse_ranger   r   r/   r0   r.   itemsrA   rY   rN   r   r   )
r3   r&   r'   r   r   r   r   r   r   r   r   r   r   r4     s:   
zFileResponse.__call__)NNNNr   )r5   r6   r7   r8   rM   r   r
   r   r   r!   rD   boolr   r   r9   r   r   r   r   r   r   r	   r4   rV   r   r   rE   r   r     s|    



r   )8rT   rg   r   r   r   httpr   	mimetypesr   randomr   r   typingr   r   r   r   r	   r
   r   r   r   r   r   baize.concurrencyr   baize.datastructuresr   r   baize.exceptionsr   r   baize.responsesr   r   r   r   baize.typingr   r   r   r/   r%   r:   ABCr;   r9   rM   rW   rZ   r[   rj   rn   rs   rv   r   r   r   r   r   <module>   s:    4+Y