B
    |bj                 @   s   d dl mZmZmZ d dlZd dlZd dlZd dlZd dlm	Z	m
Z
 ddlmZmZmZmZ ddlmZ ddlmZmZmZmZ dd
dZdd Zdd Zdd ZG dd deZdS )    )absolute_importdivisionunicode_literalsN)chainislice   )compathandlerstagsutil)json)PY2PY3numeric_typesstring_typesTFc             C   sD   |pt }|p(t|||||||	||
||d}|j|j| |d||dS )a  Return a JSON formatted representation of value, a Python object.

    :param unpicklable: If set to ``False`` then the output will not contain the
        information necessary to turn the JSON data back into Python objects,
        but a simpler JSON stream is produced. It's recommended to set this
        parameter to ``False`` when your code does not rely on two objects
        having the same ``id()`` value, and when it is sufficient for those two
        objects to be equal by ``==``, such as when serializing sklearn
        instances. If you experience (de)serialization being incorrect when you
        use numpy, pandas, or sklearn handlers, this should be set to ``False``.
        If you want the output to not include the dtype for numpy arrays, add
        ``jsonpickle.register(numpyp.generic,
         UnpicklableNumpyGenericHandler, base=True)`` before your pickling code.
    :param max_depth: If set to a non-negative integer then jsonpickle will
        not recurse deeper than 'max_depth' steps into the object.  Anything
        deeper than 'max_depth' is represented using a Python repr() of the
        object.
    :param make_refs: If set to False jsonpickle's referencing support is
        disabled.  Objects that are id()-identical won't be preserved across
        encode()/decode(), but the resulting JSON stream will be conceptually
        simpler.  jsonpickle detects cyclical objects and will break the cycle
        by calling repr() instead of recursing when make_refs is set False.
    :param keys: If set to True then jsonpickle will encode non-string
        dictionary keys instead of coercing them into strings via `repr()`.
        This is typically what you want if you need to support Integer or
        objects as dictionary keys.
    :param numeric_keys: Only use this option if the backend supports integer
        dict keys natively.  This flag tells jsonpickle to leave numeric keys
        as-is rather than conforming them to json-friendly strings.
        Using ``keys=True`` is the typical solution for integer keys, so only
        use this if you have a specific use case where you want to allow the
        backend to handle serialization of numeric dict keys.
    :param warn: If set to True then jsonpickle will warn when it
        returns None for an object which it cannot pickle
        (e.g. file descriptors).
    :param max_iter: If set to a non-negative integer then jsonpickle will
        consume at most `max_iter` items when pickling iterators.
    :param use_decimal: If set to True jsonpickle will allow Decimal
        instances to pass-through, with the assumption that the simplejson
        backend will be used in `use_decimal` mode.  In order to use this mode
        you will need to configure simplejson::

            jsonpickle.set_encoder_options('simplejson',
                                           use_decimal=True, sort_keys=True)
            jsonpickle.set_decoder_options('simplejson',
                                           use_decimal=True)
            jsonpickle.set_preferred_backend('simplejson')

        NOTE: A side-effect of the above settings is that float values will be
        converted to Decimal when converting to json.
    :param use_base85:
        If possible, use base85 to encode binary data. Base85 bloats binary data
        by 1/4 as opposed to base64, which expands it by 1/3. This argument is
        ignored on Python 2 because it doesn't support it.
    :param fail_safe: If set to a function exceptions are ignored when pickling
        and if a exception happens the function is called and the return value
        is used as the value for the object that caused the error
    :param indent: When `indent` is a non-negative integer, then JSON array
        elements and object members will be pretty-printed with that indent
        level.  An indent level of 0 will only insert newlines. ``None`` is
        the most compact representation.  Since the default item separator is
        ``(', ', ': ')``,  the output might include trailing whitespace when
        ``indent`` is specified.  You can use ``separators=(',', ': ')`` to
        avoid this.  This value is passed directly to the active JSON backend
        library and not used by jsonpickle directly.
    :param separators:
        If ``separators`` is an ``(item_separator, dict_separator)`` tuple
        then it will be used instead of the default ``(', ', ': ')``
        separators.  ``(',', ':')`` is the most compact JSON representation.
        This value is passed directly to the active JSON backend library and
        not used by jsonpickle directly.

    >>> encode('my string') == '"my string"'
    True
    >>> encode(36) == '36'
    True
    >>> encode({'foo': True}) == '{"foo": true}'
    True
    >>> encode({'foo': [1, 2, [3, 4]]}, max_depth=1)
    '{"foo": "[1, 2, [3, 4]]"}'

    )unpicklable	make_refskeysbackend	max_depthwarnmax_iternumeric_keysuse_decimal
