U
    Mb[b                     @   s  d Z ddlmZ ddl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ZdZzddlmZmZ W n( ek
r   ddlmZmZ eZY nX dZdZd	Zd
ZejdkreefZG dd deZG dd deZG dd deZG dd deeZdd Z ej!ej"e dZ#d0ddZ$dd Z%G dd de&Z'G dd de&Z(G d d! d!e(Z)G d"d# d#e(Z*G d$d% d%e(Z+G d&d' d'e(Z,G d(d) d)e(Z-G d*d+ d+e(Z.G d,d- d-e&Z/d.d/ Z0dS )1z Apply JSON-Patches (RFC 6902)     )unicode_literalsN)JsonPointerJsonPointerException   )MutableMappingMutableSequenceu    Stefan Kögl <stefan@skoegl.net>z1.22z0https://github.com/stefankoegl/python-json-patchzModified BSD License)   r   c                   @   s   e Zd ZdZdS )JsonPatchExceptionzBase Json Patch exceptionN__name__
__module____qualname____doc__ r   r   +/usr/lib/python3/dist-packages/jsonpatch.pyr	   E   s   r	   c                   @   s   e Zd ZdZdS )InvalidJsonPatchz, Raised if an invalid JSON Patch is created Nr
   r   r   r   r   r   I   s   r   c                   @   s   e Zd ZdZdS )JsonPatchConflicta  Raised if patch could not be applied due to conflict situation such as:
    - attempt to add object key then it already exists;
    - attempt to operate with nonexistence object key;
    - attempt to insert value to array at position beyond of it size;
    - etc.
    Nr
   r   r   r   r   r   M   s   r   c                   @   s   e Zd ZdZdS )JsonPatchTestFailedz A Test operation failed Nr
   r   r   r   r   r   V   s   r   c                 C   s<   t t}| D ]\}}|| | qtdd | D S )z'Convert duplicate keys values to lists.c                 s   s.   | ]&\}}|t |d kr |d n|fV  qdS )r   r   N)len).0keyvaluesr   r   r   	<genexpr>a   s   zmultidict.<locals>.<genexpr>)collectionsdefaultdictlistappenddictitems)Zordered_pairsZmdictr   valuer   r   r   	multidictZ   s    
r    )Zobject_pairs_hookFc                 C   s*   t |trt|}nt|}|| |S )aO  Apply list of patches to specified json document.

    :param doc: Document object.
    :type doc: dict

    :param patch: JSON patch as list of dicts or raw JSON-encoded string.
    :type patch: list or str

    :param in_place: While :const:`True` patch will modify target document.
                     By default patch will be applied to document copy.
    :type in_place: bool

    :return: Patched document object.
    :rtype: dict

    >>> doc = {'foo': 'bar'}
    >>> patch = [{'op': 'add', 'path': '/baz', 'value': 'qux'}]
    >>> other = apply_patch(doc, patch)
    >>> doc is not other
    True
    >>> other == {'foo': 'bar', 'baz': 'qux'}
    True
    >>> patch = [{'op': 'add', 'path': '/baz', 'value': 'qux'}]
    >>> apply_patch(doc, patch, in_place=True) == {'foo': 'bar', 'baz': 'qux'}
    True
    >>> doc == other
    True
    )
isinstance
basestring	JsonPatchfrom_stringapply)docpatchin_placer   r   r   apply_patchm   s    
r)   c                 C   s   t | |S )a  Generates patch by comparing of two document objects. Actually is
    a proxy to :meth:`JsonPatch.from_diff` method.

    :param src: Data source document object.
    :type src: dict

    :param dst: Data source document object.
    :type dst: dict

    >>> src = {'foo': 'bar', 'numbers': [1, 3, 4, 8]}
    >>> dst = {'baz': 'qux', 'numbers': [1, 4, 7]}
    >>> patch = make_patch(src, dst)
    >>> new = patch.apply(src)
    >>> new == dst
    True
    )r#   	from_diff)srcdstr   r   r   
