U
    \[0                     @   s   d 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
 ddlmZmZ d	Zd
d Zdd ZedfddZefddZG dd deZdd Zdd Zdd Zdd ZdddefddZd S )!z&
Tools for formatting logging events.
    )datetime)unicode)Failure)	safe_repr)FixedOffsetTimeZone   )
flatFormat
aFormatterz%Y-%m-%dT%H:%M:%S%zc                 C   s   t | ddddS )  
    Formats an event as a L{unicode}, 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.
    @type event: L{dict}

    @return: A formatted string.
    @rtype: L{unicode}
    F)includeTracebackincludeTimestampincludeSystem)eventAsText)event r   8/usr/lib/python3/dist-packages/twisted/logger/_format.pyformatEvent   s    r   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 )	a(  
    Formats an event as a L{unicode} that describes the event generically and a
    formatting error.

    @param event: A logging event.
    @type event: L{dict}

    @param error: The formatting error.
    @type error: L{Exception}

    @return: A formatted string.
    @rtype: L{unicode}
    z)Unable to format event {event!r}: {error})r   errorz, c                 s   s(   | ] \}}d  t|t|fV  qdS )z = N)joinr   ).0keyvaluer   r   r   	<genexpr>I   s   z+formatUnformattableEvent.<locals>.<genexpr>zrMESSAGE LOST: unformattable object logged: {error}
Recoverable data: {text}
Exception during formatting:
{failure})r   failuretextN)formatBaseExceptionr   r   itemsr   )r   r   r   r   r   r   r   formatUnformattableEvent.   s"     
  r   -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.
    @type then: L{float}

    @param timeFormat: A time format.
    @type timeFormat: L{unicode} or L{None}

    @param default: Text to return if C{when} or C{timeFormat} is L{None}.
    @type default: L{unicode}

    @return: A formatted time.
    @rtype: L{unicode}
    N)r   ZfromLocalTimeStampDateTimeZfromtimestampr   strftime)ZwhenZ
timeFormatdefaultZtzr   r   r   r   
formatTimeW   s
    
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{u"{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{u"#"}.  Each
          defaults to C{u"-"} is not set.

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

    Example::

        >>> from __future__ import print_function
        >>> from time import time
        >>> from twisted.logger import formatEventAsClassicLogText
        >>> from twisted.logger import LogLevel
        >>>
        >>> formatEventAsClassicLogText(dict())  # No format, returns None
        >>> formatEventAsClassicLogText(dict(log_format=u"Hello!"))
        u'- [-#-] Hello!\n'
        >>> formatEventAsClassicLogText(dict(
        ...     log_format=u"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=u"Hello!",
        ...     log_time=time(),
        ...     log_system="my_system",
        ... ))
        u'2013-11-11T17:22:06-0800 [my_system] Hello!\n'
        >>>

    @param event: an event.
    @type event: L{dict}

    @param formatTime: A time formatter
    @type formatTime: L{callable} that takes an C{event} argument and returns
        a L{unicode}

    @return: A formatted event, or L{None} if no output is appropriate.
    @rtype: L{unicode} or L{None}
    )r#   N
z
	)r   replace)r   r#   	eventTextr   r   r   formatEventAsClassicLogText|   s
    3r'   c                   @   s    e Zd ZdZdd Z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}.
    c                 C   s
   || _ dS )zo
        @param submapping: Another read-only mapping which will be used to look
            up items.
        N)_submapping)selfZ
submappingr   r   r   __init__   s    zCallMapping.__init__c                 C   s6   | d}|r|dd n|}| j| }|r2| }|S )z|
        Look up an item in the submapping for this L{CallMapping}, calling it
        if C{key} ends with C{"()"}.
        z()N)endswithr)   )r*   r   ZcallitZrealKeyr   r   r   r   __getitem__   s    

zCallMapping.__getitem__N)__name__
__module____qualname____doc__r+   r.   r   r   r   r   r(      s   r(   c                 C   s   t t| dt|S )a0  
    Format a string like L{unicode.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.
    @type formatString: L{unicode}

    @param mapping: A L{dict}-like object to format.

    @return: The string with formatted values interpolated.
    @rtype: L{unicode}
    r   )r   r	   Zvformatr(   )ZformatStringmappingr   r   r   formatWithCall   s    r4   c              
   C   s   zfd| krt | W S | dd}|dkr.W dS t|trD|d}nt|ts\td|t|| W S  t	k
r } zt
| | W Y S d}~X Y nX dS )r
   Zlog_flattenedZ
log_formatN utf-8z.Log format must be unicode or bytes, not {0!r})r   get
isinstancebytesdecoder   	TypeErrorr   r4   r   r   )r   r   er   r   r   _formatEvent   s    


r=   c              
   C   sX   z$|   }t|tr"|jddd}W n. tk
rR } 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.
    @type failure: L{twisted.python.failure.Failure}

    @return: The formatted traceback.
    @rtype: L{unicode}
    r6   r%   )errorsz((UNABLE TO OBTAIN TRACEBACK FROM EVENT):N)ZgetTracebackr8   r9   r:   r   r   )r   	tracebackr<   r   r   r   _formatTraceback  s    

r@   c                 C   sv   |  dd}|dkrL|  dd}|dkr.d}n|j}dj|  dd|d}n&zt|}W n tk
rp   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{u"#"}.
    Each defaults to C{u"-"} is not set.  If formatting fails completely,
    "UNFORMATTABLE" is returned.

    @param event: The event containing the system specification.
    @type event: L{dict}

    @return: A formatted string representing the "log_system" key.
    @rtype: L{unicode}
    Z
log_systemNZ	log_levelr   z{namespace}#{level}Zlog_namespace)	namespacelevelZUNFORMATTABLE)r7   namer   r   	Exception)r   systemrB   Z	levelNamer   r   r   _formatSystem4  s    

rF   Tc           
      C   s   t | }|r2d| kr2| d }t|}d||f}|s:|S d}|r\d|| dddg}d}	|rzddt| ddg}	d	j||	|d
S )aw  
    Format an event as a unicode string.  Optionally, attach timestamp,
    traceback, and system information.

    The full output format is:
    C{u"{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{u"#"}.  Each
          defaults to C{u"-"} 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.
    @type event: L{dict}

    @param includeTraceback: If true and a C{"log_failure"} key exists, append
        a traceback.
    @type includeTraceback: L{bool}

    @param includeTimestamp: If true include a formatted timestamp before the
        event.
    @type includeTimestamp: L{bool}

    @param includeSystem:  If true, include the event's C{"log_system"} value.
    @type includeSystem: L{bool}

    @param formatTime: A time formatter
    @type formatTime: L{callable} that takes an C{event} argument and returns
        a L{unicode}

    @return: A formatted string with specified options.
    @rtype: L{unicode}

    @since: Twisted 18.9.0
    Zlog_failurer$   r5   Zlog_timeN []z{timeStamp}{system}{eventText})	timeStamprE   r&   )r=   r@   r   r7   rF   r   )
r   r   r   r   r#   r&   fr?   rJ   rE   r   r   r   r   V  s.    5r   N)r2   r   r    Ztwisted.python.compatr   Ztwisted.python.failurer   Ztwisted.python.reflectr   Ztwisted.python._tzhelperr   Z_flattenr   r	   ZtimeFormatRFC3339r   r   r#   r'   objectr(   r4   r=   r@   rF   r   r   r   r   r   <module>   s*   )%; '$