U
    el7                     @  s\  d dl mZ d dlZd dlmZmZm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mZmZmZmZmZmZmZ d	d
lmZ d	dlmZm Z m!Z! d	dl"m#Z# d	dl$m%Z%m&Z& d	dl'm(Z( edZ)edZ*ddddddZ+ddddddZ,G dd dee* eZ-G dd de(Z.G dd dZ/ed&d d!d"d#d$d%Z0dS )'    )annotationsN)	AwaitableCallable	Generator)FIRST_COMPLETEDFutureThreadPoolExecutorwait)AbstractContextManagercontextmanager)isawaitable)TracebackType)AnyAsyncContextManagerContextManagerGenericIterableTypeVarcastoverload   )
_eventloop)get_async_backendget_cancelled_exc_classthreadlocals)Event)CancelScopecreate_task_group)
TaskStatusT_RetvalT_co"Callable[..., Awaitable[T_Retval]]objectfuncargsreturnc                 G  s>   zt j}t j}W n tk
r,   tdY nX |j| ||dS )z
    Call a coroutine function from a worker thread.

    :param func: a coroutine function
    :param args: positional arguments for the callable
    :return: the return value of the coroutine function

    9This function can only be run from an AnyIO worker threadtoken)r   current_async_backendcurrent_tokenAttributeErrorRuntimeErrorZrun_async_from_threadr$   r%   Zasync_backendr)    r/   R/var/www/html/assets/scripts/venv/lib/python3.8/site-packages/anyio/from_thread.pyrun   s    	
r1   Callable[..., T_Retval]c                 G  s>   zt j}t j}W n tk
r,   tdY nX |j| ||dS )z
    Call a function in the event loop thread from a worker thread.

    :param func: a callable
    :param args: positional arguments for the callable
    :return: the return value of the callable

    r'   r(   )r   r*   r+   r,   r-   Zrun_sync_from_threadr.   r/   r/   r0   run_sync0   s    	
r3   c                   @  sr   e Zd ZU ded< ded< ded< dZded< d	d
dddZddddZddddZdddddddZdS )_BlockingAsyncContextManagerr   _enter_future_exit_futurer   _exit_event)NNNzMtuple[type[BaseException] | None, BaseException | None, TracebackType | None]_exit_exc_infoAsyncContextManager[T_co]BlockingPortal)async_cmportalc                 C  s   || _ || _d S N)	_async_cm_portal)selfr;   r<   r/   r/   r0   __init__J   s    z%_BlockingAsyncContextManager.__init__bool | Noner&   c              
     s   zt  | _| j I d H }W n0 tk
rL } z| j|  W 5 d }~X Y nX | j| d z| j
 I d H  W 5 | jj| j	 I d H }|  S X  r=   )r   r7   r>   
__aenter__BaseExceptionr5   set_exception
set_result	__aexit__r8   r	   )r@   valueexcresultr/   r/   r0   run_async_cmN   s    z)_BlockingAsyncContextManager.run_async_cmr    c                 C  s,   t  | _| j| j| _| j }tt|S r=   )	r   r5   r?   start_task_soonrL   r6   rK   r   r    r@   cmr/   r/   r0   	__enter__e   s    
z&_BlockingAsyncContextManager.__enter__type[BaseException] | NoneBaseException | NoneTracebackType | None)&_BlockingAsyncContextManager__exc_type'_BlockingAsyncContextManager__exc_value'_BlockingAsyncContextManager__tracebackr&   c                 C  s&   |||f| _ | j| jj | j S r=   )r8   r?   callr7   setr6   rK   )r@   rT   rU   rV   r/   r/   r0   __exit__k   s    z%_BlockingAsyncContextManager.__exit__N)	__name__
__module____qualname____annotations__r8   rA   rL   rP   rY   r/   r/   r/   r0   r4   B   s   

