a
    VbP                     @   sv   d dl Z d dlmZ d dlZd dlZd dlZd dlmZmZ d dl	m
Z
 dddZdd Zdd	 Zd
d Zdd ZdS )    N)contextmanagersuppress)heappopc                 C   s*   t   t  t  | pt } t|  dS )z/Patch asyncio to make its event loop reentrant.N)_patch_asyncio_patch_task_patch_tornadoasyncioget_event_loop_patch_looploop r   +lib/python3.9/site-packages/nest_asyncio.pyapply
   s
    r   c                  C   s   dddd} ddd}t tdr&d	S tjd
krdtjj t_ tj_tj_tjj	 t_
 tj_tj_
tjdk rtjjjtj_tjjjt_tjdkr| t_ t_t_| | t_dt_d	S )z
    Patch asyncio module to use pure Python tasks and futures,
    use module level _current_tasks, all_tasks and patch run method.
    F)debugc                S   s   zt  }W n, ty8   t  }t | t| Y n0 || t | }zb||W |	 s|
  tt j || W d    S 1 s0    Y  S 1 s0    Y  nJ|	  s|
  tt j || W d    n1  s0    Y  0 d S N)r   r	   RuntimeErrorZnew_event_loopZset_event_loopr
   Z	set_debugensure_futurerun_until_completedonecancelr   ZCancelledError)mainr   r   taskr   r   r   run   s.    



(   
z_patch_asyncio.<locals>.run   c                 S   s    t  }|d u rt   }|S r   )events_get_running_loopZget_event_loop_policyr	   )
stacklevelr   r   r   r   _get_event_loop*   s    z'_patch_asyncio.<locals>._get_event_loop_nest_patchedN)r      r   r      r   )r   	   r   T)r   )hasattrr   sysversion_infotasksZ_PyTaskTaskZ_CTaskZfuturesZ	_PyFutureFutureZ_CFuture_current_tasksZ	all_tasksr   r   r	   r   r   )r   r   r   r   r   r      s&    




r   c                    s    fdd}fdd}dd }t dd t d	d
  dd }t| drPdS t| tjsltdt|  | j}||_||_	||_
||_||_d|_tjdkot|tj|_tjdk r|j|_d|_dS )z Patch loop to make it reentrant.c              	      sl   | J  | " |    | jrq&qW d    n1 s:0    Y  W d    n1 sX0    Y  d| _d S )NF)	_run_once	_stoppingselfmanage_asyncgens
manage_runr   r   run_foreverE   s
    @z _patch_loop.<locals>.run_foreverc                    sz    | ^ t j|| d}||ur&d|_| s@|   | jr&q@q&| sPtd| W  d    S 1 sl0    Y  d S )Nr   Fz+Event loop stopped before Future completed.)r   r   Z_log_destroy_pendingr   r+   r,   r   result)r.   Zfuturef)r1   r   r   r   M   s    
z'_patch_loop.<locals>.run_until_completec                 S   s   | j }| j}|r$|d jr$t| q|s.| jr2dn$|rTtt|d j|   ddnd}| j	
|}| | |  | j }|r|d j|k rt|}|| q|tt|D ]"}|s q| }|js|  qd}dS )zu
        Simplified re-implementation of asyncio's _run_once that
        runs handles as they become ready.
        r   iQ N)Z_readyZ
_scheduledZ
_cancelledr   r,   minmaxZ_whentimeZ	_selectorZselectZ_process_eventsZ_clock_resolutionappendrangelenpopleftZ_run)r.   ZreadyZ	scheduledZtimeoutZ
event_listZend_timeZhandle_r   r   r   r+   [   s4    


z_patch_loop.<locals>._run_oncec              	   s   s6  |    | j}t }zt | _t|  |  jd7  _| jrV| j	du rV| 
| j dV  W || _t| |  jd8  _| jr| jdkr| j	dur| j	j}| j	  |dur| j| d| _	nn|| _t| |  jd8  _| jr0| jdkr0| j	dur0| j	j}| j	  |dur*| j| d| _	0 dS )zSet up the loop for running.   Nr   )Z_check_closedZ
_thread_idr   r   	threading	get_identZ_set_running_loop_num_runs_pending_is_proactorloopZ_self_reading_futureZ	call_soonZ_loop_self_readingZ_ovr   Z	_proactorZ_unregister)r.   Zold_thread_idZold_running_loopZovr   r   r   r1   z   sF    








z_patch_loop.<locals>.manage_runc              	   s   s   t tdsd S t }zP| | j | jd ur@tj| j| jd d V  W | d | jd urtj|  n | d | jd urtj|  0 d S )Nget_asyncgen_hooks)	firstiter	finalizerF)	r$   r%   rB   _set_coroutine_origin_trackingZ_debugZ
_asyncgensset_asyncgen_hooksZ_asyncgen_firstiter_hookZ_asyncgen_finalizer_hook)r.   Zold_agen_hooksr   r   r   r0      s"    





z%_patch_loop.<locals>.manage_asyncgensc                 S   s   dS )z2Do not throw exception if loop is already running.Nr   r-   r   r   r   _check_running   s    z#_patch_loop.<locals>._check_runningr   NzCan't patch loop of type %sr   ntr!   T)r   r$   
isinstancer   ZBaseEventLoop
ValueErrortype	__class__r2   r   r+   rG   Z_check_runnungr@   osname
issubclassZProactorEventLooprA   r%   r&   Z_set_coroutine_wrapperrE   r   )r   r2   r   r+   rG   clsr   r/   r   r
   B   s0    



r
   c                     s   d fdd	} t j}t|dr$dS tjdkrl fdd} fdd	}|t j_|t j_t jj |j	| |_	n|j |j
| |_
d
|_dS )zCPatch the Task's step and enter/leave methods to make it reentrant.Nc              
      sf     | j}z0| | W |d u r2 | jd  qb| | j< n$|d u rV | jd  n
| | j< 0 d S r   )getZ_looppop)r   excZ	curr_task
curr_tasksZ	step_origr   r   step   s    z_patch_task.<locals>.stepr   r!   c                    s   | | < d S r   r   r   r   rU   r   r   
enter_task   s    z_patch_task.<locals>.enter_taskc                    s     | d  d S r   )rR   rW   rX   r   r   
leave_task   s    z_patch_task.<locals>.leave_taskT)N)r   r(   r$   r%   r&   r'   Z_enter_taskZ_leave_taskr*   Z_Task__stepZ_stepr   )rV   r(   rY   rZ   r   rT   r   r      s     


r   c                  C   s@   dt jv r<ddlm}  tj| _tj| jvr<|  jtjf7  _dS )z{
        If tornado is imported before nest_asyncio, make tornado aware of
        the pure-Python asyncio Future.
        Ztornador   N)r%   modulesZtornado.concurrentZ
concurrentr   r)   ZFUTURES)Ztcr   r   r   r      s
    
r   )N)r   Zasyncio.eventsr   rM   r%   r>   
contextlibr   r   heapqr   r   r   r
   r   r   r   r   r   r   <module>   s   

.{$