o
    :ήcj                     @   s  d dl Z d dlZd dlZd dlZ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 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 d dlmZ ejd	krld d
lmZ nd d
l mZ ej!g ej"ej#j$ f Z%ej!eegej&d f Z'ej!ege'f Z(ej!eeegej&d f Z)dej*e(e)f de+fddZ,G dd dZ-G dd deZ.G dd de/Z0G dd dZ1G dd dej2Z3G dd dej4Z5dS )    N)Future)GeneratorType)unquoteurljoin)StapledObjectStream)is_async_callable)ASGIAppMessageReceiveScopeSend)WebSocketDisconnect)      )	TypedDictappreturnc                 C   s   t | r
t| dS t| S )N	__await__)inspectisclasshasattrr   r    r   ;/tmp/pip-target-vg8gfxp4/lib/python/starlette/testclient.py	_is_asgi3$   s   

r   c                   @   s<   e Zd ZdZdeddfddZdeded	eddfd
dZ	dS )
_WrapASGI2z7
    Provide an ASGI3 interface onto an ASGI2 app.
    r   r   Nc                 C   
   || _ d S Nr   )selfr   r   r   r   __init__/      
z_WrapASGI2.__init__scopereceivesendc                    s    |  |}|||I d H  d S r   r   )r   r!   r"   r#   instancer   r   r   __call__2   s   
z_WrapASGI2.__call__)
__name__
__module____qualname____doc__ASGI2Appr   r   r
   r   r%   r   r   r   r   r   *   s    r   c                   @   s*   e Zd ZU eed< ejeejf ed< dS )_AsyncBackendbackendbackend_optionsN)r&   r'   r(   str__annotations__typingDictAnyr   r   r   r   r+   7   s   
 r+   c                   @   s   e Zd ZdddZdS )_UpgradesessionWebSocketTestSessionr   Nc                 C   r   r   )r4   )r   r4   r   r   r   r   =   r    z_Upgrade.__init__)r4   r5   r   N)r&   r'   r(   r   r   r   r   r   r3   <   s    r3   c                   @   s$  e Zd ZdedededdfddZd-dd	Zd
ej	ddfddZ
d.ddZdefddZdeddfddZdeddfddZdeddfddZdeddfddZdeddfddZd/dej	deddfdd Zd0d"eddfd#d$Zdefd%d&Zdefd'd(Zdefd)d*Zd/dedej	fd+d,ZdS )1r5   r   r!   portal_factoryr   Nc                 C   s6   || _ || _d | _|| _t | _t | _d | _d S r   )	r   r!   accepted_subprotocolr6   queueQueue_receive_queue_send_queueextra_headers)r   r   r!   r6   r   r   r   r   B   s   


zWebSocketTestSession.__init__c                 C   s   t  | _| j|  | _z| j| j}| ddi | 	 }| 
| W n ty4   | j   w |dd | _|dd | _| S )Ntypezwebsocket.connectsubprotocolheaders)
contextlib	ExitStack
exit_stackenter_contextr6   portalstart_task_soon_runr#   r"   _raise_on_close	Exceptionclosegetr7   r<   )r   _messager   r   r   	__enter__P   s   

zWebSocketTestSession.__enter__argsc                 G   sZ   z|  d W | j   n| j   w | j s+| j }t|tr$|| j rd S d S )N  )rI   rB   r;   emptyrJ   
isinstanceBaseException)r   rN   rL   r   r   r   __exit__`   s   


zWebSocketTestSession.__exit__c              
      sV   | j }| j}| j}z| |||I dH  W dS  ty* } z| j|  d}~ww )zE
        The sub-thread in which the websocket session runs.
        N)r!   _asgi_receive
_asgi_sendr   rR   r;   put)r   r!   r"   r#   excr   r   r   rF   j   s   zWebSocketTestSession._runc                    s0   | j  rtdI d H  | j  s| j  S )Nr   )r:   rP   anyiosleeprJ   r   r   r   r   rT   w   s
   


z"WebSocketTestSession._asgi_receiverL   c                    s   | j | d S r   )r;   rV   r   rL   r   r   r   rU   |   s   zWebSocketTestSession._asgi_sendc                 C   s*   |d dkrt |dd|ddd S )Nr=   zwebsocket.closecoderO   reason )r   rJ   r[   r   r   r   rG      s
   z$WebSocketTestSession._raise_on_closec                 C   s   | j | d S r   )r:   rV   r[   r   r   r   r#      s   zWebSocketTestSession.senddatac                 C      |  d|d d S )Nwebsocket.receiver=   textr#   r   r_   r   r   r   	send_text      zWebSocketTestSession.send_textc                 C   r`   )Nra   r=   bytesrd   re   r   r   r   