r4   c                   @  s,   e Zd ZddddZddddd	d
ZdS )_BlockingPortalTaskStatusr   futurec                 C  s
   || _ d S r=   )_future)r@   r`   r/   r/   r0   rA   w   s    z"_BlockingPortalTaskStatus.__init__Nr"   None)rI   r&   c                 C  s   | j | d S r=   )ra   rG   )r@   rI   r/   r/   r0   startedz   s    z!_BlockingPortalTaskStatus.started)N)rZ   r[   r\   rA   rc   r/   r/   r/   r0   r^   v   s   r^   c                   @  sh  e Zd ZdZd dddZddddZd ddd	Zd
ddddddZddddZddddZ	d@dddddZ
dddddddd Zdd!dd"ddd#d$d%Zed&d"d'd(d)d*Zed+d"d'd(d,d*Zd-d"d'd(d.d*Zed/d0d&d"d"d1d2d3d4Zed/d0d+d"d"d1d2d5d4Zd/d0d-d"d"d1d2d6d4Zd/d0d7d"d"d8d2d9d:Zd;d<d=d>d?Zd/S )Ar:   zLAn object that lets external threads run code in an asynchronous event loop.rC   c                 C  s
   t   S r=   )r   Zcreate_blocking_portal)clsr/   r/   r0   __new__   s    zBlockingPortal.__new__rb   c                 C  s&   t  | _t | _t | _t | _d S r=   )		threading	get_ident_event_loop_thread_idr   _stop_eventr   _task_groupr   _cancelled_exc_classr@   r/   r/   r0   rA      s    
zBlockingPortal.__init__c                   s   | j  I d H  | S r=   )rj   rD   rl   r/   r/   r0   rD      s    zBlockingPortal.__aenter__rQ   rR   rS   rB   )exc_typeexc_valexc_tbr&   c                   s$   |   I d H  | j|||I d H S r=   )stoprj   rH   )r@   rm   rn   ro   r/   r/   r0   rH      s    zBlockingPortal.__aexit__c                 C  s,   | j d krtd| j t kr(tdd S )NzThis portal is not runningz7This method cannot be called from the event loop thread)rh   r-   rf   rg   rl   r/   r/   r0   _check_running   s    
zBlockingPortal._check_runningc                   s   | j  I dH  dS )z#Sleep until :meth:`stop` is called.N)ri   r	   rl   r/   r/   r0   sleep_until_stopped   s    z"BlockingPortal.sleep_until_stoppedFbool)cancel_remainingr&   c                   s$   d| _ | j  |r | jj  dS )a.  
        Signal the portal to shut down.

        This marks the portal as no longer accepting new calls and exits from
        :meth:`sleep_until_stopped`.

        :param cancel_remaining: ``True`` to cancel all the remaining tasks, ``False``
            to let them finish before returning

        N)rh   ri   rX   rj   Zcancel_scopecancel)r@   rt   r/   r/   r0   rp      s    
zBlockingPortal.stopr   tuplezdict[str, Any]r   )r$   r%   kwargsr`   r&   c              
     s   ddd fdd}zzN|||}t |rdt , | rF   n
|| |I d H }W 5 Q R X W nd jk
r   |  |  Y nR tk
r } z"| s|| t	|t
s W 5 d }~X Y nX | s|| W 5 d  X d S )Nr   rb   )fr&   c                   s*   |   r&jd t fkr& j d S r=   )	cancelledrh   rf   rg   rW   ru   )rx   scoper@   r/   r0   callback   s
    z+BlockingPortal._call_func.<locals>.callback)r   r   ry   ru   add_done_callbackrk   set_running_or_notify_cancelrE   rF   
