o
    ¯bqZ  ã                   @   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   ú9/usr/lib/python3/dist-packages/twisted/application/app.pyÚ__init__%   s   
z_BasicProfiler.__init__c                 C   s    d|› d|› �}|d7 }t |ƒ‚)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.
)Ú
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                   @   ó   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y } z|  d|¡ W Y d}~nd}~ww | ¡ }| |j¡ | jr4| | j¡ dS t	j
t| jdƒ}t	_
z| ¡  W |t	j
t	_
}| ¡  dS |t	j
t	_
}| ¡  w )z:
        Run reactor under the standard profiler.
        r   NÚprofileÚa)r*   ÚImportErrorr#   ÚProfileÚruncallÚrunr   Ú
dump_statsr   ÚsysÚstdoutÚopenÚprint_statsÚclose)r   Úreactorr*   r!   ÚpÚtmpr   r   r   r/   >   s"   €ÿ
ÿ
zProfileRunner.runN©r$   r%   r&   r'   r/   r   r   r   r   r)   9   ó    r)   c                   @   r(   )ÚCProfileRunnerz)
    Runner for the cProfile module.
    c              
   C   sÊ   z
ddl }ddl}W n ty" } z|  d|¡ W Y d}~nd}~ww | ¡ }| |j¡ | jr8| | j	¡ dS t
| j	dƒ�}|j||d�}| ¡  | d¡ | ¡  W d  ƒ dS 1 s^w   Y  dS )z:
        Run reactor under the cProfile profiler.
        r   NÚcProfileÚw)Ústreaméÿÿÿÿ)r<   Úpstatsr,   r#   r-   r.   r/   r   r0   r   r3   ÚStatsÚ
strip_dirsÚ
sort_statsr4   )r   r6   r<   r@   r!   r7   r>   r"   r   r   r   r/   Y   s"   €ÿ

"üzCProfileRunner.runNr9   r   r   r   r   r;   T   r:   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   sd   |  dd¡}|  dd ¡}|  dd¡ ¡ | _| j| jv r*| j| j ||ƒ}|j| _d S td| j› �ƒ‚)NÚ	savestatsFr*   ÚprofilerrE   zUnsupported profiler name: )ÚgetÚlowerrG   Ú	profilersr/   r   )r   Úoptionsr   r   rG   r   r   r   r   z   s   zAppProfiler.__init__N)r$   r%   r&   r'   r)   r;   rJ   r   r   r   r   r   rD   o   s    
rD   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)rH   Ú_logfilenameÚ_observerFactory©r   rK   r   r   r   r   ™   s   zAppLogger.__init__c                 C   sº   | j dur
|   ¡ }n| tjd¡}|du r| tjd¡}|du r$|  ¡ }|| _tj | j¡r3| jg}ntj | j¡rBt | 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)rO   ÚgetComponentr   ÚILogObserverr   Ú_getLogObserverÚ	_observerÚ
providedByÚLegacyLogObserverWrapperÚwarningsÚwarnÚDeprecationWarningÚglobalLogBeginnerÚbeginLoggingToÚ_initialLog)r   ÚapplicationÚobserverÚ	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   ©r6   z1twistd {version} ({exe} {pyVersion}) starting up.)ÚversionÚexeÚ	pyVersionzreactor class: {reactor}.N)Útwisted.internetr6   r   Ú
_loggerForÚinfor   rd   r1   Ú
executabler   ÚshortPythonVersionr   Ú	__class__)r   r6   r   r   r   r^   Ò   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.
        ú-)rN   r1   r2   r   ÚLogFileÚfromFullPathr   ÚtextFileLogObserver)r   ÚlogFiler   r   r   rU   â   s   
zAppLogger._getLogObserverc                 C   s6   t  | ¡ d¡ | jdurt j | j¡ d| _dS dS )zS
        Remove all log observers previously set up by L{AppLogger.start}.
        zServer Shut Down.N)r   rh   ri   rV   ÚglobalLogPublisherÚremoveObserver©r   r   r   r   Ústopí   s
   

