o
    i1                     @   s  d 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 ddlm	Z	 ddl
Z
zddlZdZW n ey?   d	Ze ZY nw ddlZd
dlmZ d
dlmZ d
dlmZ d
dlmZ g dZG dd dejZG dd dejZe
jdejfddZe
jjeddZe
jd	ddd Z dejfddZ!e
jjdejfddZ"e
jjdejfd d!Z#e
jjdejfd"d#Z$e
jjdejfd$d%Z%e
jjdejfd&d'Z&ee
jjdejfd(d)Z'ee
jjdejfd*d+Z(ee
jjdejfd,d-Z)ee
jjdejfd.d/Z*d0d1 Z+e	d2d3d4 Z,e	d2d5d6 Z-e	d2d7d8 Z.d9d: Z/e	d;e
jjd<d= Z0e	d;e
jjd>d? Z1dS )@zTests for async stream.    N)List)mock)	AsyncMock)	MagicMock)patchFT   )_api_client)Client)errors)types)G   {"candidates":[{"content":{"parts":[{"text":"test"}],"role":"model"}}]}   
s<   {"error":{"code":500,"message":"Error","status":"INTERNAL"}}c                   @   s4   e Zd ZdZdee fddZdee fddZdS )MockHTTPXResponsez&Mock httpx.Response class for testing.linesc                 C   s*   t  | _t | |d| jj_t | _d S )N)return_value)r   aiter_lines_async_line_iteratorr   	__aiter__r   acloseselfr    r   _/home/ubuntu/.local/lib/python3.10/site-packages/google/genai/tests/client/test_async_stream.py__init__5   s
   zMockHTTPXResponse.__init__c                 C  s   |D ]}|V  qd S Nr   )r   r   liner   r   r   r   <   s   z&MockHTTPXResponse._async_line_iteratorN)__name__
__module____qualname____doc__r   strr   r   r   r   r   r   r   2   s    r   c                   @   s,   e Zd Zdee fddZdefddZdS )MockAIOHTTPResponser   c                 C   sJ   t  | _t | j_ddd |D d | _d| _| j| jj_t  | _	d S )Nr   c                 s   s    | ]}| d V  qdS )zutf-8N)encode.0r   r   r   r   	<genexpr>G   s    z/MockAIOHTTPResponse.__init__.<locals>.<genexpr>r   )
r   contentr   readlinejoin
_read_data	_read_pos_async_read_lineside_effectreleaser   r   r   r   r   C   s   
zMockAIOHTTPResponse.__init__returnc                    sp   | j t| jkrdS | jd| j }|dkr'| j| j d  }t| j| _ |S | j| j |d  }|d | _ |S )N    r      )r*   lenr)   find)r   newline_posr   r   r   r   r+   L   s   
z$MockAIOHTTPResponse._async_read_lineN)r   r   r   r   r    r   bytesr+   r   r   r   r   r!   A   s    	r!   r.   c                   C   s   t ji dS )Nheaders)
api_clientHttpResponser   r   r   r   	responses[   s   r:   z(aiohttp is not installed, skipping test.)reason)autousec                   c   s    d V  dt _d S )NF)r8   has_aiohttpr   r   r   r   reset_has_aiohttpe   s   
r>   c                    sR   dt _tjtdd  fdd}t|  W d   dS 1 s"w   Y  dS )z;Tests that an invalid response stream type raises an error.FzVExpected self.response_stream to be an httpx.Response or aiohttp.ClientResponse object)matchc                     s      2 z3 d H W } q6 d S r   )_aiter_response_stream)_r:   r   r   runv   s   z.test_invalid_response_stream_type.<locals>.runN)r8   r=   pytestraises	TypeErrorasynciorC   )r:   rC   r   rB   r   !test_invalid_response_stream_typek   s   "rH   c                    sT   g d}t |}|| _dd |  2 I d H }||ksJ |j  |j  d S )Nhelloworldtestingc                       g | z3 d H W }|q6 S r   r   r#   r   r   r   
<listcomp>       z+test_httpx_simple_lines.<locals>.<listcomp>r   response_streamr@   r   assert_called_oncer   r:   r   mock_responseresultsr   r   r   test_httpx_simple_lines}   s   
rV   c                    sX   ddg}t |}|| _dd |  2 I d H }|ddgks J |j  |j  d S )Ndata: { 'message': 'hello' }data: { 'status': 'ok' }c                    rM   r   r   r#   r   r   r   rN      rO   z*test_httpx_data_prefix.<locals>.<listcomp>{ 'message': 'hello' }{ 'status': 'ok' }rP   rS   r   r   r   test_httpx_data_prefix   s   
r[   c                    sX   g d}t |}|| _dd |  2 I d H }|g dks J |j  |j  d S )N{ "id": 1 } zdata: { "id": 2 }zdata: { "id": 3 }c                    rM   r   r   r#   r   r   r   rN      rO   z2test_httpx_multiple_json_chunk.<locals>.<listcomp>r]   z{ "id": 2 }z{ "id": 3 }rP   rS   r   r   r   test_httpx_multiple_json_chunk   s   
r`   c                    sT   dg}t |}|| _dd |  2 I d H }|dgksJ |j  |j  d S )N{ "partial": "data"c                    rM   r   r   r#   r   r   r   rN      rO   z5test_httpx_incomplete_json_at_end.<locals>.<listcomp>rP   rS   r   r   r   !test_httpx_incomplete_json_at_end   s   
rb   c                    sP   g }t |}|| _dd |  2 I d H }|g ksJ |j  |j  d S )Nc                    rM   r   r   r#   r   r   r   rN      rO   z+test_httpx_empty_stream.<locals>.<listcomp>rP   rS   r   r   r   test_httpx_empty_stream   s   
rc   c                    s\   dt _g d}t|}|| _dd |  2 I d H }||ks!J |jj  |j	  d S )NTrI   c                    rM   r   r   r#   r   r   r   rN      rO   z-test_aiohttp_simple_lines.<locals>.<listcomp>
r8   r=   r!   rQ   r@   r&   r'   assert_any_callr-   rR   rS   r   r   r   test_aiohttp_simple_lines   s   rf   c                    s`   dt _ddg}t|}|| _dd |  2 I d H }|ddgks#J |jj  |j	  d S )NTrW   rX   c                    rM   r   r   r#   r   r   r   rN      rO   z,test_aiohttp_data_prefix.<locals>.<listcomp>rY   rZ   rd   rS   r   r   r   test_aiohttp_data_prefix   s   rg   c                    s`   dt _g d}t|}|| _dd |  2 I d H }|g dks#J |jj  |j	  d S )NTr\   c                    rM   r   r   r#   r   r   r   rN      rO   z5test_aiohttp_multiple_json_chunks.<locals>.<listcomp>r_   rd   rS   r   r   r   !test_aiohttp_multiple_json_chunks   s   rh   c                    s\   dt _dg}t|}|| _dd |  2 I d H }|dgks!J |jj  |j	  d S )NTra   c                    rM   r   r   r#   r   r   r   rN     rO   z7test_aiohttp_incomplete_json_at_end.<locals>.<listcomp>rd   rS   r   r   r   #test_aiohttp_incomplete_json_at_end   s   ri   c                 C   s"   t tjd}| |j_tjd|dS N)spec   )status_codestream)r   httpxSyncByteStream__iter__r   Response)chunksmock_streamr   r   r   rT     s   rT   zhttpx.Client.sendc                 C   s   g d}t || _tjdd}|ddi }t|}|tji ddks%J t	t
j t| W d    d S 1 s;w   Y  d S )N)r   r   s   {"error": bad_json}test_api_keyapi_keyPOSTmodels/gemini-2.5-flashM{"candidates": [{"content": {"parts": [{"text": "test"}], "role": "model"}}]}r7   body)rT   r   r8   BaseApiClientrequest_streamednextr   r9   rD   rE   r
   UnknownApiResponseError)mock_send_methodwith_bad_jsonclientrn   chunkr   r   r   /test_error_event_in_streamed_responses_bad_json  s   

