B
    indr                 @   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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rd 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*ej+e,ej-e,ej.e, f f Z/ej-e)e*f e0dddZ1G dd dZ2G dd de Z3G dd de4Z5G dd dZ6G dd dej7Z8G dd dej9Z:d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   8/tmp/pip-unpacked-wheel-_bom8ime/starlette/testclient.py	_is_asgi3(   s    

r   c               @   s4   e Zd ZdZeddddZeeeddddZ	dS )	
_WrapASGI2z7
    Provide an ASGI3 interface onto an ASGI2 app.
    N)r   r   c             C   s
   || _ d S )N)r   )selfr   r   r   r   __init__3   s    z_WrapASGI2.__init__)scopereceivesendr   c                s   |  |}|||I d H  d S )N)r   )r   r   r   r   instancer   r   r   __call__6   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'   ;   s   
r'   c               @   s   e Zd ZdddddZdS )_UpgradeWebSocketTestSessionN)sessionr   c             C   s
   || _ d S )N)r1   )r   r1   r   r   r   r   A   s    z_Upgrade.__init__)r"   r#   r$   r   r   r   r   r   r/   @   s   r/   c               @   s  e Zd ZeeeddddZd dddZej	ddd	d
Z
ddddZedddZeddddZeddddZeddddZeddddZeddddZd,ej	eddddZd-edd d!d"Zedd#d$Zedd%d&Zedd'd(Zd.eej	d)d*d+ZdS )/r0   N)r   r   portal_factoryr   c             C   s6   || _ || _d | _|| _t | _t | _d | _d S )N)	r   r   accepted_subprotocolr2   queueQueue_receive_queue_send_queueextra_headers)r   r   r   r2   r   r   r   r   F   s    

zWebSocketTestSession.__init__)r   c             C   s   t  | _| j|  | _y2| j| j}| ddi | 	 }| 
| W n  tk
rn   | j   Y nX |dd | _|dd | _| S )Ntypezwebsocket.connectsubprotocolheaders)
contextlib	ExitStack
exit_stackenter_contextr2   portalstart_task_soon_runr   r   _raise_on_close	Exceptionclosegetr3   r8   )r   _messager   r   r   	__enter__T   s    

zWebSocketTestSession.__enter__)argsr   c             G   sH   z|  d W d | j   X x&| j sB| j }t|tr|qW d S )Ni  )rE   r>   r7   emptyrF   
isinstanceBaseException)r   rJ   rH   r   r   r   __exit__d   s    

