o
    Yi1                     @   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   e/home/kim/smarthome/.venv/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_lineZ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   Z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   r8   z(aiohttp is not installed, skipping test.)reason)Zautousec                   c   s    d V  dt _d S )NF)r6   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)_r8   r   r   runv   s   z.test_invalid_response_stream_type.<locals>.runN)r6   r:   pytestraises	TypeErrorasyncior@   )r8   r@   r   r?   r   !test_invalid_response_stream_typek   s   "rE   c                    sT   g d}t |}|| _dd |  2 I d H }||ksJ |j  |j  d S )NZhelloZworldZ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   r8   r   mock_responseresultsr   r   r   test_httpx_simple_lines}   s   
rP   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                    rG   r   r   r#   r   r   r   rH      rI   z*test_httpx_data_prefix.<locals>.<listcomp>{ 'message': 'hello' }{ 'status': 'ok' }rJ   rM   r   r   r   test_httpx_data_prefix   s   
rU   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                    rG   r   r   r#   r   r   r   rH      rI   z2test_httpx_multiple_json_chunk.<locals>.<listcomp>rW   z{ "id": 2 }z{ "id": 3 }rJ   rM   r   r   r   test_httpx_multiple_json_chunk   s   
rZ   c                    sT   dg}t |}|| _dd |  2 I d H }|dgksJ |j  |j  d S )N{ "partial": "data"c                    rG   r   r   r#   r   r   r   rH      rI   z5test_httpx_incomplete_json_at_end.<locals>.<listcomp>rJ   rM   r   r   r   !test_httpx_incomplete_json_at_end   s   
r\   c                    sP   g }t |}|| _dd |  2 I d H }|g ksJ |j  |j  d S )Nc                    rG   r   r   r#   r   r   r   rH      rI   z+test_httpx_empty_stream.<locals>.<listcomp>rJ   rM   r   r   r   test_httpx_empty_stream   s   
r]   c                    s\   dt _g d}t|}|| _dd |  2 I d H }||ks!J |jj  |j	  d S )NTrF   c                    rG   r   r   r#   r   r   r   rH      rI   z-test_aiohttp_simple_lines.<locals>.<listcomp>
r6   r:   r!   rK   r=   r&   r'   Zassert_any_callr,   rL   rM   r   r   r   test_aiohttp_simple_lines   s   r_   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 )NTrQ   rR   c                    rG   r   r   r#   r   r   r   rH      rI   z,test_aiohttp_data_prefix.<locals>.<listcomp>rS   rT   r^   rM   r   r   r   test_aiohttp_data_prefix   s   r`   c                    s`   dt _g d}t|}|| _dd |  2 I d H }|g dks#J |jj  |j	  d S )NTrV   c                    rG   r   r   r#   r   r   r   rH      rI   z5test_aiohttp_multiple_json_chunks.<locals>.<listcomp>rY   r^   rM   r   r   r   !test_aiohttp_multiple_json_chunks   s   ra   c                    s\   dt _dg}t|}|| _dd |  2 I d H }|dgks!J |jj  |j	  d S )NTr[   c                    rG   r   r   r#   r   r   r   rH     rI   z7test_aiohttp_incomplete_json_at_end.<locals>.<listcomp>r^   rM   r   r   r   #test_aiohttp_incomplete_json_at_end   s   rb   c                 C   s"   t tjd}| |j_tjd|dS N)spec   )status_codestream)r   httpxZSyncByteStream__iter__r   Response)chunksmock_streamr   r   r   rN     s   rN   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"}}]}r5   body)rN   r   r6   BaseApiClientrequest_streamednextr   r7   rA   rB   r
   ZUnknownApiResponseError)mock_send_methodZwith_bad_jsonclientrg   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 )Nrm   rn   rp   rq   rr   )rt   r5   )rN   EVENT_STREAM_DATA_WITH_ERRORr   r6   ru   rv   rw   r   r7   rA   rB   r
   ServerError)rx   ry   rg   rz   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 )Nrm   rn   gemini-2.5-flashTell me a story in 300 words.modelcontentstesttextr   partsZroler&   r4   
candidatesZsdk_http_response)rN   r|   r   r	   modelsgenerate_content_streamrw   r   GenerateContentResponse	CandidateContentPartr7   rA   rB   r
   r}   )rx   ry   generated_responserz   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 rc   )	r   rh   ZAsyncByteStreamr|   r   r   r   r   rj   )r>   rl   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 )Nrm   	transportZasync_client_argsro   Zhttp_optionsrp   rq   keyvaluerr   rs   )r6   ru   r   HttpOptionsr   handle_async_requestr   r   Zasync_request_streamedanextr7   rA   rB   r
   r}   )mock_transportry   resprz   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 )Nrm   r   r   r   r   r   r   r   r   r   r   r   r4   r   )r	   r   r   r   r   r   r   Zaior   r   r   r   r   r   r   r7   rA   rB   r
   r}   )r   ry   r   rz   r   r   r   1test_error_event_in_generate_content_stream_async  s<   
"r   )2r   rD   typingr   Zunittestr   Zunittest.mockr   r   r   rA   ZaiohttpZAIOHTTP_NOT_INSTALLEDImportErrorrh   rX   r   r6   r	   r
   r   r|   rj   r   ZClientResponser!   Zfixturer7   r8   markZskipifZrequires_aiohttpr;   rE   rP   rU   rZ   r\   r]   r_   r`   ra   rb   rN   r{   r~   r   r   r   r   r   r   r   r   <module>   s   

	



