
    \dqZ                        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          Z$ G d de$          Z% G d de$          Z& G d d          Z' G d d          Z(d Z)d%dZ*d Z+d Z, G d d          Z-d Z.d Z/ G d d          Z0 G d d ej1        e0          Z2d! Z3d" Z4d# Z5d$ Z6dS )&    N)
attrgetter)	copyrightloggerplugin)reactorsservice)NoSuchReactorinstallReactor)defer)_ISupportsExitSignalCapturing)sob)failureloglogfileruntimeusageutil)namedAnynamedModulequalc                       e Zd ZdZd Z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                 "    || _         || _        d S N)profileOutput	saveStats)selfr   r   s      7lib/python3.11/site-packages/twisted/application/app.py__init__z_BasicProfiler.__init__%   s    *"    c                 :    d| d| }|dz  }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ss       r   _reportImportErrorz!_BasicProfiler._reportImportError)   s6     5v4444	  	 mmr    N)__name__
__module____qualname____doc__r   r'    r    r   r   r      s<         # # #    r    r   c                       e Zd ZdZd ZdS )ProfileRunnerz1
    Runner for the standard profile module.
    c                 N   	 ddl }n-# t          $ r }|                     d|           Y d}~nd}~ww xY w|                                }|                    |j                   | j        r|                    | j                   dS t          j
        t          | j        d          c}t          _
        	 |                                 |t          j
        ct          _
        }|                                 dS # |t          j
        ct          _
        }|                                 w xY w)z:
        Run reactor under the standard profiler.
        r   Nprofilea)r0   ImportErrorr'   Profileruncallrunr   
dump_statsr   sysstdoutopenprint_statsclose)r   reactorr0   r%   ptmps         r   r5   zProfileRunner.run>   s   	2NNNN 	2 	2 	2##Iq11111111	2 OO			'+> 	LL+,,,,,!j$t/A3*G*GOC"%sz
C		 #&sz
C		s    
1,12C5 5/D$Nr(   r)   r*   r+   r5   r,   r    r   r.   r.   9   s-             r    r.   c                       e Zd ZdZd ZdS )CProfileRunnerz)
    Runner for the cProfile module.
    c                    	 ddl }ddl}n-# t          $ r }|                     d|           Y d}~nd}~ww xY w|                                }|                    |j                   | j        r|                    | j	                   dS t          | j	        d          5 }|                    ||          }|                                 |                    d           |                                 ddd           dS # 1 swxY w Y   dS )z:
        Run reactor under the cProfile profiler.
        r   NcProfilew)stream)rC   pstatsr2   r'   r3   r4   r5   r   r6   r   r9   Stats