zWebSocketTestSession.__exit__c          
      s`   | j }| j}| j}y| |||I dH  W n0 tk
rZ } z| j|  W dd}~X Y nX dS )zE
        The sub-thread in which the websocket session runs.
        N)r   _asgi_receive
_asgi_sendr   rM   r7   put)r   r   r   r   excr   r   r   rB   n   s    zWebSocketTestSession._runc                s*   x| j  rtdI d H  qW | j  S )Nr   )r6   rK   anyiosleeprF   )r   r   r   r   rO   {   s    z"WebSocketTestSession._asgi_receive)rH   r   c                s   | j | d S )N)r7   rQ   )r   rH   r   r   r   rP      s    zWebSocketTestSession._asgi_sendc             C   s*   |d dkr&t |dd|ddd S )Nr9   zwebsocket.closecodei  reason )r   rF   )r   rH   r   r   r   rC      s    z$WebSocketTestSession._raise_on_closec             C   s   | j | d S )N)r6   rQ   )r   rH   r   r   r   r      s    zWebSocketTestSession.send)datar   c             C   s   |  d|d d S )Nzwebsocket.receive)r9   text)r   )r   rX   r   r   r   	send_text   s    zWebSocketTestSession.send_textc             C   s   |  d|d d S )Nzwebsocket.receive)r9   bytes)r   )r   rX   r   r   r   
send_bytes   s    zWebSocketTestSession.send_bytesrY   )rX   moder   c             C   sN   |dkst tj|dd}|dkr4| d|d n| d|dd d S )	N)rY   binary),:)
separatorsrY   zwebsocket.receive)r9   rY   zutf-8)r9   r[   )AssertionErrorjsondumpsr   encode)r   rX   r]   rY   r   r   r   	send_json   s
    zWebSocketTestSession.send_json  )rU   r   c             C   s   |  d|d d S )Nzwebsocket.disconnect)r9   rU   )r   )r   rU   r   r   r   rE      s    zWebSocketTestSession.closec             C   s   | j  }t|tr||S )N)r7   rF   rL   rM   )r   rH   r   r   r   r      s    

zWebSocketTestSession.receivec             C   s   |   }| | |d S )NrY   )r   rC   )r   rH   r   r   r   receive_text   s    
z!WebSocketTestSession.receive_textc             C   s   |   }| | |d S )Nr[   )r   rC   )r   rH   r   r   r   receive_bytes   s    
z"WebSocketTestSession.receive_bytes)r]   r   c             C   sH   |dkst |  }| | |dkr0|d }n|d d}t|S )N)rY   r^   rY   r[   zutf-8)rb   r   rC   decoderc   loads)r   r]   rH   rY   r   r   r   receive_json   s    

z!WebSocketTestSession.receive_json)rY   )rg   )rY   )r"   r#   r$   ASGI3Appr   _PortalFactoryTyper   rI   r,   r.   rN   rB   r	   rO   rP   rC   r   r*   rZ   r[   r\   rf   intrE   r   rh   ri   rl   r   r   r   r   r0   E   s&   	
r0   c               @   sF   e Zd Zd
eeeeejeej	f ddddZ
ejejddd	ZdS )_TestClientTransportTrW   N)r   r2   raise_server_exceptions	root_path	app_stater   c            C   s"   || _ || _|| _|| _|| _d S )N)r   rq   rr   r2   rs   )r   r   r2   rq   rr   rs   r   r   r   r      s
    	z_TestClientTransport.__init__)requestr   c                s  j j}j jjdd}j j}j j}j jjdd}ddddd| }d|krl|dd\}}	t|	}
n|}|}
dj	krg }n0|
|krd	|
 fg}nd	| d|
 
 fg}|d
d j	 D 7 }|dkrRj	dd }|d krg }ndd |dD }dt||| j||
 |ddg||
g|| j d}t| j|| j}t|ddjt||| j||
 |ddg||
gdi i| j d}dddt id d  tdfdd}td d fdd}y6|  $}|tj|| j||| W d Q R X W n0 tk
rF } z| jr6|W d d }~X Y nX | jr`svtd nsvd!g t d"t d ! d< tj"f d#i}d k	r|_# |_$|S )$Nascii)encodingP   i  )httpwshttpswssr`      hosts   hostc             S   s$   g | ]\}}|   | fqS r   )lowerre   ).0keyvaluer   r   r   
<listcomp>   s   z7_TestClientTransport.handle_request.<locals>.<listcomp>>   ry   r{   zsec-websocket-protocolc             S   s   g | ]}|  qS r   )strip)r   r   r   r   r   r      s    r_   Z	websocket
testclientiP  )r9   pathraw_pathrr   schemequery_stringr;   clientserversubprotocolsstaterx   z1.1zhttp.response.debug)r9   http_versionmethodr   r   rr   r   r   r;   r   r   
extensionsr   Fstream)r   c                 s   r"  s I d H  ddiS   } t| tr@| d}nh| d krNd}nZt| try*| d }t|trx|d}d|ddS  tk
r   ddddS X n| }dd|dS )	Nr9   zhttp.disconnectzutf-8    zhttp.requestT)r9   body	more_body)r9   r   )	is_setwaitreadrL   r*   re   r   r   StopIteration)r   Z
body_byteschunk)rt   request_completeresponse_completer   r   r     s*    




z4_TestClientTransport.handle_request.<locals>.receive)rH   r   c                s   | d dkrDrt d| d d< dd | dg D d< d	n| d d
krs\t d rlt d| dd}| dd}jdkrd | |s܈d d   n$| d dkr| d d | d d  d S )Nr9   zhttp.response.startz1Received multiple "http.response.start" messages.statusstatus_codec             S   s    g | ]\}}|  |  fqS r   )rj   )r   r   r   r   r   r   r   :  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   zhttp.response.debuginfotemplatecontext)rb   rF   r   r   writeseekset)rH   r   r   )r   
raw_kwargsrt   r   response_startedr   r   r   r   1  s,    


z1_TestClientTransport.handle_request.<locals>.sendz(TestClient did not receive any response.i  )r   r;   r   rt   )%urlr   netlocrj   r   r   querysplitro   r;   re   itemsrF   r   rr   rs   copyr0   r   r2   r/   r   ioBytesIOr	   callrS   EventrM   rq   rb   httpxZ
ByteStreamr   Responser   r   )r   rt   r   r   r   r   r   default_portr}   Zport_stringportr;   r:   r   r   r1   r   r   r@   rR   responser   )r   r   rt   r   r   r   r   r   handle_request   s    



 
z#_TestClientTransport.handle_request)TrW   )r"   r#   r$   rm   rn   boolr*   r,   r-   r.   r   r   Requestr   r   r   r   r   r   rp      s
    
rp   c                   s  e Zd ZU dZded< dZejej	j
 ed< d6eeeeeejejeejf  ejjejeef dd
	 fddZejejej	j
