U
    ˆj¨4  ã                   @  s„  d 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mZ ddlmZ ddlmZ ddlmZ ddlmZ d	d
lmZmZ d	dlmZ dZdddœdd„Zddddœdd„Zedfdddddœdd„Zefddddœdd„Zdd d!d"œd#d$„ZG d%d!„ d!e ƒZ!G d&d'„ d'e	e"ef ƒZ#dd(dd)œd*d+„Z$dddœd,d-„Z%d.dd/œd0d1„Z&dddœd2d3„Z'd4d4d4efdd5d5d5d6dd7œd8d9„Z(d:S );z&
Tools for formatting logging events.
é    )Úannotations)Údatetime)ÚAnyÚCallableÚIteratorÚMappingÚOptionalÚUnionÚcast)ÚNamedConstant)ÚFixedOffsetTimeZone)ÚFailure)Ú	safe_repré   )Ú
aFormatterÚ
flatFormat)ÚLogEventz%Y-%m-%dT%H:%M:%S%zr   Ústr)ÚeventÚreturnc                 C  s   t | dddd�S )aa  
    Formats an event as text, using the format in C{event["log_format"]}.

    This implementation should never raise an exception; if the formatting
    cannot be done, the returned string will describe the event generically so
    that a useful message is emitted regardless.

    @param event: A logging event.

    @return: A formatted string.
    F)ÚincludeTracebackÚincludeTimestampÚincludeSystem)ÚeventAsText)r   © r   ú:/tmp/pip-unpacked-wheel-j5h_c8_q/twisted/logger/_format.pyÚformatEvent   s    ür   ÚBaseException)r   Úerrorr   c                 C  s\   zdj | |d�W S  tk
rV   tƒ }d dd„ |  ¡ D ƒ¡}dj t|ƒ||d� Y S X dS )	zÑ
    Formats an event as text that describes the event generically and a
    formatting error.

    @param event: A logging event.
    @param error: The formatting error.

    @return: A formatted string.
    z)Unable to format event {event!r}: {error})r   r   z, c                 s  s(   | ] \}}d   t|ƒt|ƒf¡V  qdS )z = N)Újoinr   )Ú.0ÚkeyÚvaluer   r   r   Ú	<genexpr>C   s   ÿz+formatUnformattableEvent.<locals>.<genexpr>zrMESSAGE LOST: unformattable object logged: {error}
Recoverable data: {text}
Exception during formatting:
{failure})r   ÚfailureÚtextN)Úformatr   r   r   Úitemsr   )r   r   r$   r%   r   r   r   ÚformatUnformattableEvent-   s     
 ÿ
þ  ýÿr(   ú-zOptional[float]zOptional[str])ÚwhenÚ
timeFormatÚdefaultr   c                 C  s<   |dks| dkr|S t  | ¡}t | |¡}t| |¡ƒS dS )aÿ  
    Format a timestamp as text.

    Example::

        >>> from time import time
        >>> from twisted.logger import formatTime
        >>>
        >>> t = time()
        >>> formatTime(t)
        u'2013-10-22T14:19:11-0700'
        >>> formatTime(t, timeFormat="%Y/%W")  # Year and week number
        u'2013/42'
        >>>

    @param when: A timestamp.
    @param timeFormat: A time format.
    @param default: Text to return if C{when} or C{timeFormat} is L{None}.

    @return: A formatted time.
    N)r   ZfromLocalTimeStampÚDateTimeÚfromtimestampr   Ústrftime)r*   r+   r,   Útzr   r   r   r   Ú
formatTimeQ   s
    
r1   z Callable[[Optional[float]], str])r   r1   r   c                 C  s(   t | |d�}|sdS | dd¡}|d S )a&  
    Format an event as a line of human-readable text for, e.g. traditional log
    file output.

    The output format is C{"{timeStamp} [{system}] {event}\n"}, where:

        - C{timeStamp} is computed by calling the given C{formatTime} callable
          on the event's C{"log_time"} value

        - C{system} is the event's C{"log_system"} value, if set, otherwise,
          the C{"log_namespace"} and C{"log_level"}, joined by a C{"#"}.  Each
          defaults to C{"-"} is not set.

        - C{event} is the event, as formatted by L{formatEvent}.

    Example::

        >>> from time import time
        >>> from twisted.logger import formatEventAsClassicLogText
        >>> from twisted.logger import LogLevel
        >>>
        >>> formatEventAsClassicLogText(dict())  # No format, returns None
        >>> formatEventAsClassicLogText(dict(log_format="Hello!"))
        u'- [-#-] Hello!\n'
        >>> formatEventAsClassicLogText(dict(
        ...     log_format="Hello!",
        ...     log_time=time(),
        ...     log_namespace="my_namespace",
        ...     log_level=LogLevel.info,
        ... ))
        u'2013-10-22T17:30:02-0700 [my_namespace#info] Hello!\n'
        >>> formatEventAsClassicLogText(dict(
        ...     log_format="Hello!",
        ...     log_time=time(),
        ...     log_system="my_system",
        ... ))
        u'2013-11-11T17:22:06-0800 [my_system] Hello!\n'
        >>>

    @param event: an event.
    @param formatTime: A time formatter

    @return: A formatted event, or L{None} if no output is appropriate.
    )r1   NÚ
