o
    0׾gx                     @   s  d dl mZ d dl 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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gZ$dd Z%efddZ&efddZ'G dd deZ(G d d deZ)G d!d" d"e*Z+e+ Z+G d#d de*Z,zd dl-Z.W n
 e/y   Y dS w e$0d$ d d%l1m2Z3 d d&l4m5Z5 d d'l-m6Z7 d(d) Z8d*d+ Z9G d,d- d-e*Z:G d.d$ d$e.j;j<Z<dS )/    )absolute_import)division)print_functionN)greenlet)monkey)integer_types)AsyncResult)InvalidThreadUseError)Greenlet)get_hub_if_exists)_get_hub_noargs)
getcurrent)sleep)	Semaphore)GroupMappingMixin)clear_stack_frames)Queue)EmptyTimeout)start_new_thread)get_thread_ident
ThreadPoolThreadResultc                 C   s$   | d u rdS d| j jt| | jf S )Nz	<missing>z<%s at 0x%x thread_ident=0x%x>)	__class____name__idthread_ident)hub r   [/var/www/html/backend_erp/backend_erp_env/lib/python3.10/site-packages/gevent/threadpool.py_format_hub%   s
   r   c                 C      d| j v r| j d jS d S N	threading)modules_profile_hook_sysr   r   r   _get_thread_profile-      
r'   c                 C   r    r!   )r#   _trace_hookr%   r   r   r   _get_thread_trace2   r(   r*   c                   @   s   e Zd ZdZdZejZee	Z
dZdZdZdZdd ZeefddZd	d
 Zedd ZeeefddZefddZdd Zdd Zdd ZefddZdS )_WorkerGreenletTr   Nc                 C   s   t |  |j| _tdrtdd}ntj}|| _	|j
| _| j | _|j| _|j| _||  z	t| jd W d S    | |   )Nsysstderrr   )RawGreenlet__init__r   _hubr   is_module_patchedget_originalr-   r.   _stderr
task_queue_task_queueallocate_cookie_task_queue_cookie_unregister_worker_idle_task_timeout_register_workerr   _begin)self
threadpoolr.   r   r   r   r0   P   s    



z_WorkerGreenlet.__init__c                 C   s4   | | _ | | _d| j _z|   W d S    Y d S NT)parent_thread_identgreenlet_tree_is_ignoredswitch)r=   _get_c_get_tir   r   r   r<   o   s   z_WorkerGreenlet._beginc                 C   s@   |   }|d urd|_|d ur|jd ur|j  || _d S d S )NzThreadPool Worker Hub)_get_hub_if_existsnameperiodic_monitoring_thread ignore_current_greenlet_blocking_hub_of_worker)r=   r   r   r   r   __fixup_hub_before_block   s   

