o
     #b &                     @   s   d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
 ede G dd deZG d	d
 d
eeZG dd deeZG dd deeZG dd dZdddZdd Zdd ZdS )z Daemon runner library.     N   pidfile)DaemonContextu@   The ‘runner’ module is not a supported API for this library.c                   @      e Zd ZdZdS )DaemonRunnerErrorz3 Abstract base class for errors from DaemonRunner. N__name__
__module____qualname____doc__ r   r   1usr/lib/python3.10/site-packages/daemon/runner.pyr          r   c                   @   r   )DaemonRunnerInvalidActionErrorz; Raised when specified action for DaemonRunner is invalid. Nr   r   r   r   r   r      r   r   c                   @   r   )DaemonRunnerStartFailureErrorz, Raised when failure starting DaemonRunner. Nr   r   r   r   r   r   #   r   r   c                   @   r   )DaemonRunnerStopFailureErrorz, Raised when failure stopping DaemonRunner. Nr   r   r   r   r   r   '   r   r   c                   @   sr   e Zd ZdZdZdd Zdd Zdd Zdd
dZdd Z	dd Z
dd Zdd Ze	eedZdd Zdd Zd	S )DaemonRunnera3   Controller for a callable running in a separate background process.

        The first command-line argument is the action to take:

        * 'start': Become a daemon and call `app.run()`.
        * 'stop': Exit the daemon process specified in the PID file.
        * 'restart': Stop, then start.
        zstarted with pid {pid:d}c                 C   sN   |    || _t | _| | d| _|jdur t|j|j| _| j| j_dS )a"   Set up the parameters of a new runner.

            :param app: The application instance; see below.
            :return: ``None``.

            The `app` argument must have the following attributes:

            * `stdin_path`, `stdout_path`, `stderr_path`: Filesystem paths
              to open and replace the existing `sys.stdin`, `sys.stdout`,
              `sys.stderr`.

            * `pidfile_path`: Absolute filesystem path to a file that will
              be used as the PID file for the daemon. If ``None``, no PID
              file will be used.

            * `pidfile_timeout`: Used as the default acquisition timeout
              value supplied to the runner's PID lock file.

            * `run`: Callable that will be invoked when the daemon is
              started.
            N)	
parse_argsappr   daemon_context#_open_streams_from_app_stream_pathsr   Zpidfile_pathmake_pidlockfileZpidfile_timeoutselfr   r   r   r   __init__7   s   

zDaemonRunner.__init__c                 C   s8   t |jd| j_t |jd| j_t |jddd| j_dS )ab   Open the `daemon_context` streams from the paths specified.

            :param app: The application instance.

            Open the `daemon_context` standard streams (`stdin`,
            `stdout`, `stderr`) as stream objects of the appropriate
            types, from each of the corresponding filesystem paths
            from the `app`.
            rtzw+tr   )	bufferingN)openZ
stdin_pathr   stdinZstdout_pathstdoutZstderr_pathstderrr   r   r   r   r   X   s
   
z0DaemonRunner._open_streams_from_app_stream_pathsc                 C   sH   t j|d }d}d| j }dj||d}t| t	| dS )z Emit a usage message, then exit.

            :param argv: The command-line arguments used to invoke the
                program, as a sequence of strings.
            :return: ``None``.
            r      |zusage: {progname} {usage})prognameusageN)
ospathbasenamejoinaction_funcskeysformatemit_messagesysexit)r   argvr$   Zusage_exit_codeaction_usagemessager   r   r   _usage_exitg   s   zDaemonRunner._usage_exitNc                 C   sT   |du rt j}d}t||k r| | t|d | _| j| jvr(| | dS dS )a   Parse command-line arguments.

            :param argv: The command-line arguments used to invoke the
                program, as a sequence of strings.

            :return: ``None``.

            The parser expects the first argument as the program name, the
            second argument as the action to perform.

            If the parser fails to parse the arguments, emit a usage
            message and exit the program.
            Nr"   r   )r.   r0   lenr3   stractionr*   )r   r0   Zmin_argsr   r   r   r   v   s   
