B
    H/\j              
   @   s  d Z ddlmZmZ 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	d
dddddddg
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%m&Z& dd!l'm(Z( e(j)Z*e(j+Z,dd"l-m.Z. dd#l/m0Z0 e1ej2Z3e3 Z4d$d
 Z5d/d&dZ6d0d'd(Z7efd)dZ8G d*d de9Z:d1d+dZ;G d,d de&Z<e"e< G d-d. d.e9Z=dS )2z
Event-loop hub.
    )absolute_importprint_function)partialN)greenlet)
getcurrent)GreenletExitr   r   	spawn_rawsleepkillsignalreinitget_hubHubWaiter)config)thread_mod_name)readproperty)Lazy)gmctime)IdentRegistry)r   )get_loop)set_hub)set_loop)get_hub_if_exists)get_hub_noargs)set_default_hub_class)TrackedRawGreenlet)WaitOperationsGreenlet)_hub_primitives)LoopExit)r   c             O   st   t | stdt }tjr tnt}|rRt| f||} || |}|j	|j
 n|| |}|jj	|j
f|  |S )aG  
    Create a new :class:`greenlet.greenlet` object and schedule it to
    run ``function(*args, **kwargs)``.

    This returns a raw :class:`~greenlet.greenlet` which does not have all the useful
    methods that :class:`gevent.Greenlet` has. Typically, applications
    should prefer :func:`~gevent.spawn`, but this method may
    occasionally be useful as an optimization if there are many
    greenlets involved.

    .. versionchanged:: 1.1a3
        Verify that ``function`` is callable, raising a TypeError if not. Previously,
        the spawned greenlet would have failed the first time it was switched to.

    .. versionchanged:: 1.1b1
       If *function* is not callable, immediately raise a :exc:`TypeError`
       instead of spawning a greenlet that will raise an uncaught TypeError.

    .. versionchanged:: 1.1rc2
        Accept keyword arguments for ``function`` as previously (incorrectly)
        documented. Note that this may incur an additional expense.

    .. versionchanged:: 1.3a2
       Populate the ``spawning_greenlet`` and ``spawn_tree_locals``
       attributes of the returned greenlet.

    .. versionchanged:: 1.3b1
       *Only* populate ``spawning_greenlet`` and ``spawn_tree_locals``
       if ``GEVENT_TRACK_GREENLET_TREE`` is enabled (the default). If not enabled,
       those attributes will not be set.

    zfunction must be callable)callable	TypeError_get_hub_noargsGEVENT_CONFIGZtrack_greenlet_treer   RawGreenlet_functools_partiallooprun_callbackswitch)Zfunctionargskwargshubfactoryg r.   )lib/python3.7/site-packages/gevent/hub.pyr   C   s    !

Tc          	   C   sd   t  }|j}| dkr4t|}||jd |  n,|j| |d}|  || W dQ R X dS )a  
    Put the current greenlet to sleep for at least *seconds*.

    *seconds* may be specified as an integer, or a float if fractional
    seconds are desired.

    .. tip:: In the current implementation, a value of 0 (the default)
       means to yield execution to any other runnable greenlets, but
       this greenlet may be scheduled again before the event loop
       cycles (in an extreme case, a greenlet that repeatedly sleeps
       with 0 can prevent greenlets that are ready to do I/O from
       being scheduled for some (small) period of time); a value greater than
       0, on the other hand, will delay running this greenlet until
       the next iteration of the loop.

    If *ref* is False, the greenlet running ``sleep()`` will not prevent :func:`gevent.wait`
    from exiting.

    .. versionchanged:: 1.3a1
       Sleeping with a value of 0 will now be bounded to approximately block the
       loop for no longer than :func:`gevent.getswitchinterval`.

    .. seealso:: :func:`idle`
    r   N)ref)	r"   r&   r   r'   r(   gettimerZ
update_nowwait)Zsecondsr0   r+   r&   waitertr.   r.   r/   r	   z   s    
c             C   s(   t  }|j }| r| |_|| dS )aO  
    Cause the calling greenlet to wait until the event loop is idle.

    Idle is defined as having no other events of the same or higher
    *priority* pending. That is, as long as sockets, timeouts or even
    signals of the same or higher priority are being processed, the loop
    is not idle.

    .. seealso:: :func:`sleep`
    N)r"   r&   idlepriorityr3   )r7   r+   watcherr.   r.   r/   r6      s
    