z
	)r   Úreplace)r   r1   Ú	eventTextr   r   r   ÚformatEventAsClassicLogTexts   s
    /r5   zCallable[[str], Any]ÚPotentialCallWrapper)r!   Úgetterr   c                 C  s8   |   d¡}|r| dd… n| }||ƒ}|r0|ƒ }t|ƒS )at  
    Check to see if C{key} ends with parentheses ("C{()}"); if not, wrap up the
    result of C{get} in a L{PotentialCallWrapper}.  Otherwise, call the result
    of C{get} first, before wrapping it up.

    @param key: The last dotted segment of a formatting key, as parsed by
        L{Formatter.vformat}, which may end in C{()}.

    @param getter: A function which takes a string and returns some other
        object, to be formatted and stringified for a log.

    @return: A L{PotentialCallWrapper} that will wrap up the result to allow
        for subsequent usages of parens to defer execution to log-format time.
    z()Néþÿÿÿ)Úendswithr6   )r!   r7   ZcallitZrealKeyr"   r   r   r   Úkeycall©   s    
r:   c                   @  sl   e Zd ZdZdddœdd„Zdddœd	d
„Zdddœdd„Zdddœdd„Zddœdd„Zddœdd„Z	dS )r6   z
    Object wrapper that wraps C{getattr()} so as to process call-parentheses
    C{"()"} after a dotted attribute access.
    ÚobjectÚNone)Úwrappedr   c                 C  s
   || _ d S ©N)Ú_wrapped)Úselfr=   r   r   r   Ú__init__Æ   s    zPotentialCallWrapper.__init__r   )Únamer   c                   s   t |‡ fdd„ƒS )Nc                   s   t ˆ j| ƒS r>   )Úgetattrr?   )Zname_©r@   r   r   Ú<lambda>Ê   ó    z2PotentialCallWrapper.__getattr__.<locals>.<lambda>)r:   )r@   rB   r   rD   r   Ú__getattr__É   s    z PotentialCallWrapper.__getattr__c                 C  s   | j | }t|ƒS r>   )r?   r6   )r@   rB   r"   r   r   r   Ú__getitem__Ì   s    
z PotentialCallWrapper.__getitem__)Úformat_specr   c                 C  s   t | j|ƒS r>   )r&   r?   )r@   rI   r   r   r   Ú
__format__Ò   s    zPotentialCallWrapper.__format__©r   c                 C  s
   t | jƒS r>   )Úreprr?   rD   r   r   r   Ú__repr__Õ   s    zPotentialCallWrapper.__repr__c                 C  s
   t | jƒS r>   )r   r?   rD   r   r   r   Ú__str__Ø   s    zPotentialCallWrapper.__str__N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__rA   rG   rH   rJ   rM   rN   r   r   r   r   r6   À   s   c                   @  sL   e Zd ZdZdddœdd„Zddœd	d
„Zddœdd„Zdddœdd„ZdS )ÚCallMappingz¸
    Read-only mapping that turns a C{()}-suffix in key names into an invocation
    of the key rather than a lookup of the key.

    Implementation support for L{formatWithCall}.
    úMapping[str, Any]r<   )Ú
submappingr   c                 C  s
   || _ dS )zo
        @param submapping: Another read-only mapping which will be used to look
            up items.
        N)Ú_submapping)r@   rU   r   r   r   rA   ä   s    zCallMapping.__init__zIterator[Any]rK   c                 C  s
   t | jƒS r>   )ÚiterrV   rD   r   r   r   Ú__iter__ë   s    zCallMapping.__iter__Úintc                 C  s
   t | jƒS r>   )ÚlenrV   rD   r   r   r   Ú__len__î   s    zCallMapping.__len__r   r   )r!   r   c                 C  s   t || jjƒS )z|
        Look up an item in the submapping for this L{CallMapping}, calling it
        if C{key} ends with C{"()"}.
        )r:   rV   rH   )r@   r!   r   r   r   rH   ñ   s    zCallMapping.__getitem__N)rO   rP   rQ   rR   rA   rX   r[   rH   r   r   r   r   rS   Ü   s
   rS   rT   )ÚformatStringÚmappingr   c                 C  s   t t | dt|ƒ¡ƒS )añ  
    Format a string like L{str.format}, but:

        - taking only a name mapping; no positional arguments

        - with the additional syntax that an empty set of parentheses
          correspond to a formatting item that should be called, and its result
          C{str}'d, rather than calling C{str} on the element directly as
          normal.

    For example::

        >>> formatWithCall("{string}, {function()}.",
        ...                dict(string="just a string",
        ...                     function=lambda: "a function"))
        'just a string, a function.'

    @param formatString: A PEP-3101 format string.
    @param mapping: A L{dict}-like object to format.

    @return: The string with formatted values interpolated.
    r   )r   r   ÚvformatrS   )r\   r]   r   r   r   ÚformatWithCallù   s    r_   c              
   C  s°   zzd| krt | ƒW S tttttf  |  dd¡ƒ}|dkr@W dS t|tƒrLn$t|tƒrb| d¡}nt	d|›�ƒ‚t
