U
    /j]                  	   @   s"  d dl Z d dlmZ d dlZd dlZd dlmZmZ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Zerd dlZd d	lmZ n6zd dlZd d	lmZ W n eefk
r   dZY nX zd d
lmZ dZW n ek
r   dZY nX edd ZG dd dZ dS )    N)asynccontextmanager)MappingOptionalTYPE_CHECKINGUnion)_exponential_backoff
exceptions)	transport)Credentials)mtls)TimeoutError)ClientTimeout)RequestTFc                   s@   t  | fdd  fdd}z
|V  W 5    X dS )a  
    timeout_guard is an asynchronous context manager to apply a timeout to an asynchronous block of code.

    Args:
        timeout (float): The time in seconds before the context manager times out.

    Raises:
        google.auth.exceptions.TimeoutError: If the code within the context exceeds the provided timeout.

    Usage:
        async with timeout_guard(10) as with_timeout:
            await with_timeout(async_function())
    c                     s0   t    } |  }|dkr,td d|S )Nr   z3Context manager exceeded the configured timeout of s.)time	monotonicr   )elapsed	remaining)starttotal_timeout F/tmp/pip-unpacked-wheel-l8yytoim/google/auth/aio/transport/sessions.py_remaining_timeB   s    
z&timeout_guard.<locals>._remaining_timec              
      sd   z  }t | |I d H }|W S  t jtfk
r^ } ztd|  d d|W 5 d }~X Y nX d S )NzThe operation z$ exceeded the configured timeout of r   )asynciowait_forr   )coror   responsee)r   r   r   r   with_timeoutK   s    z#timeout_guard.<locals>.with_timeoutN)r   r   )timeoutr   r   )r   r   r   r   timeout_guard0   s    	

r    c                
   @   s<  e Zd ZdZdeeej dddZdddZ	ddej
ej
ejfeeee eeeef  eeeef ee ejdd	d
Zeeddej
ej
ejfeee eeeef  eeeef ee ejdddZeeddej
ej
ejfeee eeeef  eeeef ee ejdddZeeddej
ej
ejfeee eeeef  eeeef ee ejdddZeeddej
ej
ejfeee eeeef  eeeef ee ejdddZeeddej
ej
ejfeee eeeef  eeeef ee ejdddZedd ZddddZdS )AsyncAuthorizedSessiona  This is an asynchronous implementation of :class:`google.auth.requests.AuthorizedSession` class.
    We utilize an instance of a class that implements :class:`google.auth.aio.transport.Request` configured
    by the caller or otherwise default to `google.auth.aio.transport.aiohttp.Request` if the external aiohttp
    package is installed.

    A Requests Session class with credentials.

    This class is used to perform asynchronous requests to API endpoints that require
    authorization::

        import aiohttp
        from google.auth.aio.transport import sessions

        async with sessions.AsyncAuthorizedSession(credentials) as authed_session:
            response = await authed_session.request(
                'GET', 'https://www.googleapis.com/storage/v1/b')

    The underlying :meth:`request` implementation handles adding the
    credentials' headers to the request and refreshing credentials as needed.

    Args:
        credentials (google.auth.aio.credentials.Credentials):
            The credentials to add to the request.
        auth_request (Optional[google.auth.aio.transport.Request]):
            An instance of a class that implements
            :class:`~google.auth.aio.transport.Request` used to make requests
            and refresh credentials. If not passed,
            an instance of :class:`~google.auth.aio.transport.aiohttp.Request`
            is created.

    Raises:
        - google.auth.exceptions.TransportError: If `auth_request` is `None`
            and the external package `aiohttp` is not installed.
        - google.auth.exceptions.InvalidType: If the provided credentials are
            not of type `google.auth.aio.credentials.Credentials`.
    N)credentialsauth_requestc                 C   sf   t |ts tdt| d|| _|}|s8tr8t }d| _d | _	d | _
