o
    .j8                     @  s  d dl 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	 ddl
mZ ddlmZ dd	lmZmZ dd
lmZ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mZ ddlm Z  ddl!m"Z" ej#ruddlm$Z$m%Z%m&Z&m'Z' G dd dZ(G dd deZ)dZ*dS )    )annotationsN)	timedelta)run_sync)pyfetch   )DEFAULT_RETRIES)BaseAdapter)ConnectionErrorConnectTimeout)PreparedRequestResponse)MaxRetryError)BytesQueueBuffer)HTTPResponse)Timeout)Retry)CaseInsensitiveDict)get_encoding_from_headers)	ProxyType	RetryTypeTLSClientCertTypeTLSVerifyTypec                   @  sn   e Zd ZdZ		d"d#d	d
Zd$ddZd%ddZ		d&d'ddZd(d)ddZd$ddZ	d*ddZ
d+d d!ZdS ),_PyodideRawIOaN  File-like wrapper around a Pyodide Fetch response with true streaming via JSPI.

    When constructed with a JS Response object, reads chunks incrementally from the
    JavaScript ReadableStream using ``run_sync(reader.read())`` per chunk.
    When constructed with preloaded content (non-streaming), serves from a memory buffer.
    Njs_response
typing.Anypreloaded_contentbytes | NonereturnNonec                 C  sT   || _ t | _d| _|d up|d u | _d | _i | _d | _|d ur(| j| d S d S )NF)	_js_responser   _buffer_closed	_finished_readerheaders	extensionput)selfr   r    r(   Y/home/thesage/.local/lib/python3.10/site-packages/niquests/extensions/pyodide/__init__.py__init__"   s   z_PyodideRawIO.__init__c                 C  sX   | j du r(| jdur*z| jj}|dur| | _ W dS W dS  ty'   Y dS w dS dS )z9Initialize the ReadableStream reader if not already done.N)r#   r   body	getReader	Exception)r'   r+   r(   r(   r)   _ensure_reader2   s   z_PyodideRawIO._ensure_readerc                 C  sh   |    | jdu rdS zt| j }|jrW dS |j}|dur't| W S W dS  ty3   Y dS w )zBRead the next chunk from the JS ReadableStream, blocking via JSPI.N)	r.   r#   r   readdonevaluebytesto_pyr-   )r'   resultr1   r(   r(   r)   _get_next_chunk<   s   
z_PyodideRawIO._get_next_chunkTamt
int | Nonedecode_contentboolr2   c                 C  sN  | j rt| jdkr| jt| jS dS | jr>t| jdkr!dS |d u s)|dk r2| jt| jS | jt|t| jS |d u sF|dk rl	 |  }|d u rPn| j| qGd| _t| jdkrj| jt| jS dS t| j|k r| js|  }|d u rd| _n| j| t| j|k r| jrvt| jdkrdS | jt|t| jS )Nr       T)r!   lenr    getr"   minr5   r&   r'   r6   r8   chunkr(   r(   r)   r/   P   s6   $$z_PyodideRawIO.readint#typing.Generator[bytes, None, None]c                 c  s    	 |  |}|sdS |V  q)z$Iterate over chunks of the response.TN)r/   r>   r(   r(   r)   streamv   s   
z_PyodideRawIO.streamc                 C  sF   d| _ | jd urz	t| j  W n	 ty   Y nw d | _d | _d S NT)r!   r#   r   cancelr-   r   r'   r(   r(   r)   close~   s   

z_PyodideRawIO.closetyping.Iterator[bytes]c                 C  s   | S Nr(   rE   r(   r(   r)   __iter__      z_PyodideRawIO.__iter__c                 C  s   |  d}|s	t|S )Ni    )r/   StopIteration)r'   r?   r(   r(   r)   __next__   s   
z_PyodideRawIO.__next__)NN)r   r   r   r   r   r   r   r   )r   r   rC   )r6   r7   r8   r9   r   r2   )T)r6   r@   r8   r9   r   rA   )r   rG   )r   r2   )__name__
__module____qualname____doc__r*   r.   r5   r/   rB   rF   rI   rL   r(   r(   r(   r)   r      s    	


&


r   c                      sv   e Zd ZdZefd/ fddZd0d	d
Z									d1d2d"d#Zd3d%d&Zd4d(d)Z	d5d+d,Z
d6d-d.Z  ZS )7PyodideAdapterzMSynchronous adapter for making HTTP requests in Pyodide using JSPI + pyfetch.max_retriesr   r   r   c                   s.   t    t|tr|| _d S t|| _d S rH   )superr*   
isinstancer   rS   from_int)r'   rS   	__class__r(   r)   r*      s   


zPyodideAdapter.__init__strc                 C     dS )Nz<PyodideAdapter WASM/>r(   rE   r(   r(   r)   __repr__   rJ   zPyodideAdapter.__repr__FNTrequestr   rB   r9   timeout)int | float | tuple | TimeoutSauce | Noneverifyr   certTLSClientCertType | NoneproxiesProxyType | Noneon_post_connection*typing.Callable[[typing.Any], None] | Noneon_upload_body;typing.Callable[[int, int | None, bool, bool], None] | Noneon_early_response(typing.Callable[[Response], None] | Nonemultiplexedr   c              
   C  sH  t |trt|dkr|d p|d }n|d }nt |tr$|jp#|j}| j}|jp+d}t }	 z	| 	|||}W n t