|| ƒW S  tk
rª } zt| |ƒ W Y ¢S d}~X Y nX dS )ae  
    Formats an event as a string, using the format in C{event["log_format"]}.

    This implementation should never raise an exception; if the formatting
    cannot be done, the returned string will describe the event generically so
    that a useful message is emitted regardless.

    @param event: A logging event.

    @return: A formatted string.
    Zlog_flattenedZ
log_formatNÚ zutf-8zLog format must be str, not )r   r
   r   r	   r   ÚbytesÚgetÚ
isinstanceÚdecodeÚ	TypeErrorr_   r   r(   )r   r&   Úer   r   r   Ú_formatEvent  s    


rg   r   )r$   r   c              
   C  s@   z|   ¡ }W n. tk
r: } zdt|ƒ }W 5 d}~X Y nX |S )a^  
    Format a failure traceback, assuming UTF-8 and using a replacement
    strategy for errors.  Every effort is made to provide a usable
    traceback, but should not that not be possible, a message and the
    captured exception are logged.

    @param failure: The failure to retrieve a traceback from.

    @return: The formatted traceback.
    z((UNABLE TO OBTAIN TRACEBACK FROM EVENT):N)ZgetTracebackr   r   )r$   Ú	tracebackrf   r   r   r   Ú_formatTraceback5  s
    ri   c                 C  s�   t tt |  dd¡ƒ}|dkrft tt |  dd¡ƒ}|dkrBd}n|j}djt t|  dd¡ƒ|d�}n&zt|ƒ}W n tk
rŠ   d}Y nX |S )	a�  
    Format the system specified in the event in the "log_system" key if set,
    otherwise the C{"log_namespace"} and C{"log_level"}, joined by a C{"#"}.
    Each defaults to C{"-"} is not set.  If formatting fails completely,
    "UNFORMATTABLE" is returned.

    @param event: The event containing the system specification.

    @return: A formatted string representing the "log_system" key.
    Z
log_systemNZ	log_levelr)   z{namespace}#{level}Zlog_namespace)Ú	namespaceÚlevelZUNFORMATTABLE)r
   r   r   rb   r   rB   r&   Ú	Exception)r   Úsystemrk   Ú	levelNamer   r   r   Ú_formatSystemG  s    þ
ro   TÚboolzCallable[[float], str])r   r   r   r   r1   r   c           
   	   C  s�   t | ƒ}|r2d| kr2| d }t|ƒ}d ||f¡}|s:|S d}|rbd |tt|  dd¡ƒƒdg¡}d}	|r€d dt| ƒddg¡}	d	j||	|d
�S )ah  
    Format an event as text.  Optionally, attach timestamp, traceback, and
    system information.

    The full output format is:
    C{"{timeStamp} [{system}] {event}\n{traceback}\n"} where:

        - C{timeStamp} is the event's C{"log_time"} value formatted with
          the provided C{formatTime} callable.

        - C{system} is the event's C{"log_system"} value, if set, otherwise,
          the C{"log_namespace"} and C{"log_level"}, joined by a C{"#"}.  Each
          defaults to C{"-"} is not set.

        - C{event} is the event, as formatted by L{formatEvent}.

        - C{traceback} is the traceback if the event contains a
          C{"log_failure"} key.  In the event the original traceback cannot
          be formatted, a message indicating the failure will be substituted.

    If the event cannot be formatted, and no traceback exists, an empty string
    is returned, even if includeSystem or includeTimestamp are true.

    @param event: A logging event.
    @param includeTraceback: If true and a C{"log_failure"} key exists, append
        a traceback.
    @param includeTimestamp: If true include a formatted timestamp before the
        event.
    @param includeSystem:  If true, include the event's C{"log_system"} value.
    @param formatTime: A time formatter

    @return: A formatted string with specified options.

    @since: Twisted 18.9.0
    Zlog_failurer2   r`   Zlog_timeNú ú[ú]z{timeStamp}{system}{eventText})Ú	timeStamprm   r4   )rg   ri   r   r
   Úfloatrb   ro   r&   )
r   r   r   r   r1   r4   Úfrh   rt   rm   r   r   r   r   f  s$    * ýr   N))rR   Ú
__future__r   r   r-   Útypingr   r   r   r   r   r	   r
   Z
constantlyr   Ztwisted.python._tzhelperr   Ztwisted.python.failurer   Ztwisted.python.reflectr   Ú_flattenr   r   Z_interfacesr   ZtimeFormatRFC3339r   r(   r1   r5   r:   r;   r6   r   rS   r_   rg   ri   ro   r   r   r   r   r   Ú<module>   s:   $&ý#ÿ6"!û