|d kr\td|| _d S )Nz#The configured credentials of type zJ are invalid and must be of type `google.auth.aio.credentials.Credentials`Fzv`auth_request` must either be configured or the external package `aiohttp` must be installed to use the default value.)
isinstancer
   r   ZInvalidTypetype_credentialsAIOHTTP_INSTALLEDAiohttpRequest_is_mtls_mtls_init_task_cached_certZTransportError_auth_request)selfr"   r#   r,   r   r   r   __init__   s     
zAsyncAuthorizedSession.__init__c                    s2   j dkr& fdd}t| _ j I dH S )a  Configure the client certificate and key for SSL connection.

        The function does nothing unless `GOOGLE_API_USE_CLIENT_CERTIFICATE` is
        explicitly set to `true`. In this case if client certificate and key are
        successfully obtained (from the given client_cert_callback or from application
        default SSL credentials), the underlying transport will be reconfigured
        to use mTLS.
        Note: This function does nothing if the `aiohttp` library is not
        installed.
        Important: Calling this method will close any ongoing API requests associated
        with the current session. To ensure a smooth transition, it is recommended
        to call this during session initialization.

        Args:
            client_cert_callback (Optional[Callable[[], (bytes, bytes)]]):
                The optional callback returns the client certificate and private
                key bytes both in PEM format.
                If the callback is None, application default SSL credentials
                will be used.

        Raises:
            google.auth.exceptions.MutualTLSChannelError: If mutual TLS channel
                creation failed for any reason.
        Nc            	   
      s   t tjjjjI d H } | s&d_d S zt  I d H \_}}jr|_	t t j
||I d H }trtjtrtj|d}tj|d}j}t|d_| I d H  W n: tjttfk
r } zt|}||W 5 d }~X Y nX d S )NF)ssl)	connector)session)r   Z_run_in_executorgoogleauthr	   Z_mtls_helperZcheck_use_client_certr)   Zget_client_cert_and_keyr+   Zmake_client_cert_ssl_contextr'   r$   r,   r(   aiohttpZTCPConnectorZClientSessioncloser   ZClientCertErrorImportErrorOSErrorZMutualTLSChannelError)	Zuse_client_certcertkeyssl_contextr0   Znew_sessionZold_auth_requestZ
caught_excnew_excclient_cert_callbackr-   r   r   _do_configure   sF    

  
 
zDAsyncAuthorizedSession.configure_mtls_channel.<locals>._do_configure)r*   r   Zcreate_task)r-   r=   r>   r   r<   r   configure_mtls_channel   s    
*z-AsyncAuthorizedSession.configure_mtls_channel)methodurldataheadersmax_allowed_timer   total_attemptsreturnc              
      s  | j r,z| j I dH  W n tk
r*   Y nX tj|d}	|dkrDi }t|4 I dH }
|
| j| j|||I dH  d}tdk	rt	|tr|j
dk	r|j
nd}nt	|ttfrt|}|	2 z<3 dH W }|
| j|||||f|I dH }|jtjkr qq6 W 5 Q I dH R X |S )aY  
        Args:
                method (str): The http method used to make the request.
                url (str): The URI to be requested.
                data (Optional[bytes]): The payload or body in HTTP request.
                headers (Optional[Mapping[str, str]]): Request headers.
                timeout (float, aiohttp.ClientTimeout):
                The amount of time in seconds to wait for the server response
                with each individual request.
                max_allowed_time (float):
                If the method runs longer than this, a ``Timeout`` exception is
                automatically raised. Unlike the ``timeout`` parameter, this
                value applies to the total method execution time, even if
                multiple requests are made under the hood.
                total_attempts (int):
                The total number of retry attempts.

                Mind that it is not guaranteed that the timeout error is raised
                at ``max_allowed_time``. It might take longer, for example, if
                an underlying request takes a lot of time, but the request
                itself does not timeout, e.g. if a large file is being
                transmitted. The timeout error will be raised after such
                request completes.

        Returns:
                google.auth.aio.transport.Response: The HTTP response.

        Raises:
                google.auth.exceptions.TimeoutError: If the method does not complete within
                the configured `max_allowed_time` or the request exceeds the configured
                `timeout`.
        N)rE   g        )r*   	Exceptionr   ZAsyncExponentialBackoffr    r&   Zbefore_requestr,   r   r$   totalintfloatstatus_coder	   ZDEFAULT_RETRYABLE_STATUS_CODES)r-   r@   rA   rB   rC   rD   r   rE   kwargsretriesr   Zactual_timeout_r   r   r   r   request   sN    +   
    
