o
    ߥifD                     @   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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 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%m&Z&m'Z' d
dl(m)Z)m*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/e0f  Z1G dd de1Z2G dd de.e Z3G dd de+Z4G dd de+e j-ee, Z5G dd de5e/ Z6G dd de5e' Z7G dd  d e#Z8ej9d!krd"ee0e/d#d$f d%e:fd&d'Z;nd"ee0e/d#d$f d%e:fd(d'Z;G d)d* d*e+eZ<dS )+    N)
guess_type)choices)AnyAsyncGeneratorAsyncIterableDictGenericMappingOptionalSequenceTupleTypeVarUnion)run_in_threadpool)URL)MalformedRangeHeaderRangeNotSatisfiable)BaseResponseFileResponseMixinbuild_bytes_from_sse
iri_to_uri)ProtocolReceiveScopeSendServerSentEvent   )send_http_bodysend_http_startc                   @   s*   e Zd ZdZdedededdfddZdS )	Responsezh
    The parent class of all responses, whose objects can be used directly as ASGI
    application.
    scopereceivesendreturnNc                    s6   d| j d< t|| j| jddI d H  t|I d H S )N0content-lengthTas_bytes)headersr   status_codelist_headersr   )selfr    r!   r"    r,   H/home/ubuntu/.local/lib/python3.10/site-packages/baize/asgi/responses.py__call__*   s   
zResponse.__call__)__name__
__module____qualname____doc__r   r   r   r.   r,   r,   r,   r-   r   $   s    r   _ContentTypec                       s   e Zd ZU dZdZeed< dZ				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ddfddZ  ZS )SmallResponsez9
    Abstract base class for small response objects.
     
media_typeutf-8   Ncontentr)   r(   charsetr#   c                    s0   t  || || _|p| j| _|p| j| _d S N)super__init__r9   r6   r:   )r+   r9   r)   r(   r6   r:   	__class__r,   r-   r=   ;   s   zSmallResponse.__init__c                    s   t r;   NotImplementedErrorr+   r9   r,   r,   r-   renderH      zSmallResponse.renderr    r!   r"   c                    s   |  | jI d H }|rd| jvrtt|}|| jd< | j}|r7d| jvr7|dr2|d| j 7 }|| jd< t|| j	| j
ddI d H  t||I d H  d S )Nr%   content-typeztext/
; charset=Tr&   )rC   r9   r(   strlenr6   
startswithr:   r   r)   r*   r   )r+   r    r!   r"   bodycontent_lengthcontent_typer,   r,   r-   r.   L   s   


zSmallResponse.__call__)r8   NNN)r/   r0   r1   r2   r6   rG   __annotations__r:   r3   intr
   r	   r=   abcabstractmethodbytesrC   r   r   r   r.   __classcell__r,   r,   r>   r-   r4   3   s0   
 "r4   c                   @   s*   e Zd ZdZdeeef defddZdS )PlainTextResponsez
text/plainr9   r#   c                    s   t |tr|| jS |S r;   )
isinstancerG   encoder:   rB   r,   r,   r-   rC   ]   s   zPlainTextResponse.renderN)r/   r0   r1   r6   r   rQ   rG   rC   r,   r,   r,   r-   rS   Z   s    rS   c                   @   s   e Zd ZdZdS )HTMLResponsez	text/htmlN)r/   r0   r1   r6   r,   r,   r,   r-   rV   a   s    rV   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/jsonr8   Nr9   r)   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r)   r(   r,   )json_kwargsupdater<   r=   )r+   r9   r)   r(   rX   r>   r,   r-   r=   l   s   zJSONResponse.__init__c                    s   t j|fi | j| jS r;   )jsondumpsra   rU   r:   rB   r,   r,   r-   rC   }   s   zJSONResponse.renderr8   N)r/   r0   r1   r2   r6   r   rN   r
   r	   rG   r=   rQ   rC   rR   r,   r,   r>   r-   rW   e   s"    rW   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urlr)   r(   r#   c                    s&   t  j||d tt|| jd< d S )Nr`   location)r<   r=   r   rG   r(   )r+   rh   r)   r(   r>   r,   r-   r=      s   zRedirectResponse.__init__)rg   N)r/   r0   r1   r   rG   r   rN   r
   r	   r=   rR   r,   r,   r>   r-   rf      s    
rf   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f fd	d
ZdeddfddZdedededdfddZ  ZS )StreamingResponser8   Niterabler)   r(   r#   c                    s   t  || || _d| _d S )NF)r<   r=   rk   _client_closed)r+   rk   r)   r(   r>   r,   r-   r=      s   
zStreamingResponse.__init__c                 C  s   t r;   r@   )r+   r,   r,   r-   render_stream   rD   zStreamingResponse.render_streamr!   c                    s0   | j s| I d H }|d dk| _ | j rd S d S )Ntypezhttp.disconnect)rl   )r+   r!   messager,   r,   r-   
wait_close   s
   zStreamingResponse.wait_closer    r"   c                    s   t || j| jddI d H  t| |}|  }z1z| js5|d I d H }t	||ddI d H  | jr W n	 t