use_base85	fail_safe)reset)indent
separators)r   Picklerencodeflatten)valuer   r   r   r   r   r   r   contextr   r   r   r   r   r   r    r$   1lib/python3.7/site-packages/jsonpickle/pickler.pyr       s    dr    c             C   s.   |s| o,t | |ko,t|  o,t|  S )z>Detect cyclic structures that would lead to infinite recursion)idr   Zis_primitiveZis_enum)objZobjsmax_reachedr   r$   r$   r%   	_in_cycle   s    r)   c             C   s   t jt| iS )zxReturn a typeref dictionary

    >>> _mktyperef(AssertionError) == {'py/type': 'builtins.AssertionError'}
    True

    )r
   ZTYPEr   importable_name)r'   r$   r$   r%   
_mktyperef   s    r+   c             C   s   t | tr| fS | S )z0Converts __slots__ = 'a' into __slots__ = ('a',))
isinstancer   )stringr$   r$   r%   _wrap_string_slot   s    
r.   c               @   s   e Zd Zd>ddZdd Zdd	 Zd
d Zdd Zdd Zdd Z	dd Z
d?ddZdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd@d4d5Zd6d7 Zd8d9 Zd:d; Zd<d= ZdS )Ar   TNFc             C   s   || _ || _|pt| _|| _|| _|| _|
o0t | _d| _	|| _
i | _g | _|| _|	| _i | _| jrvtj| _tj| _ntj| _tj| _|| _d S )N)r   r   r   r   r   r   r   r   r   _depth
_max_depth_objs_seen	_max_iter_use_decimal
_flattenedr
   ZB85
_bytes_tagr   Z	b85encode_bytes_encoderZB64Z	b64encoder   )selfr   r   r   r   r   r   r   r   r   r   r   r$   r$   r%   __init__   s(    

zPickler.__init__c             C   s   i | _ d| _g | _i | _d S )Nr/   )r2   r0   r3   r6   )r9   r$   r$   r%   r      s    zPickler.resetc             C   s   |  j d7  _ dS )z&Steps down one level in the namespace.r   N)r0   )r9   r$   r$   r%   _push   s    zPickler._pushc             C   s$   |  j d8  _ | j dkr |   |S )zzStep up one level in the namespace and return the value.
        If we're at the root, reset the pickler's state.
        r   r/   )r0   r   )r9   r"   r$   r$   r%   _pop   s    
zPickler._popc             C   s.   t |}|| jk}|r*t| j}|| j|< |S )z
        Log a reference to an in-memory object.
        Return True if this object is new and was assigned
        a new ID. Otherwise return False.
        )r&   r2   len)r9   r'   Zobjidis_newZnew_idr$   r$   r%   _log_ref   s    


zPickler._log_refc             C   s"   |  |}| j p| j }|p |S )z~
        Log a reference to an in-memory object, and return
        if that object should be considered newly logged.
        )r?   r   r   )r9   r'   r>   Zpretend_newr$   r$   r%   _mkref   s    