zAsyncAuthorizedSession.request)rA   rB   rC   rD   r   rE   rF   c                    s    | j d||||||f|I dH S )  
        Args:
                url (str): The URI to be requested.
                data (Optional[bytes]): The payload or body in HTTP request.
                headers (Optional[Mapping[str, str]]): Request headers.
                max_allowed_time (float):
                If the method runs longer than this, a ``Timeout`` exception is
                automatically raised. Unlike the ``timeout`` parameter, this
                value applies to the total method execution time, even if
                multiple requests are made under the hood.
                timeout (float, aiohttp.ClientTimeout):
                The amount of time in seconds to wait for the server response
                with each individual request.
                total_attempts (int):
                The total number of retry attempts.

                Mind that it is not guaranteed that the timeout error is raised
                at ``max_allowed_time``. It might take longer, for example, if
                an underlying request takes a lot of time, but the request
                itself does not timeout, e.g. if a large file is being
                transmitted. The timeout error will be raised after such
                request completes.

        Returns:
                google.auth.aio.transport.Response: The HTTP response.

        Raises:
                google.auth.exceptions.TimeoutError: If the method does not complete within
                the configured `max_allowed_time` or the request exceeds the configured
                `timeout`.
        GETNrO   r-   rA   rB   rC   rD   r   rE   rL   r   r   r   get.  s    *zAsyncAuthorizedSession.getc                    s    | j d||||||f|I dH S )rP   POSTNrR   rS   r   r   r   postc  s    *zAsyncAuthorizedSession.postc                    s    | j d||||||f|I dH S )rP   PUTNrR   rS   r   r   r   put  s    *zAsyncAuthorizedSession.putc                    s    | j d||||||f|I dH S )rP   PATCHNrR   rS   r   r   r   patch  s    *zAsyncAuthorizedSession.patchc                    s    | j d||||||f|I dH S )rP   DELETENrR   rS   r   r   r   delete  s    *zAsyncAuthorizedSession.deletec                 C   s   | j S )z#Indicates if mutual TLS is enabled.)r)   r-   r   r   r   is_mtls7  s    zAsyncAuthorizedSession.is_mtls)rF   c                    s   | j  I dH  dS )z<
        Close the underlying auth request session.
        N)r,   r5   r]   r   r   r   r5   <  s    zAsyncAuthorizedSession.close)N)N)__name__
__module____qualname____doc__r
   r   r	   r   r.   r?   Z_DEFAULT_TIMEOUT_SECONDSZDEFAULT_MAX_RETRY_ATTEMPTSstrbytesr   rJ   r   r   rI   ResponserO   	functoolswrapsrT   rV   rX   rZ   r\   propertyr^   r5   r   r   r   r   r!   \   s   &  
M
O
4
4
4
4
4
r!   )!r   
contextlibr   rf   r   typingr   r   r   r   Zgoogle.authr   r   Zgoogle.auth.aior	   Zgoogle.auth.aio.credentialsr
   Zgoogle.auth.aio.transportr   Zgoogle.auth.exceptionsr   Z"google.auth.transport._mtls_helperr2   r4   r   r6   AttributeErrorZ!google.auth.aio.transport.aiohttpr   r(   r'   r    r!   r   r   r   r   <module>   s4   


+