U
    �AcjØ?  ã                   @  sÔ   d 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 ddlmZ dd	lmZmZ dd
lmZmZ G dd„ deƒZG dd„ dƒZG dd„ dƒZG dd„ dƒZeƒ Zdddœdd„ZdS )z
Logger class.
é    )Úannotations)Útime)ÚTracebackType)ÚAnyÚCallableÚContextManagerÚOptionalÚProtocolÚcast)Úcurrentframe)ÚFailureé   )ÚILogObserverÚLogTrace)ÚInvalidLogLevelErrorÚLogLevelc                   @  sF   e Zd ZdZeddœdd„ƒZeddœdd„ƒZeddœd	d
„ƒZdS )Ú	Operationz™
    An L{Operation} represents the success (or lack thereof) of code performed
    within the body of the L{Logger.failureHandler} context manager.
    Úbool©Úreturnc                 C  s   dS )zÅ
        Did the operation succeed?  C{True} iff the code completed without
        raising an exception; C{False} while the code is running and C{False}
        if it raises an exception.
        N© ©Úselfr   r   ú:/tmp/pip-unpacked-wheel-nrvc_22y/twisted/logger/_logger.pyÚ	succeeded   s    zOperation.succeededúFailure | Nonec                 C  s   dS )zj
        Did the operation raise an exception?  If so, this L{Failure} is that
        exception.
        Nr   r   r   r   r   Úfailure#   s    zOperation.failurec                 C  s   dS )z³
        Did the operation fail?  C{True} iff the code raised an exception;
        C{False} while the code is running and C{False} if it completed without
        error.
        Nr   r   r   r   r   Úfailed*   s    zOperation.failedN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úpropertyr   r   r   r   r   r   r   r      s   r   c                   @  sj   e Zd ZU dZded< dZded< ddd	œd
d„Zeddœdd„ƒZddœdd„Z	dddddœdd„Z
dS )Ú_FailCtxMgrFr   r   Nr   r   úCallable[[Failure], None]ÚNone©Úfailr   c                 C  s
   || _ d S ©N©Ú_fail©r   r'   r   r   r   Ú__init__7   s    z_FailCtxMgr.__init__r   c                 C  s
   | j d k	S r(   ©r   r   r   r   r   r   :   s    z_FailCtxMgr.failedr   c                 C  s   | S r(   r   r   r   r   r   Ú	__enter__>   s    z_FailCtxMgr.__enter__útype[BaseException] | NoneúBaseException | NoneúTracebackType | None©Úexc_typeÚ	exc_valueÚ	tracebackr   c                C  s*   |d k	r t ƒ }|| _|  |¡ nd| _dS ©NT)r   r   r*   r   ©r   r3   r4   r5   r   r   r   r   Ú__exit__A   s    z_FailCtxMgr.__exit__)r   r   r    r   Ú__annotations__r   r,   r"   r   r.   r8   r   r   r   r   r#   3   s   
r#   c                   @  s>   e Zd Zdddœdd„Zddœdd„Zd	d
dddœdd„ZdS )Ú_FastFailCtxMgrr$   r%   r&   c                 C  s
   || _ d S r(   r)   r+   r   r   r   r,   R   s    z_FastFailCtxMgr.__init__r   c                 C  s   d S r(   r   r   r   r   r   r.   U   s    z_FastFailCtxMgr.__enter__r/   r0   r1   r   r2   c                C  s"   |d k	rt ƒ }|| _|  |¡ dS r6   )r   r   r*   r7   r   r   r   r8   X   s
    
z_FastFailCtxMgr.__exit__N)r   r   r    r,   r.   r8   r   r   r   r   r:   Q   s   r:   c                   @  s$  e Zd ZdZeddœdd„ƒZd1ddd	d
dœdd„Zd2ddddœdd„Zddœdd„Zd3dddd
dœdd„Z	de
jfddddd
dœdd„Zd4ddd
dœdd „Zd5ddd
dœd!d"„Zd6ddd
dœd#d$„Zd7ddd
dœd%d&„Zd8ddd
dœd'd(„Ze
jfdddd)d*œd+d,„Ze
jfddd-d.œd/d0„ZdS )9ÚLoggera~  
    A L{Logger} emits log messages to an observer.  You should instantiate it
    as a class or module attribute, as documented in L{this module's
    documentation <twisted.logger>}.

    @ivar namespace: the namespace for this logger
    @ivar source: The object which is emitting events via this logger
    @ivar observer: The observer that this logger will send events to.
    Ústrr   c                   C  s2   zt ttdƒjd ƒW S  tk