þzAppLogger.stop)
r$   r%   r&   r'   rV   r   rb   r^   rU   ru   r   r   r   r   rL   …   s    2rL   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   rc   é   )Úclear_all_breaksÚset_continuerg   r6   Ú	callLaterru   )r   Úargr6   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.)Úprintrt   r   r   r   Ú	help_stop   s   ÿzfixPdb.<locals>.help_stopc                 S   s   t  d¡ d S )Nr   )ÚosÚ_exitrt   r   r   r   Úset_quit  s   zfixPdb.<locals>.set_quit)ÚpdbÚPdbr€   r{   r}   )r{   r}   r€   r   r   r   ÚfixPdb÷   s   rƒ   c                 C   s  |du r
ddl m} zG| d r|dur| |¡ W dS W dS | d rK|t_|t_tjdkr?t tj	dd„ ¡ t tj
d	d„ ¡ tƒ  t |j¡ W dS | ¡  W dS  tyˆ   d
}| d ra|}ntddƒ}d}ztj|d� | ¡  W |r}| ¡  Y dS Y dS |r‡| ¡  w w w )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   rc   r*   ÚdebugÚposixc                  W   ó   t  ¡ S r   ©r�   Ú	set_trace©Úargsr   r   r   Ú<lambda>+  ó    z'runReactorWithLogging.<locals>.<lambda>c                  W   r†   r   r‡   r‰   r   r   r   r‹   ,  rŒ   FÚnodaemonzTWISTD-CRASH.logr+   T©Úfile)rg   r6   r/   r1   r2   Ústderrr   ÚplatformTypeÚsignalÚSIGUSR2ÚSIGINTrƒ   r�   r.   ÚBaseExceptionr3   Ú	tracebackÚ	print_excÚflushr5   )ÚconfigÚ	oldstdoutÚ	oldstderrrG   r6   r5   r�   r   r   r   ÚrunReactorWithLogging  s>   ÿ



ÿ
ÿõrœ   c                 C   s   | rt   d¡S d S )NzPassphrase: )Úgetpass©Úneededr   r   r   ÚgetPassphrase@  ó   
r    c                 C   s   | rt  d¡S d S )NzEncryption passphrase: )r   ÚgetPasswordrž   r   r   r   ÚgetSavePassphraseG  r¡   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™   ÚprofilerFactoryrG   Ú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ÚcreateOrGetApplicationr_   r   rb   ÚpostApplicationru   rt   r   r   r   r/   m  s
   
zApplicationRunner.runc                 C   sH   |du r
ddl m} t| j||| j|ƒ t |¡r|j| _dS d| _dS )z®
        Run the reactor with the given configuration.  Subclasses should
        probably call this from C{postApplication}.

        @see: L{runReactorWithLogging}
        Nr   rc   )rg   r6   rœ   r™   rG   r   rW   Ú_exitSignal)r   r6   rš   r›   r   r   r   ÚstartReactory  s   

zApplicationRunner.startReactorc                 C   ó   t ƒ ‚)z‹
        Override in subclass.

        This should set up any state necessary before loading and
        running the Application.
        ©ÚNotImplementedErrorrt   r   r   r   r§   ‰  s   z ApplicationRunner.preApplicationc                 C   r¬   )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.
        r­   rt   r   r   r   r©   ’  s   z!ApplicationRunner.postApplicationc                 C   s^   | j jr | j j| j j }| | j j¡}t |j¡}| |¡ |S 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ÚloadedPluginsÚmakeServiceÚ
subOptionsr   ÚApplicationÚtapnameÚsetServiceParentr    ÚgetApplication)r   ÚplgÚserr_   Ú
passphraser   r   r   r¨   œ  s   
þz(ApplicationRunner.createOrGetApplicationN)r$   r%   r&   r'   rD   r¥   rL   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 |S  tyr } z4d
| }t|tƒrN|jd dkrN|d7 }t	j
tjd� t |¡ t ¡  t d| d ¡ W Y d }~|S d }~ww )Nc                    s    g | ]}ˆ | rˆ | |f‘qS r   r   )Ú.0Út©r™   r   r   Ú
<listcomp>º  s     z"getApplication.<locals>.<listcomp>)ÚpythonÚsourcer�   r   r�   Úpicklerv   zLoading %s...zLoaded.zFailed to load application: %sr_   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.
rŽ   Ú
)rH   r   Úmsgr   ÚloadApplicationÚ	ExceptionÚ
isinstanceÚKeyErrorrŠ   r–   r—   r   Údeferrr1   Úexit)r™   rº   r"   ÚfilenameÚstyler_   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   Ú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.
    r6   )Ú
optActionsc                 C   sÀ   t |  ¡ tdƒd�}d}|D ]9}zt|jƒ | j d|jd›d|j› d�¡ W q t	yG } z|d 
|j|j|jd	 ¡7 }W Y d
}~qd
}~ww |r\| j d¡ | j d¡ | j |¡ td	ƒ‚)zE
        Display a list of possibly available reactor names.
        rÌ   ©ÚkeyrM   z    z<4ú	rÂ   z    !{:<4}	{} ({})
r   Nz.    reactors not available on this platform:

)ÚsortedÚ_getReactorTypesr   r   Ú
moduleNameÚmessageOutputÚwriterÌ   Údescriptionr,   ÚformatrŠ   r   )r   ÚrctsÚnotWorkingReactorsrÍ   r!   r   r   r   Úopt_help_reactorsã  s*   
$ý€ÿÿz'ReactorSelectionMixin.opt_help_reactorsc              
   C   sf   zt |ƒ W n& ty   d|f }t |¡‚ ty, } z
