U
    W[[                     @   s  d dl mZmZm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
Z
d dl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mZmZmZmZmZ d d	lm Z  d d
l!m"Z"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+G dd de+Z,G dd de+Z-G dd de*Z.G dd de*Z/dd Z0d2ddZ1dd Z2dd Z3G d d! d!e*Z4d"d# Z5d$d% Z6e G d&d' d'Z7G d(d) d)ej8e7Z9d*d+ Z:d,d- Z;d.d/ Z<d0d1 Z=dS )3    )absolute_importdivisionprint_functionN)
attrgetter)	copyrightpluginlogger)servicereactors)defer)sob)runtimelogusagefailureutillogfile)	_oldStyle)qualnamedAnynamedModule)_ISupportsExitSignalCapturing)installReactor)NoSuchReactorc                   @   s    e Zd ZdZdd Zdd ZdS )_BasicProfilerz
    @ivar saveStats: if C{True}, save the stats information instead of the
        human readable format
    @type saveStats: C{bool}

    @ivar profileOutput: the name of the file use to print profile data.
    @type profileOutput: C{str}
    c                 C   s   || _ || _d S N)profileOutput	saveStats)selfr   r    r   9/usr/lib/python3/dist-packages/twisted/application/app.py__init__)   s    z_BasicProfiler.__init__c                 C   s    d||f }|d7 }t |dS )z
        Helper method to report an import error with a profile module. This
        has to be explicit because some of these modules are removed by
        distributions due to them being non-free.
        zFailed to import module %s: %sz
This is most likely caused by your operating system not including
the module due to it being non-free. Either do not use the option
--profile, or install the module; your operating system vendor
may provide it in a separate package.
N)
SystemExit)r   moduleesr   r   r    _reportImportError.   s    z!_BasicProfiler._reportImportErrorN)__name__
__module____qualname____doc__r!   r&   r   r   r   r    r      s   	r   c                   @   s   e Zd ZdZdd ZdS )ProfileRunnerz1
    Runner for the standard profile module.
    c              
   C   s   zddl }W n. tk
r: } z| d| W 5 d}~X Y nX | }||j | jrd|| j n<t	j
t| jd }t	_
z|  W 5 |t	j
 t	_
}|  X dS )z:
        Run reactor under the standard profiler.
        r   Nprofilea)r,   ImportErrorr&   Profileruncallrunr   
dump_statsr   sysstdoutopencloseprint_stats)r   reactorr,   r$   pZtmpr   r   r    r1   D   s    zProfileRunner.runNr'   r(   r)   r*   r1   r   r   r   r    r+   ?   s   r+   c                   @   s   e Zd ZdZdd ZdS )CProfileRunnerz)
    Runner for the cProfile module.
    c              
   C   s   zddl }ddl}W n. tk
rB } z| d| W 5 d}~X Y nX | }||j | jrl|| j	 n@t
| j	d.}|j||d}|  |d |  W 5 Q R X dS )z:
        Run reactor under the cProfile profiler.
        r   NcProfilew)stream)r<   pstatsr.   r&   r/   r0   r1   r   r2   r   r5   ZStatsZ