r,   Y dS X dS )z“
        Derive a namespace from the module containing the caller's caller.

        @return: the fully qualified python name of a module.
        é   r   z	<unknown>N)r
   r<   r   Ú	f_globalsÚKeyErrorr   r   r   r   Ú_namespaceFromCallingContextq   s    z#Logger._namespaceFromCallingContextNzOptional[str]zOptional[object]zOptional['ILogObserver']r%   )Ú	namespaceÚsourceÚobserverr   c                 C  sB   |dkr|   ¡ }|| _|| _|dkr8ddlm} || _n|| _dS )a3  
        @param namespace: The namespace for this logger.  Uses a dotted
            notation, as used by python modules.  If not L{None}, then the name
            of the module of the caller is used.
        @param source: The object which is emitting events via this
            logger; this is automatically set on instances of a class
            if this L{Logger} is an attribute of that class.
        @param observer: The observer that this logger will send events to.
            If L{None}, use the L{global log publisher <globalLogPublisher>}.
        Nr   )ÚglobalLogPublisher)r@   rA   rB   Z_globalrD   rC   )r   rA   rB   rC   rD   r   r   r   r,   }   s    zLogger.__init__ÚobjectzOptional[type]z'Logger')ÚinstanceÚownerr   c                 C  s>   |dk	st ‚|dkr|}n|}| jd |j|jg¡|| jd�S )a‡  
        When used as a descriptor, i.e.::

            # File: athing.py
            class Something:
                log = Logger()
                def hello(self):
                    self.log.info("Hello")

        a L{Logger}'s namespace will be set to the name of the class it is
        declared on.  In the above example, the namespace would be
        C{athing.Something}.

        Additionally, its source will be set to the actual object referring to
        the L{Logger}.  In the above example, C{Something.log.source} would be
        C{Something}, and C{Something().log.source} would be an instance of
        C{Something}.
        NÚ.)rC   )ÚAssertionErrorÚ	__class__Újoinr   r   rC   )r   rF   rG   rB   r   r   r   Ú__get__š   s    ýzLogger.__get__c                 C  s   d| j j› d| j›d�S )Nú<ú ú>)rJ   r   rA   r   r   r   r   Ú__repr__º   s    zLogger.__repr__r   )ÚlevelÚformatÚkwargsr   c                 K  sz   |t  ¡ kr*| jdtt|ƒƒ|| d� dS |}|j| || j| j|tƒ d� d|krlt	t
|d ƒ | | jf¡ |  |¡ dS )a  
        Emit a log event to all log observers at the given level.

        @param level: a L{LogLevel}
        @param format: a message format using new-style (PEP 3101)
            formatting.  The logging event (which is a L{dict}) is
            used to render this format string.
        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        z:Got invalid log level {invalidLevel!r} in {logger}.emit().)ZinvalidLevelÚloggerN)Z
