U
    Â“«jpZ  ã                   @   s   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mZ d dl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!m"Z"m#Z# G dd„ dƒZ$G dd„ de$ƒZ%G dd„ de$ƒZ&G dd„ dƒZ'G dd„ dƒZ(dd„ Z)d/dd„Z*dd„ Z+dd„ Z,G dd„ dƒZ-dd „ Z.d!d"„ Z/G d#d$„ d$ƒZ0G d%d&„ d&ej1e0ƒZ2d'd(„ Z3d)d*„ Z4d+d,„ Z5d-d.„ Z6dS )0é    N)Ú
attrgetter)Ú	copyrightÚloggerÚplugin)ÚreactorsÚservice)ÚNoSuchReactorÚinstallReactor)Údefer)Ú_ISupportsExitSignalCapturing)Úsob)ÚfailureÚlogÚlogfileÚruntimeÚusageÚutil)ÚnamedAnyÚnamedModuleÚqualc                   @   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   ú;/tmp/pip-unpacked-wheel-59kc99xd/twisted/application/app.pyÚ__init__%   s    z_BasicProfiler.__init__c                 C   s$   d|› d|› �}|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 ú: zê
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!   ÚpÚtmpr   r   r   r.   >   s    zProfileRunner.runN©r$   r%   r&   r'   r.   r   r   r   r   r(   9   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,   r-   r.   r   r/   r   r2   ZStatsZ
strip_dirsZ
sort_statsr4   )r   r5   r:   r>   r!   r6   r<   r"   r   r   r   r.   Y   s    
zCProfileRunner.runNr8   r   r   r   r   r9   T   s   r9   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› �ƒ‚d S )NÚ	savestatsFr)   Úprofilerr@   zUnsupported profiler name: )ÚgetÚlowerrB   Ú	profilersr.   r   )r   Úoptionsr   r   rB   r   r   r   r   z   s    
zAppProfiler.__init__N)r$   r%   r&   r'   r(   r9   rE   r   r   r   r   r   r?   o   s   
r?   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)rC   Ú_logfilenameÚ_observerFactory©r   rF   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¡r„t | 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)rJ   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   ©r5   z1twistd {version} ({exe} {pyVersion}) starting up.)ÚversionZexeZ	pyVersionzreactor class: {reactor}.N)Útwisted.internetr5   r   Ú
_loggerForÚinfor   rX   r0   Ú
executabler   ZshortPythonVersionr   Ú	__class__)r   r5   r   r   r   rT   Ò   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.
        ú-)rI   r0   r1   r   ZLogFileZfromFullPathr   ZtextFileLogObserver)r   ZlogFiler   r   r   rN   â   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   rZ   r[   rO   ZglobalLogPublisherZremoveObserver©r   r   r   r   Ústopí   s    
zAppLogger.stop)
r$   r%   r&   r'   rO   r   rV   rT   rN   r`   r   r   r   r   rG   …   s   2rG   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   rW   é   )Zclear_all_breaksZset_continuerY   r5   Z	callLaterr`   )r   Úargr5   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.)Úprintr_   r   r   r   Ú	help_stop   s    ÿzfixPdb.<locals>.help_stopc                 S   s   t  d¡ d S )Nr   )ÚosÚ_exitr_   r   r   r   Úset_quit  s    zfixPdb.<locals>.set_quit)ÚpdbZPdbrh   rc   re   )rc   re   rh   r   r   r   ÚfixPdb÷   s    rj   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 n\ tk
rî   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   rW   r)   ÚdebugÚposixc                  W   s   t  ¡ S r   ©ri   Ú	set_trace©Úargsr   r   r   Ú<lambda>+  ó    z'runReactorWithLogging.<locals>.<lambda>c                  W   s   t  ¡ S r   rm   ro   r   r   r   rq   ,  rr   FZnodaemonzTWISTD-CRASH.logr*   T©Úfile)rY   r5   r.   r0   r1   Ústderrr   ZplatformTypeÚsignalÚSIGUSR2ÚSIGINTrj   ri   r-   ÚBaseExceptionr2   r3   Ú	tracebackÚ	print_excÚflush)ÚconfigÚ	oldstdoutÚ	oldstderrrB   r5   r3   rt   r   r   r   ÚrunReactorWithLogging  s4    