zPickler._mkrefc             C   s   t j| jt|iS )N)r
   ZIDr2   getr&   )r9   r'   r$   r$   r%   _getref   s    zPickler._getrefc             C   s\   | j r| jr| |}n@y| jt| }W n, tk
rV   | | }| jt|< Y nX |S )N)r   r   _flatten_implr6   r&   KeyError)r9   r'   resultr$   r$   r%   _flatten  s    zPickler._flattenc             C   s   |r|    | |S )a  Takes an object and returns a JSON-safe representation of it.

        Simply returns any of the basic builtin datatypes

        >>> p = Pickler()
        >>> p.flatten('hello world') == 'hello world'
        True
        >>> p.flatten(49)
        49
        >>> p.flatten(350.0)
        350.0
        >>> p.flatten(True)
        True
        >>> p.flatten(False)
        False
        >>> r = p.flatten(None)
        >>> r is None
        True
        >>> p.flatten(False)
        False
        >>> p.flatten([1, 2, 3, 4])
        [1, 2, 3, 4]
        >>> p.flatten((1,2,))[tags.TUPLE]
        [1, 2]
        >>> p.flatten({'key': 'value'}) == {'key': 'value'}
        True
        )r   rF   )r9   r'   r   r$   r$   r%   r!     s    zPickler.flattenc             C   s   t st|tjstdS )z+
        Special case file objects
        N)r   r,   typesFileTypeAssertionError)r9   r'   r$   r$   r%   _flatten_file+  s    zPickler._flatten_filec             C   s4   t r$y
|dS  tk
r"   Y nX | j| |iS )Nzutf-8)r   decodeUnicodeDecodeErrorr7   r8   )r9   r'   r$   r$   r%   _flatten_bytestring2  s    
zPickler._flatten_bytestringc             C   sl   t rt|tjr| |S t|tkr0| |S t|tj	ksP| j
rTt|tjrT|S |   | | |S )N)r   r,   rG   rH   rJ   typebytesrM   r   Z
PRIMITIVESr5   decimalZDecimalr;   r<   _flatten_obj)r9   r'   r$   r$   r%   rC   :  s    

zPickler._flatten_implc             C   s   | j | jkS )N)r0   r1   )r9   r$   r$   r%   _max_reachedN  s    zPickler._max_reachedc             C   s   | j rd| }t | d S )Nz/jsonpickle cannot pickle %r: replaced with None)r   warnings)r9   r'   msgr$   r$   r%   _pickle_warningQ  s    zPickler._pickle_warningc          
   C   s   | j | |  }yDt|| j|| j}|r2t}n
| |}|d krR| | d S ||S  t	t
fk
r } z|W d d }~X Y n< tk
r } z| jd kr|n
| |S W d d }~X Y nX d S )N)r3   appendrR   r)   r2   r   repr_get_flattenerrU   KeyboardInterrupt
SystemExit	Exceptionr   )r9   r'   r(   in_cycleZflatten_funcer$   r$   r%   rQ   V  s"    


zPickler._flatten_objc                s    fdd|D S )Nc                s   g | ]}  |qS r$   )rF   ).0v)r9   r$   r%   
<listcomp>s  s    z)Pickler._list_recurse.<locals>.<listcomp>r$   )r9   r'   r$   )r9   r%   _list_recurser  s    zPickler._list_recursec             C   s    | j rtjt|i}nd }|S )N)r   r
   ZFUNCTIONr   r*   )r9   r'   datar$   r$   r%   _flatten_functionu  s    zPickler._flatten_functionc                s   t |ttfkrB |r2t |tkr, jS  jS     jS nVt |tt	fkrj j
