U
    cc                     @   s   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ZddlmZ ddl	m
Z
 dd	lmZ ee d
Zdd ZG dd dejZeedddZeedddZddeedddZG dd dZdd Zdd Zdd  ZdS )!    N)Any)Callable)	Coroutine   )compat)memoized_property   )exc
gr_contextc                 C   s   t | t pt | tjtjfS N)
isinstance	ExceptionasyncioTimeoutErrorZCancelledError)e r   E/tmp/pip-unpacked-wheel-8u86ls_i/sqlalchemy/util/_concurrency_py3k.pyis_exit_exception   s     
r   c                   @   s   e Zd Zdd ZdS )_AsyncIoGreenletc                 C   s&   t j | || || _tr"|j| _d S r   )greenlet__init__driver_has_gr_contextr
   )selffnr   r   r   r   r   (   s    z_AsyncIoGreenlet.__init__N)__name__
__module____qualname__r   r   r   r   r   r   '   s   r   )	awaitablereturnc                 C   s(   t  }t|tstd|j| S )zAwaits an async function in a sync method.

    The sync method must be inside a :func:`greenlet_spawn` context.
    :func:`await_only` calls cannot be nested.

    :param awaitable: The coroutine to call.

    zjgreenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place?)r   
getcurrentr   r   r	   MissingGreenletr   switch)r   currentr   r   r   
await_only/   s    

	r$   c                 C   s@   t  }t|ts4t }| r*td|| S |j	
| S )zAwaits an async function in a sync method.

    The sync method must be inside a :func:`greenlet_spawn` context.
    :func:`await_fallback` calls cannot be nested.

    :param awaitable: The coroutine to call.

    zgreenlet_spawn has not been called and asyncio event loop is already running; can't call await_fallback() here. Was IO attempted in an unexpected place?)r   r    r   r   get_event_loop
is_runningr	   r!   run_until_completer   r"   )r   r#   loopr   r   r   await_fallbackG   s    


r)   F)_require_await)r   r   c                   s   t | t }d}zX|j||}|jshd}z|I dH }W n" tk
rZ   |jt	  }Y q X ||}q W 5 |`X |r|st
d|S )aG  Runs a sync function ``fn`` in a new greenlet.

    The sync function can then use :func:`await_only` to wait for async
    functions.

    :param fn: The sync callable to call.
    :param \*args: Positional arguments to pass to the ``fn`` callable.
    :param \*\*kwargs: Keyword arguments to pass to the ``fn`` callable.
    FTNzThe current operation required an async execution but none was detected. This will usually happen when using a non compatible DBAPI driver. Please ensure that an async DBAPI is used.)r   r   r    r   r"   ZdeadBaseExceptionthrowsysexc_infor	   ZAwaitRequired)r   r*   argskwargscontextZswitch_occurredresultvaluer   r   r   greenlet_spawn_   s"    r4   c                   @   s(   e Zd Zedd Zdd Zdd ZdS )AsyncAdaptedLockc                 C   s   t  S r   )r   Lockr   r   r   r   mutex   s    zAsyncAdaptedLock.mutexc                 C   s   t | j  | S r   )r)   r8   acquirer7   r   r   r   	__enter__   s    zAsyncAdaptedLock.__enter__c                 O   s   | j   d S r   )r8   release)r   argkwr   r   r   __exit__   s    zAsyncAdaptedLock.__exit__N)r   r   r   r   r8   r:   r>   r   r   r   r   r5      s   
r5   c                 O   s&   t  }| rtd|| ||S )for test suite/ util onlyz]for async run coroutine we expect that no greenlet or event loop is running when we start out)r%   r&   r   r'   r   r/   r0   r(   r   r   r   "_util_async_run_coroutine_function   s    rA   c                 O   sD   t  }| s$|t| f||S tt ts6t| ||S dS )r?   N)	r%   r&   r'   r4   r   r   r    r   AssertionErrorr@   r   r   r   _util_async_run   s
    rC   c                   C   s@   t jr4z
t W S  tk
r0   t   Y S X nt S dS )z}vendor asyncio.get_event_loop() for python 3.7 and above.

    Python 3.10 deprecates get_event_loop() as a standalone.

    N)r   Zpy37r   Zget_running_loopRuntimeErrorZget_event_loop_policyr%   r   r   r   r   r%      s    
r%   )r   r-   typingr   r   r   r    r   Zlanghelpersr   r	   hasattrr    r   r   r   r$   r)   r4   r5   rA   rC   r%   r   r   r   r   <module>   s,   .