U
    
W[U'                     @   s  d Z ddlZddl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 dd
lmZ ddlmZmZ ddlmZ e Zdd Zdd Zdd Zdd eddd dd fdd edeefgZedd eD Zdd Zdd Zd d! Zd"d# Z d*d%d&Z!d+d(d)Z"dS ),zA
Tools for saving and loading log events in a structured format.
    N)NamedConstant)dumpsloads)UUID   )flattenEventFileLogObserver)LogLevel)Logger)unicode_PY3)Failurec                 C   s    t |  t | jj| jjddS )a  
    Convert a failure to a JSON-serializable data structure.

    @param failure: A failure to serialize.
    @type failure: L{Failure}

    @return: a mapping of strings to ... stuff, mostly reminiscent of
        L{Failure.__getstate__}
    @rtype: L{dict}
    )
__module____name__)type)dict__getstate__r   r   r   )Zfailure r   6/usr/lib/python3/dist-packages/twisted/logger/_json.pyfailureAsJSON   s    r   c                 C   sP   t | trtt| S t | tr4tdd |  D S t | trH| dS | S dS )a  
    On Python 2, we really need native strings in a variety of places;
    attribute names will sort of work in a __dict__, but they're subtly wrong;
    however, printing tracebacks relies on I/O to containers that only support
    bytes.  This function converts _all_ native strings within a
    JSON-deserialized object to bytes.

    @param obj: An object to convert to bytes.
    @type obj: L{object}

    @return: A string of UTF-8 bytes.
    @rtype: L{bytes}
    c                 s   s"   | ]\}}t |t |fV  qd S N)asBytes).0kvr   r   r   	<genexpr>A   s     zasBytes.<locals>.<genexpr>utf-8N)
isinstancelistmapr   r   itemsr   encode)objr   r   r   r   0   s    




r   c                 C   sZ   t tdd}|dkr tt}n|t}ts4t| } | d }t|d d|| d< | |_|S )a#  
    Load a L{Failure} from a dictionary deserialized from JSON.

    @param failureDict: a JSON-deserialized object like one previously returned
        by L{failureAsJSON}.
    @type failureDict: L{dict} mapping L{unicode} to attributes

    @return: L{Failure}
    @rtype: L{Failure}
    __new__Nr   r   r   )getattrr   typesZInstanceTyper   r   r   __dict__)ZfailureDictZ
newFailurefZtypeInfor   r   r   failureFromJSONI   s    r)   c                 C   s   t | tott| jd | kS r   )r   r   r%   r
   namelevelr   r   r   <lambda>i   s    
r-   z$02E59486-F24D-46AD-8224-3ACDF2A5732Ac                 C   s   t | jdS )N)r*   )r   r*   r+   r   r   r   r-   n       c                 C   s   t t| d d S )Nr*   )r%   r
   r+   r   r   r   r-   o   r.   c                 C   s
   t | tS r   )r   r   )or   r   r   r-   s   r.   z$E76887E2-20ED-49BF-A8F8-BA25CC586F2Dc                 C   s   g | ]\}}}}||fqS r   r   )r   	predicateuuidsaverloaderr   r   r   
<listcomp>{   s   
 r4   c                 C   s    d| krt t| d  | S | S )aR  
    Dictionary-to-object-translation hook for certain value types used within
    the logging system.

    @see: the C{object_hook} parameter to L{json.load}

    @param aDict: A dictionary loaded from a JSON object.
    @type aDict: L{dict}

    @return: C{aDict} itself, or the object represented by C{aDict}
    @rtype: L{object}
    __class_uuid__)uuidToLoaderr   )ZaDictr   r   r   objectLoadHook   s    r7   c                 C   s>   t D ]0\}}}}|| r|| }t||d< |  S qddiS )a  
    Object-to-serializable hook for certain value types used within the logging
    system.

    @see: the C{default} parameter to L{json.dump}

    @param pythonObject: Any object.
    @type pythonObject: L{object}

    @return: If the object is one of the special types the logging system
        supports, a specially-formatted dictionary; otherwise, a marker
        dictionary indicating that it could not be serialized.
    r5   ZunpersistableT)	classInfostr)ZpythonObjectr0   r1   r2   r3   resultr   r   r   objectSaveHook   s    