z(_WorkerGreenlet.__fixup_hub_before_blockc                 C   sR   | d ur'| j }| j}|j}|j}|j}td|||f |d | j} | d usd S d S )Nz  File "%s", line %d, in %sfile)tb_frame	tb_linenof_codeco_filenameco_nameprinttb_next)tbr.   flinenocofilenamerG   r   r   r   
__print_tb   s   z_WorkerGreenlet.__print_tbc                 C   s   | |  ||  d S N
setprofilesettrace)r=   funcargskwargsthread_resultr&   r'   r*   r   r   r   _before_run_task   s   z _WorkerGreenlet._before_run_taskc                 C   s   | d  |d  d S r[   r\   )r=   r_   r`   ra   rb   r&   r   r   r   _after_run_task   s   
z_WorkerGreenlet._after_run_taskc                 C   s   |  |||| z9z|||i | W n   || |f|   Y W | |||| ~~~~d S W | |||| ~~~~d S | |||| ~~~~w r[   )rc   sethandle_error	_exc_inford   )r=   r_   r`   ra   rb   r   r   r   
__run_task   s   
z_WorkerGreenlet.__run_taskc           
   
   C   sx  d }t j}| j}| jj}| j}| j}| jj}| j}zzh	 |  z|||}W n t	y9   Y W W | 
|   d S w z:z#|d u rYW W t|tsId n|}|  W W | 
|   d S ||  W n   t|} W t|tsod n|}|  nt|ts|d n|}|  w q ty }	 ztd||	f | jd | | d | j W Y d }	~	nd }	~	ww W | 
|   d S | 
|   w )N   z1Failed to run worker thread. Task=%r Exception=%rrL   r,   )r-   exc_info'_WorkerGreenlet__fixup_hub_before_blockr6   getr8   _WorkerGreenlet__run_task	task_doner:   r   cleanuprF   
isinstancestrrepr	ExceptionrS   r4   _WorkerGreenlet__print_tb)
r=   taskrj   fixup_hub_before_blocktask_queue_gettask_queue_cookierun_tasktask_queue_doneidle_task_timeouter   r   r   run   sZ   
 "z_WorkerGreenlet.runc                 C   sJ   | j d urd | _ | |  dd | _d | _d | _|d ur#|d d S d S )Nc                 S      d S r[   r   _r   r   r   <lambda>       z)_WorkerGreenlet.cleanup.<locals>.<lambda>T)r1   r9   r6   r8   destroy)r=   hub_of_workerr   r   r   ro      s   


z_WorkerGreenlet.cleanupc                 C   s   dt | | j|| jf S )Nz><ThreadPoolWorker at 0x%x thread_ident=0x%x threadpool-hub=%s>)r   rA   r1   r=   r   r   r   r   __repr__   s
   z_WorkerGreenlet.__repr__)r   
__module____qualname__greenlet_tree_is_rootrA   r-   rj   rg   staticmethodr   rF   rJ   r1   r8   r:   r0   r   r   r<   rk   rt   r'   r*   rc   rd   rm   r}   ro   r   r   r   r   r   r   r+   7   s.    


-r+   c                   @   s   e Zd ZdZdZeZd0ddZdd Zd	d
 Zdd Z	dd Z
ee
e	ddZefddZdd Zdd Zdd ZeeeddZdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ ZdS )1r   a\
  
    A pool of native worker threads.

    This can be useful for CPU intensive functions, or those that
    otherwise will not cooperate with gevent. The best functions to execute
    in a thread pool are small functions with a single purpose; ideally they release
    the CPython GIL. Such functions are extension functions implemented in C.

    It implements the same operations as a :class:`gevent.pool.Pool`,
    but using threads instead of greenlets.

    .. note:: The method :meth:`apply_async` will always return a new
       greenlet, bypassing the threadpool entirely.

    Most users will not need to create instances of this class. Instead,
    use the threadpool already associated with gevent's hub::

        pool = gevent.get_hub().threadpool
        result = pool.spawn(lambda: "Some func").get()

    .. important:: It is only possible to use instances of this class from
       the thread running their hub. Typically that means from the thread that
       created them. Using the pattern shown above takes care of this.

       There is no gevent-provided way to have a single process-wide limit on the
       number of threads in various pools when doing that, however. The suggested
       way to use gevent and threadpools is to have a single gevent hub
       and its one threadpool (which is the default without doing any extra work).
       Only dispatch minimal blocking functions to the threadpool, functions that
       do not use the gevent hub.

    The `len` of instances of this class is the number of enqueued
    (unfinished) tasks.

    Just before a task starts running in a worker thread,
    the values of :func:`threading.setprofile` and :func:`threading.settrace`
    are consulted. Any values there are installed in that thread for the duration
    of the task (using :func:`sys.setprofile` and :func:`sys.settrace`, respectively).
    (Because worker threads are long-lived and outlast any given task, this arrangement
    lets the hook functions change between tasks, but does not let them see the
    bookkeeping done by the worker thread itself.)

    .. caution:: Instances of this class are only true if they have
       unfinished tasks.

    .. versionchanged:: 1.5a3
       The undocumented ``apply_e`` function, deprecated since 1.1,
       was removed.
    .. versionchanged:: 20.12.0
       Install the profile and trace functions in the worker thread while
       the worker thread is running the supplied task.
    .. versionchanged:: 22.08.0
       Add the option to let idle threads expire and be removed
       from the pool after *idle_task_timeout* seconds (-1 for no
       timeout)
    )	r   _maxsizemanagerpidfork_watcher&_available_worker_threads_greenlet_sem_worker_greenletsr5   r:   Nr,   c                 C   sp   |d u rt  }|| _t | _d | _t | _d | _|| _	t
 | _d| _td|| _| | |jjdd| _d S )Nr   ri   F)ref)get_hubr   osgetpidr   r   r   r5   r   r:   re   r   r   r   r   _set_maxsizeloopfork)r=   maxsizer   r{   r   r   r   r0   I  s   

zThreadPool.__init__c                 C      | j | d S r[   )r   addr=   workerr   r   r   r;   [     zThreadPool._register_workerc                 C   r   r[   )r   discardr   r   r   r   r9   ^  r   zThreadPool._unregister_workerc                 C   sd   t |tstd|f |dk rtd|f || j }| j j|7  _|| _|   | j  d S )Nzmaxsize must be integer: %rr   z maxsize must not be negative: %r)	rp   r   	TypeError
ValueErrorr   r   counteradjust_start_notify)r=   r   
differencer   r   r   r   a  s   

zThreadPool._set_maxsizec                 C   s   | j S r[   )r   r=   r   r   r   _get_maxsizem  s   zThreadPool._get_maxsizea9      The maximum allowed number of worker threads.

    This is also (approximately) a limit on the number of tasks that
    can be queued without blocking the waiting greenlet. If this many
    tasks are already running, then the next greenlet that submits a task
    will block waiting for a task to finish.
    )docc                 C   s*   d| j jt| t| | j| j|| jf S )Nz/<%s at 0x%x tasks=%s size=%s maxsize=%s hub=%s>)r   r   r   lensizer   r   r   r   r   r   r   y  s   zThreadPool.__repr__c                 C   s   | j jS r[   )r5   unfinished_tasksr   r   r   r   __len__  s   zThreadPool.__len__c                 C   
   t | jS r[   )r   r   r   r   r   r   	_get_size     
zThreadPool._get_sizec                 C   s  |dk rt d|f || jkrt d|| jf | jr!| j  t| j|k r3|   t| j|k s(| jjj	}t| j|krtt| j| | j
jkr[| j
d  t| j| | j
jksJt | ju rbnt| t|d d}t| j|ks?| jr| j| j d S | j  d S )Nr   z'Size of the pool cannot be negative: %rz7Size of the pool cannot be bigger than maxsize: %r > %r   皙?)r   r   r   killr   r   _add_threadr   r   approx_timer_resolutionr5   r   putr   r   minr   start_on_forkstop)r=   r   delayr   r   r   	_set_size  s,   


zThreadPool._set_sizea.      The number of running pooled worker threads.

    Setting this attribute will add or remove running
    worker threads, up to `maxsize`.

    Initially there are no pooled running worker threads, and
    threads are created on demand to satisfy concurrent
    requests up to `maxsize` threads.
    c                 C   sv   t  }|| jkr9tt }t| jD ]}||j	}t
| ||j |j  q| j  | | j d S d S r[   )r   r   r   dictr-   _current_frameslistr   rl   rA   r   ro   rJ   __dict__clearr5   r   r0   r   )r=   r   thread_ident_to_framer   framer   r   r   r     s   

zThreadPool._on_forkc                 C   sF   t d| jjj}| jjdkr!t| t|d d}| jjdksdS dS )z6Waits until all outstanding tasks have been completed.gMb@?r   r   r   N)maxr   r   r   r5   r   r   r   r=   r   r   r   r   join  s
   zThreadPool.joinc                 C   s   d| _ | j  d S )Nr   )r   r   closer   r   r   r   r        zThreadPool.killc                 C   s   t | j| jk r&| jjt | jkr&|   t | j| jk r&| jjt | jkst | j| j | jjkrD| jd  t | j| j | jjks2| jrP| j| j	 d S | jd ur\| j
  d S d S r[   )r   r   r   r5   r   r   r   r   r   r   r   r   r   r   r   _adjust_step  s   
zThreadPool._adjust_stepc                 C   s@   | j jj}	 |   t| j| jkrd S t| t|d d}q)NTr   r   )	r   r   r   r   r   r   r   r   r   r   r   r   r   _adjust_wait  s   
zThreadPool._adjust_waitc                 C   s8   |    | jst| j| jkrt| j| _d S d S d S r[   )r   r   r   r   r   r
   spawnr   r   r   r   r   r     s   zThreadPool.adjustc                 C   s   |  |  d S r[   )r+   r   r   r   r   r     s   zThreadPool._add_threadc                 O   s   | j t krt	 | j}|  || ju rnq	t }| j}d}zt|| j |j}|	||||f | 
  W |S    |durC|  |   )a  
        Add a new task to the threadpool that will run ``func(*args,
        **kwargs)``.

        Waits until a slot is available. Creates a new native thread
        if necessary.

        This must only be called from the native thread that owns this
        object's hub. This is because creating the necessary data
        structures to communicate back to this thread isn't thread
        safe, so the hub must not be running something else. Also,
        ensuring the pool size stays correct only works within a
        single thread.

        :return: A :class:`gevent.event.AsyncResult`.
        :raises InvalidThreadUseError: If called from a different thread.

        .. versionchanged:: 1.5
           Document the thread-safety requirements.
        ri   N)r   r   r	   r   acquirer   r5   r   releaser   r   destroy_in_main_thread)r=   r_   r`   ra   	semaphoreresultr5   rb   r   r   r   r     s*   