strip_dirsZ
sort_statsr7   )r   r8   r<   r@   r$   r9   r>   r%   r   r   r    r1   `   s    
zCProfileRunner.runNr:   r   r   r   r    r;   [   s   r;   c                   @   s"   e Zd ZdZeedZdd ZdS )AppProfilerz
    Class which selects a specific profile runner based on configuration
    options.

    @ivar profiler: the name of the selected profiler.
    @type profiler: C{str}
    )r,   cprofilec                 C   sf   | dd}| dd }| dd | _| j| jkrR| j| j ||}|j| _ntd| jf d S )N	savestatsFr,   profilerrB   zUnsupported profiler name: %s)getlowerrD   	profilersr1   r"   )r   optionsr   r   rD   r   r   r    r!      s    
zAppProfiler.__init__N)r'   r(   r)   r*   r+   r;   rG   r!   r   r   r   r    rA   w   s   
rA   c                   @   s<   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dS )	AppLoggera]  
    An L{AppLogger} attaches the configured log observer specified on the
    commandline to a L{ServerOptions} object, a custom L{logger.ILogObserver},
    or a legacy custom {log.ILogObserver}.

    @ivar _logfilename: The name of the file to which to log, if other than the
        default.
    @type _logfilename: C{str}

    @ivar _observerFactory: Callable object that will create a log observer, or
        None.

    @ivar _observer: log observer added at C{start} and removed at C{stop}.
    @type _observer: a callable that implements L{logger.ILogObserver} or
        L{log.ILogObserver}.
    Nc                 C   s"   | dd| _| dpd| _dS )zE
        Initialize an L{AppLogger} with a L{ServerOptions}.
        r    r   N)rE   _logfilename_observerFactoryr   rH   r   r   r    r!      s    zAppLogger.__init__c                 C   s   | j dk	r|   }n$|tjd}|dkr8|tjd}|dkrH|  }|| _tj| jrf| jg}n<tj| jrt| jg}nt	j
dtdd t| jg}tj| |   dS )a  
        Initialize the global logging system for the given application.

        If a custom logger was specified on the command line it will be used.
        If not, and an L{logger.ILogObserver} or legacy L{log.ILogObserver}
        component has been set on C{application}, then it will be used as the
        log observer. Otherwise a log observer will be created based on the
        command line options for built-in loggers (e.g. C{--logfile}).

        @param application: The application on which to check for an
            L{logger.ILogObserver} or legacy L{log.ILogObserver}.
        @type application: L{twisted.python.components.Componentized}
        NaZ  Passing a logger factory which makes log observers which do not implement twisted.logger.ILogObserver or twisted.python.log.ILogObserver to twisted.application.app.AppLogger was deprecated in Twisted 16.2. Please use a factory that produces twisted.logger.ILogObserver (or the legacy twisted.python.log.ILogObserver) implementing objects instead.   )
stacklevel)rL   ZgetComponentr   ZILogObserverr   _getLogObserver	_observer
providedByZLegacyLogObserverWrapperwarningswarnDeprecationWarningZglobalLogBeginnerZbeginLoggingTo_initialLog)r   applicationZobserverZ	observersr   r   r    start   s(    


zAppLogger.startc                 C   sJ   ddl m} t| jdtjtjt	
 d t| jdt|jd dS )z1
        Print twistd start log message.
        r   r8   z1twistd {version} ({exe} {pyVersion}) starting up.)versionexeZ	pyVersionzreactor class: {reactor}.N)twisted.internetr8   r   
_loggerForinfor   rZ   r3   
executabler   ZshortPythonVersionr   	__class__)r   r8   r   r   r    rV      s    
 zAppLogger._initialLogc                 C   s0   | j dks| j stj}ntj| j }t|S )zr
        Create a log observer to be added to the logging system before running
        this application.
        -)rK   r3   r4   r   ZLogFileZfromFullPathr   ZtextFileLogObserver)r   ZlogFiler   r   r    rP      s    zAppLogger._getLogObserverc                 C   s2   t | d | jdk	r.t j| j d| _dS )zS
        Remove all log observers previously set up by L{AppLogger.start}.
        zServer Shut Down.N)r   r]   r^   rQ   ZglobalLogPublisherZremoveObserverr   r   r   r    stop   s    
zAppLogger.stop)
r'   r(   r)   r*   rQ   r!   rX   rV   rP   rc   r   r   r   r    rI      s   0rI   c                  C   s4   dd } dd }dd }|t j_| t j_|t j_d S )Nc                 S   s.   |    |   ddlm} |d|j dS )Nr   rY      )Zclear_all_breaksZset_continuer\   r8   Z	callLaterrc   )r   argr8   r   r   r    do_stop   s
    zfixPdb.<locals>.do_stopc                 S   s   t d d S )NzEstop - Continue execution, then cleanly shutdown the twisted reactor.)printrb   r   r   r    	help_stop  s    zfixPdb.<locals>.help_stopc                 S   s   t d d S )Nr   )os_exitrb   r   r   r    set_quit  s    zfixPdb.<locals>.set_quit)pdbZPdbrk   rf   rh   )rf   rh   rk   r   r   r    fixPdb   s    rm   c                 C   s   |dkrddl m} z~| d r2|dk	r|| n^| d r|t_|t_tjdkrtttj	dd  ttj
d	d  t  t|j n|  W nT   d
}| d r|}ntdd}d}ztj|d |  W 5 |r|  X Y nX dS )aN  
    Start the reactor, using profiling if specified by the configuration, and
    log any error happening in the process.

    @param config: configuration of the twistd application.
    @type config: L{ServerOptions}

    @param oldstdout: initial value of C{sys.stdout}.
    @type oldstdout: C{file}

    @param oldstderr: initial value of C{sys.stderr}.
    @type oldstderr: C{file}

    @param profiler: object used to run the reactor with profiling.
    @type profiler: L{AppProfiler}

    @param reactor: The reactor to use.  If L{None}, the global reactor will
        be used.
    Nr   rY   r,   debugposixc                  W   s   t  S r   rl   Z	set_traceargsr   r   r    <lambda>3      z'runReactorWithLogging.<locals>.<lambda>c                  W   s   t  S r   rp   rq   r   r   r    rs   4  rt   FZnodaemonzTWISTD-CRASH.logr-   Tfile)r\   r8   r1   r3   r4   stderrr   ZplatformTypesignalSIGUSR2SIGINTrm   rl   r0   r5   r6   	traceback	print_excflush)config	oldstdout	oldstderrrD   r8   r6   rv   r   r   r    runReactorWithLogging  s4    

r   c                 C   s   | rt  dS d S d S )NzPassphrase: )getpassZneededr   r   r    getPassphraseI  s    
r   c                 C   s   | rt dS d S d S )NzEncryption passphrase: )r   ZgetPasswordr   r   r   r    getSavePassphraseQ  s    
r   c                   @   sH   e Zd ZdZeZeZdd Zdd Z	dd Z
dd	 Zd
d Zdd ZdS )ApplicationRunnera  
    An object which helps running an application based on a config object.

    Subclass me and implement preApplication and postApplication
    methods. postApplication generally will want to run the reactor
    after starting the application.

    @ivar config: The config object, which provides a dict-like interface.

    @ivar application: Available in postApplication, but not
       preApplication. This is the application object.

    @ivar profilerFactory: Factory for creating a profiler object, able to
        profile the application if options are set accordingly.

    @ivar profiler: Instance provided by C{profilerFactory}.

    @ivar loggerFactory: Factory for creating object responsible for logging.

    @ivar logger: Instance provided by C{loggerFactory}.
    c                 C   s"   || _ | || _| || _d S r   )r~   profilerFactoryrD   loggerFactoryr   )r   r~   r   r   r    r!   r  s    zApplicationRunner.__init__c                 C   s6   |    |  | _| j| j |   | j  dS )z&
        Run the application.
        N)preApplicationcreateOrGetApplicationrW   r   rX   postApplicationrc   rb   r   r   r    r1   x  s
    
zApplicationRunner.runc                 C   sF   |dkrddl m} t| j||| j| t|r<|j| _nd| _dS )z
        Run the reactor with the given configuration.  Subclasses should
        probably call this from C{postApplication}.

        @see: L{runReactorWithLogging}
        Nr   rY   )r\   r8   r   r~   rD   r   rR   Z_exitSignal)r   r8   r   r   r   r   r    startReactor  s        

zApplicationRunner.startReactorc                 C   s
   t  dS )z
        Override in subclass.

        This should set up any state necessary before loading and
        running the Application.
        NNotImplementedErrorrb   r   r   r    r     s    z ApplicationRunner.preApplicationc                 C   s
   t  dS )z
        Override in subclass.

        This will be called after the application has been loaded (so
        the C{application} attribute will be set). Generally this
        should start the application and run the reactor.
        Nr   rb   r   r   r    r     s    z!ApplicationRunner.postApplicationc                 C   s\   | j jr>| j j| j j }|| j j}t|j}|| nt	| j d }t
| j |}|S )a  
        Create or load an Application based on the parameters found in the
        given L{ServerOptions} instance.

        If a subcommand was used, the L{service.IServiceMaker} that it
        represents will be used to construct a service to be added to
        a newly-created Application.

        Otherwise, an application will be loaded based on parameters in
        the config.
        	encrypted)r~   
subCommandloadedPluginsZmakeServiceZ
subOptionsr	   ZApplicationtapnameZsetServiceParentr   getApplication)r   ZplgZserrW   
passphraser   r   r    r     s    z(ApplicationRunner.createOrGetApplicationN)r'   r(   r)   r*   rA   r   rI   r   r!   r1   r   r   r   r   r   r   r   r    r   Y  s   
r   c              
      s    fdddD d }|d ddi |d |d  }}z*td|  t|||}td	 W n| tk
r } z^d
| }t|tr|jd dkr|d7 }t	j
tjd t| t  td| d  W 5 d }~X Y nX |S )Nc                    s    g | ]} | r | |fqS r   r   ).0tr~   r   r    
<listcomp>  s    z"getApplication.<locals>.<listcomp>)pythonsourcerv   r   rv   picklerd   zLoading %s...zLoaded.zFailed to load application: %srW   aN  
Could not find 'application' in the file. To use 'twistd -y', your .tac
file must create a suitable object (e.g., by calling service.Application())
and store it in a variable named 'application'. twistd loads your .tac file
and scans the global variables for one of this name.

Please read the 'Using Application' HOWTO for details.
ru   
)rE   r   msgr	   loadApplication	Exception
isinstanceKeyErrorrr   r{   r|   r   Zdeferrr3   exit)r~   r   r%   filenameZstylerW   r$   r   r   r    r     s&    
"
$r   c                   C   s   t dd t D S )Nc                 S   s   g | ]
}|j qS r   )	shortName)r   rr   r   r    r     s     z"_reactorAction.<locals>.<listcomp>)r   ZCompleteListr
   getReactorTypesr   r   r   r    _reactorAction  s    
r   c                   @   sD   e Zd ZdZejdeidZej	Z
eejZdd Zdd ZeZdS )	ReactorSelectionMixinz
    Provides options for selecting a reactor to install.

    If a reactor is installed, the short name which was used to locate it is
    saved as the value for the C{"reactor"} key.
    r8   )
optActionsc                 C   s   t |  tdd}d}|D ]j}z&t|j | jd|j|jf  W q t	k
r } z |d|j|j|j
d f 7 }W 5 d}~X Y qX q|r| jd | jd	 | j| tddS )
zE
        Display a list of possibly available reactor names.
        r   keyrJ   z    %-4s	%s
z    !%-4s	%s (%s)
r   Nr   z.    reactors not available on this platform:

)sorted_getReactorTypesr   r   Z
moduleNamemessageOutputwriter   descriptionr.   rr   r"   )r   ZrctsZnotWorkingReactorsr   r$   r   r   r    opt_help_reactors  s"    


z'ReactorSelectionMixin.opt_help_reactorsc              
   C   sv   zt | W n\ tk
r4   d|f }t|Y n> tk
rh } zd|f }t|W 5 d}~X Y n
X || d< dS )zX
        Which reactor to use (see --help-reactors for a list of possibilities)
        zcThe specified reactor does not exist: '%s'.
See the list of available reactors with --help-reactorsztThe specified reactor cannot be used, failed with error: %s.
See the list of available reactors with --help-reactorsNr8   )r   r   r   
UsageErrorr   )r   r   r   r$   r   r   r    opt_reactor  s    	z!ReactorSelectionMixin.opt_reactorN)r'   r(   r)   r*   r   Completionsr   compDatar3   r4   r   staticmethodr
   r   r   r   r   Zopt_rr   r   r   r    r     s   
r   c                   @   s  e Zd ZdZdddgdddgdd	d
ggZddddgddddgddddgdddddej gddddgddddgdddd gd!d"d#d$ggZe	j
d%ge	d&e	d'e	d(e	 d)d*ZeejZd+d, Zd-d. ZeZd/d0 Zd7d1d2Zd3d4 Zd5d6 ZeeZdS )8ServerOptionszQtwistd reads a twisted.application.service.Application out of a file and runs it.rC   NzBsave the Stats object rather than the text output of the profiler.no_saveozdo not save state on shutdownr   r$   z(The specified tap/aos file is encrypted.r   lz%log to a specified file, - for stdoutr   zA fully-qualified name to a log observer factory to use for the initial log observer.  Takes precedence over --logfile and --syslog (when available).r,   r9   z7Run in profile mode, dumping results to specified file.rD   rB   z!Name of the profiler to use (%s).z, rv   fz
twistd.tapzread the given .tap filer   yz:read an application from within a Python file (implies -o)r   r%   z2Read an application from a .tas file (AOT format).rundird.z-Change to a supplied directory before running)rv   r   r   z*.tapz
*.(tac|py)z*.tas)rv   r   r   r   )ZmutuallyExclusiver   c                 O   s4   d| d< d|kr|d | _ ntj | _ tj|  d S )NFrn   r4   )r4   r3   r   Optionsr!   )r   r-   kwr   r   r    r!   X  s
    zServerOptions.__init__c                 C   s   t d t  d| d< dS )z
        Run the application in the Python Debugger (implies nodaemon),
        sending SIGUSR2 will drop into debugger
        Trn   N)r   ZsetDebuggingr   ZstartDebugModerb   r   r   r    	opt_debuga  s    
zServerOptions.opt_debugc                 C   s@   t tj zddl}W n tk
r.   Y dS X |tj dS )z
        Print an insanely verbose log of everything that happens.
        Useful when debugging freezes or locks in complex code.
        r   N)r3   settracer   Zspewer	threadingr.   )r   r   r   r   r    opt_spewl  s    zServerOptions.opt_spewc                 C   s.   |d krt jdd  pdg}tj| | d S )Nrd   z--help)r3   argvr   r   parseOptionsrM   r   r   r    r   y  s    zServerOptions.parseOptionsc              
   C   st   | j s| d rd| d< | d d k	rpzt| d | d< W n8 tk
rn } ztd| d |f W 5 d }~X Y nX d S )Nr   Tr   r   z%Logger '%s' could not be imported: %s)r   r   r   r   r   )r   r$   r   r   r    postOptions  s    
zServerOptions.postOptionsc                 c   sR   |  tj}i | _t|tddD ]*}|| j|j< |jd |fdd|jfV  q"d S )Nr   r   c                 S   s   |   S r   )rH   )plugr   r   r    rs     rt   z+ServerOptions.subCommands.<locals>.<lambda>)_getPluginsr	   ZIServiceMakerr   r   r   r   r   )r   Zpluginsr   r   r   r    subCommands  s    
zServerOptions.subCommands)N)r'   r(   r)   ZlongdescZoptFlagsjoinrA   rG   ZoptParametersr   r   ZCompleteFilesZCompleteDirsr   r   r   Z
getPluginsr   r!   r   Zopt_br   r   r   r   propertyr   r   r   r    r   ,  sj   

	
r   c              
   C   sb   | }z|   W nB tjk
rT } z"t| tdtjd |f  W 5 d }~X Y n
X | | d S )Nz%s: %sr   )r   r   errorrg   r3   r   )ZrunAppr   r~   Zuer   r   r    r1     s    (r1   c                 C   sF   t | ||}t|| t|}|r.d }t|j||d d S )N)r   r   )r	   r   r   IPersistableZsetStyler   save)ZfileinZtypeinr   ZfileoutZtypeoutZencryptrW   r   r   r    convertStyle  s    r   c                 C   sT   ddl m} t|   |r:t| }|dd|jd |ddt| j	 d S )Nr   rY   ZafterZshutdownZbefore)
r\   r8   r	   ZIServiceZstartServicer   r   ZaddSystemEventTriggerr   ZstopService)rW   r   r8   r9   r   r   r    startApplication  s    

r   c                 C   s"   t  | t j tt |  dS )a  
    Force the application to terminate with the specified signal by replacing
    the signal handler with the default and sending the signal to ourselves.

    @param sig:  Signal to use to terminate the process with C{os.kill}.
    @type sig:  C{int}
    N)rx   SIG_DFLri   killgetpid)Zsigr   r   r    _exitWithSignal  s    r   )NN)>Z
__future__r   r   r   r3   ri   rl   r   r{   rx   rS   operatorr   Ztwistedr   r   r   Ztwisted.applicationr	   r
   r\   r   Ztwisted.persistedr   Ztwisted.pythonr   r   r   r   r   r   Ztwisted.python._oldstyler   Ztwisted.python.reflectr   r   r   Ztwisted.internet.interfacesr   Ztwisted.application.reactorsr   r   objectr   r+   r;   rA   rI   rm   r   r   r   r   r   r   r   r   r   r1   r   r   r   r   r   r   r    <module>   sN     o  
5q@n