y?   Y nw W |  | I d H  n|  | I d H  w t	|I d H S )NTr&   	more_body)r   r)   r*   asyncioensure_futurerp   rm   rl   asendr   StopAsyncIterationcancelaclose)r+   r    r!   r"   wait_close_future	generatorchunkr,   r,   r-   r.      s&   zStreamingResponse.__call__re   )r/   r0   r1   r   r3   rN   r
   r	   rG   r=   rO   rP   r   rQ   rm   r   rp   r   r   r.   rR   r,   r,   r>   r-   rj      s     
"rj   c                       s`   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f fddZ  ZS )StreamResponser8   Napplication/octet-streamrk   r)   r(   rL   r#   c                    s   t  ||| || jd< d S )NContent-Type)r<   r=   r(   )r+   rk   r)   r(   rL   r>   r,   r-   r=      s   zStreamResponse.__init__c              	   C  sj   z"| j 2 z	3 d H W }|V  q6 W | j }t|dr"| I d H  d S d S | j }t|dr4| I d H  w w )Nrx   )rk   hasattrrx   )r+   r{   gr,   r,   r-   rm      s   

zStreamResponse.render_stream)r8   Nr}   )r/   r0   r1   r   rQ   rN   r
   r	   rG   r=   r   rm   rR   r,   r,   r>   r-   r|      s     