zThreadPool.spawnc                 C   s   t  | juS r[   )r   r   r   r   r   r   _apply_immediately*  s   zThreadPool._apply_immediatelyc                 C   s   || d S r[   r   )r=   callbackr   r   r   r   _apply_async_cb_spawn2     z ThreadPool._apply_async_cb_spawnc                 C      dS r?   r   r   r   r   r   _apply_async_use_greenlet5  s   z$ThreadPool._apply_async_use_greenlet)Nr,   )r   r   r   __doc__	__slots__r+   r0   r;   r9   r   r   propertyr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s4    9
		5c                   @   s0   e Zd Zdd Ze ZZdd Zdd ZeZdS )
_FakeAsyncc                 C   r~   r[   r   r   r   r   r   send;     z_FakeAsync.sendc                 C   r   )zfake out for 'receiver'Nr   )r=   r   r   r   r   __call__?  r   z_FakeAsync.__call__c                 C   r   )NFr   r   r   r   r   __bool__B  r   z_FakeAsync.__bool__N)	r   r   r   r   r   r   r   r   __nonzero__r   r   r   r   r   9  s    r   c                   @   sP   e Zd ZdZdZdd Zedd Zdd Zd	d
 Z	dd Z
dd Zdd ZdS )r   a  
    A one-time event for cross-thread communication.

    Uses a hub's "async" watcher capability; it must be constructed and
    destroyed in the thread running the hub (because creating, starting, and
    destroying async watchers isn't guaranteed to be thread safe).
    )rj   async_watcher_call_when_readyvaluecontextr   receiverc                 C   sB   || _ || _d | _d | _d| _|j | _|| _| j	| j
 d S )Nr   )r   r   r   r   rj   r   async_r   r   r   	_on_async)r=   r   r   call_when_readyr   r   r   r0   V  s   zThreadResult.__init__c                 C   s   | j r| j d S d S )Nri   )rj   r   r   r   r   	exception`  s   zThreadResult.exceptionc              	   C   s   | j }t| _ |  |  z>|   | jr"| jj| jg| jR   d | _t| _ d | _t| _| 	|  W t| _	d | _
| jrK| jd | jd d f| _d S d S t| _	d | _
| jrb| jd | jd d f| _w )Nr   ri   )r   r   r   r   r   rj   r   rf   r   r   r   )r=   awr   r   r   r   d  s,   zThreadResult._on_asyncc                 C   s6   | j   | j   t| _ d| _d| _t| _t| _dS )zK
        This must only be called from the thread running the hub.
        N)r   r   r   r   r   r   r   r   r   r   r   r   r     s   


z#ThreadResult.destroy_in_main_threadc                 C   s   || _ | j  d S r[   )r   r   r   )r=   r   r   r   r   re     r   zThreadResult.setc                 C   s   || _ || _| j  d S r[   )r   rj   r   r   )r=   r   rj   r   r   r   rf     s   zThreadResult.handle_errorc                 C   s
   | j d u S r[   )r   r   r   r   r   
successful  r   zThreadResult.successfulN)r   r   r   r   r   r0   r   r   r   r   re   rf   r   r   r   r   r   r   I  s    	

ThreadPoolExecutor)Timeout)Lazy)_basec                        fdd}|S )Nc              	      s<   ~ z  W d S  t y   j fd d d  Y d S w r[   )rs   r   print_exceptionr   fnfuture_proxyr   r   cbwrap  s   z_ignore_error.<locals>.cbwrapr   )r   r   r   r   r   r   _ignore_error  s   	r   c                    r   )Nc                    s     d S r[   r   r   r   r   r   rV     r   z_wrap.<locals>.fr   )r   r   rV   r   r   r   _wrap  s   r   c                   @   s|   e Zd Zdd Zedd Zedd Zdd Zed	d
 Z	dd Z
dddZdddZdd Zdd Zdd Zdd ZdS )_FutureProxyc                 C   s
   || _ d S r[   )asyncresult)r=   r   r   r   r   r0     r   z_FutureProxy.__init__c                 C   s*   t ds	|  rdd l}| S td)Nr"   r   
_condition)r   r2   doner"   	ConditionAttributeError)r=   r"   r   r   r   r     s   z_FutureProxy._conditionc                 C   s   | j | j g S r[   )r   rawlink_FutureProxy__when_doner   r   r   r   _waiters  s   z_FutureProxy._waitersc                 C   s6   t | d}|D ]}|  r||  q||  qd S )Nr   )getattrr   
add_resultadd_exception)r=   r   waiterswr   r   r   __when_done  s   
z_FutureProxy.__when_donec                 C   s   |   rtjS tjS r[   )r   cfbFINISHEDRUNNINGr   r   r   r   _state  s   z_FutureProxy._statec                 C   r~   r[   r   r   r   r   r   set_running_or_notify_cancel     z)_FutureProxy.set_running_or_notify_cancelNc                 C   s*   z| j j|dW S  ty   tj w N)timeout)r   r   GTimeout
concurrentfuturesTimeoutErrorr=   r  r   r   r   r     s
   
z_FutureProxy.resultc                 C   s2   z| j j|d | j jW S  ty   tj w r
  )r   rl   r   r  r  r  r  r  r   r   r   r     s   

z_FutureProxy.exceptionc                 C   s*   |   r
||  dS | jt| | dS )z&Exceptions raised by *fn* are ignored.N)r   r   r   r   r=   r   r   r   r   add_done_callback  s   z_FutureProxy.add_done_callbackc                 C   s   | j t| | d S r[   )r   r   r   r  r   r   r   r     s   z_FutureProxy.rawlinkc                 C   r   r[   )rq   r   r   r   r   r   __str__  r   z_FutureProxy.__str__c                 C   s   t | j|S r[   )r   r   )r=   rG   r   r   r   __getattr__  r   z_FutureProxy.__getattr__r[   )r   r   r   r0   r   r   r   r   r   r  r  r   r   r  r   r  r  r   r   r   r   r     s     
	




r   c                       sB   e Zd ZdZ fddZdd Zd fdd	ZeZd	d
 Z  Z	S )r   a  
        A version of :class:`concurrent.futures.ThreadPoolExecutor` that
        always uses native threads, even when threading is monkey-patched.

        The ``Future`` objects returned from this object can be used
        with gevent waiting primitives like :func:`gevent.wait`.

        .. caution:: If threading is *not* monkey-patched, then the ``Future``
           objects returned by this object are not guaranteed to work with
           :func:`~concurrent.futures.as_completed` and :func:`~concurrent.futures.wait`.
           The individual blocking methods like :meth:`~concurrent.futures.Future.result`
           and :meth:`~concurrent.futures.Future.exception` will always work.

        .. versionadded:: 1.2a1
           This is a provisional API.
        c                    s&   t t| j|i | t| j| _dS )a.  
            Takes the same arguments as ``concurrent.futures.ThreadPoolExecuter``, which
            vary between Python versions.

            The first argument is always *max_workers*, the maximum number of
            threads to use. Most other arguments, while accepted, are ignored.
            N)superr   r0   r   _max_workers_threadpool)r=   r`   ra   r   r   r   r0     s   zThreadPoolExecutor.__init__c                 O   sZ   | j   | jrtd| jj|g|R i |}t|W  d    S 1 s&w   Y  d S )Nz*cannot schedule new futures after shutdown)_shutdown_lock	_shutdownRuntimeErrorr  r   r   )r=   r   r`   ra   futurer   r   r   submit  s   $zThreadPoolExecutor.submitTc                    s>   t t| j|fi | t| jdd }|r| j  d | _d S )Nr   )r  r   shutdownr   r  r   )r=   waitra   r   r  r   r   r  %  s
   

zThreadPoolExecutor.shutdownc                 C   r~   r[   r   r   r   r   r   _adjust_thread_count0  r	  z'ThreadPoolExecutor._adjust_thread_count)T)
r   r   r   r   r0   r  r  r   r   __classcell__r   r   r  r   r      s    	)=
__future__r   r   r   r   r-   r   r/   geventr   gevent._compatr   gevent.eventr   gevent.exceptionsr	   gevent.greenletr
   gevent._hub_localr   
gevent.hubr   r   r   r   gevent.lockr   gevent.poolr   gevent.utilr   gevent._threadingr   r   r   r   __all__r   r'   r*   r+   r   objectr   r   concurrent.futuresr  ImportErrorappendgevent.timeoutr   r  gevent._utilr   r   r  r   r   r   r  r   r   r   r   r   <module>   sb    >  GR
I