make_patch   s    r-   c                   @   s   e Zd ZdZdd Zdd Zdd ZeZdd	 Zd
d Z	dd Z
dd Zedd ZedddZdd Zedd Zd ddZdd ZdS )!r#   ag  A JSON Patch is a list of Patch Operations.

    >>> patch = JsonPatch([
    ...     {'op': 'add', 'path': '/foo', 'value': 'bar'},
    ...     {'op': 'add', 'path': '/baz', 'value': [1, 2, 3]},
    ...     {'op': 'remove', 'path': '/baz/1'},
    ...     {'op': 'test', 'path': '/baz', 'value': [1, 3]},
    ...     {'op': 'replace', 'path': '/baz/0', 'value': 42},
    ...     {'op': 'remove', 'path': '/baz/1'},
    ... ])
    >>> doc = {}
    >>> result = patch.apply(doc)
    >>> expected = {'foo': 'bar', 'baz': [42]}
    >>> result == expected
    True

    JsonPatch object is iterable, so you could easily access to each patch
    statement in loop:

    >>> lpatch = list(patch)
    >>> expected = {'op': 'add', 'path': '/foo', 'value': 'bar'}
    >>> lpatch[0] == expected
    True
    >>> lpatch == patch.patch
    True

    Also JsonPatch could be converted directly to :class:`bool` if it contains
    any operation statements:

    >>> bool(patch)
    True
    >>> bool(JsonPatch([]))
    False

    This behavior is very handy with :func:`make_patch` to write more readable
    code:

    >>> old = {'foo': 'bar', 'numbers': [1, 3, 4, 8]}
    >>> new = {'baz': 'qux', 'numbers': [1, 4, 7]}
    >>> patch = make_patch(old, new)
    >>> if patch:
    ...     # document have changed, do something useful
    ...     patch.apply(old)    #doctest: +ELLIPSIS
    {...}
    c                 C   s   || _ ttttttd| _d S )N)removeaddreplacemoveZtestcopy)r'   RemoveOperationAddOperationReplaceOperationMoveOperationTestOperationCopyOperation
operations)selfr'   r   r   r   __init__   s    zJsonPatch.__init__c                 C   s   |   S )zstr(self) -> self.to_string())	to_stringr:   r   r   r   __str__   s    zJsonPatch.__str__c                 C   s
   t | jS N)boolr'   r=   r   r   r   __bool__   s    zJsonPatch.__bool__c                 C   s
   t | jS r?   )iterr'   r=   r   r   r   __iter__   s    zJsonPatch.__iter__c                 C   s   t t| jS r?   )hashtuple_opsr=   r   r   r   __hash__   s    zJsonPatch.__hash__c                 C   s   t |tsdS | j|jkS NF)r!   r#   rF   r:   otherr   r   r   __eq__   s    
zJsonPatch.__eq__c                 C   s
   | |k S r?   r   rI   r   r   r   __ne__   s    zJsonPatch.__ne__c                 C   s   t |}| |S )zCreates JsonPatch instance from string source.

        :param patch_str: JSON patch as raw string.
        :type patch_str: str

        :return: :class:`JsonPatch` instance.
        )
_jsonloads)clsZ	patch_strr'   r   r   r   r$      s    	zJsonPatch.from_stringTc                 C   s*   t  }|dd|| t| }| |S )aO  Creates JsonPatch instance based on comparing of two document
        objects. Json patch would be created for `src` argument against `dst`
        one.

        :param src: Data source document object.
        :type src: dict

        :param dst: Data source document object.
        :type dst: dict

        :return: :class:`JsonPatch` instance.

        >>> src = {'foo': 'bar', 'numbers': [1, 3, 4, 8]}
        >>> dst = {'baz': 'qux', 'numbers': [1, 4, 7]}
        >>> patch = JsonPatch.from_diff(src, dst)
        >>> new = patch.apply(src)
        >>> new == dst
        True
         N)DiffBuilder_compare_valuesr   execute)rN   r+   r,   optimizationZbuilderZopsr   r   r   r*     s    zJsonPatch.from_diffc                 C   s   t | jS )z!Returns patch set as JSON string.)jsondumpsr'   r=   r   r   r   r<     s    zJsonPatch.to_stringc                 C   s   t t| j| jS r?   )rE   map_get_operationr'   r=   r   r   r   rF   #  s    zJsonPatch._opsFc                 C   s(   |st |}| jD ]}||}q|S )a/  Applies the patch to given object.

        :param obj: Document object.
        :type obj: dict

        :param in_place: Tweaks way how patch would be applied - directly to
                         specified `obj` or to his copy.
        :type in_place: bool

        :return: Modified `obj`.
        )r2   deepcopyrF   r%   )r:   objr(   	operationr   r   r   r%   '  s
    

zJsonPatch.applyc                 C   sT   d|krt d|d }t|ts*t d|| jkrBt d|| j| }||S )Nopz&Operation does not contain 'op' memberzOperation must be a stringzUnknown operation {0!r})r   r!   r"   r9   format)r:   rZ   r[   rN   r   r   r   rW   <  s    