log_loggerZ	log_levelZlog_namespaceZ
log_sourceZ
log_formatZlog_timeZ	log_trace)r   Ziterconstantsr   r   r   ÚupdaterA   rB   r   r
   r   ÚappendrC   )r   rQ   rR   rS   Úeventr   r   r   Úemit½   s(    
üú	zLogger.emitzOptional[Failure])rR   r   rQ   rS   r   c                 K  s*   |dkrt ƒ }| j||fd|i|—Ž dS )am  
        Log a failure and emit a traceback.

        For example::

            try:
                frob(knob)
            except Exception:
                log.failure("While frobbing {knob}", knob=knob)

        or::

            d = deferredFrob(knob)
            d.addErrback(lambda f: log.failure("While frobbing {knob}",
                                               f, knob=knob))

        This method is meant to capture unexpected exceptions in code; an
        exception that is caught and handled somehow should be logged, if
        appropriate, via L{Logger.error} instead.  If some unknown exception
        occurs and your code doesn't know how to handle it, as in the above
        example, then this method provides a means to describe the failure.
        This is done at L{LogLevel.critical} by default, since no corrective
        guidance can be offered to an user/administrator, and the impact of the
        condition is unknown.

        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.

        @param failure: a L{Failure} to log.  If L{None}, a L{Failure} is
            created from the exception in flight.

        @param level: a L{LogLevel} to use.

        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.

        @see: L{Logger.failureHandler}

        @see: L{Logger.failuresHandled}
        NZlog_failure)r   rX   )r   rR   r   rQ   rS   r   r   r   r   ä   s    2zLogger.failure)rR   rS   r   c                 K  s   | j tj|f|Ž dS )að  
        Emit a log event at log level L{LogLevel.debug}.

        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.

        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        N)rX   r   Údebug©r   rR   rS   r   r   r   rY     s    zLogger.debugc                 K  s   | j tj|f|Ž dS )aï  
        Emit a log event at log level L{LogLevel.info}.

        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.

        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        N)rX   r   ÚinforZ   r   r   r   r[   *  s    zLogger.infoc                 K  s   | j tj|f|Ž dS )aï  
        Emit a log event at log level L{LogLevel.warn}.

        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.

        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        N)rX   r   ÚwarnrZ   r   r   r   r\   9  s    zLogger.warnc                 K  s   | j tj|f|Ž dS )að  
        Emit a log event at log level L{LogLevel.error}.

        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.

        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        N)rX   r   ÚerrorrZ   r   r   r   r]   H  s    zLogger.errorc                 K  s   | j tj|f|Ž dS )aó  
        Emit a log event at log level L{LogLevel.critical}.

        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.

        @param kwargs: additional key/value pairs to include in the event.
            Note that values which are later mutated may result in
            non-deterministic behavior from observers that schedule work for
            later execution.
        N)rX   r   ÚcriticalrZ   r   r   r   r^   W  s    zLogger.criticalzContextManager[Operation])rR   rQ   rS   r   c                   s   t ‡ ‡‡‡fdd„ƒS )a/  
        Run some application code, logging a failure and emitting a traceback
        in the event that any of it fails, but continuing on.  For example::

            log = Logger(...)

            def frameworkCode() -> None:
                with log.failuresHandled("While frobbing {knob}:", knob=knob) as op:
                    frob(knob)
                if op.succeeded:
                    log.info("frobbed {knob} successfully", knob=knob)

        This method is meant to capture unexpected exceptions from application
        code; an exception that is caught and handled somehow should be logged,
        if appropriate, via L{Logger.error} instead.  If some unknown exception
        occurs and your code doesn't know how to handle it, as in the above
        example, then this method provides a means to describe the failure.
        This is done at L{LogLevel.critical} by default, since no corrective
        guidance can be offered to an user/administrator, and the impact of the
        condition is unknown.

        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.

        @param level: a L{LogLevel} to use.

        @param kwargs: additional key/value pairs to include in the event, if
            it is emitted.  Note that values which are later mutated may result
            in non-deterministic behavior from observers that schedule work for
            later execution.

        @see: L{Logger.failure}
        @see: L{Logger.failureHandler}

        @return: A context manager which yields an L{Operation} which will have
            either its C{succeeded} or C{failed} attribute set to C{True} upon
            completion of the code within the code within the C{with} block.
        c                   s   ˆj ˆ | ˆfˆŽS r(   r-   ©Úf©rR   rS   rQ   r   r   r   Ú<lambda>�  ó    z(Logger.failuresHandled.<locals>.<lambda>)r#   )r   rR   rQ   rS   r   ra   r   ÚfailuresHandledf  s    *zLogger.failuresHandledzContextManager[None])ÚstaticMessagerQ   r   c                   s   t ‡ ‡‡fdd„ƒS )aª  
        For performance-sensitive frameworks that needs to handle potential
        failures from frequently-called application code, and do not need to
        include detailed structured information about the failure nor inspect
        the result of the operation, this method returns a context manager that
        will log exceptions and continue, that can be shared across multiple
        invocations.  It should be instantiated at module scope to avoid
        additional object creations.

        For example::

            log = Logger(...)
            ignoringFrobErrors = log.failureHandler("while frobbing:")

            def hotLoop() -> None:
                with ignoringFrobErrors:
                    frob()

        This method is meant to capture unexpected exceptions from application
        code; an exception that is caught and handled somehow should be logged,
        if appropriate, via L{Logger.error} instead.  If some unknown exception
        occurs and your code doesn't know how to handle it, as in the above
        example, then this method provides a means to describe the failure in
        nerd-speak.  This is done at L{LogLevel.critical} by default, since no
        corrective guidance can be offered to an user/administrator, and the
        impact of the condition is unknown.

        @param format: a message format using new-style (PEP 3101) formatting.
            The logging event (which is a L{dict}) is used to render this
            format string.

        @param level: a L{LogLevel} to use.

        @see: L{Logger.failure}

        @return: A context manager which does not return a value, but will
            always exit from exceptions.
        c                   s   ˆ  ˆ| ˆ ¡S r(   r-   r_   ©rQ   r   re   r   r   rb   ½  rc   z'Logger.failureHandler.<locals>.<lambda>)r:   )r   re   rQ   r   rf   r   ÚfailureHandler’  s    +zLogger.failureHandler)NNN)N)N)N)N)N)N)N)r   r   r    r!   Ústaticmethodr@   r,   rL   rP   rX   r   r^   r   rY   r[   r\   r]   rd   rg   r   r   r   r   r;   f   s.   
   ü  ÿ*ü7ÿ/ýr;   rE   )Úobjr   c                 C  s   t  | | j¡S )z?
    Get a L{Logger} instance attached to the given class.
    )Ú_logrL   rJ   )ri   r   r   r   Ú
_loggerForÃ  s    rk   N)r!   Ú
__future__r   r   Útypesr   Útypingr   r   r   r   r	   r
   Ztwisted.python.compatr   Ztwisted.python.failurer   Z_interfacesr   r   Z_levelsr   r   r   r#   r:   r;   rj   rk   r   r   r   r   Ú<module>   s       \