strip_dirs
sort_statsr:   )r   r<   rC   rG   r%   r=   rE   r&   s           r   r5   zCProfileRunner.runY   s`   	3OOOMMMM 	3 	3 	3##J22222222	3 			'+> 	 LL+,,,,,d(#..  &LL6L22R   	                                   s#    
505AD  DDNr?   r,   r    r   rA   rA   T   s-                  r    rA   c                   "    e Zd ZdZeedZ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}
    )r0   cprofilec                 R   |                     dd          }|                     dd           }|                     dd                                          | _        | j        | j        v r* | j        | j                 ||          }|j        | _        d S t          d| j                   )N	savestatsFr0   profilerrM   zUnsupported profiler name: )getlowerrP   	profilersr5   r#   )r   optionsr   r   rP   s        r   r   zAppProfiler.__init__z   s    KKU33	It44J
;;AACC=DN**4t~dm4]INNH|DHHHJ4=JJKKKr    N)r(   r)   r*   r+   r.   rA   rS   r   r,   r    r   rL   rL   o   sA          *~FFIL L L L Lr    rL   c                   4    e Zd ZdZdZd Zd Zd Zd Z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                 t    |                     dd          | _        |                     d          pd| _        dS )zE
        Initialize an L{AppLogger} with a L{ServerOptions}.
        r    r   N)rQ   _logfilename_observerFactoryr   rT   s     r   r   zAppLogger.__init__   s9     $KK	266 'H 5 5 =r    c                    | j         |                                  }nB|                    t          j        d          }| |                    t          j        d          }||                                 }|| _        t          j                            | j                  r	| j        g}nut          j                            | j                  rt          j        | j                  g}n6t          j
        dt          d           t          j        | 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)rZ   getComponentr   ILogObserverr   _getLogObserver	_observer
providedByLegacyLogObserverWrapperwarningswarnDeprecationWarningglobalLogBeginnerbeginLoggingTo_initialLog)r   applicationobserver	observerss       r   startzAppLogger.start   s;     ,,,..HH"//0CTJJH&33C4DdKK++--H!))$.99 	J(II((88 	J8HHIIIM #     8HHII //	:::r    c                 (   ddl m} t          j        |                               dt
          j        t          j        t          j
                               t          j        |                               dt          |j                             dS )z1
        Print twistd start log message.
        r   r<   z1twistd {version} ({exe} {pyVersion}) starting up.)versionexe	pyVersionzreactor class: {reactor}.N)twisted.internetr<   r   
_loggerForinfor   rq   r7   
executabler   shortPythonVersionr   	__class__)r   r<   s     r   rj   zAppLogger._initialLog   s     	-,,,,,$$$?%022	 	% 	
 	
 	
 	$$$'g6G1H1H 	% 	
 	
 	
 	
 	
r    c                     | j         dk    s| j         st          j        }n$t          j                            | j                   }t          j        |          S )zr
        Create a log observer to be added to the logging system before running
        this application.
        -)rY   r7   r8   r   LogFilefromFullPathr   textFileLogObserver)r   logFiles     r   ra   zAppLogger._getLogObserver   sL    
 ##4+<#jGGo2243DEEG)'222r    c                     t          j        |                               d           | j        -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   ru   rv   rb   globalLogPublisherremoveObserverr   s    r   stopzAppLogger.stop   sX     	$$$%8999>%%44T^DDD!DNNN &%r    )
r(   r)   r*   r+   rb   r   rn   rj   ra   r   r,   r    r   rV   rV      sq         " I> > >0 0 0d
 
 
 	3 	3 	3" " " " "r    rV   c                  ~    d } d }d }|t           j        _        | t           j        _        |t           j        _        d S )Nc                     |                                   |                                  ddlm} |                    d|j                   dS )Nr   rp      )clear_all_breaksset_continuert   r<   	callLaterr   )r   argr<   s      r   do_stopzfixPdb.<locals>.do_stop   sU    ,,,,,,!W\***qr    c                 $    t          d           d S )NzEstop - Continue execution, then cleanly shutdown the twisted reactor.)printr   s    r   	help_stopzfixPdb.<locals>.help_stop   s!    V	
 	
 	
 	
 	
r    c                 .    t          j        d           d S )Nr   )os_exitr   s    r   set_quitzfixPdb.<locals>.set_quit  s    
r    )pdbPdbr   r   r   )r   r   r   s      r   fixPdbr      sT      
 
 

    CGCGO!CGr    c                    |ddl m} 	 | d         r||                    |           dS dS | d         r|t          _        |t          _        t          j        dk    r@t          j        t          j	        d            t          j        t          j
        d            t                       t          j        |j                   dS |                                 dS # t          $ r d	}| d
         r|}nt          dd          }d}	 t!          j        |           |                                 |r|                                 Y dS Y dS # |r|                                 w w xY ww xY 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   rp   r0   debugposixc                  (    t          j                    S r   r   	set_traceargss    r   <lambda>z'runReactorWithLogging.<locals>.<lambda>+  s    CMOO r    c                  (    t          j                    S r   r   r   s    r   r   z'runReactorWithLogging.<locals>.<lambda>,  s    3=?? r    FnodaemonzTWISTD-CRASH.logr1   Tfile)rt   r<   r5   r7   r8   stderrr   platformTypesignalSIGUSR2SIGINTr   r   r4   BaseExceptionr9   	traceback	print_excflushr;   )config	oldstdout	oldstderrrP   r<   r;   r   s          r   runReactorWithLoggingr     s   ( ,,,,,,) 	#W%%%%% $#G_ 		"CJ"CJ#w..fn.K.KLLLfm-J-JKKKHHHK$$$$$KKMMMMM   * 	DD*C00DE	T****JJLLL 

  u 

s/   C BC C )E()E/E(E$$E(c                 2    | rt          j         d          S d S )NzPassphrase: )getpassneededs    r   getPassphraser   @  s     ~...tr    c                 2    | rt          j        d          S d S )NzEncryption passphrase: )r   getPasswordr   s    r   getSavePassphraser   G  s!      9:::tr    c                   >    e Zd ZdZeZeZd Zd Z	d Z
d Zd Z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                 |    || _         |                     |          | _        |                     |          | _        d S r   )r   profilerFactoryrP   loggerFactoryr   )r   r   s     r   r   zApplicationRunner.__init__h  s7    ,,V44((00r    c                     |                                   |                                 | _        | j                            | j                   |                                  | j                                         dS )z&
        Run the application.
        N)preApplicationcreateOrGetApplicationrk   r   rn   postApplicationr   r   s    r   r5   zApplicationRunner.runm  so     	6688$*+++r    c                     |ddl m} t          | j        ||| j        |           t          j        |          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   rp   )rt   r<   r   r   rP   r   rc   _exitSignal)r   r<   r   r   s       r   startReactorzApplicationRunner.startReactory  sh     ?000000dk9iPWXXX(3G<< 	$&2D#Dr    c                     t                      )z
        Override in subclass.

        This should set up any state necessary before loading and
        running the Application.
        NotImplementedErrorr   s    r   r   z ApplicationRunner.preApplication  s     "###r    c                     t                      )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   r   s    r   r   z!ApplicationRunner.postApplication  s     "###r    c                 P   | j         j        rj| j         j        | j         j                 }|                    | j         j                  }t          j        |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loadedPluginsmakeService
subOptionsr   ApplicationtapnamesetServiceParentr   getApplication)r   plgserrk   
passphrases        r   r   z(ApplicationRunner.createOrGetApplication  s     ;! 	B ++DK,BCC//$+"899C!-ck::K  ----&t{;'?@@J(jAAKr    N)r(   r)   r*   r+   rL   r   rV   r   r   r5   r   r   r   r   r,   r    r   r   r   N  s         , "OM1 1 1

 
 
$ $ $ $ $ $$ $ $    r    r   c                 \     fddD             d         }|d         ddi                     |d         |d                   }}	 t          j        d|z             t          j        |||          }t          j        d           n# t
          $ r}d	|z  }t          |t                    r|j        d         d
k    r|dz  }t          j
        t          j                   t          j        |           t          j                     t          j        d|z   dz              Y d }~nd }~ww xY w|S )Nc                 4    g | ]}|         
|         |fS r,   r,   ).0tr   s     r   
<listcomp>z"getApplication.<locals>.<listcomp>  s*    KKKAK&)QKKKr    )pythonsourcer   r   r   pickler   zLoading %s...zLoaded.zFailed to load application: %srk   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   
)rQ   r   msgr   loadApplication	Exception
isinstanceKeyErrorr   r   r   r   deferrr7   exit)r   r   r&   filenamestylerk   r%   s   `      r   r   r     sF   KKKK!=KKKANAdVX.221Q41>>eH"(*+++-hzJJ	 " " ",q0a"" 	qvayM'A'A  A 	----