send_bytes   rg   zWebSocketTestSession.send_bytesrc   modec                 C   sL   |dv sJ t |}|dkr| d|d d S | d|dd d S )Nrc   binaryrc   ra   rb   utf-8rh   )jsondumpsr#   encode)r   r_   rk   rc   r   r   r   	send_json   s
   
zWebSocketTestSession.send_jsonrO   r\   c                 C   r`   )Nzwebsocket.disconnect)r=   r\   rd   )r   r\   r   r   r   rI      rg   zWebSocketTestSession.closec                 C   s   | j  }t|tr||S r   )r;   rJ   rQ   rR   r[   r   r   r   r"      s   

zWebSocketTestSession.receivec                 C      |   }| | |d S )Nrc   r"   rG   r[   r   r   r   receive_text      
z!WebSocketTestSession.receive_textc                 C   rs   )Nri   rt   r[   r   r   r   receive_bytes   rv   z"WebSocketTestSession.receive_bytesc                 C   sH   |dv sJ |   }| | |dkr|d }n|d d}t|S )Nrl   rc   ri   rn   )r"   rG   decodero   loads)r   rk   rL   rc   r   r   r   receive_json   s   


z!WebSocketTestSession.receive_json)r   r5   r   N)rc   )rO   )r&   r'   r(   ASGI3Appr   _PortalFactoryTyper   rM   r0   r2   rS   rF   r	   rT   rU   rG   r#   r.   rf   ri   rj   rr   intrI   r"   ru   rw   rz   r   r   r   r   r5   A   s2    



r5   c                   @   sF   e Zd Z		ddededededdf
d	d
Zdej	dej
fddZdS )_TestClientTransportTr^   r   r6   raise_server_exceptions	root_pathr   Nc                 C   s   || _ || _|| _|| _d S r   )r   r   r   r6   )r   r   r6   r   r   r   r   r   r      s   
z_TestClientTransport.__init__requestc                    s  j j}tj jjdd}j j}j j}tj jjdd}ddddd| }d|v r:|dd\}}	t	|	}
n|}|}
dj
v rFg }n|
|krRd	| fg}nd	| d|
  fg}|d
d j
 D 7 }|dv rj
dd }|d u r|g }n
dd |dD }dt||| j|| |ddg||
g|d
}t| j|| j}t|ddjt||| j|| |ddg||
gdi id}dddt id d  dtffdd}dtdd f fdd}z&|  }|tj|| j||| W d    n	1 sw   Y  W n ty+ } z| jr!|W Y d }~nd }~ww | jr8s7J d nsCd!g t d"td  d< tjd$i d#i}d ure|_  |_!|S )%Nascii)encodingP   i  )httpwshttpswss:   hosts   hostc                 S   s$   g | ]\}}|   | fqS r   )lowerrq   .0keyvaluer   r   r   
<listcomp>   s    z7_TestClientTransport.handle_request.<locals>.<listcomp>>   r   r   sec-websocket-protocolc                 S   s   g | ]}|  qS r   )strip)r   r   r   r   r   r      s    ,	websocket
testclientiP  )
r=   pathraw_pathr   schemequery_stringr?   clientserversubprotocolsr   z1.1http.response.template)r=   http_versionmethodr   r   r   r   r   r?   r   r   
extensionsFstreamr   c                     s   r  s I d H  ddiS   } t| tr!| d}n5| d u r(d}n.t| trTz| d }t|tr=|d}d|ddW S  tyS   dddd Y S w | }dd|dS )	Nr=   zhttp.disconnectrn       zhttp.requestT)r=   body	more_body)r=   r   )	is_setwaitreadrQ   r.   rq   r   r#   StopIteration)r   
body_byteschunk)r   request_completeresponse_completer   r   r"     s.   





z4_TestClientTransport.handle_request.<locals>.receiverL   c                    s   | d dkr$rJ d| d d< dd |  dg D d< d	d S | d d
kras0J d r8J d|  dd}|  dd}jdkrPd | |s_d d   d S d S | d dkrq| d | d  d S d S )Nr=   zhttp.response.startz1Received multiple "http.response.start" messages.statusstatus_codec                 S   s    g | ]\}}|  |  fqS r   )rx   r   r   r   r   r   0  s    zE_TestClientTransport.handle_request.<locals>.send.<locals>.<listcomp>r?   Tzhttp.response.bodyz<Received "http.response.body" without "http.response.start".z7Received "http.response.body" after response completed.r   r   r   FHEADr   r   r   templatecontext)rJ   r   r   writeseekset)rL   r   r   )r   
raw_kwargsr   r   response_startedr   r   r   r#   (  s@   


z1_TestClientTransport.handle_request.<locals>.sendz(TestClient did not receive any response.i  )r   r?   r   r   r   )"urlr   r   netlocrx   r   r   querysplitr~   r?   rq   itemsrJ   r   r5   r   r6   r3   r   ioBytesIOr	   callrX   EventrR   r   httpx
ByteStreamr   Responser   r   )r   r   r   r   r   r   r   default_portr   port_stringportr?   r>   r   r!   r4   r"   r#   rD   rW   responser   )r   r   r   r   r   r   r   r   handle_request   s   

 

z#_TestClientTransport.handle_request)Tr^   )r&   r'   r(   r|   r}   boolr.   r   r   Requestr   r   r   r   r   r   r      s    
r   c                       s  e Zd ZU dZded< dZejej	j
 ed< 							dFd
edededededejejeejf  dejjddf fddZejdejej	j
ddf fddZdeje deje dejeejjf fddZdddddddejjddejjdddedejjdejjdejjdejj d ejd!ejj!d"ejj"dejjd#ejejj#ejjf deded$ejejj$ejjf d%e%dej&f fd&d'Z'dddejjddejjdd(dejjd!ejj!d"ejj"dejjd#ejejj#ejjf deded$ejejj$ejjf d%e%dej&f fd)d*Z(dddejjddejjdd(dejjd!ejj!d"ejj"dejjd#ejejj#ejjf deded$ejejj$ejjf d%e%dej&f fd+d,Z)dddejjddejjdd(dejjd!ejj!d"ejj"dejjd#ejejj#ejjf deded$ejejj$ejjf d%e%dej&f fd-d.Z*dddddddejjddejjdddejjdejjdejjdejj d ejd!ejj!d"ejj"dejjd#ejejj#ejjf deded$ejejj$ejjf d%e%dej&f fd/d0Z+dddddddejjddejjdddejjdejjdejjdejj d ejd!ejj!d"ejj"dejjd#ejejj#ejjf deded$ejejj$ejjf d%e%dej&f fd1d2Z,dddddddejjddejjdddejjdejjdejjdejj d ejd!ejj!d"ejj"dejjd#ejejj#ejjf deded$ejejj$ejjf d%e%dej&f fd3d4Z-dddejjddejjdd(dejjd!ejj!d"ejj"dejjd#ejejj#ejjf deded$ejejj$ejjf d%e%dej&f fd5d6Z.	dGded7ej/e d8ejdejf fd9d:Z0dHd;d<Z1d=ejddfd>d?Z2dId@dAZ3dIdBdCZ4dIdDdEZ5  Z6S )J
TestClientFzFuture[None]taskNrD   http://testserverTr^   asyncior   base_urlr   r   r,   r-   cookiesr   c           
         s|   t ||pi d| _t|rtt|}|}n
tt|}t|}|| _t	| j| j
||d}	t j| j|ddi|	d|d d S )N)r,   r-   )r6   r   r   z
user-agentr   T)r   r   r?   	transportfollow_redirectsr   )r+   async_backendr   r0   castr|   r*   r   r   r   _portal_factorysuperr   )
r   r   r   r   r   r,   r-   r   asgi_appr   	__class__r   r   r   f  s.   

zTestClient.__init__c                 c   sV    | j d ur| j V  d S tjdi | j}|V  W d    d S 1 s$w   Y  d S )Nr   )rD   rX   start_blocking_portalr   )r   rD   r   r   r   r     s   
"zTestClient._portal_factoryr   allow_redirectsc                 C   sP   t jj}|d urd}t|t |}|d ur|}|S |d ur&|d ur&td|S )NzMThe `allow_redirects` argument is deprecated. Use `follow_redirects` instead.z9Cannot use both `allow_redirects` and `follow_redirects`.)r   _clientUSE_CLIENT_DEFAULTwarningswarnDeprecationWarningRuntimeError)r   r   r   redirectrL   r   r   r   _choose_redirect_arg  s   zTestClient._choose_redirect_arg)contentr_   filesro   paramsr?   r   authr   r   timeoutr   r   r   r   r_   r   ro   r   r?   r   r   r   c                   s>   | j |}| ||}t j|||||||||	|
|||dS N)r   r_   r   ro   r   r?   r   r   r   r   r   )r   joinr   r   r   )r   r   r   r   r_   r   ro   r   r?   r   r   r   r   r   r   r   r   r   r   r     s"   zTestClient.request)r   r?   r   r   r   r   r   r   c             
      (   |  ||}
t j||||||
||	dS N)r   r?   r   r   r   r   r   )r   r   rJ   r   r   r   r?   r   r   r   r   r   r   r   r   r   r   rJ        zTestClient.getc             
      r   r   )r   r   optionsr   r   r   r   r     r   zTestClient.optionsc             
      r   r   )r   r   headr   r   r   r   r   
  r   zTestClient.headc                   0   |  |
|}t j|||||||||	|||dS r   )r   r   postr   r   r   r_   r   ro   r   r?   r   r   r   r   r   r   r   r   r   r   r   '     zTestClient.postc                   r   r   )r   r   rV   r   r   r   r   rV   L  r   zTestClient.putc                   r   r   )r   r   patchr   r   r   r   r   q  r   zTestClient.patchc             
      r   r   )r   r   deleter   r   r   r   r     r   zTestClient.deleter   kwargsc              
      s   t d|}|di }|dd |dd |dd |d ur*|d	d
| ||d< zt jd|fi | W td tyT } z
|j}W Y d }~|S d }~ww )Nzws://testserverr?   
connectionupgradezsec-websocket-keyztestserver==zsec-websocket-version13r   z, GETzExpected WebSocket upgrade)	r   rJ   
setdefaultr   r   r   r3   r4   r   )r   r   r   r   r?   rW   r4   r   r   r   websocket_connect  s    
zTestClient.websocket_connectc                    s   t  Q}|tjdi j _ |jdfdd}tt	t
j _tt	t
j _ j_ j |jd fdd}| _W d    S 1 sXw   Y  S )Nr   c                      s
   d  _ d S r   )rD   r   rZ   r   r   reset_portal  s   
z*TestClient.__enter__.<locals>.reset_portalc                      s     j d S r   )r   wait_shutdownr   rD   r   r   r   r     s   z+TestClient.__enter__.<locals>.wait_shutdownr   r{   )r@   rA   rC   rX   r   r   rD   callbackr   create_memory_object_streammathinfstream_sendstream_receiverE   lifespanr   r   wait_startuppop_allrB   )r   stackr   r   r   r  r   rM     s*   




zTestClient.__enter__rN   c                 G   s   | j   d S r   )rB   rI   )r   rN   r   r   r   rS     s   zTestClient.__exit__c              	      sT   ddi}z|  || jj| jjI d H  W | jd I d H  d S | jd I d H  w )Nr=   r  )r   r  r"   r  r#   )r   r!   r   r   r   r    s
   *zTestClient.lifespanc                    sh    j ddiI d H  dtjf fdd}| I d H }|d dv s$J |d dkr2| I d H  d S d S )Nr=   zlifespan.startupr   c                     (    j  I d H } | d u r j  | S r   r  r"   r   resultrL   rZ   r   r   r"     
   
z(TestClient.wait_startup.<locals>.receive)zlifespan.startup.completelifespan.startup.failedr  )r  r#   r0   r2   r   r"   rL   r   rZ   r   r	    s   zTestClient.wait_startupc              	      s   dt jf fdd} j4 I d H <  jddiI d H  | I d H }|d dv s,J |d dkrC| I d H  W d   I d H  d S W d   I d H  d S 1 I d H sTw   Y  d S )Nr   c                     r  r   r  r  rZ   r   r   r"     r  z)TestClient.wait_shutdown.<locals>.receiver=   zlifespan.shutdown)zlifespan.shutdown.completelifespan.shutdown.failedr  )r0   r2   r  r  r#   r  r   rZ   r   r     s   .zTestClient.wait_shutdown)r   Tr^   r   NNr   )r   r   r{   )7r&   r'   r(   __test__r/   rD   r0   OptionalrX   abcBlockingPortalr   r.   r   r1   r2   r   r   CookieTypesr   r@   contextmanager	Generatorr   UnionUseClientDefaultr   r   _typesURLTypesRequestContentRequestDataRequestFilesQueryParamTypesHeaderTypes	AuthTypesTimeoutTypesdictr   r   rJ   r   r   r   rV   r   r   Sequencer   rM   rS   r  r	  r   __classcell__r   r   r   r   r   a  s  
 	# 
	
,
!
!
!	
)	
)	
)



r   )6r@   r   r   ro   r  r8   sysr0   r   concurrent.futuresr   typesr   urllib.parser   r   rX   r   anyio.streams.stapledr   starlette._utilsr   starlette.typesr   r	   r
   r   r   starlette.websocketsr   version_infor   typing_extensionsCallableContextManagerr  r  r}   	AwaitableASGIInstancer*   r|   r  r   r   r   r+   rH   r3   r5   BaseTransportr   Clientr   r   r   r   r   <module>   sF    
s .