r6   c             C   s6   | j s2t| dr | j|dd nt j| j| dS )a%  
    Kill greenlet asynchronously. The current greenlet is not unscheduled.

    .. note::

        The method :meth:`Greenlet.kill` method does the same and
        more (and the same caveats listed there apply here). However, the MAIN
        greenlet - the one that exists initially - does not have a
        ``kill()`` method, and neither do any created with :func:`spawn_raw`,
        so you have to use this function.

    .. caution:: Use care when killing greenlets. If they are not prepared for
       exceptions, this could result in corrupted state.

    .. versionchanged:: 1.1a2
        If the ``greenlet`` has a :meth:`kill <Greenlet.kill>` method, calls it. This prevents a
        greenlet from being switched to for the first time after it's been
        killed but not yet executed.
    r
   F)	exceptionblockN)deadhasattrr
   r"   r&   r'   throw)r   r9   r.   r.   r/   r
      s    
c               @   sR   e Zd ZdZdZdd Zdd Zdd ZeeeZ	[[d	d
 Z
dd Zdd ZdS )r   a_  
    Call the *handler* with the *args* and *kwargs* when the process
    receives the signal *signalnum*.

    The *handler* will be run in a new greenlet when the signal is delivered.

    This returns an object with the useful method ``cancel``, which, when called,
    will prevent future deliveries of *signalnum* from calling *handler*.

    .. note::

        This may not operate correctly with SIGCHLD if libev child watchers
        are used (as they are by default with os.fork).

    .. versionchanged:: 1.2a1
       The ``handler`` argument is required to be callable at construction time.
    Nc             O   sl   t |stdt | _| jjj|dd| _| j| j || _	|| _
|| _| jd krhddlm} || _d S )Nz signal handler must be callable.F)r0   r   )Greenlet)r    r!   r"   r+   r&   r   r8   start_starthandlerr)   r*   greenlet_classgeventr>   )selfZ	signalnumrA   r)   r*   r>   r.   r.   r/   __init__   s    
zsignal.__init__c             C   s   | j jS )N)r8   r0   )rD   r.   r.   r/   _get_ref   s    zsignal._get_refc             C   s   || j _d S )N)r8   r0   )rD   valuer.   r.   r/   _set_ref   s    zsignal._set_refc             C   s   | j   d S )N)r8   stop)rD   r.   r.   r/   cancel  s    zsignal.cancelc             C   s>   y|  | j}|  W n    | jjdt   Y nX d S )N)N)rB   handler(   r+   handle_errorsysZ	_exc_info)rD   r   r.   r.   r/   r@     s
    zsignal._startc             C   s:   y| j | j| j W n    | jjdt   Y nX d S )N)N)rA   r)   r*   r+   rL   rM   exc_info)rD   r.   r.   r/   rK     s    zsignal.handle)__name__
__module____qualname____doc__rB   rE   rF   rH   propertyr0   rJ   r@   rK   r.   r.   r.   r/   r      s   
c             C   sX   | dkrt  n| } | dkrdS | j  x*| j| j| jfD ]}t|ddd   q:W dS )a  
    reinit() -> None

    Prepare the gevent hub to run in a new (forked) process.

    This should be called *immediately* after :func:`os.fork` in the
    child process. This is done automatically by
    :func:`gevent.os.fork` or if the :mod:`os` module has been
    monkey-patched. If this function is not called in a forked
    process, symptoms may include hanging of functions like
    :func:`socket.getaddrinfo`, and the hub's threadpool is unlikely
    to work.

    .. note:: Registered fork watchers may or may not run before
       this function (and thus ``gevent.os.fork``) return. If they have
       not run, they will run "soon", after an iteration of the event loop.
       You can force this by inserting a few small (but non-zero) calls to :func:`sleep`
       after fork returns. (As of gevent 1.1 and before, fork watchers will
       not have run, but this may change in the future.)

    .. note:: This function may be removed in a future major release
       if the fork process can be more smoothly managed.

    .. warning:: See remarks in :func:`gevent.os.fork` about greenlets
       and event loop watchers in the child process.
    NZ_on_forkc               S   s   d S )Nr.   r.   r.   r.   r/   <lambda>J  s    zreinit.<locals>.<lambda>)_get_hubr&   r   _threadpool	_resolverperiodic_monitoring_threadgetattr)r+   objr.   r.   r/   r     s    
c               @   s$  e Zd ZdZeeefZeefZ	dZ
dZdZdZdZd4ddZedd	 Zed
d Zedd Zedd Zdd Zdd Zdd Zedd Zdd Zdd Zdd Zd5ddZd6d d!Zed"d# Z d$d% Z!d&d' Z"d(d) Z#ee!e"e#d*Z$ed+d, Z%d-d. Z&d/d0 Z'd1d2 Z(ee&e'e(d3Z)dS )7r   a  
    A greenlet that runs the event loop.

    It is created automatically by :func:`get_hub`.

    .. rubric:: Switching

    Every time this greenlet (i.e., the event loop) is switched *to*,
    if the current greenlet has a ``switch_out`` method, it will be
    called. This allows a greenlet to take some cleanup actions before
    yielding control. This method should not call any gevent blocking
    functions.
    
   N r   c             C   s   t | d d  t | _t|dr8|d k	r0td|| _nHt d k	rLt | _n4|d krb| jtkrbd}|d krp| j	}| j