s^ jS  fddS t|rz jS t|rtS t|r jS  | d S )Nc                s*   t | tkrtjntj fdd| D iS )Nc                s   g | ]}  |qS r$   )rF   )r^   r_   )r9   r$   r%   r`     s    z<Pickler._get_flattener.<locals>.<lambda>.<locals>.<listcomp>)rN   tupler
   ZTUPLEZSET)r'   )r9   r$   r%   <lambda>  s    z(Pickler._get_flattener.<locals>.<lambda>)rN   listdictr@   ra   _flatten_dict_objr;   rB   rd   setr   r   Z	is_object_ref_obj_instanceis_typer+   Zis_module_functionrc   rU   )r9   r'   r$   )r9   r%   rX   }  s"    




zPickler._get_flattenerc             C   s\   | j r$| |r| |S | |S |  }t|| j|d}|rDdS | | | |S dS )z.Reference an existing object or flatten if newFN)r   r@   _flatten_obj_instancerB   rR   r)   r2   )r9   r'   r(   r\   r$   r$   r%   rj     s    



zPickler._ref_obj_instancec             C   s$   |  |}| jr||tj< n|}|S )N)rF   r   r
   ZSTATE)r9   r'   rb   stater$   r$   r%   	_getstate  s
    
zPickler._getstatec             C   s`  i }t |d}t |d}| o&t |d}t|d}t|d}t|d}t|\}	}
t |d}|rp|j}nt|}t|}t|t|}|dk	r| j	r||t
j< || ||S d}| j	r|	r|
sy| }W n tk
r   Y nX n,|
r y|d	}W n tk
r   Y nX |rt|try@t|d
}tjt| }x|D ]}t||}| |S W W n tk
r   Y nX n|rt|}dt| }|r|dg| 7 }t|d dddkrt
j|d< |\}}}}}|rt |drt |dst|tr|d r.t|d |d< |d rHt|d |d< tt| j|}t|d }x&|d	kr|| dkr|d8 }qfW |d|d  |t
j < |S |r$t!|s$| j	r||t
j< |rtt| j|" |t
j#< |r
|s
| |$ |t
j%< |r$| |& |t
j'< |rdy|( }W n  tk
rV   | )| dS X | *||S t!|r| j	rdj+|j,d|t
j-< n
t./|}|S t0|r| 1|| |S t2|r| 3||S t4|rtt| jt5|| j6|t
j7< |S |r6t2|r| 3||S t|dd | 1|j8|S |rH| 9||S |rR|S | )| dS )z?Recursively flatten an instance and return a json-friendly dict	__class____dict__	__slots____getnewargs____getnewargs_ex____getinitargs____getstate__N   .   r   __name__ 
__newobj____setstate__      r   z{name}/{name})name_):hasattrr   Z
has_method
has_reducero   rN   r*   r	   rA   r   r
   ZOBJECTr!   
__reduce__	TypeError__reduce_ex__r,   r   itersplitsysmodulesnextgetattrrF   rD   rf   r=   ZNEWOBJrg   rd   mapZREDUCEZ	is_modulers   Z	NEWARGSEXrr   ZNEWARGSrt   ZINITARGSru   rU   rn   formatry   ZREPRr   ustrZis_dictionary_subclassrh   Zis_sequence_subclass_flatten_sequence_objZis_iteratorr   r4   ZITERATORrp   _flatten_newstyle_with_slots)r9   r'   rb   Z	has_classZhas_dictZ	has_slotsZhas_getnewargsZhas_getnewargs_exZhas_getinitargsr   Zhas_reduce_exZhas_getstatecls
class_nameZhandlerZ
reduce_valZvarpathZcurmodmodnameZ
rv_as_listZinsufficiencyfargsrm   Z	listitemsZ	dictitemsZreduce_argsZ
last_indexr$   r$   r%   rl     s    