"r   c                 C   s|   t t| _tjdd}|ddi }t|}|tjdi dks!J t	
tj t| W d    d S 1 s7w   Y  d S )Nru   rv   rx   ry   rz   )r|   r7   )rT   EVENT_STREAM_DATA_WITH_ERRORr   r8   r}   r~   r   r   r9   rD   rE   r
   ServerError)r   r   rn   r   r   r   r   &test_error_event_in_streamed_responses.  s   

"r   c                 C   s   t t| _tdd}|jjddd}t|}|tjtj	tj
tjddgdd	d
gtji ddks4J ttj t| W d    d S 1 sJw   Y  d S )Nru   rv   gemini-2.5-flashTell me a story in 300 words.modelcontentstesttextr   partsroler&   r6   
candidatessdk_http_response)rT   r   r   r	   modelsgenerate_content_streamr   r   GenerateContentResponse	CandidateContentPartr9   rD   rE   r
   r   )r   r   generated_responser   r   r   r   +test_error_event_in_generate_content_streamB  s.   



"r   c                    s,   t tjd}t|j_t |_tjd|dS rj   )	r   ro   AsyncByteStreamr   r   r   r   r   rr   )rA   rt   r   r   r   _async_httpx_responsea  s   r   zhttpx.AsyncBaseTransportc                    s   t jdtjd| idd}t| _t | _|ddddiI d H }t	|I d H }|tj
i d	d
ks3J ttj t	|I d H  W d    d S 1 sLw   Y  d S )Nru   	transportasync_client_argsrw   http_optionsrx   ry   keyvaluerz   r{   )r8   r}   r   HttpOptionsr   handle_async_requestr   r   async_request_streamedanextr9   rD   rE   r
   r   )mock_transportr   respr   r   r   r   ,test_error_event_in_streamed_responses_asynck  s(   

"r   c                    s   t dtjd| idd}t| _t | _|jjj	dddI d H }t
|I d H }|tjtjtjtjdd	gd
ddgtji ddksEJ ttj t
|I d H  W d    d S 1 s^w   Y  d S )Nru   r   r   r   r   r   r   r   r   r   r   r   r6   r   )r	   r   r   r   r   r   r   aior   r   r   r   r   r   r   r9   rD   rE   r
   r   )r   r   r   r   r   r   r   1test_error_event_in_generate_content_stream_async  s<   
"r   )2r   rG   typingr   unittestr   unittest.mockr   r   r   rD   aiohttpAIOHTTP_NOT_INSTALLEDImportErrorro   r^   r   r8   r	   r
   r   r   rr   r   ClientResponser!   fixturer9   r:   markskipifrequires_aiohttpr>   rH   rV   r[   r`   rb   rc   rf   rg   rh   ri   rT   r   r   r   r   r   r   r   r   r   r   <module>   s   

	