ddf dddZeje eje ejeejjf dddZdddddddejjddejjddeejjejejj eje ejejj  ejejejj! ejejj" ejejj ejejj#ejjf eje eje ejejj$ejjf ejejeejf  ej%d fddZ&dddejjddejjddejjejejj! ejejj" ejejj ejejj#ejjf eje eje ejejj$ejjf ejejeejf  ej%d
 fddZ'dddejjddejjddejjejejj! ejejj" ejejj ejejj#ejjf eje eje ejejj$ejjf ejejeejf  ej%d
 fddZ(dddejjddejjddejjejejj! ejejj" ejejj ejejj#ejjf eje eje ejejj$ejjf ejejeejf  ej%d
 fddZ)dddddddejjddejjddejjejejj eje ejejj  ejejejj! ejejj" ejejj ejejj#ejjf eje eje ejejj$ejjf ejejeejf  ej%d fd d!Z*dddddddejjddejjddejjejejj eje ejejj  ejejejj! ejejj" ejejj ejejj#ejjf eje eje ejejj$ejjf ejejeejf  ej%d fd"d#Z+dddddddejjddejjddejjejejj eje ejejj  ejejejj! ejejj" ejejj ejejj#ejjf eje eje ejejj$ejjf ejejeejf  ej%d fd$d%Z,dddejjddejjddejjejejj! ejejj" ejejj ejejj#ejjf eje eje ejejj$ejjf ejejeejf  ej%d
 fd&d'Z-d7eej.e ejejd( fd)d*Z/d dd+d,Z0ejdd-d.d/Z1ddd0d1Z2ddd2d3Z3ddd4d5Z4  Z5S )8
TestClientFzFuture[None]taskNr@   http://testserverTrW   asyncio)	r   base_urlrq   rr   r(   r)   cookiesr;   r   c	                s   t ||p
i d| _t|r,tt|}|}	ntt|}t|}	|	| _i | _	t
| j| j||| j	d}
|d krpi }|dd t j| j|||
d|d d S )N)r(   r)   )r2   rq   rr   rs   z
user-agentr   T)r   r   r;   	transportfollow_redirectsr   )r'   async_backendr   r,   castrm   r&   r   r   rs   rp   _portal_factory
setdefaultsuperr   )r   r   r   rq   rr   r(   r)   r   r;   Zasgi_appr   )	__class__r   r   r   o  s2    
zTestClient.__init__)r   c          	   c   s:   | j d k	r| j V  n"tjjf | j}|V  W d Q R X d S )N)r@   rS   from_threadstart_blocking_portalr   )r   r@   r   r   r   r     s    

zTestClient._portal_factory)r   allow_redirectsr   c             C   sN   t jj}|d k	r$d}t|t |}|d k	r2|}n|d k	rJ|d k	rJt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   redirectrH   r   r   r   _choose_redirect_arg  s    zTestClient._choose_redirect_arg)contentrX   filesrc   paramsr;   r   authr   r   timeoutr   )r   r   r   rX   r   rc   r   r;   r   r   r   r   r   r   r   c               s>   | j |}| ||}t j|||||||||	|
|||dS )N)r   rX   r   rc   r   r;   r   r   r   r   r   )r   joinr   r   rt   )r   r   r   r   rX   r   rc   r   r;   r   r   r   r   r   r   r   )r   r   r   rt     s     zTestClient.request)r   r;   r   r   r   r   r   r   )
r   r   r;   r   r   r   r   r   r   r   c         
      s(   |  ||}
t j||||||
||	dS )N)r   r;   r   r   r   r   r   )r   r   rF   )r   r   r   r;   r   r   r   r   r   r   r   )r   r   r   rF     s    zTestClient.getc         
      s(   |  ||}
t j||||||
||	dS )N)r   r;   r   r   r   r   r   )r   r   options)r   r   r   r;   r   r   r   r   r   r   r   )r   r   r   r     s    zTestClient.optionsc         
      s(   |  ||}
t j||||||
||	dS )N)r   r;   r   r   r   r   r   )r   r   head)r   r   r   r;   r   r   r   r   r   r   r   )r   r   r   r     s    zTestClient.head)r   r   rX   r   rc   r   r;   r   r   r   r   r   r   r   c               s0   |  |
|}t j|||||||||	|||dS )N)r   rX   r   rc   r   r;   r   r   r   r   r   )r   r   post)r   r   r   rX   r   rc   r   r;   r   r   r   r   r   r   r   )r   r   r   r   8  s    zTestClient.postc               s0   |  |
|}t j|||||||||	|||dS )N)r   rX   r   rc   r   r;   r   r   r   r   r   )r   r   rQ   )r   r   r   rX   r   rc   r   r;   r   r   r   r   r   r   r   )r   r   r   rQ   ]  s    zTestClient.putc               s0   |  |
|}t j|||||||||	|||dS )N)r   rX   r   rc   r   r;   r   r   r   r   r   )r   r   patch)r   r   r   rX   r   rc   r   r;   r   r   r   r   r   r   r   )r   r   r   r     s    zTestClient.patchc         
      s(   |  ||}