yY } z|j||j|d}|  W Y d}~q0d}~ww td|j|j|j|jd	}t|jd
}|||j|rz|j||j|d}W n ty   |jr | Y S w || q0tt | d|_|S )zFSend a PreparedRequest using Pyodide's pyfetch (synchronous via JSPI).r      r   GETT)errorNr:   )r+   r$   statusrequest_methodrequest_urlzRetry-After)response)seconds)rU   tupler;   TimeoutSaucetotalconnect_timeoutrS   methodtime_do_sendr-   	incrementurlsleepBaseHTTPResponser$   status_coder9   r<   is_retryr   raise_on_statusr   elapsed)r'   r\   rB   r]   r_   r`   rb   rd   rf   rh   rj   retriesrw   startrq   errbase_responsehas_retry_afterr(   r(   r)   send   sL   




zPyodideAdapter.sendint | float | Nonec              
   C  s  |j pd}d|v r|dd  nd}|dv r| ||S |dv r)| |||S i }|jrV|j D ]"\}}| dvrUt|trD|n|	d|t|trP|n|	d< q3|j
}	|	durt|	trh|	d	}	n1t|	tjrt|	ttfsg }
|	D ]}t|tr|
|d	 qyt|tr|
| qyd
|
}	|jpd|d}|	r|	|d< d}|durddlm} |t|d }ztt|j fd|i|}W n2 ty } z&t| }d|v sd|v sd|v rtd|j  dtd|j  d| d}~ww i }zLt|drK|j}t|dr5| D ]\}}t|tr |n|	d|t|tr-|n|	d< qnt|drK| D ]}|d ||d < q?W n
 tyV   Y nw t }|j|_ t!||_||_"|j pl|j |_ t#||_$z	|j%pyd|_&W n ty   d|_&Y nw |rt'|j(d}||_||_)d|_*d|_+|S zt| }W n ty   d
}Y nw t'|d}||_||_)||_*|S )zCPerform the actual request using pyfetch made synchronous via JSPI. z://r   )wswss)ssepsse)hostcontent-length
connectionztransfer-encodinglatin-1Nzutf-8r:   rl   )rw   r$   r+   )AbortSignali  signalabortr]   z	timed outzConnection to z
 timed outzFailed to fetch z: r$   itemsentries   )r   F)r   ),r{   splitlower_do_send_ws_do_send_sser$   r   rU   rY   decoder+   encodetypingIterabler2   	bytearrayappendjoinrw   jsr   r]   r@   r   r   r-   r
   r	   hasattrr   r   rn   r~   r   r\   r   encodingstatus_textreasonr   r   raw_content_content_consumed)r'   r\   rB   r]   r{   schemeheaders_dictkeyr1   r+   chunksr?   fetch_optionsr   r   r   eerr_strresponse_headers
js_headersentryrq   raw_ioresponse_bodyr(   r(   r)   ry      s   





 



zPyodideAdapter._do_sendr{   c              
   C  s   ddl m} z||}W n ty" } z
td| d| d}~ww t }d|_tddd	|_||_||_	d
|_
t }||_||_d|_|S )z>Handle WebSocket connections via browser native WebSocket API.r   )PyodideWebSocketExtensionzWebSocket connection to 	 failed: Ne   	websocketupgrade)r   r   zSwitching Protocolsr:   )_wsr   r-   r	   r   r~   r   r$   r\   r{   r   r   r%   r   r   )r'   r\   r{   r   extr   rq   r   r(   r(   r)   r   Q  s$   zPyodideAdapter._do_send_wsr   c              
   C  s  ddl m} |dkr|dddn|ddd}i }|jrE|j D ]"\}}| dvrDt|tr3|n|d	|t|tr?|n|d	< q"z|||d
}	W n t	yc }
 z
t
d| d|
 d}
~
ww t }d|_tddi|_||_||_d|_t }|	|_||_d|_d|_|S )z>Handle SSE connections via pyfetch streaming + manual parsing.r   )PyodideSSEExtensionr   zsse://zhttps://zpsse://zhttp://)r   r   r   r   )r$   zSSE connection to r   N   zcontent-typeztext/event-streamOKF)_sser   replacer$   r   r   rU   rY   r   r-   r	   r   r~   r   r\   r{   r   r   r%   r   r   r   )r'   r\   r{   r   r   http_urlr   r   r1   r   r   rq   r   r(   r(   r)   r   h  s6   $zPyodideAdapter._do_send_ssec                 C  rZ   )zClean up adapter resources.Nr(   rE   r(   r(   r)   rF     s   zPyodideAdapter.close)rS   r   r   r   )r   rY   )	FNTNNNNNF)r\   r   rB   r9   r]   r^   r_   r   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   r9   r   r   )r\   r   rB   r9   r]   r   r   r   )r\   r   r{   rY   r   r   )r\   r   r{   rY   r   rY   r   r   rM   )rN   rO   rP   rQ   r   r*   r[   r   ry   r   r   rF   __classcell__r(   r(   rW   r)   rR      s$    

;
v
#rR   )rR   )+
__future__r   rx   r   datetimer   pyodide.ffir   pyodide.httpr   	_constantr   adaptersr   
exceptionsr	   r
   modelsr   r   packages.urllib3.exceptionsr   packages.urllib3.responser   r   r}   packages.urllib3.utilr   rt   packages.urllib3.util.retryr   
structuresr   utilsr   TYPE_CHECKINGr   r   r   r   r   rR   __all__r(   r(   r(   r)   <module>   s.    x 