zJsonPatch._get_operationN)T)F)r   r   r   r   r;   r>   rA   Z__nonzero__rC   rG   rK   rL   classmethodr$   r*   r<   propertyrF   r%   rW   r   r   r   r   r#      s$   -


r#   c                   @   s^   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Ze	dd Z
e	dd Zejdd ZdS )PatchOperationz'A single operation inside a JSON Patch.c                 C   sF   t |d tr&|d j| _|d | _n|d | _t| j| _|| _d S )Npath)r!   r   r`   locationpointerrZ   )r:   rZ   r   r   r   r;   O  s    
zPatchOperation.__init__c                 C   s   t ddS )zAAbstract method that applies patch operation to specified object.z!should implement patch operation.N)NotImplementedError)r:   rY   r   r   r   r%   Z  s    zPatchOperation.applyc                 C   s   t t| j S r?   )rD   	frozensetrZ   r   r=   r   r   r   rG   ^  s    zPatchOperation.__hash__c                 C   s   t |tsdS | j|jkS rH   )r!   r_   rZ   rI   r   r   r   rK   a  s    
zPatchOperation.__eq__c                 C   s
   | |k S r?   r   rI   r   r   r   rL   f  s    zPatchOperation.__ne__c                 C   s   d | jjd d S )N/)joinrb   partsr=   r   r   r   r`   i  s    zPatchOperation.pathc                 C   s8   zt | jjd W S  tk
r2   | jjd  Y S X d S )Nrf   )intrb   rh   
ValueErrorr=   r   r   r   r   m  s    zPatchOperation.keyc                 C   s*   t || jjd< | jj| _| j| jd< d S )Nrf   r`   )strrb   rh   r`   ra   rZ   )r:   r   r   r   r   r   t  s    
N)r   r   r   r   r;   r%   rG   rK   rL   r^   r`   r   setterr   r   r   r   r_   L  s   

r_   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r3   z/Removes an object property or an array element.c              
   C   sX   | j |\}}z
||= W n8 ttfk
rR } zd|}t|W 5 d }~X Y nX |S )Nz&can't remove non-existent object '{0}')rb   to_lastKeyError
IndexErrorr\   r   )r:   rY   subobjpartexmsgr   r   r   r%   ~  s    

zRemoveOperation.applyc                 C   s0   | j |kr,| j|kr$|  jd7  _n|d8 }|S Nr   r`   r   r:   r`   r   r   r   r   _on_undo_remove  s
    

zRemoveOperation._on_undo_removec                 C   s0   | j |kr,| j|kr$|  jd8  _n|d8 }|S rt   ru   rv   r   r   r   _on_undo_add  s
    

zRemoveOperation._on_undo_addNr   r   r   r   r%   rw   rx   r   r   r   r   r3   {  s   
r3   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r4   z,Adds an object property or an array element.c              
   C   s   z| j d }W n* tk
r8 } ztdW 5 d }~X Y nX | j|\}}t|tr|dkrh|| q|t|ks||dk rt	dq|
|| nPt|tr|d kr|}q|||< n.|d krtdt|nt	d| j||S )Nr   /The operation does not contain a 'value' member-r   zcan't insert outside of listinvalid document type {0}2unable to fully resolve json pointer {0}, part {1})rZ   rn   r   rb   rm   r!   r   r   r   r   insertr   	TypeErrorr\   typera   )r:   rY   r   rr   rp   rq   r   r   r   r%     s*    



zAddOperation.applyc                 C   s0   | j |kr,| j|kr$|  jd7  _n|d7 }|S rt   ru   rv   r   r   r   rw     s
    

zAddOperation._on_undo_removec                 C   s0   | j |kr,| j|kr$|  jd8  _n|d7 }|S rt   ru   rv   r   r   r   rx     s
    

zAddOperation._on_undo_addNry   r   r   r   r   r4     s    r4   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r5   z=Replaces an object property or an array element by new value.c              
   C   s   z| j d }W n* tk
r8 } ztdW 5 d }~X Y nX | j|\}}|d krV|S t|tr~|t|kst|dk rtdnTt|t	r||krd
|}t|n.|d krtd
t|ntd
| j||||< |S )Nr   rz   r   zcan't replace outside of listz'can't replace non-existent object '{0}'r|   r}   )rZ   rn   r   rb   rm   r!   r   r   r   r   r\   r   r   ra   )r:   rY   r   rr   rp   rq   rs   r   r   r   r%     s*    




