U
    hI#                     @  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
 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 d dlm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 ededZededdZededZG dd dee ZG dd  d ee ejZ G d!d" d"e e Z!d#d$d%d&d'Z"G d(d) d)ee Z#dS )*    )annotationsN)Any)AsyncGenerator)AsyncIterator)	Awaitable)Callable)ClassVar)Dict)	Generator)Generic)NoReturn)Optional)overload)Tuple)TypeVar   )exc   )util)Literal)Self_T)bound_T_coT)r   	covariant_PTc                   @  s   e Zd ZU i Zded< dZedddddZedddd	dZd
d
dddZed!ddddddZ	eddddddZ
eed"dddddddZeed#dddddddZed$dddddd dZdS )%ReversibleProxyzCClassVar[Dict[weakref.ref[Any], weakref.ref[ReversibleProxy[Any]]]]_proxy_objects)__weakref__r   )targetreturnc                 C  s   d S N selfr   r"   r"   ?/tmp/pip-unpacked-wheel-y9ln43lq/sqlalchemy/ext/asyncio/base.py_assign_proxied.   s    zReversibleProxy._assign_proxiedNonec                 C  s   d S r!   r"   r#   r"   r"   r%   r&   1   s    zOptional[_PT]c                 C  s:   |d k	r6t |tj}t | ttj|}|tj|< |S r!   )weakrefrefr   _target_gced	functoolspartialr   )r$   r   Z
target_ref	proxy_refr"   r"   r%   r&   4   s     
Nzweakref.ref[_PT]zOptional[weakref.ref[Self]])r)   r-   r    c                 C  s   | j |d  d S r!   )r   pop)clsr)   r-   r"   r"   r%   r*   A   s    zReversibleProxy._target_gcedr   r   )r   additional_kwr    c                 K  s
   t  d S r!   NotImplementedError)r/   r   r0   r"   r"   r%   _regenerate_proxy_for_targetI   s    z,ReversibleProxy._regenerate_proxy_for_target.zLiteral[True])r   
regenerater0   r    c                 K  s   d S r!   r"   r/   r   r4   r0   r"   r"   r%   _retrieve_proxy_for_targetO   s    z*ReversibleProxy._retrieve_proxy_for_targetTboolzOptional[Self]c                 K  s   d S r!   r"   r5   r"   r"   r%   r6   U   s    c                 K  sV   z| j t| }W n tk
r(   Y nX | }|d k	r<|S |rN| j|f|S d S d S r!   )r   r(   r)   KeyErrorr3   )r/   r   r4   r0   r-   proxyr"   r"   r%   r6   [   s    )N).)T)T)__name__
__module____qualname__r   __annotations__	__slots__r   r&   classmethodr*   r3   r6   r"   r"   r"   r%   r   (   s0   

    r   c                   @  sl   e Zd ZdZejddddddZdd	d
dZdd	ddZejdddddddZ	dd	ddZ
dS )StartableContextr"   Fr7   r   is_ctxmanagerr    c                   s
   t  d S r!   r1   )r$   rB   r"   r"   r%   startq   s    zStartableContext.startzGenerator[Any, Any, _T_co]r    c                 C  s   |    S r!   )rC   	__await__r$   r"   r"   r%   rE   u   s    zStartableContext.__await__c                   s   | j ddI d H S )NT)rB   )rC   rF   r"   r"   r%   
__aenter__x   s    zStartableContext.__aenter__r   Optional[bool])type_value	tracebackr    c                   s   d S r!   r"   )r$   rI   rJ   rK   r"   r"   r%   	__aexit__{   s    zStartableContext.__aexit__r   c                 C  s   t d| jj d S )Nz@%s context has not been started and object has not been awaited.)	async_excZAsyncContextNotStarted	__class__r:   rF   r"   r"   r%   _raise_for_not_started   s
    z'StartableContext._raise_for_not_startedN)F)r:   r;   r<   r>   abcabstractmethodrC   rE   rG   rL   rO   r"   r"   r"   r%   r@   n   s   r@   c                   @  sR   e Zd ZU dZded< dddddd	ZddddddZdddddddZdS )GeneratorStartableContextgenzAsyncGenerator[_T_co, Any]rT   #Callable[..., AsyncIterator[_T_co]]zTuple[Any, ...]zDict[str, Any])funcargskwdsc                 C  s   |||| _ d S r!   rS   )r$   rV   rW   rX   r"   r"   r%   __init__   s    z"GeneratorStartableContext.__init__Fr7   r   rA   c                   sN   zt | jI d H }W n tk