zDaemonRunner.parse_argsc              
   C   s   t | jr
| j  z| j  W n tjy* } ztdj| jd}||d}~ww t	
 }| jj|d}t| | j  dS )z Open the daemon context and run the application.

            :return: ``None``.
            :raises DaemonRunnerStartFailureError: If the PID file cannot
                be locked by this process.
            z(PID file {pidfile.path!r} already lockedr   N)pid)is_pidfile_staler   
break_lockr   r   lockfileZAlreadyLockedr   r,   r&   getpidstart_messager-   r   run)r   excerrorr7   r2   r   r   r   _start   s"   

zDaemonRunner._startc              
   C   sP   | j  }z
t|tj W dS  ty' } ztdj||d}||d}~ww )z Terminate the daemon process specified in the current PID file.

            :return: ``None``.
            :raises DaemonRunnerStopFailureError: If terminating the daemon
                fails with an OS error.
            z"Failed to terminate {pid:d}: {exc})r7   r>   N)	r   read_pidr&   killsignalSIGTERMOSErrorr   r,   )r   r7   r>   r?   r   r   r   _terminate_daemon_process   s   
z&DaemonRunner._terminate_daemon_processc                 C   sD   | j  stdj| j d}|t| j r| j   dS |   dS )z Exit the daemon process specified in the current PID file.

            :return: ``None``.
            :raises DaemonRunnerStopFailureError: If the PID file is not
                already locked.
            z$PID file {pidfile.path!r} not lockedr   N)r   Z	is_lockedr   r,   r8   r9   rF   )r   r?   r   r   r   _stop   s   

zDaemonRunner._stopc                 C   s   |    |   dS )z Stop, then start. N)rG   r@   )r   r   r   r   _restart   s   zDaemonRunner._restart)startstopZrestartc                 C   s8   z	| j | j }W |S  ty   tdj| jd}|w )ad   Get the function for the specified action.

            :return: The function object corresponding to the specified
                action.
            :raises DaemonRunnerInvalidActionError: if the action is
               unknown.

            The action is specified by the `action` attribute, which is set
            during `parse_args`.
            zUnknown action: {action!r})r6   )r*   r6   KeyErrorr   r,   )r   funcr?   r   r   r   _get_action_func   s   zDaemonRunner._get_action_funcc                 C   s   |   }||  dS )z Perform the requested action.

            :return: ``None``.

            The action is specified by the `action` attribute, which is set
            during `parse_args`.
            N)rM   )r   rL   r   r   r   	do_action   s   zDaemonRunner.do_actionN)r	   r
   r   r   r<   r   r   r3   r   r@   rF   rG   rH   r*   rM   rN   r   r   r   r   r   +   s"    	!
r   c                 C   s,   |du rt j}|dj| d |  dS )z@ Emit a message to the specified stream (default `sys.stderr`). Nz
{message}
)r2   )r.   r!   writer,   flush)r2   streamr   r   r   r-      s   r-   c                 C   sN   t | tstdj| d}|tj| stdj| d}|t| |}|S )z= Make a PIDLockFile instance with the given filesystem path. zNot a filesystem path: {path!r})r'   zNot an absolute path: {path!r})	
isinstancer5   
ValueErrorr,   r&   r'   isabsr   ZTimeoutPIDLockFile)r'   Zacquire_timeoutr?   r:   r   r   r   r      s   
r   c                 C   sF   d}|   }|dur!z
t|tj W |S  ty    d}Y |S w |S )u    Determine whether a PID file is stale.

        :return: ``True`` iff the PID file is stale; otherwise ``False``.

        The PID file is “stale” if its contents are valid but do not
        match the PID of a currently-running process.
        FNT)rA   r&   rB   rC   SIG_DFLProcessLookupError)r   resultZpidfile_pidr   r   r   r8     s   r8   rO   )r   errnor&   rC   r.   warningsr:    r   daemonr   warnDeprecationWarning	Exceptionr   rT   r   RuntimeErrorr   r   r   r-   r   r8   r   r   r   r   <module>   s,    
J