t j||||||
||	dS )N)r   r;   r   r   r   r   r   )r   r   delete)r   r   r   r;   r   r   r   r   r   r   r   )r   r   r   r     s    zTestClient.delete)r   r   kwargsr   c          
      s   t d|}|di }|dd |dd |dd |d k	rT|d	d
| ||d< yt jd|f| W n( tk
r } z
|j}W d d }~X Y n
X td|S )Nzws://testserverr;   
connectionupgradezsec-websocket-keyztestserver==zsec-websocket-versionZ13zsec-websocket-protocolz, GETzExpected WebSocket upgrade)	r   rF   r   r   r   rt   r/   r1   r   )r   r   r   r   r;   rR   r1   )r   r   r   websocket_connect  s    
zTestClient.websocket_connectc          	      s   t  }|tjjf j _ |jd dfdd}t	t
tj _t	t
tj _ j_ j |jd d fdd}| _W d Q R X S )N)r   c                  s
   d  _ d S )N)r@   r   )r   r   r   reset_portal  s    z*TestClient.__enter__.<locals>.reset_portalc                  s     j d S )N)r   wait_shutdownr   )r@   r   r   r   r     s    z+TestClient.__enter__.<locals>.wait_shutdown)r<   r=   r?   rS   r   r   r   r@   callbackr   Zcreate_memory_object_streammathinfstream_sendstream_receiverA   lifespanr   r   wait_startuppop_allr>   )r   stackr   r   r   )r@   r   r   rI     s    
zTestClient.__enter__)rJ   r   c             G   s   | j   d S )N)r>   rE   )r   rJ   r   r   r   rN     s    zTestClient.__exit__c          	      sF   d| j d}z | || jj| jjI d H  W d | jd I d H  X d S )Nr   )r9   r   )rs   r   r   r   r   r   )r   r   r   r   r   r     s     zTestClient.lifespanc                sb    j ddiI d H  tjd fdd}| I d H }|d dksFt|d dkr^| I d H  d S )Nr9   zlifespan.startup)r   c                 s&    j  I d H } | d kr" j  | S )N)r   r   r   result)rH   )r   r   r   r      s    
z(TestClient.wait_startup.<locals>.receive)zlifespan.startup.completezlifespan.startup.failedzlifespan.startup.failed)r   r   r,   r.   rb   )r   r   rH   r   )r   r   r     s    
zTestClient.wait_startupc          
      s   t jd fdd} j4 I d H P  jddiI d H  | I d H }|d dksVt|d dkrn| I d H  W d Q I d H R X d S )N)r   c                 s&    j  I d H } | d kr" j  | S )N)r   r   r   r   )rH   )r   r   r   r     s    
z)TestClient.wait_shutdown.<locals>.receiver9   zlifespan.shutdown)zlifespan.shutdown.completezlifespan.shutdown.failedzlifespan.shutdown.failed)r,   r.   r   r   r   rb   )r   r   rH   r   )r   r   r     s    
zTestClient.wait_shutdown)r   TrW   r   NNN)N)6r"   r#   r$   Z__test__r+   r@   r,   OptionalrS   abcBlockingPortalr   r*   r   r-   r.   r   r   ZCookieTypesr   r<   contextmanager	Generatorr   UnionZUseClientDefaultr   r   _typesZURLTypesZRequestContent_RequestDataZRequestFilesZQueryParamTypesZHeaderTypesZ	AuthTypesZTimeoutTypesr   rt   rF   r   r   r   rQ   r   r   Sequencer   rI   rN   r   r   r   __classcell__r   r   )r   r   r   j  s   
      2 ||||r   );r<   r   r   rc   r   r4   sysr,   r   concurrent.futuresr   typesr   urllib.parser   r   rS   Zanyio.from_threadr   Zanyio.streams.stapledr   Zstarlette._utilsr   Zstarlette.typesr   r	   r
   r   r   Zstarlette.websocketsr   version_infor   typing_extensionsCallableContextManagerr   r   rn   	AwaitableZASGIInstancer&   rm   Mappingr*   r   Iterabler   r   r   r   r'   rD   r/   r0   ZBaseTransportrp   ZClientr   r   r   r   r   <module>   sF   
s 3