r;   c                 C   sZ   t tkrttddd}ndd }t|dd}t|  t| f|}t|tsVt|ddS |S )	a  
    Encode an event as JSON, flattening it if necessary to preserve as much
    structure as possible.

    Not all structure from the log event will be preserved when it is
    serialized.

    @param event: A log event dictionary.
    @type event: L{dict} with arbitrary keys and values

    @return: A string of the serialized JSON; note that this will contain no
        newline characters, and may thus safely be stored in a line-delimited
        file.
    @rtype: L{unicode}
    charmapT)defaultencodingskipkeysc                 S   s   t | tr| dS t| S )z
            Serialize an object not otherwise serializable by L{dumps}.

            @param unencodable: An unencodable object.
            @return: C{unencodable}, serialized
            r<   )r   bytesdecoder;   )Zunencodabler   r   r   r=      s    

zeventAsJSON.<locals>.default)r=   r?   r   replace)r@   r9   r   r;   r   r   r   r   )eventkwr=   r:   r   r   r   eventAsJSON   s    
rE   c                 C   s   t | td}|S )z
    Decode a log event from JSON.

    @param eventText: The output of a previous call to L{eventAsJSON}
    @type eventText: L{unicode}

    @return: A reconstructed version of the log event.
    @rtype: L{dict}
    )Zobject_hook)r   r7   )Z	eventTextZloadedr   r   r   eventFromJSON   s    
rF   c                    s   t |  fddS )a;  
    Create a L{FileLogObserver} that emits JSON-serialized events to a
    specified (writable) file-like object.

    Events are written in the following form::

        RS + JSON + NL

    C{JSON} is the serialized event, which is JSON text.  C{NL} is a newline
    (C{u"\n"}).  C{RS} is a record separator.  By default, this is a single
    RS character (C{u"\x1e"}), which makes the default output conform to the
    IETF draft document "draft-ietf-json-text-sequence-13".

    @param outFile: A file-like object.  Ideally one should be passed which
        accepts L{unicode} data.  Otherwise, UTF-8 L{bytes} will be used.
    @type outFile: L{io.IOBase}

    @param recordSeparator: The record separator to use.
    @type recordSeparator: L{unicode}

    @return: A file log observer.
    @rtype: L{FileLogObserver}
    c                    s   d  t| S )Nz{0}{1}
)formatrE   )rC   recordSeparatorr   r   r-      r.   z%jsonFileLogObserver.<locals>.<lambda>r   )ZoutFilerJ   r   rI   r   jsonFileLogObserver   s    
rK      c                 #   s   dd }dd  |dkr:||  d}|dkr4|}qFd}n||}d}|dkrXd	} }n fd
d}t|}|  |}|st|dkr||}|dk	r|V  q|||7 }||}	|	dd D ]&}
t|
dkr||
}|dk	r|V  q|	d }qldS )a  
    Load events from a file previously saved with L{jsonFileLogObserver}.
    Event records that are truncated or otherwise unreadable are ignored.

    @param inFile: A (readable) file-like object.  Data read from C{inFile}
        should be L{unicode} or UTF-8 L{bytes}.
    @type inFile: iterable of lines

    @param recordSeparator: The expected record separator.
        If L{None}, attempt to automatically detect the record separator from
        one of C{u"\x1e"} or C{u""}.
    @type recordSeparator: L{unicode}

    @param bufferSize: The size of the read buffer used while reading from
        C{inFile}.
    @type bufferSize: integer

    @return: Log events as read from C{inFile}.
    @rtype: iterable of L{dict}
    c                 S   s   t | tkr| S | dS d S )Nr   )r   r@   r"   )sr   r   r   r     s    z&eventsFromJSONLogFile.<locals>.asBytesc                 S   st   zt | d}W n( tk
r:   tjdt | d Y d S X z
t|W S  tk
rn   tjdt | d Y d S X d S )Nr   z2Unable to decode UTF-8 for JSON record: {record!r}recordz&Unable to read JSON record: {record!r})r@   rA   UnicodeDecodeErrorlogerrorrF   
ValueError)rO   textr   r   r   eventFromBytearray  s     
z1eventsFromJSONLogFile.<locals>.eventFromBytearrayNr      r.      
c                    s.   | d t dkr | S tjdt| d d S )N
z0Unable to read truncated JSON record: {record!r}rN   )ordrQ   rR   r@   rN   rU   r   r   eventFromRecordD  s    z.eventsFromJSONLogFile.<locals>.eventFromRecordr   rX   )read	bytearraylensplit)ZinFilerJ   Z
bufferSizer   firstr\   bufferZnewDatarC   ZrecordsrO   r   r[   r   eventsFromJSONLogFile  s:    


rc   )rG   )NrL   )#__doc__r&   Z
constantlyr   Zjsonr   r   r1   r   Z_flattenr   Z_filer	   Z_levelsr
   Z_loggerr   Ztwisted.python.compatr   r   Ztwisted.python.failurer   rQ   r   r   r)   r8   r   r6   r7   r;   rE   rF   rK   rc   r   r   r   r   <module>   sD     (