zReplaceOperation.applyc                 C   s   |S r?   r   rv   r   r   r   rw     s    z ReplaceOperation._on_undo_removec                 C   s   |S r?   r   rv   r   r   r   rx     s    zReplaceOperation._on_undo_addNry   r   r   r   r   r5     s   r5   c                   @   sN   e Zd ZdZdd Zedd Zedd Zejdd Zd	d
 Z	dd Z
dS )r6   z=Moves an object property or an array element to new location.c              
   C   s
  z.t | jd tr| jd }nt| jd }W n* tk
rX } ztdW 5 d }~X Y nX ||\}}z|| }W n2 ttfk
r } ztt|W 5 d }~X Y nX | j	|kr|S t |t
r| j	|rtdtd| jd d|}td| j|d|}|S )Nfrom.The operation does not contain a 'from' memberz(Cannot move values into its own childrenr.   r[   r`   r/   r[   r`   r   )r!   rZ   r   rn   r   rm   ro   r   rk   rb   r   containsr3   r%   r4   ra   r:   rY   from_ptrrr   rp   rq   r   r   r   r   r%     sB    


zMoveOperation.applyc                 C   s"   t | jd }d|jd d S )Nr   re   rf   )r   rZ   rg   rh   r:   r   r   r   r   	from_path  s    zMoveOperation.from_pathc                 C   sB   t | jd }zt|jd W S  tk
r<   |jd  Y S X d S Nr   rf   )r   rZ   ri   rh   r   r   r   r   r   from_key!  s
    zMoveOperation.from_keyc                 C   s,   t | jd }t||jd< |j| jd< d S r   )r   rZ   rk   rh   r`   )r:   r   r   r   r   r   r   )  s    c                 C   s\   | j |kr,| j|kr$|  jd7  _n|d8 }| j|krX| j|krP|  jd7  _n|d7 }|S rt   r   r   r`   r   rv   r   r   r   rw   /  s    



zMoveOperation._on_undo_removec                 C   s\   | j |kr,| j|kr$|  jd8  _n|d8 }| j|krX| j|krP|  jd8  _n|d7 }|S rt   r   rv   r   r   r   rx   <  s    



zMoveOperation._on_undo_addN)r   r   r   r   r%   r^   r   r   rl   rw   rx   r   r   r   r   r6     s   %


r6   c                   @   s   e Zd ZdZdd ZdS )r7   z!Test value by specified location.c              
   C   s   z0| j |\}}|d kr |}n| j ||}W n. tk
r^ } ztt|W 5 d }~X Y nX z| jd }W n* tk
r } ztdW 5 d }~X Y nX ||krd}t|	|t
||t
||S )Nr   rz   z0{0} ({1}) is not equal to tested value {2} ({3}))rb   rm   walkr   r   rk   rZ   rn   r   r\   r   )r:   rY   rp   rq   valrr   r   rs   r   r   r   r%   M  s(     zTestOperation.applyNr   r   r   r   r%   r   r   r   r   r7   J  s   r7   c                   @   s   e Zd ZdZdd ZdS )r8   zA Copies an object property or an array element to a new location c              
   C   s   zt | jd }W n* tk
r< } ztdW 5 d }~X Y nX ||\}}zt|| }W n2 ttfk
r } ztt	|W 5 d }~X Y nX t
d| j|d|}|S )Nr   r   r/   r   )r   rZ   rn   r   rm   r2   rX   ro   r   rk   r4   ra   r%   r   r   r   r   r%   h  s&    zCopyOperation.applyNr   r   r   r   r   r8   e  s   r8   c                   @   s|   e Z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dd ZdS )rP   c                 C   s4   i i g| _ g g g| _g  | _}||d g|d d < d S r?   )index_storageindex_storage2_DiffBuilder__root)r:   rootr   r   r   r;     s    


zDiffBuilder.__init__c                 C   sh   z:| j | }||}|d kr*|g||< n|| | W n( tk
rb   | j| ||f Y nX d S r?   )r   getr   r   r   )r:   r   indexststoragestoredr   r   r   store_index  s    

