B
    |b'                 @   s>   d dl mZmZmZ ddlmZmZ G dd deZe Z	dS )    )absolute_importdivisionunicode_literals   )PY3_ORDERED_DICTstring_typesc               @   s   e Zd ZdZdd Zd ddZeZdd ZeZd!d
dZ	dd Z
dd ZddefddZdd Zd"ddZdd Zdd Zdd Zdd ZdS )#JSONBackenda  Manages encoding and decoding using various backends.

    It tries these modules in this order:
        simplejson, json, jsonlib, yajl, ujson

    simplejson is a fast and popular backend and is tried first.
    json comes with Python and is tried second.

    c             C   s   | j r
dS tddS )z4Ensures that we've loaded at least one JSON backend.NzLjsonpickle requires at least one of the following:
    python2.6, simplejson)	_verifiedAssertionError)self r   1lib/python3.7/site-packages/jsonpickle/backend.py_verify   s    zJSONBackend._verifyNc             C   s   |    | js*| jd }| j||||dS xbt| jD ]T\}}y| j||||dS  tk
r } z|t| jd krx|W dd}~X Y q6X q6W dS )z
        Attempt to encode an object into JSON.

        This tries the loaded backends in order and passes along the last
        exception if no backend is able to encode the object.

        r   )indent
separatorsr   N)r   _fallthrough_backend_namesbackend_encode	enumerate	Exceptionlen)r   objr   r   nameidxer   r   r   encode   s    
zJSONBackend.encodec             C   s   |    | js$| jd }| ||S xdt| jD ]V\}}y| ||S  | j| k
r } z|t| jd krt|n W dd}~X Y q0X q0W dS )z
        Attempt to decode an object from a JSON string.

        This tries the loaded backends in order and passes along the last
        exception if no backends are able to decode the string.

        r   r   N)r   r   r   backend_decoder   _decoder_exceptionsr   )r   stringr   r   r   r   r   r   decode5   s    
zJSONBackend.decodeTc             C   s   || _ g | _i | _i | _i | _i | _i | _d| _| d | d | dddd | d | d	 t	 }d
d|if}d
|ddf|||d| _d S )NF
simplejsonjsonZjsonlibwritereadZ	ReadErrorZyajlujsonr   	sort_keys)r%   Zescape_forward_slashes)r$   r!   r    zdjango.util.simplejson)
r   r   	_encoders	_decoders_encoder_options_decoder_optionsr   r	   load_backendr   )r   ZfallthroughsortZ	json_optsr   r   r   __init__O   s&    



zJSONBackend.__init__c             C   s
   || _ dS )a  
        Disable jsonpickle's fallthrough-on-error behavior

        By default, jsonpickle tries the next backend when decoding or
        encoding using a backend fails.

        This can make it difficult to force jsonpickle to use a specific
        backend, and catch errors, because the error will be suppressed and
        may not be raised by the subsequent backend.

        Calling `enable_backend(False)` will make jsonpickle immediately
        re-raise any exceptions raised by the backends.

        N)r   )r   enabler   r   r   enable_fallthroughu   s    zJSONBackend.enable_fallthroughc             C   s6   yt ||||< W n tk
r0   | | dS X dS )NFT)getattrAttributeErrorremove_backend)r   ZdctZbackendr   r   r   r   r   _store   s    
zJSONBackend._storedumpsloadsc             C   s   yt |}W n tk
r    dS X y*x$|ddd D ]}t||}q8W W n tk
r`   dS X | | j|||r| | j|||sdS t|t	r| | j
|||sdS n
|| j
|< | j|g i f | j|g i f | j| d| _dS )a  Load a JSON backend by name.

        This method loads a backend and sets up references to that
        backend's loads/dumps functions and exception classes.

        :param dumps: is the name of the backend's encode method.
          The method should take an object and return a string.
          Defaults to 'dumps'.
        :param loads: names the backend's method for the reverse
          operation -- returning a Python object from a string.
        :param loads_exc: can be either the name of the exception class
          used to denote decoding errors, or it can be a direct reference
          to the appropriate exception class itself.  If it is a name,
          then the assumption is that an exception class of that name
          can be found in the backend module's namespace.
        :param load: names the backend's 'load' method.
        :param dump: names the backend's 'dump' method.
        :rtype bool: True on success, False if the backend could not be loaded.

        F.r   NT)
__import__ImportErrorsplitr/   r0   r2   r&   r'   
isinstancer   r   r(   
setdefaultr)   r   appendr	   )r   r   r3   r4   Z	loads_excmodattrr   r   r   r*      s*    

zJSONBackend.load_backendc             C   sl   | j |d | j|d | j|d | j|d | j|d || jkr\| j| t| j| _	dS )z,Remove all entries for a particular backend.N)
r&   popr'   r   r)   r(   r   removeboolr	   )r   r   r   r   r   r1      s    
zJSONBackend.remove_backendc       	      C   s\   | j |g i f\}}| }|d k	r.||d< |d k	r>||d< |ft| }| j| ||S )Nr   r   )r(   getcopytupler&   )	r   r   r   r   r   optargs	optkwargsZencoder_kwargsZencoder_argsr   r   r   r      s    zJSONBackend.backend_encodec             C   s4   | j |di f\}}| }| j| |f||S )Nr   )r)   rA   rB   r'   )r   r   r   rD   rE   Zdecoder_kwargsr   r   r   r      s    zJSONBackend.backend_decodec             C   s:   || j kr&| j | | j d| nd| }t|dS )a  
        Set the preferred json backend.

        If a preferred backend is set then jsonpickle tries to use it
        before any other backend.

        For example::

            set_preferred_backend('simplejson')

        If the backend is not one of the built-in jsonpickle backends
        (json/simplejson) then you must load the backend
        prior to calling set_preferred_backend.

        AssertionError is raised if the backend has not been loaded.

        r   z%The "%s" backend has not been loaded.N)r   r?   insertr
   )r   r   errmsgr   r   r   set_preferred_backend   s
    
z!JSONBackend.set_preferred_backendc             O   s   ||f| j |< dS )a  
        Associate encoder-specific options with an encoder.

        After calling set_encoder_options, any calls to jsonpickle's
        encode method will pass the supplied args and kwargs along to
        the appropriate backend's encode method.

        For example::

            set_encoder_options('simplejson', sort_keys=True, indent=4)

        See the appropriate encoder's documentation for details about
        the supported arguments and keyword arguments.

        N)r(   )r   r   argskwargsr   r   r   set_encoder_options   s    zJSONBackend.set_encoder_optionsc             O   s   ||f| j |< dS )a  
        Associate decoder-specific options with a decoder.

        After calling set_decoder_options, any calls to jsonpickle's
        decode method will pass the supplied args and kwargs along to
        the appropriate backend's decode method.

        For example::

            set_decoder_options('simplejson', encoding='utf8', cls=JSONDecoder)

        See the appropriate decoder's documentation for details about
        the supported arguments and keyword arguments.

        N)r)   )r   r   rI   rJ   r   r   r   set_decoder_options  s    zJSONBackend.set_decoder_options)NN)T)NN)__name__
__module____qualname____doc__r   r   r3   r   r4   r,   r.   r2   
ValueErrorr*   r1   r   r   rH   rK   rL   r   r   r   r   r      s    	


&;

r   N)
Z
__future__r   r   r   compatr   r   objectr   r!   r   r   r   r   <module>   s
     