isinstance	ExceptionrG   )r@   r$   r%   rw   r`   r|   retvalrJ   r/   rz   r0   
_call_func   s(    




zBlockingPortal._call_funcztuple[Any, ...]r"   )r$   r%   rw   namer`   r&   c                 C  s   t dS )a%  
        Spawn a new task using the given callable.

        Implementors must ensure that the future is resolved when the task finishes.

        :param func: a callable
        :param args: positional arguments to be passed to the callable
        :param kwargs: keyword arguments to be passed to the callable
        :param name: name of the task (will be coerced to a string if not ``None``)
        :param future: a future that will resolve to the return value of the callable,
            or the exception raised during its execution

        N)NotImplementedError)r@   r$   r%   rw   r   r`   r/   r/   r0   _spawn_task_from_thread   s    z&BlockingPortal._spawn_task_from_threadr!   r   r#   c                 G  s   d S r=   r/   r@   r$   r%   r/   r/   r0   rW      s    zBlockingPortal.callr2   c                 G  s   d S r=   r/   r   r/   r/   r0   rW      s    z-Callable[..., Awaitable[T_Retval] | T_Retval]c                 G  s   t t| j|f|  S )a3  
        Call the given function in the event loop thread.

        If the callable returns a coroutine object, it is awaited on.

        :param func: any callable
        :raises RuntimeError: if the portal is not running or if this method is called
            from within the event loop thread

        )r   r   rM   rK   r   r/   r/   r0   rW      s    N)r   zFuture[T_Retval])r$   r%   r   r&   c                G  s   d S r=   r/   r@   r$   r   r%   r/   r/   r0   rM     s    zBlockingPortal.start_task_soonc                G  s   d S r=   r/   r   r/   r/   r0   rM     s    c                G  s$   |    t }| ||i || |S )a  
        Start a task in the portal's task group.

        The task will be run inside a cancel scope which can be cancelled by cancelling
        the returned future.

        :param func: the target function
        :param args: positional arguments passed to ``func``
        :param name: name of the task (will be coerced to a string if not ``None``)
        :return: a future that resolves with the return value of the callable if the
            task completes successfully, or with the exception raised in the task
        :raises RuntimeError: if the portal is not running or if this method is called
            from within the event loop thread
        :rtype: concurrent.futures.Future[T_Retval]

        .. versionadded:: 3.0

        )rq   r   r   )r@   r$   r   r%   rx   r/   r/   r0   rM     s    zCallable[..., Awaitable[Any]]ztuple[Future[Any], Any]c                  s\   ddd fdd}|    t  t }t }|| | ||d|i|| |  fS )a  
        Start a task in the portal's task group and wait until it signals for readiness.

        This method works the same way as :meth:`.abc.TaskGroup.start`.

        :param func: the target function
        :param args: positional arguments passed to ``func``
        :param name: name of the task (will be coerced to a string if not ``None``)
        :return: a tuple of (future, task_status_value) where the ``task_status_value``
            is the value passed to ``task_status.started()`` from within the target
            function
        :rtype: tuple[concurrent.futures.Future[Any], Any]

        .. versionadded:: 3.0

        r   rb   )r`   r&   c                   sH      sD|  r   n*|  r2 |   ntd} | d S )Nz1Task exited without calling task_status.started())donery   ru   	exceptionrF   r-   )r`   rJ   Ztask_status_futurer/   r0   	task_doneJ  s    
z,BlockingPortal.start_task.<locals>.task_donetask_status)rq   r   r^   r}   r   rK   )r@   r$   r   r%   r   r   rx   r/   r   r0   
start_task3  s    
zBlockingPortal.start_taskr9   zContextManager[T_co])rO   r&   c                 C  s
   t || S )a  
        Wrap an async context manager as a synchronous context manager via this portal.

        Spawns a task that will call both ``__aenter__()`` and ``__aexit__()``, stopping
        in the middle until the synchronous context manager exits.

        :param cm: an asynchronous context manager
        :return: a synchronous context manager

        .. versionadded:: 2.1

        )r4   rN   r/   r/   r0   wrap_async_context_manager^  s    z)BlockingPortal.wrap_async_context_manager)F)rZ   r[   r\   __doc__re   rA   rD   rH   rq   rr   rp   r   r   r   rW   rM   r   r   r/   r/   r/   r0   r:   ~   s4   	$	!+r:   asynciostrzdict[str, Any] | Nonez$Generator[BlockingPortal, Any, None])backendbackend_optionsr&   c                 #  s   dd fdd}t   td}|jtj|| |d}ztttt  | gtd W n& t	k
rz    
  |
   Y nX   r  }d}z*z
|V  W n t	k
r   d	} Y nX W 5 z||j| W n tk
r   Y nX X |  W 5 Q R X d
S )a|  
    Start a new event loop in a new thread and run a blocking portal in its main task.

    The parameters are the same as for :func:`~anyio.run`.

    :param backend: name of the backend
    :param backend_options: backend options
    :return: a context manager that yields a blocking portal

    .. versionchanged:: 3.0
        Usage as a context manager is now required.

    rb   rC   c               
     sD   t  4 I d H &}   r0 |  |  I d H  W 5 Q I d H R X d S r=   )r:   r~   rG   rr   )Zportal_r_   r/   r0   
run_portal  s    
z)start_blocking_portal.<locals>.run_portalr   )r   r   )return_whenFTN)r   r   submitr   r1   r	   r   r   r   rE   ru   r   rK   rW   rp   r-   )r   r   r   executorZ
run_futurer<   Zcancel_remaining_tasksr/   r_   r0   start_blocking_portalp  s>    


r   )r   N)1
__future__r   rf   collections.abcr   r   r   concurrent.futuresr   r   r   r	   
contextlibr
   r   inspectr   typesr   typingr   r   r   r   r   r   r   r   Z_corer   Z_core._eventloopr   r   r   Z_core._synchronizationr   Z_core._tasksr   r   Z
abc._tasksr   r   r    r1   r3   r4   r^   r:   r   r/   r/   r/   r0   <module>   s0   (4 s   