r€   c                 C   s   | rt   d¡S d S d S )NzPassphrase: )Úgetpass©Úneededr   r   r   ÚgetPassphrase@  s    
r„   c                 C   s   | rt  d¡S d S d S )NzEncryption passphrase: )r   ZgetPasswordr‚   r   r   r   ÚgetSavePassphraseG  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}   ÚprofilerFactoryrB   ÚloggerFactoryr   )r   r}   r   r   r   r   h  s    zApplicationRunner.__init__c                 C   s6   |   ¡  |  ¡ | _| j | j¡ |  ¡  | j ¡  dS )z&
        Run the application.
        N)ÚpreApplicationÚcreateOrGetApplicationrU   r   rV   ÚpostApplicationr`   r_   r   r   r   r.   m  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   rW   )rY   r5   r€   r}   rB   r   rP   Z_exitSignal)r   r5   r~   r   r   r   r   ÚstartReactory  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©ÚNotImplementedErrorr_   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�   r_   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   ÚApplicationÚtapnameZsetServiceParentr„   ÚgetApplication)r   ZplgZserrU   Ú
passphraser   r   r   rŠ   œ  s    z(ApplicationRunner.createOrGetApplicationN)r$   r%   r&   r'   r?   r‡   rG   rˆ   r   r.   rŒ   r‰   r‹   rŠ   r   r   r   r   r†   N  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Úsourcert   r   rt   Úpicklera   zLoading %s...zLoaded.zFailed to load application: %srU   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.
rs   Ú
)rC   r   Úmsgr   ÚloadApplicationÚ	ExceptionÚ
isinstanceÚKeyErrorrp   rz   r{   r   Zdeferrr0   Úexit)r}   r•   r"   ÚfilenameÚstylerU   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.
    r5   )Ú
optActionsc                 C   sÄ   t |  ¡ tdƒd�}d}|D ]r}z.t|jƒ | j d|jd›d|j› d�¡ W q t	k
rŒ } z |d 
|j|j|jd	 ¡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¦   ©ÚkeyrH   z    z<4ú	r�   z    !{:<4}	{} ({})
r   Nz.    reactors not available on this platform:

)ÚsortedÚ_getReactorTypesr   r   Z
moduleNameÚmessageOutputÚwriter¦   Údescriptionr+   Úformatrp   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-reactorsNr5   )r	   r   r   Ú
UsageErrorr    )r   r¦   rž   r!   r   r   r   Úopt_reactorü  s    	þÿþÿz!ReactorSelectionMixin.opt_reactorN)r$   r%   r&   r'   r   ÚCompletionsr©   ÚcompDatar0   r1   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ed5d6„ ƒZdS )8ÚServerOptionszQtwistd reads a twisted.application.service.Application out of a file and runs it.rA   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   z•A fully-qualified name to a log observer factory to use for the initial log observer.  Takes precedence over --logfile and --syslog (when available).r)   r6   z7Run in profile mode, dumping results to specified file.rB   r@   z!Name of the profiler to use (%s).z, rt   Ú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)rt   rš   r›   z*.tapz
*.(tac|py)z*.tas)rt   rš   r›   rÁ   )ZmutuallyExclusiver«   c                 O   s4   d| d< d|kr|d | _ ntj | _ tj | ¡ d S )NFrk   r1   )r1   r0   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
        Trk   N)r
   ZsetDebuggingr   ZstartDebugModer_   r   r   r   Ú	opt_debug`  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)r0   Úsettracer   ZspewerÚ	threadingr+   )r   rÈ   r   r   r   Úopt_spewk  s    zServerOptions.opt_spewc                 C   s.   |d krt jdd … pdg}tj | |¡ d S )Nra   z--help)r0   Úargvr   rÄ   ÚparseOptionsrK   r   r   r   rË   w  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 |¡¡‚W 5 d }~X Y nX d S )Nrš   Tr¼   r   z%Logger '{}' could not be imported: {})r�   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   )rF   )Úplugr   r   r   rq   “  rr   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Újoinr?   rE   ZoptParametersr   r¸   ZCompleteFilesÚCompleteDirsr¹   rº   r   Z
getPluginsrÎ   r   rÆ   Zopt_brÉ   rË   rÌ   ÚpropertyrÏ   r   r   r   r   r»     sf   ÿýù
ü	üü
ü

â!üþ

	
r»   c              
   C   sr   |ƒ }z|  ¡  W nR tjk
rd } z2d tjdd… ¡}t|ƒ t|› d|› �ƒ W 5 d }~X Y n
X | |ƒ d S )Nú r   rL   r   )rË   r   ÚerrorrÐ   r0   rÊ   rd   )ZrunAppr»   r}   ZueZcommstrr   r   r   r.   ˜  s    $r.   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•   ÚfileoutZtypeoutZencryptrU   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   rW   ÚafterÚshutdownÚbefore)
rY   r5   r   ZIServiceZstartServicer   rÕ   ZaddSystemEventTriggerrÖ   ZstopService)rU   rÖ   r5   r6   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)rv   ÚSIG_DFLrf   ÚkillÚgetpid)Úsigr   r   r   Ú_exitWithSignal¹  s    rá   )NN)7r�   rf   ri   rv   r0   rz   rQ   Úoperatorr   Ztwistedr   r   r   Ztwisted.applicationr   r   Ztwisted.application.reactorsr   r	   rY   r
   Ztwisted.internet.interfacesr   Ztwisted.persistedr   Ztwisted.pythonr   r   r   r   r   r   Ztwisted.python.reflectr   r   r   r   r(   r9   r?   rG   rj   r€   r„   r…   r†   r”   r©   rª   rÄ   r»   r.   rØ   rÜ   rá   r   r   r   r   Ú<module>   sB    r
3kE}	