d|f }t |¡‚d}~ww || 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-reactorsNr6   )r	   r   r   Ú
UsageErrorrÅ   )r   rÌ   rÃ   r!   r   r   r   Úopt_reactorü  s"   	þÿ
þÿ
€úz!ReactorSelectionMixin.opt_reactorN)r$   r%   r&   r'   r   ÚCompletionsrÐ   ÚcompDatar1   r2   rÙ   Ústaticmethodr   rÏ   r×   rß   rá   Úopt_rr   r   r   r   rÑ   Ö  s    
rÑ   c                
   @   sÞ   e Zd ZdZg d¢g d¢g d¢gZg d¢g d¢g d¢dd	d
dd ej¡ gg d¢g d¢g d¢g d¢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d„ Zd#dd„Zdd „ Zed!d"„ ƒZd	S )$ÚServerOptionszQtwistd reads a twisted.application.service.Application out of a file and runs it.)rF   NzBsave the Stats object rather than the text output of the profiler.)Úno_saveÚozdo not save state on shutdown)r¯   r!   z(The specified tap/aos file is encrypted.)r   ÚlNz%log to a specified file, - for stdout)r   NNz•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*   r7   Nz7Run in profile mode, dumping results to specified file.rG   NrE   z!Name of the profiler to use (%s).z, )r�   Úfz
twistd.tapzread the given .tap file)r¿   ÚyNz:read an application from within a Python file (implies -o))rÀ   r"   Nz2Read an application from a .tas file (AOT format).)ÚrundirÚdÚ.z-Change to a supplied directory before running)r�   r¿   rÀ   z*.tapz
*.(tac|py)z*.tas)r�   r¿   rÀ   rì   )ÚmutuallyExclusiverÒ   c                 O   s4   d| d< d|v r|d | _ ntj | _ tj | ¡ d S )NFr„   r2   )r2   r1   r   ÚOptionsr   )r   r+   Úkwr   r   r   r   Y  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
        Tr„   N)r
   ÚsetDebuggingr   ÚstartDebugModert   r   r   r   Ú	opt_debuga  s   
zServerOptions.opt_debugc                 C   s>   t  tj¡ zddl}W n
 ty   Y dS w | 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)r1   Úsettracer   ÚspewerÚ	threadingr,   )r   r÷   r   r   r   Úopt_spewl  s   ÿzServerOptions.opt_spewc                 C   s.   |d u rt jdd … pdg}tj | |¡ d S )Nrv   z--help)r1   Úargvr   rð   ÚparseOptionsrP   r   r   r   rú   x  s   zServerOptions.parseOptionsc              
   C   sl   | j s| d rd| d< | d d ur4zt| d ƒ| d< W d S  ty3 } zt d | d |¡¡‚d }~ww 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   sT   � |   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   )rK   )Úplugr   r   r   r‹   ”  rŒ   z+ServerOptions.subCommands.<locals>.<lambda>)Ú_getPluginsr   ÚIServiceMakerr±   rÖ   r   rµ   rÛ   )r   Úpluginsrü   r   r   r   ÚsubCommandsˆ  s   €
ùþzServerOptions.subCommandsr   )r$   r%   r&   ÚlongdescÚoptFlagsÚjoinrD   rJ   ÚoptParametersr   râ   ÚCompleteFilesÚCompleteDirsrã   rä   r   Ú
getPluginsrý   r   rô   Úopt_brø   rú   rû   Úpropertyr   r   r   r   r   ræ     sJ    ÿùüâ!üþ

	
ræ   c              
   C   sv   |ƒ }z|  ¡  W n+ tjy4 } zd tjdd… ¡}t|ƒ t|› d|› �ƒ W Y d }~d S d }~ww | |ƒ d S )Nú r   rQ   r   )rú   r   Úerrorr  r1   rù   r|   )ÚrunAppræ   r™   ÚueÚ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   ÚIPersistableÚsetStyler£   Úsave)ÚfileinÚtypeinrº   ÚfileoutÚtypeoutÚencryptr_   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   rc   ÚafterÚshutdownÚbefore)
rg   r6   r   ÚIServiceÚstartServicer   r  ÚaddSystemEventTriggerr  ÚstopService)r_   r  r6   r7   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)r’   ÚSIG_DFLr~   ÚkillÚgetpid)Úsigr   r   r   Ú_exitWithSignalº  s   r$  )NN)7r�   r~   r�   r’   r1   r–   rY   Úoperatorr   Útwistedr   r   r   Útwisted.applicationr   r   Útwisted.application.reactorsr   r	   rg   r
   Útwisted.internet.interfacesr   Útwisted.persistedr   Útwisted.pythonr   r   r   r   r   r   Útwisted.python.reflectr   r   r   r   r)   r;   rD   rL   rƒ   rœ   r    r£   r¤   r·   rÐ   rÑ   rð   ræ   r/   r  r  r$  r   r   r   r   Ú<module>   sD    r
3kE~	