r|   c                       sz   e Zd ZdZd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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
    async def generator():
        try:
            while True:
                yield ServerSentEvent()
        finally:
            print("generator closed")

    response = SendEventResponse(generator())
    ```
    zno-cachez
keep-aliveztext/event-stream)zCache-Control
Connectionr~   r8   N   r7   )ping_intervalr:   rk   r)   r(   r   r:   r#   c                   sT   |r
i | j |}nt| j }|d  d| 7  < t ||| || _|| _d S )Nr~   rF   )required_headersdictr<   r=   r   r:   )r+   rk   r)   r(   r   r:   r>   r,   r-   r=      s   	

zSendEventResponse.__init__c                   s"  t jdd dd
 fdd}t | }z[| r!  sSzt j  jdI d H }|d u r5W nt|j	V  W n t j
yJ   dV  Y nw | r!  r!W d	  sb     rZ| sp| }|d urr|d S d S d	  s     rz| s| }|d ur|w )Nr   )maxsizeFr#   c               	      s   z@j  } s&z |  I d H I d H  W n ty#   dY nw r	W  d I d H  j }t|dr@| I d H  d S d S  d I d H  j }t|drZ| I d H  w w )NTrx   )rk   	__aiter__put	__anext__rv   r   rx   )ir   qr+   should_stopr,   r-   push   s*   


z-SendEventResponse.render_stream.<locals>.push)timeouts   : ping

T)r#   N)rs   Queuert   doneemptywait_forgetr   r   r:   TimeoutError
get_nowaitrw   	exception)r+   r   push_futureeventexcr,   r   r-   rm      sF   
	zSendEventResponse.render_streamre   )r/   r0   r1   r2   r   r   r   rN   r
   r	   rG   floatr=   r   rQ   rm   rR   r,   r,   r>   r-   r      s2    	r   c                   @   s:   e Zd Z			d
dedee dee deddf
dd	ZdS )SendfileNFfile_descriptoroffsetcountrr   r#   c                    s   d S r;   r,   )r+   r   r   r   rr   r,   r,   r-   r.     s   zSendfile.__call__NNF)r/   r0   r1   rN   r
   boolr.   r,   r,   r,   r-   r     s    r   ntpathzos.PathLike[str]zos.PathLike[bytes]r#   c                    s   t tj| tjtjB I d H S r;   )r   osopenO_RDONLYO_BINARYr   r,   r,   r-   open_for_sendfile*  s   r   c                    s   t tj| tjI d H S r;   )r   r   r   r   r   r,   r,   r-   r   1  s   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fddZdede	deded
df
ddZdede	dedede	de	d
dfddZdede	dededeee	e	f  d
dfddZdededed
d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(   rL   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   r}   z is a directory)r<   r=   r   r   r   r   basenamerL   r   statr   S_ISDIRst_modeIsADirectoryErrorr   r(   rb   generate_common_headers)r+   r   r(   rL   r   r   r   r>   r,   r-   r=   ?  s"   	zFileResponse.__init__r    r"   c                    s   d|v r%d|d v r%			ddt dtt  dtt  dtd	df
fd
d}|S 			ddt dtt  dtt  dtd	df
 fdd}|S )zV
        https://asgi.readthedocs.io/en/latest/extensions.html#zero-copy-send
        
extensionshttp.response.zerocopysendNFr   r   r   rr   r#   c                    s@   d| |d}|d ur||d< |d ur||d<  |I d H  d S )Nr   )rn   filerr   r   r   r,   )r   r   r   rr   ro   )r"   r,   r-   sendfilec  s   z6FileResponse.create_send_or_zerocopy.<locals>.sendfilec                    s   |d urt tj| |tjI d H  d}d}|d u rK j}|sIt tj| |I d H }t||kr9t|ddI d H  nt||dI d H  d}|rd S d S |s{t j|| }||| k}||7 }t tj| |I d H }t||rp|nddI d H  |rMd S d S )Nr   FTrq   )	r   r   lseekSEEK_SETr   readrH   r   min)r   r   r   rr   herer   lengthdatar+   r"   r,   r-   fake_sendfilew  s2   
z;FileResponse.create_send_or_zerocopy.<locals>.fake_sendfiler   )rN   r
   r   )r+   r    r"   r   r   r,   r   r-   create_send_or_zerocopyZ  s@    z$FileResponse.create_send_or_zerocopysend_header_only	file_sizec              	      s   t | j| jd< t || jd< t|d| jddI d H  |r&t|I d H S | ||}t| jI d H }z||I d H  W t	t
j|I d H  d S t	t
j|I d H  w )NrE   r%   r8   Tr&   )rG   rL   r(   r   r*   r   r   r   r   r   r   close)r+   r   r   r    r"   r   r   r,   r,   r-   
handle_all  s   *zFileResponse.handle_allstartendc           	   	      s   d| d|d  d| | j d< t| j| j d< t|| | j d< t|d| jd	d
I d H  |r8t|I d H S | ||}t| jI d H }z||||| I d H  W t	t
j|I d H  d S t	t
j|I d H  w )Nzbytes -r   /zcontent-rangerE   r%      Tr&   )r(   rG   rL   r   r*   r   r   r   r   r   r   r   )	r+   r   r   r    r"   r   r   r   r   r,   r,   r-   handle_single_range  s    	*z FileResponse.handle_single_rangerangesc              	      s,  d tddd}d| | jd< | |||| j\}}t|| jd< t|d| jd	d
I d H  |r:t|I d H S | 	||}	t
| jI d H }
zC|D ]'\}}t||||d	dI d H  |	|
||| d	I d H  t|dd	dI d H  qKt|d| ddI d H W ttj|
I d H  S ttj|
I d H  w )Nr5   $abcdefghijklmnopqrstuvwxyz0123456789   )kzmultipart/byteranges; boundary=rE   r%   r   Tr&   rq      
z--z--
ascii)joinrandom_choicesr(   generate_multipartrL   rG   r   r*   r   r   r   r   rU   r   r   r   )r+   r   r   r    r"   r   boundaryrK   generate_headersr   r   r   r   r,   r,   r-   handle_several_ranges  s&   
(z"FileResponse.handle_several_rangesr!   c              
      s^  |d dk}| j }|j}d\}}|d D ]\}	}
|	dkr#|
d}q|	dkr,|
d}q|dks;|dkrF| ||sF| ||||I d H S z| ||}W n; ttfy } z-t||j	d	d
 |j
pci  D I d H  t||jd u rudn|jdI d H W  Y d }~S d }~ww t|dkr|d \}}| ||||||I d H S | |||||I d H S )NmethodHEAD)r5   r5   r(   s   rangelatin-1s   if-ranger5   c                 S   s$   g | ]\}}| d | d fqS )r   )rU   ).0r   vr,   r,   r-   
<listcomp>  s    z)FileResponse.__call__.<locals>.<listcomp>    utf8r   r   )r   st_sizedecodejudge_if_ranger   parse_ranger   r   r   r)   r(   itemsr   r9   rU   rH   r   r   )r+   r    r!   r"   r   r   r   
http_rangehttp_if_rangekeyvaluer   r   r   r   r,   r,   r-   r.     sL   




zFileResponse.__call__)NNNNr   )r/   r0   r1   r2   rG   r
   r	   r   r   rN   r=   r   r   r   r   r   r   r   r   r   r   r   r.   rR   r,   r,   r>   r-   r   7  s~    
?


"r   )=rO   rs   rc   r   r   	mimetypesr   randomr   r   typingr   r   r   r   r   r	   r
   r   r   r   r   baize.concurrencyr   baize.datastructuresr   baize.exceptionsr   r   baize.responsesr   r   r   r   baize.typingr   r   r   r   r   helperr   r   r   r3   ABCr4   rQ   rG   rS   rV   rW   rf   rj   r|   r   r   namerN   r   r   r,   r,   r,   r-   <module>   sJ    4'&V