D!!!!!!!!" s   AB 
D)BD$$D)c                  `    t          j        d t          j                    D                       S )Nc                     g | ]	}|j         
S r,   )	shortName)r   rs     r   r   z"_reactorAction.<locals>.<listcomp>  s    OOOqq{OOOr    )r   CompleteListr   getReactorTypesr,   r    r   _reactorActionr     s+    OOH4L4N4NOOOPPPr    c                   v    e Zd ZdZ ej        dei          Zej	        Z
 eej                  Zd Z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.
    r<   )
optActionsc           	      <   t          |                                 t          d                    }d}|D ]}	 t          |j                   | j                            d|j        dd|j         d           D# t          $ r9}|d
                    |j        |j        |j        d	                   z  }Y d
}~d
}~ww xY w|rN| j                            d           | j                            d           | j                            |           t          d	          )zE
        Display a list of possibly available reactor names.
        r   keyrX   z    z<4	r   z    !{:<4}	{} ({})
r   Nz.    reactors not available on this platform:

)sorted_getReactorTypesr   r   
moduleNamemessageOutputwriter   descriptionr2   formatr   r#   )r   rctsnotWorkingReactorsr   r%   s        r   opt_help_reactorsz'ReactorSelectionMixin.opt_help_reactors  sM    d++--:k3J3JKKK 		 		AAL)))"(()S)S)S)S!-)S)S)STTTT   "&=&D&DKMF1I' ' """"""  	9$$T***$$E   $$%7888mms   A A99
B</B77B<c                     	 t          |           || d<   dS # t          $ r d|d}t          j        |          t          $ r}d|d}t          j        |          d}~ww xY w)zX
        Which reactor to use (see --help-reactors for a list of possibilities)
        r<   z'The specified reactor does not exist: 'z:'.
See the list of available reactors with --help-reactorsz9The specified reactor cannot be used, failed with error: z9.
See the list of available reactors with --help-reactorsN)r
   r	   r   
UsageErrorr   )r   r   r   r%   s       r   opt_reactorz!ReactorSelectionMixin.opt_reactor  s    	(9%%%  (DOOO  	( 	( 	( 	( &/YY1 
 "3''' 	( 	( 	( 	( &'QQ) 
 "3'''	(s    -A$AA$N)r(   r)   r*   r+   r   Completionsr   compDatar7   r8   r   staticmethodr   r   r   r   r  opt_rr,   r    r   r   r     ss          !u Y,GHHHHJM#|H$<==  2( ( (8 EEEr    r   c            
          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                  z  gg dg dg dg dgZ e	j
        dg e	j        d           e	j        d           e	j        d           e	j                    d          Z eej                  Zd Zd ZeZd ZddZd Zed             Zd	S )ServerOptionszQtwistd reads a twisted.application.service.Application out of a file and runs it.)rO   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   NNzA fully-qualified name to a log observer factory to use for the initial log observer.  Takes precedence over --logfile and --syslog (when available).)r0   r=   Nz7Run in profile mode, dumping results to specified file.rP   NrM   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                     d| d<   d|v r|d         | _         nt          j         | _         t          j                            |            d S )NFr   r8   )r8   r7   r   Optionsr   )r   r1   kws      r   r   zServerOptions.__init__Y  sF    Wr>>X,DKK*DKt$$$$$r    c                 ^    t          j        d           t          j                     d| d<   dS )z
        Run the application in the Python Debugger (implies nodaemon),
        sending SIGUSR2 will drop into debugger
        Tr   N)r   setDebuggingr   startDebugModer   s    r   	opt_debugzServerOptions.opt_debuga  s1    
 	4      Wr    c                     t          j        t          j                   	 ddl}n# t
          $ r Y dS w xY 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)r7   settracer   spewer	threadingr2   )r   r  s     r   opt_spewzServerOptions.opt_spewl  sh    
 	T[!!!	 	 	 	FF	4;'''''s   % 
33c                 x    |t           j        dd          pdg}t          j                            | |           d S )Nr   z--help)r7   argvr   r  parseOptionsr[   s     r   r   zServerOptions.parseOptionsx  s;    ?hqrrl0xjG""411111r    c                     | j         s| d         rd| d<   | d         [	 t          | d                   | d<   d S # t          $ r3}t          j        d                    | d         |                    d }~ww xY wd S )Nr   Tr	  r   z%Logger '{}' could not be imported: {})r   r   r   r   r  r   )r   r%   s     r   postOptionszServerOptions.postOptions}  s    ? 	#d8n 	#"DO>%!)$x.!9!9X   &;BB4>STUU   &%s   8 
A5.A00A5c              #      K   |                      t          j                  }i | _        t	          |t          d                    D ]&}|| j        |j        <   |j        d |fd|j        fV  'd S )Nr   r   c                 *    |                                  S r   )rT   )plugs    r   r   z+ServerOptions.subCommands.<locals>.<lambda>  s    $,,.. r    )_getPluginsr   IServiceMakerr   r   r   r   r   )r   pluginsr%  s      r   subCommandszServerOptions.subCommands  s      ""7#8997
9(=(=>>> 
	 
	D/3Dt|, !000     
	 
	r    r   )r(   r)   r*   longdescoptFlagsjoinrL   rS   optParametersr   r  CompleteFilesCompleteDirsr  r  r   
getPluginsr&  r   r  opt_br  r   r"  propertyr)  r,   r    r   r  r    s       	! 	
 	
 	

 	:99FFFH 	HGG	
 	
 	
	
 	
 	
 /$))K<Q2R2RR		
 	@??	
 	
 	
 	TSSMMM=MB !u 78'E'00)e),77)e)'22(e(**	
 
  H ,v011K% % %   E
( 
( 
(2 2 2 2
	 	 	   X  r    r  c                 (    |            }	 |                                   | |           d S # t          j        $ rU}d                    t          j        dd                   }t          |           t          | d|            Y d }~d S d }~ww xY w)N r   r]   r"   )r   r   errorr,  r7   r  r   )runAppr  r   uecommstrs        r   r5   r5     s    ]__F 	v ; " " "((38AaC=))f  B  !!!!!!!!!"s   - BA
BBc                     t          j        | ||          }t          j        |                              |           t          |          }|rd }t          j        |                              ||           d S )N)r   r   )r   r   r   IPersistablesetStyler   save)fileintypeinr   fileouttypeoutencryptrk   s          r   convertStylerB    sy    )&&*EEK[!!**7333"7++J [!!&&J&OOOOOr    c                     ddl m} t          j        |                                            |r1t          j        |           }|                    dd|j        d           |                    ddt          j        |           j	                   d S )Nr   rp   aftershutdownbefore)
rt   r<   r   IServicestartServicer   r:  addSystemEventTriggerr<  stopService)rk   r<  r<   r=   s       r   startApplicationrK    s    (((((([!!..000 O[))%%gz16:NNN!!*g.{;;G    r    c                     t          j         | t           j                   t          j        t          j                    |            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)sigs    r   _exitWithSignalrQ    s6     M#v~&&&GBIKKr    )NN)7r   r   r   r   r7   r   re   operatorr   twistedr   r   r   twisted.applicationr   r   twisted.application.reactorsr	   r
   rt   r   twisted.internet.interfacesr   twisted.persistedr   twisted.pythonr   r   r   r   r   r   twisted.python.reflectr   r   r   r   r.   rA   rL   rV   r   r   r   r   r   r   r   r   r  r  r5   rB  rK  rQ  r,   r    r   <module>rZ     sS    				 



  



            - - - - - - - - - - 1 1 1 1 1 1 1 1 G F F F F F F F " " " " " " E E E E E E ! ! ! ! ! ! F F F F F F F F F F F F F F F F > > > > > > > > > >       <    N   6         ^      6L L L L L L L L,o" o" o" o" o" o" o" o"d" " ",0 0 0 0f    h h h h h h h hV  2Q Q QB B B B B B B BJ{ { { { {EM#8 { { {|	 	 	P P P	 	 		 	 	 	 	r    