||d| _d | _d | _tj| _t jd7  _tj| _d S )NrunzUnexpected argument: defaultF)flagsdefault   )r   rE   get_thread_identthread_identr<   r!   r&   r   MAIN_THREAD_IDENTbackend
loop_classrW   rV   r#   format_contextr   _hub_counterZminimal_ident)rD   r&   r_   r.   r.   r/   rE     s$    


zHub.__init__c             C   s   t  S )N)r   )rD   r.   r.   r/   ident_registry  s    zHub.ident_registryc             C   s   t jS )N)r#   r&   )rD   r.   r.   r/   re     s    zHub.loop_classc             C   s   t jS )N)r#   Zlibev_backend)rD   r.   r.   r/   rd     s    zHub.backendc             C   s
   | j tkS )zW
        Is this the hub for the main thread?

        .. versionadded:: 1.3b1
        )rb   rc   )rD   r.   r.   r/   main_hub  s    zHub.main_hubc          
   C   s   | j d krd}nFy| j  }W n6 tk
rT } zt|pBt|pBd}W d d }~X Y nX d| jj| jt| |f }| j	d k	r|d| j	 7 }| j
d k	r|d| j
 7 }|dt| jf 7 }|d S )NZ	destroyederrorz<%s %r at 0x%x %sz resolver=%rz threadpool=%rz thread_ident=%s>)r&   Z_format	Exceptionstrrepr	__class__rO   nameidrW   rV   hexrb   )rD   infoexresultr.   r.   r/   __repr__  s"    
&

zHub.__repr__c             C   sR   t |tr||}t|| js.| |||| |dksBt|| jrN| || dS )aY  
        Called by the event loop when an error occurs. The arguments
        type, value, and tb are the standard tuple returned by :func:`sys.exc_info`.

        Applications can set a property on the hub with this same signature
        to override the error handling provided by this class.

        Errors that are :attr:`system errors <SYSTEM_ERROR>` are passed
        to :meth:`handle_system_error`.

        :param context: If this is ``None``, indicates a system error that
            should generally result in exiting the loop and being thrown to the
            parent greenlet.
        N)
isinstancerm   
issubclass	NOT_ERRORprint_exceptionSYSTEM_ERRORhandle_system_error)rD   contexttyperG   tbr.   r.   r/   rL     s    
zHub.handle_errorc             C   s   t  }|| ks"|| jks"| jdkr2| j|| nXd}y| j|j}W n   tj| jd Y nX z| j|| W d|dk	r|	  X dS )z
        Called from `handle_error` when the exception type is determined
        to be a :attr:`system error <SYSTEM_ERROR>`.

        System errors cause the exception to be raised in the main
        greenlet (the parent of this hub).
        N)file)
r   parentr&   r=   r'   r(   	traceback	print_excexception_streamrI   )rD   r~   rG   Zcurrentcbr.   r.   r/   r|     s    zHub.handle_system_errorc             C   s&   t r
t jnd}t|jdkr"|j}|S )z
        The stream to which exceptions will be written.
        Defaults to ``sys.stderr`` unless assigned to.

        .. versionadded:: 1.2a1
        NZFileObjectThread)rM   stderrr~   rO   io)rD   r   r.   r.   r/   r      s    zHub.exception_streamc             C   s   | j }|sd S |d kr(|d|j  ntj||||d ~y&|t  ||d k	rZdnd W n   Y nX |d k	rt|tsy| |}W n"   tj	| j d t
|}Y nX |d|t|ddf  d S )Nz%s
)r    
z%s failed with %s

rO   r9   )r   writerO   r   rz   r   rw   rm   rf   r   rn   rY   )rD   r}   r~   rG   r   Z	errstreamr.   r.   r/   rz     s(    
zHub.print_exceptionc             C   sp   | t  kstd|   xP| j}| |_z|  W dd|_X g }t|drT| }| j	t
d| | qW dS )a  
        Entry-point to running the loop. This method is called automatically
        when the hub greenlet is scheduled; do not call it directly.

        :raises gevent.exceptions.LoopExit: If the loop finishes running. This means
           that there are no other scheduled greenlets, and no active
           watchers or servers. In some situations, this indicates a
           programming error.
        zDo not call Hub.run() directlyNdebugz"This operation would block forever)r   AssertionError start_periodic_monitoring_threadr&   Zerror_handlerr]   r<   r   r   r=   r   )rD   r&   r   r.   r.   r/   r]   6  s    

