o
    eR                     @  s<  d Z ddlmZ ddlZddlZddlZddlmZ ddl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mZ dd	l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" G dd de	Z#d*ddZ$dd Z%G dd dej&j'Z(d+d d!Z)G d"d# d#eZ*ed$d% Z+ed&d' Z,ed(d) Z-dS ),a  Semaphore-free alternate executor.

There are two popular environments that do not fully support the standard Python
multiprocessing module: AWS Lambda, and Termux (a terminal emulator for Android).

This alternate executor divvies up work among worker processes before processing,
rather than having each worker consume work from a shared queue when they finish
their task. This means workers have no need to coordinate with each other. Each
worker communicates only with the main process.

This is not without drawbacks. If the tasks are not "even" in size, which cannot
be guaranteed, some workers may end up with too much work while others are idle.
It is less efficient than the standard implementation, so not th edefault.
    )annotationsN)suppress)Enumauto)islicerepeat	takewhilezip_longest)PipeProcess)
Connectionwait)CallableIterableIterator)ExecutorhookimplNullProgressBarInputFileError)remove_all_log_handlersc                   @  s"   e Zd ZdZe Ze Ze ZdS )MessageTypezImplement basic IPC messaging.N)__name__
__module____qualname____doc__r   	exceptionresultcomplete r    r    ND:\Projects\ConvertPro\env\Lib\site-packages\ocrmypdf/extra_plugins/semfree.pyr   $   s
    
r   nintiterabler   returnr   c                   s&   t | tt fddtdD S )zSplit iterable into groups of n.

    >>> list(split_every(4, range(10)))
    [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

    https://stackoverflow.com/a/22919323
    c                 3  s    | ]
}t t V  qd S N)listr   ).0_iteratorr"   r    r!   	<genexpr>5   s    zsplit_every.<locals>.<genexpr>N)iterr   boolr   )r"   r$   r    r*   r!   split_every,   s   r/   c                  G  s   t d)Nz-A worker process lost access to an input filer   )argsr    r    r!   process_sigbus8   s   r1   c                      s*   e Zd ZdZd
 fddZdd	 Z  ZS )ConnectionLogHandlerzBHandler used by child processes to forward log messages to parent.connr   r%   Nonec                   s   t  d  || _d S r&   )super__init__r3   )selfr3   	__class__r    r!   r6   ?   s   
zConnectionLogHandler.__init__c                 C  s   | j d|f d S )Nlog)r3   send)r7   recordr    r    r!   enqueueE   s   zConnectionLogHandler.enqueue)r3   r   r%   r4   )r   r   r   r   r6   r=   __classcell__r    r    r8   r!   r2   <   s    r2   r3   r   	user_initCallable[[], None]c           
      C  s   t t ttjt W d   n1 sw   Y  t| }t }t| |	| |
| |  |D ],}z||}W n tyY }	 z| tj|	f W Y d}	~	 nd}	~	ww | tj|f q6| tjdf |   dS )z Initialize a process pool workerN)r   AttributeErrorsignalZSIGBUSr1   r2   logging	getLoggerr   setLevel
addHandler	Exceptionr;   r   r   r   r   close)
r3   r?   ZlogleveltaskZ	task_argshrootr0   r   er    r    r!   process_loopI   s*   


rM   c                   @  s   e Zd ZdZdddZdS )LambdaExecutorzEExecutor for AWS Lambda or similar environments that lack semaphores.use_threadsr.   max_workersr#   tqdm_kwargsdictworker_initializerr   rI   task_argumentsr   task_finishedc             
   C  s  |r/|dkr/| j d	i |}|D ]}	||	}
||
| qW d    d S 1 s(w   Y  d S t|}tttt|| }|sBd S g }g }|D ]*}t \}}dd |D }tt||tdj	||fd}d|_
|| || qH|D ]}|  qu| j d	i |m}|rt|D ]\}
t|
tstdz|
 \}}W n ty   ||
 Y qw |tjkr|r||| q|dkr|}t|j}|| q|tjkr||
 q|tjkr|D ]}|  q|q|sW d    n1 sw   Y  |D ]}|  qd S )
N   c                 S  s   g | ]}|d ur|qS r&   r    )r(   r0   r    r    r!   
<listcomp>   s    z+LambdaExecutor._execute.<locals>.<listcomp> )targetr0   TzWe only support Connection()r:   r    )
pbar_classr'   r	   r/   r
   r   rM   rC   rD   leveldaemonappendstartr   
isinstancer   NotImplementedErrorrecvEOFErrorremover   r   namehandler   r   	terminatejoin)r7   rO   rP   rQ   rS   rI   rT   rU   Zpbarr0   r   Zgrouped_argsZ	processesconnectionschunkZparent_connZ
child_connZworker_argsprocessmsg_typemsgr<   loggerr    r    r!   _executem   s   













zLambdaExecutor._executeN)rO   r.   rP   r#   rQ   rR   rS   r   rI   r   rT   r   rU   r   )r   r   r   r   rn   r    r    r    r!   rN   j   s    rN   c                 C  s
   t | dS )N)rZ   )rN   )Zprogressbar_classr    r    r!   get_executor   s   
ro   c                   C  s   t  S r&   )rC   StreamHandlerr    r    r    r!   get_logging_console   s   rq   c                   C  s   t S r&   r   r    r    r    r!   get_progressbar_class   s   rr   )r"   r#   r$   r   r%   r   )r3   r   r?   r@   ).r   
__future__r   rC   logging.handlersrB   
contextlibr   enumr   r   	itertoolsr   r   r   r	   multiprocessingr
   r   Zmultiprocessing.connectionr   r   typingr   r   r   Zocrmypdfr   r   Zocrmypdf._concurrentr   Zocrmypdf.exceptionsr   Zocrmypdf.helpersr   r   r/   r1   handlersQueueHandlerr2   rM   rN   ro   rq   rr   r    r    r    r!   <module>   s6   

!P

