B
    ÐH/\bL  ã               @   sn  d 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Zeed	d
ƒZyddlZW n ek
r”   dZY nX dgZddgZejZejZeejgZeräedddg7 Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z e!edƒr:ej"Z#dd„ Z$dd„ Z"e!edƒrHej%Z&dd„ Z'e'Z%e (d¡ e (d¡ e!edƒs`e!edƒrDddl)Z)ej*Z+ej,Z-dd„ Z.i Z/d d!„ Z0d2d#d$„Z1d%d&„ Z*ddd'e$fd(d)„Z2e (d)¡ e (d¡ dekræddd'e'fd*d+„Z3e (d+¡ e
j4sd,d„ Z"dekrd-d„ Z%e (d&¡ n$d.d„ Z"dekr.d/d„ Z%e (d&¡ n
e 5d¡ eee6ƒ ee d0d1Z7e8e9ee ƒƒZ:dS )3aQ  
Low-level operating system functions from :mod:`os`.

Cooperative I/O
===============

This module provides cooperative versions of :func:`os.read` and
:func:`os.write`. These functions are *not* monkey-patched; you
must explicitly call them or monkey patch them yourself.

POSIX functions
---------------

On POSIX, non-blocking IO is available.

- :func:`nb_read`
- :func:`nb_write`
- :func:`make_nonblocking`

All Platforms
-------------

On non-POSIX platforms (e.g., Windows), non-blocking IO is not
available. On those platforms (and on POSIX), cooperative IO can
be done with the threadpool.

- :func:`tp_read`
- :func:`tp_write`

Child Processes
===============

The functions :func:`fork` and (on POSIX) :func:`forkpty` and :func:`waitpid` can be used
to manage child processes.

.. warning::

   Forking a process that uses greenlets does not eliminate all non-running
   greenlets. Any that were scheduled in the hub of the forking thread in the parent
   remain scheduled in the child; compare this to how normal threads operate. (This behaviour
   may change is a subsequent major release.)
é    )Úabsolute_importN)Ú_get_hub_noargs)Úreinit)Úconfig)ÚPY3)Úcopy_globalsÚEAGAINé   ÚforkÚtp_readÚtp_writeÚmake_nonblockingÚnb_readÚnb_writec             C   s<   t   | t jd¡}t|tj@ ƒs8t   | t j|tjB ¡ dS dS )z™Put the file descriptor *fd* into non-blocking mode if
        possible.

        :return: A boolean value that evaluates to True if successful.
        r   TN)ÚfcntlZF_GETFLÚboolÚosÚ
O_NONBLOCKZF_SETFL)ÚfdÚflags© r   ú(lib/python3.7/site-packages/gevent/os.pyr   L   s    c          
   C   s¢   d}d}zzxtyt | |ƒ}|S  tk
rT } z|jtkr8‚ tsDt ¡  W dd}~X Y nX |dkrrtƒ }|j 	| d¡}| 
|¡ qW W d|dk	rœ| ¡  d}d}X dS )a  
        Read up to *n* bytes from file descriptor *fd*. Return a
        byte string containing the bytes read, which may be shorter than
        *n*. If end-of-file is reached, an empty string is returned.

        The descriptor must be in non-blocking mode.
        Né   )Ú_readÚOSErrorÚerrnoÚignored_errorsr   ÚsysÚ	exc_clearÚget_hubÚloopÚioÚwaitÚclose)r   ÚnÚhubÚeventÚresultÚer   r   r   r   W   s(    

c          
   C   s¢   d}d}zzxtyt | |ƒ}|S  tk
rT } z|jtkr8‚ tsDt ¡  W dd}~X Y nX |dkrrtƒ }|j 	| d¡}| 
|¡ qW W d|dk	rœ| ¡  d}d}X dS )zò
        Write some number of bytes from buffer *buf* to file
        descriptor *fd*. Return the number of bytes written, which may
        be less than the length of *buf*.

        The file descriptor must be in non-blocking mode.
        Né   )Ú_writer   r   r   r   r   r   r   r    r!   r"   r#   )r   Úbufr%   r&   r'   r(   r   r   r   r   v   s(    

c             C   s   t ƒ j t| |f¡S )zÊRead up to *n* bytes from file descriptor *fd*. Return a string
    containing the bytes read. If end-of-file is reached, an empty string
    is returned.

    Reading is done using the threadpool.
    )r   Ú
threadpoolÚapplyr   )r   r$   r   r   r   r   •   s    c             C   s   t ƒ j t| |f¡S )zŽWrite bytes from buffer *buf* to file descriptor *fd*. Return the
    number of bytes written.

    Writing is done using the threadpool.
    )r   r,   r-   r*   )r   r+   r   r   r   r   Ÿ   s    c              C   s   t ƒ } | stƒ  | S )a÷  
        Forks the process using :func:`os.fork` and prepares the
        child process to continue using gevent before returning.

        .. note::

            The PID returned by this function may not be waitable with
            either the original :func:`os.waitpid` or this module's
            :func:`waitpid` and it may not generate SIGCHLD signals if
            libev child watchers are or ever have been in use. For
            example, the :mod:`gevent.subprocess` module uses libev
            child watchers (which parts of gevent use libev child
            watchers is subject to change at any time). Most
            applications should use :func:`fork_and_watch`, which is
            monkey-patched as the default replacement for
            :func:`os.fork` and implements the ``fork`` function of
            this module by default, unless the environment variable
            ``GEVENT_NOWAITPID`` is defined before this module is
            imported.

        .. versionadded:: 1.1b2
        )Ú	_raw_forkr   )r'   r   r   r   Úfork_gevent­   s    r/   c               C   s   t ƒ S )zL
        A wrapper for :func:`fork_gevent` for non-POSIX platforms.
        )r/   r   r   r   r   r
   É   s    Úforkptyc              C   s   t ƒ \} }| stƒ  | |fS )a¶  
            Forks the process using :func:`os.forkpty` and prepares the
            child process to continue using gevent before returning.

            Returns a tuple (pid, master_fd). The `master_fd` is *not* put into
            non-blocking mode.

            Availability: Some Unix systems.

            .. seealso:: This function has the same limitations as :func:`fork_gevent`.

            .. versionadded:: 1.1b5
            )Ú_raw_forkptyr   )ÚpidZ	master_fdr   r   r   Úforkpty_geventÒ   s    
r3   ÚWNOWAITÚWNOHANGc               C   s   d S )Nr   r   r   r   r   Ú<lambda>ò   s    r6   c             C   sL   |   ¡  z4| j| jt ¡ ft| j< |r.|| ƒ tƒ  tƒ  W d |  ¡  X d S )N)Ústopr2   ÚrstatusÚtimeÚ_watched_childrenÚ_on_child_hookÚ_reap_childrenr#   )ÚwatcherÚcallbackr   r   r   Ú	_on_child÷   s    
r?   é<   c                s>   t   ¡ }||  ‰ ‡ fdd„t ¡ D ƒ}x|D ]
}t|= q,W d S )Nc                s*   g | ]"\}}t |tƒr|d  ˆ k r|‘qS )r)   )Ú
isinstanceÚtuple)Ú.0r2   Úval)Úoldest_allowedr   r   ú
<listcomp>  s    z"_reap_children.<locals>.<listcomp>)r9   r:   Úitems)ZtimeoutZnowZdeadr2   r   )rE   r   r<     s    

r<   c          	   C   s  | dkrŠ| dkr6x$t  ¡ D ]\}}t|tƒr|} P qW | dkrŠ| dkr€|dkr€tƒ }|j dd¡}| |¡ |j|j	fS Q R X t
| |ƒS | t kr|t@ sªtt |  tƒrÒt |  }t|tƒrÎt | = |dd… S dS t |  }|j | d¡}tƒ  |¡ W dQ R X |j|j	fS t
| |ƒS )a#  
            Wait for a child process to finish.

            If the child process was spawned using
            :func:`fork_and_watch`, then this function behaves
            cooperatively. If not, it *may* have race conditions; see
            :func:`fork_gevent` for more information.

            The arguments are as for the underlying
            :func:`os.waitpid`. Some combinations of *options* may not
            be supported cooperatively (as of 1.1 that includes
            WUNTRACED). Using a *pid* of 0 to request waiting on only processes
            from the current process group is not cooperative.

            Availability: POSIX.

            .. versionadded:: 1.1b1
            .. versionchanged:: 1.2a1
               More cases are handled in a cooperative manner.
            r   éÿÿÿÿFNr)   )r   r   )r:   rG   rA   rB   r   r    Úchildr"   Zrpidr8   Ú_waitpidÚ_WNOHANG)r2   ZoptionsÚkÚvr%   r=   r'   Znew_watcherr   r   r   Úwaitpid  s2    





rN   Fc             C   s>   |ƒ }|r:|pt ƒ j}|j||d}|t|< | t|| ¡ |S )a¿  
            Fork a child process and start a child watcher for it in the parent process.

            This call cooperates with :func:`waitpid` to enable cooperatively waiting
            for children to finish. When monkey-patching, these functions are patched in as
            :func:`os.fork` and :func:`os.waitpid`, respectively.

            In the child process, this function calls :func:`gevent.hub.reinit` before returning.

            Availability: POSIX.

            :keyword callback: If given, a callable that will be called with the child watcher
                when the child finishes.
            :keyword loop: The loop to start the watcher in. Defaults to the
                loop of the current hub.
            :keyword fork: The fork function. Defaults to :func:`the one defined in this
                module <gevent.os.fork_gevent>` (which automatically calls :func:`gevent.hub.reinit`).
                Pass the builtin :func:`os.fork` function if you do not need to
                initialize gevent in the child process.

            .. versionadded:: 1.1b1
            .. seealso::
                :func:`gevent.monkey.get_original` To access the builtin :func:`os.fork`.
            )Úref)r   r    rI   r:   Ústartr?   )r>   r    rO   r
   r2   r=   r   r   r   Úfork_and_watch„  s    rQ   c                s(   g ‰‡ ‡fdd„}t | |||ƒ ˆd S )z¾
                Like :func:`fork_and_watch`, except using :func:`forkpty_gevent`.

                Availability: Some Unix systems.

                .. versionadded:: 1.1b5
                c                 s   ˆ ƒ } ˆ  | ¡ | d S )Nr   )Úappend)Z
pid_and_fd)r0   r'   r   r   Ú_fork´  s    
z forkpty_and_watch.<locals>._forkr   )rQ   )r>   r    rO   r0   rS   r   )r0   r'   r   Úforkpty_and_watchª  s    rT   c              O   s
   t | |ŽS )a×  
                Forks a child process and starts a child watcher for it in the
                parent process so that ``waitpid`` and SIGCHLD work as expected.

                This implementation of ``fork`` is a wrapper for :func:`fork_and_watch`
                when the environment variable ``GEVENT_NOWAITPID`` is *not* defined.
                This is the default and should be used by most applications.

                .. versionchanged:: 1.1b2
                )rQ   )ÚargsÚkwargsr   r   r   r
   Á  s    c              O   s
   t | |ŽS )a˜  
                    Like :func:`fork`, but using :func:`forkpty_gevent`.

                    This implementation of ``forkpty`` is a wrapper for :func:`forkpty_and_watch`
                    when the environment variable ``GEVENT_NOWAITPID`` is *not* defined.
                    This is the default and should be used by most applications.

                    .. versionadded:: 1.1b5
                    )rT   )rU   rV   r   r   r   r0   Ð  s    c               C   s   t ƒ S )a›  
                Forks a child process, initializes gevent in the child,
                but *does not* prepare the parent to wait for the child or receive SIGCHLD.

                This implementation of ``fork`` is a wrapper for :func:`fork_gevent`
                when the environment variable ``GEVENT_NOWAITPID`` *is* defined.
                This is not recommended for most applications.
                )r/   r   r   r   r   r
   Þ  s    	c               C   s   t ƒ S )a~  
                    Like :func:`fork`, but using :func:`os.forkpty`

                    This implementation of ``forkpty`` is a wrapper for :func:`forkpty_gevent`
                    when the environment variable ``GEVENT_NOWAITPID`` *is* defined.
                    This is not recommended for most applications.

                    .. versionadded:: 1.1b5
                    )r3   r   r   r   r   r0   ê  s    
r   )Znames_to_ignoreZdunder_names_to_keep)r@   );Ú__doc__Z
__future__r   r   r   Z
gevent.hubr   r   r   Zgevent._configr   Zgevent._compatr   Zgevent._utilr   r   Úgetattrr   r   ÚImportErrorZ__implements__Z__extensions__Úreadr   Úwriter*   ZEINTRr   r   r   r   r   r   Úhasattrr
   r.   r/   r0   r1   r3   rR   r9   rN   rJ   r5   rK   r;   r:   r?   r<   rQ   rT   Zdisable_watch_childrenÚremoveÚglobalsZ__imports__ÚlistÚsetÚ__all__r   r   r   r   Ú<module>*   s‚   


	


f"