r4   tdd Y nX |sJ| j I d H  |S )Nzgenerator didn't yield)r   anext_rT   StopAsyncIterationRuntimeErroraclose)r$   rB   Zstart_valuer"   r"   r%   rC      s    zGeneratorStartableContext.startr   rH   )typrJ   rK   r    c              
     s*  |d kr@zt | jI d H  W n tk
r4   Y dS X tdn|d krN| }z| j|I d H  W n tk
r } z||k	 W Y S d }~X Y n tk
r } z:||krW Y ,dS t|ttfr|j|krW Y 
dS  W 5 d }~X Y n6 t	k
r } z||k	r W Y dS d }~X Y nX tdd S )NFzgenerator didn't stopz$generator didn't stop after athrow())
r   rZ   rT   r[   r\   athrow
isinstanceStopIteration	__cause__BaseException)r$   r^   rJ   rK   r   r"   r"   r%   rL      s4    

	

z#GeneratorStartableContext.__aexit__N)F)r:   r;   r<   r>   r=   rY   rC   rL   r"   r"   r"   r%   rR      s
   
rR   rU   z/Callable[..., GeneratorStartableContext[_T_co]])rV   r    c                   s$   t  dddd fdd}|S )a=  @asyncstartablecontext decorator.

    the decorated function can be called either as ``async with fn()``, **or**
    ``await fn()``.   This is decidedly different from what
    ``@contextlib.asynccontextmanager`` supports, and the usage pattern
    is different as well.

    Typical usage:

    .. sourcecode:: text

        @asyncstartablecontext
        async def some_async_generator(<arguments>):
            <setup>
            try:
                yield <value>
            except GeneratorExit:
                # return value was awaited, no context manager is present
                # and caller will .close() the resource explicitly
                pass
            else:
                <context manager cleanup>


    Above, ``GeneratorExit`` is caught if the function were used as an
    ``await``.  In this case, it's essential that the cleanup does **not**
    occur, so there should not be a ``finally`` block.

    If ``GeneratorExit`` is not invoked, this means we're in ``__aexit__``
    and we were invoked as a context manager, and cleanup should proceed.


    r   z GeneratorStartableContext[_T_co])rW   rX   r    c                    s   t  | |S r!   )rR   )rW   rX   rV   r"   r%   helper   s    z%asyncstartablecontext.<locals>.helper)r+   wraps)rV   re   r"   rd   r%   asyncstartablecontext   s    %rg   c                   @  sR   e Zd ZdZejddddZddddZd	d
dddZd	d
dddZ	dS )ProxyComparabler"   r   rD   c                 C  s
   t  d S r!   r1   rF   r"   r"   r%   _proxied  s    zProxyComparable._proxiedintc                 C  s   t | S r!   )idrF   r"   r"   r%   __hash__  s    zProxyComparable.__hash__r   r7   )otherr    c                 C  s   t || jo| j|jkS r!   r`   rN   ri   r$   rm   r"   r"   r%   __eq__  s    
zProxyComparable.__eq__c                 C  s   t || j p| j|jkS r!   rn   ro   r"   r"   r%   __ne__  s    
zProxyComparable.__ne__N)
r:   r;   r<   r>   r   Zro_non_memoized_propertyri   rl   rp   rq   r"   r"   r"   r%   rh     s   rh   )$
__future__r   rP   r+   typingr   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r(    r   rM   r   Zutil.typingr   r   r   r   r   r   ABCr@   rR   rg   rh   r"   r"   r"   r%   <module>   s:   FQ,