zHub.runc             C   sb   | j d kr\tjr\ddlm} ddlm} ddlm} || | _ | jrN| j 	  ||| j  | j S )Nr   )PeriodicMonitoringThread)!PeriodicMonitorThreadStartedEvent)notify_and_call_entry_points)
rX   r#   Zmonitor_threadZgevent._monitorr   Zgevent.eventsr   r   ri   Zinstall_monitor_memory_usage)rD   r   r   r   r.   r.   r/   r   R  s    


z$Hub.start_periodic_monitoring_threadc             C   s   t  | jkstd| jrdS t| }|dk	rL| jj|dd}||jd z&y|	  W n t
k
rn   dS X W d|dk	r|  |  X dS )an  Wait for the event loop to finish. Exits only when there are
        no more spawned greenlets, started servers, active timeouts or watchers.

        If *timeout* is provided, wait no longer for the specified number of seconds.

        Returns True if exited because the loop finished execution.
        Returns False if exited because of timeout expired.
        z$only possible from the MAIN greenletTNF)r0   )r   r   r   r;   r   r&   r2   r?   r(   r1   r   rI   close)rD   Ztimeoutr4   r.   r.   r/   joinf  s     	

zHub.joinc             C   s   | j dk	r| j   d| _ | jdk	r2| j  | `| jdk	rJ| j  | `|dkr\| jj }|rt | jkrttd | j	  n
t| j d| _t
 | krtd dS )z
        Destroy this hub and clean up its resources.

        If you manually create hubs, you *should* call this
        method before disposing of the hub object reference.
        N)rX   r
   rW   r   rV   r&   r_   r   r   destroyrU   r   )rD   Zdestroy_loopr.   r.   r/   r     s&    








zHub.destroyc             C   s   t jS )N)r#   resolver)rD   r.   r.   r/   resolver_class  s    zHub.resolver_classc             C   s   | j d kr| j| d| _ | j S )N)r+   )rW   r   )rD   r.   r.   r/   _get_resolver  s    
zHub._get_resolverc             C   s
   || _ d S )N)rW   )rD   rG   r.   r.   r/   _set_resolver  s    zHub._set_resolverc             C   s
   d | _ d S )N)rW   )rD   r.   r.   r/   _del_resolver  s    zHub._del_resolverz
                        The DNS resolver that the socket functions will use.

                        .. seealso:: :doc:`/dns`
                        c             C   s   t jS )N)r#   
threadpool)rD   r.   r.   r/   threadpool_class  s    zHub.threadpool_classc             C   s"   | j d kr| j| j| d| _ | j S )N)r+   )rV   r   threadpool_size)rD   r.   r.   r/   _get_threadpool  s    
zHub._get_threadpoolc             C   s
   || _ d S )N)rV   )rD   rG   r.   r.   r/   _set_threadpool  s    zHub._set_threadpoolc             C   s
   d | _ d S )N)rV   )rD   r.   r.   r/   _del_threadpool  s    zHub._del_threadpoola  
                          The threadpool associated with this hub.

                          Usually this is a
                          :class:`gevent.threadpool.ThreadPool`, but
                          you :attr:`can customize that
                          <gevent._config.Config.threadpool>`.

                          Use this object to schedule blocking
                          (non-cooperative) operations in a different
                          thread to prevent them from halting the event loop.
                          )NN)N)N)*rO   rP   rQ   rR   KeyboardInterrupt
SystemExitSystemErrorr{   r   ry   r   rX   rb   rp   rg   rE   r   rh   rS   re   rd   ri   rv   rL   r|   r   r   rz   r]   r   r   r   r   r   r   r   r   r   r   r   r   r   r.   r.   r.   r/   r   V  sD   

	$

$c               @   s$   e Zd ZddgZdd Zdd ZdS )	linkproxycallbackrZ   c             C   s   || _ || _d S )N)r   rZ   )rD   r   rZ   r.   r.   r/   rE     s    zlinkproxy.__init__c             G   s$   | j }| j}d | _ d | _|| d S )N)r   rZ   )rD   r)   r   rZ   r.   r.   r/   __call__  s
    zlinkproxy.__call__N)rO   rP   rQ   	__slots__rE   r   r.   r.   r.   r/   r     s   r   )r   T)r   )N)>rR   Z
__future__r   r   	functoolsr   r%   rM   r   r   r$   r   r   __all__Zgevent._configr   r#   Zgevent._compatr   Zgevent._utilr   r   r   Zgevent._identr   Zgevent._hub_localr   r   r   r   r   rU   r   r"   r   Zgevent._greenlet_primitivesr   Zgevent._hub_primitivesr   rC   r   Zwait_on_objectsr3   Ziwait_on_objectsZiwaitZgevent.exceptionsr   Zgevent._waiterr   
__import__	get_identra   rc   r   r	   r6   r
   objectr   r   r   r   r.   r.   r.   r/   <module>   sf   
7
(
@
D   