zPickler._flatten_obj_instancec          	   C   s   t jt|dd| | j| jd S )NFT)r   r   r#   r   r   )r
   JSON_KEYr    r   r   )r9   kr$   r$   r%   _escape_key`  s    zPickler._escape_keyc             C   s<   t ||s|S | jr8t|ts8| |}| |||< |S )z'Flatten only non-string key/value pairs)r   is_picklabler   r,   r   r   rF   )r9   r   r_   rb   r$   r$   r%   "_flatten_non_string_key_value_pairj  s    
z*Pickler._flatten_non_string_key_value_pairc             C   s   t ||s|S | jr<t|ts$|S |tjr| |}nT|dkrHd}| j	rZt|t
rZn6t|tsyt|}W n tk
r   t|}Y nX | |||< |S )z$Flatten string key/value pairs only.Nnull)r   r   r   r,   r   
startswithr
   r   r   r   r   rW   r[   r   r   rF   )r9   r   r_   rb   r$   r$   r%   _flatten_string_key_value_pairs  s$    

z&Pickler._flatten_string_key_value_pairc       	      C   s&  |dkr|  }| jrl| j}x"t|D ]\}}|||| q(W | j}xNt|D ]\}}|||| qRW n*| j}x"t|D ]\}}|||| q~W t|drt|j	r|j	}t
|rt|}n(| |r| t| }n
| |}||d< t|dr"| jr"i }| |j| ||d< |S )z8Recursively call flatten() and return json-friendly dictNdefault_factoryrp   )ro   r   r   r   itemsr   _flatten_key_value_pairr   callabler   rk   r+   r@   rl   r	   ZCloneFactoryrB   r   rh   rp   )	r9   r'   rb   r!   r   r_   factoryr"   Z	dict_datar$   r$   r%   rh     s2    



zPickler._flatten_dict_objc          	   C   st   | j }d}xd|D ]\}y<|ds,t||}nt|d|jj | }|||| W n tk
rf   wY nX d}qW |S )NF__r   T)r   r   r   ro   ry   AttributeError)r9   r'   attrsrb   r!   okr   r"   r$   r$   r%   _flatten_obj_attrs  s    

zPickler._flatten_obj_attrsc             C   sJ   dd |j  D }| |t| |sFdd t|D }| ||| |S )zAReturn a json-friendly dict for new-style objects with __slots__.c             S   s   g | ]}t t|d t qS )rq   )r.   r   rd   )r^   r   r$   r$   r%   r`     s   z8Pickler._flatten_newstyle_with_slots.<locals>.<listcomp>c             S   s$   g | ]}| d s|d s|qS )r   )r   endswith)r^   xr$   r$   r%   r`     s    )ro   mror   r   dir)r9   r'   rb   Zallslotsr   r$   r$   r%   r     s    z$Pickler._flatten_newstyle_with_slotsc             C   sv   t ||s|S |dkrd}| jr.t|tr.n6t|tsdyt|}W n tk
rb   t	|}Y nX | 
|||< |S )z7Flatten a key/value pair into the passed-in dictionary.Nr   )r   r   r   r,   r   r   rW   r[   r   r   rF   )r9   r   r_   rb   r$   r$   r%   r     s    
zPickler._flatten_key_value_pairc                sD   t |dr |j|  fdd|D } jr<||tj< n|S |S )z4Return a json-friendly dict for a sequence subclass.rp   c                s   g | ]}  |qS r$   )rF   )r^   r_   )r9   r$   r%   r`     s    z1Pickler._flatten_sequence_obj.<locals>.<listcomp>)r   rh   rp   r   r
   ZSEQ)r9   r'   rb   r"   r$   )r9   r%   r     s    
zPickler._flatten_sequence_obj)TTNNFFNFFFN)T)N) ry   
__module____qualname__r:   r   r;   r<   r?   r@   rB   rF   r!   rJ   rM   rC   rR   rU   rQ   ra   rc   rX   rj   rn   rl   r   r   r   rh   r   r   r   r   r$   r$   r$   r%   r      sP             
"	


 ! &
	
3r   )TTFNTNFNNFFFNNN)Z
__future__r   r   r   rP   r   rG   rS   	itertoolsr   r   rz   r   r	   r
   r   r   r   r   r   r   r   r    r)   r+   r.   objectr   r$   r$   r$   r%   <module>   s6                 
g	