zDiffBuilder.store_indexc                 C   s   z"| j | |}|r | W S W n^ tk
r   | j| }tt|d ddD ]*}|| d |krP||d    Y S qPY nX d S )Nr   rf   r   )r   r   popr   r   ranger   )r:   r   r   r   r   ir   r   r   
take_index  s    
zDiffBuilder.take_indexc                 C   s,   | j }|d }|||g |d< |d< |d S )Nr   r   r   )r:   r[   r   Zlastr   r   r   r~     s    zDiffBuilder.insertc                 C   s*   |\}}}||d< ||d< g |d d < d S )Nr   r   r   )r:   r   Z	link_prevZ	link_next_r   r   r   r.     s    
zDiffBuilder.removec                 c   s.   | j }|d }||k	r*|d V  |d }qd S Nr      r   )r:   startr   currr   r   r   	iter_from  s
    
zDiffBuilder.iter_fromc                 c   s.   | j }|d }||k	r*|d V  |d }qd S r   r   )r:   r   r   r   r   r   rC     s
    
zDiffBuilder.__iter__c                 c   s   | j }|d }||k	r|d |k	r|d |d d  }}|j|jkrt|tkrt|tkrtd|j|jd djV  |d d }q|d jV  |d }qd S )Nr   r   r0   r   r   )r   ra   r   r3   r4   r5   rZ   )r:   r   r   Zop_firstZ	op_secondr   r   r   rR     s&    

zDiffBuilder.executec           	      C   s   |  |t}|d k	r|d }t|jtkrL| |D ]}||j|j|_q4| | |j	t
||krtd|j	t
||d}| | n.tdt
|||d}| |}| ||t d S )Nr   r1   r[   r   r`   r/   r   )r   
_ST_REMOVEr   r   ri   r   rw   r`   r.   ra   
_path_joinr6   r~   r4   r   _ST_ADD)	r:   r`   r   itemr   r[   vnew_op	new_indexr   r   r   _item_added  s*    

zDiffBuilder._item_addedc           	      C   s   t dt||d}| |t}| |}|d k	r|d }t|jtkrj| |D ]}|	|j
|j|_qR| | |j|jkrtd|j|jd}||d< q| | n| ||t d S )Nr.   r   r   r1   r   )r3   r   r   r   r~   r   r   ri   r   rx   r`   r.   ra   r6   r   r   )	r:   r`   r   r   r   r   r   r[   r   r   r   r   _item_removed  s*    


zDiffBuilder._item_removedc                 C   s    |  tdt|||d d S )Nr0   r   )r~   r5   r   )r:   r`   r   r   r   r   r   _item_replaced  s
    zDiffBuilder._item_replacedc           	      C   s   t | }t | }|| }|| }|D ]}| |t|||  q,|D ]}| |t|||  qL||@ D ]}| |||| ||  qpd S r?   )setkeysr   rk   r   rQ   )	r:   r`   r+   r,   Zsrc_keysZdst_keysZ
added_keysZremoved_keysr   r   r   r   _compare_dicts  s    zDiffBuilder._compare_dictsc                 C   s   t |t | }}t||}t||}t|D ]}||k r|| ||  }	}
|	|
krXq.qt|	trt|
tr| t|||	|
 qt|	trt|
tr| 	t|||	|
 q| 
|||	 | |||
 q.||kr| 
||||  q.| ||||  q.d S r?   )r   maxminr   r!   r   r   r   r   _compare_listsr   r   )r:   r`   r+   r,   Zlen_srcZlen_dstZmax_lenZmin_lenr   oldnewr   r   r   r     s*    



zDiffBuilder._compare_listsc                 C   sr   ||krd S t |tr6t |tr6| t|||| n8t |tr`t |tr`| t|||| n| ||| d S r?   )r!   r   r   r   r   r   r   )r:   r`   r   r+   r,   r   r   r   rQ   3  s    

zDiffBuilder._compare_valuesN)r   r   r   r;   r   r   r~   r.   r   rC   rR   r   r   r   r   r   rQ   r   r   r   r   rP   ~  s   rP   c                 C   s,   |d kr| S | d t |dddd S )Nre   ~z~0z~1)rk   r0   ru   r   r   r   r   C  s    r   )F)1r   Z
__future__r   r   r2   	functoolsrT   sysZjsonpointerr   r   r   r   Zcollections.abcr   r   ImportErrorZunicoderk   
__author____version__Z__website__Z__license__version_infobytesr"   	Exceptionr	   r   r   AssertionErrorr   r    partialloadsrM   r)   r-   objectr#   r_   r3   r4   r5   r6   r7   r8   rP   r   r   r   r   r   <module>!   sP   

	
% &/4'V F