a dGZ_@sdZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl m Z m Z dZ dZzddlmZmZWn&eyddlmZmZeZYn0dZdZd Zd Ze jd kreefZGd d d eZGdddeZGdddeZGdddee Z!ddZ"ej#ej$e"dZ%d0ddZ&ddZ'Gddde(Z)Gddde(Z*Gd d!d!e*Z+Gd"d#d#e*Z,Gd$d%d%e*Z-Gd&d'd'e*Z.Gd(d)d)e*Z/Gd*d+d+e*Z0Gd,d-d-e(Z1d.d/Z2dS)1z Apply JSON-Patches (RFC 6902) )unicode_literalsN) JsonPointerJsonPointerException)MutableMappingMutableSequenceu Stefan Kögl z1.21z0https://github.com/stefankoegl/python-json-patchzModified BSD License)rc@seZdZdZdS)JsonPatchExceptionzBase Json Patch exceptionN__name__ __module__ __qualname____doc__rr-/usr/lib/python3.9/site-packages/jsonpatch.pyr Gsr c@seZdZdZdS)InvalidJsonPatchz, Raised if an invalid JSON Patch is created Nr rrrrrKsrc@seZdZdZdS)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 rrrrrOsrc@seZdZdZdS)JsonPatchTestFailedz A Test operation failed Nr rrrrrXsrcCs<tt}|D]\}}|||qtdd|DS)z'Convert duplicate keys values to lists.css.|]&\}}|t|dkr |dn|fVqdS)rrN)len).0keyvaluesrrr cszmultidict..) collections defaultdictlistappenddictitems)Z ordered_pairsZmdictrvaluerrr multidict\s   r )Zobject_pairs_hookFcCs*t|trt|}nt|}|||S)aOApply 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_stringapply)docpatchin_placerrr apply_patchos  r)cCs t||S)aGenerates 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)srcdstrrr make_patchsr-c@seZdZdZddZddZddZeZdd Zd d Z d d Z ddZ e ddZ e dddZddZeddZd ddZddZdS)!r#agA 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 {...} cCs||_ttttttd|_dS)N)removeaddreplacemovetestcopy)r'RemoveOperation AddOperationReplaceOperation MoveOperation TestOperation CopyOperation operations)selfr'rrr__init__szJsonPatch.__init__cCs|S)zstr(self) -> self.to_string()) to_stringr;rrr__str__szJsonPatch.__str__cCs t|jSN)boolr'r>rrr__bool__szJsonPatch.__bool__cCs t|jSr@)iterr'r>rrr__iter__szJsonPatch.__iter__cCstt|jSr@)hashtuple_opsr>rrr__hash__szJsonPatch.__hash__cCst|tsdS|j|jkSNF)r!r#rGr;otherrrr__eq__s zJsonPatch.__eq__cCs ||k Sr@rrJrrr__ne__szJsonPatch.__ne__cCst|}||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'rrrr$s zJsonPatch.from_stringTcCs*t}|dd||t|}||S)aOCreates 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_valuesrexecute)rOr+r, optimizationZbuilderopsrrrr*s zJsonPatch.from_diffcCs t|jS)z!Returns patch set as JSON string.)jsondumpsr'r>rrrr=!szJsonPatch.to_stringcCstt|j|jSr@)rFmap_get_operationr'r>rrrrG%szJsonPatch._opsFcCs(|st|}|jD]}||}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`. )r3deepcopyrGr%)r;objr( operationrrrr%)s    zJsonPatch.applycCsTd|vrtd|d}t|ts*td||jvrBtd||j|}||S)Nopz&Operation does not contain 'op' memberzOperation must be a stringzUnknown operation {0!r})rr!r"r:format)r;r\r]rOrrrrY>s   zJsonPatch._get_operationN)T)F)r r r rr<r?rBZ __nonzero__rDrHrLrM classmethodr$r*r=propertyrGr%rYrrrrr#s$-     r#c@s^eZdZdZddZddZddZdd Zd d Ze d d Z e ddZ e j ddZ dS)PatchOperationz'A single operation inside a JSON Patch.cCs |d|_t|j|_||_dS)Npath)locationrpointerr\)r;r\rrrr<Qs  zPatchOperation.__init__cCs tddS)zAAbstract method that applies patch operation to specified object.z!should implement patch operation.N)NotImplementedError)r;r[rrrr%VszPatchOperation.applycCstt|jSr@)rE frozensetr\rr>rrrrHZszPatchOperation.__hash__cCst|tsdS|j|jkSrI)r!rar\rJrrrrL]s zPatchOperation.__eq__cCs ||k Sr@rrJrrrrMbszPatchOperation.__ne__cCsd|jjddS)N/)joinrdpartsr>rrrrbeszPatchOperation.pathcCs6zt|jjdWSty0|jjdYS0dS)Nrh)intrdrj ValueErrorr>rrrris zPatchOperation.keycCs*t||jjd<|jj|_|j|jd<dS)Nrhrb)strrdrjrbrcr\)r;rrrrrps N) r r r rr<r%rHrLrMr`rbrsetterrrrrraNs  rac@s(eZdZdZddZddZddZdS) r4z/Removes an object property or an array element.c CsZ|j|\}}z ||=Wn:ttfyT}zd|}t|WYd}~n d}~00|S)Nz&can't remove non-existent object '{0}')rdto_lastKeyError IndexErrorr^r)r;r[subobjpartexmsgrrrr%zs  zRemoveOperation.applycCs0|j|kr,|j|kr$|jd7_n|d8}|SNrrbrr;rbrrrr_on_undo_removes   zRemoveOperation._on_undo_removecCs0|j|kr,|j|kr$|jd8_n|d8}|Srvrwrxrrr _on_undo_adds   zRemoveOperation._on_undo_addNr r r rr%ryrzrrrrr4ws r4c@s(eZdZdZddZddZddZdS) r5z,Adds an object property or an array element.c Csz|jd}Wn,ty:}ztdWYd}~n d}~00|j|\}}t|tr|dkrj||q|t|ks~|dkrt dq| ||n4t|t r|dur|}q|||<nt d t||S)Nr/The operation does not contain a 'value' member-rzcan't insert outside of listinvalid document type {0})r\rprrdror!rrrrinsertr TypeErrorr^type)r;r[rrtrrrsrrrr%s&     zAddOperation.applycCs0|j|kr,|j|kr$|jd7_n|d7}|Srvrwrxrrrrys   zAddOperation._on_undo_removecCs0|j|kr,|j|kr$|jd8_n|d7}|Srvrwrxrrrrzs   zAddOperation._on_undo_addNr{rrrrr5sr5c@s(eZdZdZddZddZddZdS) r6z=Replaces an object property or an array element by new value.c Csz|jd}Wn,ty:}ztdWYd}~n d}~00|j|\}}|durX|St|tr|t|ksv|dkrtdn8t|t r||vrd |}t|nt d t ||||<|S)Nrr|rzcan't replace outside of listz'can't replace non-existent object '{0}'r~) r\rprrdror!rrrrr^rr)r;r[rrtrrrsrurrrr%s&     zReplaceOperation.applycCs|Sr@rrxrrrrysz ReplaceOperation._on_undo_removecCs|Sr@rrxrrrrzszReplaceOperation._on_undo_addNr{rrrrr6sr6c@sNeZdZdZddZeddZeddZejddZd d Z d d Z d S)r7z=Moves an object property or an array element to new location.c Cszt|jd}Wn,ty>}ztdWYd}~n d}~00||\}}z ||}Wn4ttfy}ztt|WYd}~n d}~00|j|kr|St |t r|j |rtdt d|jdd |}td|j|d |}|S)Nfrom.The operation does not contain a 'from' memberz(Cannot move values into its own childrenr.r]rbr/r]rbr)rr\rprrorqrrmrdr!rcontainsr4r%r5rcr;r[from_ptrrtrrrsrrrrr%s> "   zMoveOperation.applycCs"t|jd}d|jddS)Nrrgrh)rr\rirjr;rrrr from_pathszMoveOperation.from_pathcCs@t|jd}zt|jdWSty:|jdYS0dSNrrh)rr\rkrjrrrrrfrom_keys  zMoveOperation.from_keycCs,t|jd}t||jd<|j|jd<dSr)rr\rmrjrb)r;rrrrrrscCs\|j|kr,|j|kr$|jd7_n|d8}|j|krX|j|krP|jd7_n|d7}|Srvrrrbrrxrrrry#s    zMoveOperation._on_undo_removecCs\|j|kr,|j|kr$|jd8_n|d8}|j|krX|j|krP|jd8_n|d7}|Srvrrxrrrrz0s    zMoveOperation._on_undo_addN) r r r rr%r`rrrnryrzrrrrr7s"    r7c@seZdZdZddZdS)r8z!Test value by specified location.c Csz0|j|\}}|dur |}n|j||}Wn0ty`}ztt|WYd}~n d}~00z|jd}Wn,ty}ztdWYd}~n d}~00||krd}t| |t ||t ||S)Nrr|z0{0} ({1}) is not equal to tested value {2} ({3})) rdrowalkrrrmr\rprr^r)r;r[rrrsvalrtrrurrrr%As&"zTestOperation.applyNr r r rr%rrrrr8>sr8c@seZdZdZddZdS)r9zA Copies an object property or an array element to a new location c Cszt|jd}Wn,ty>}ztdWYd}~n d}~00||\}}zt||}Wn4ttfy}ztt |WYd}~n d}~00t d|j |d |}|S)Nrrr/r) rr\rprror3rZrqrrmr5rcr%rrrrr%\s&"zCopyOperation.applyNrrrrrr9Ysr9c@s|eZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZddZddZdS)rQcCs4iig|_ggg|_g|_}||dg|dd<dSr@) index_storageindex_storage2_DiffBuilder__root)r;rootrrrr<ts   zDiffBuilder.__init__cCsfz:|j|}||}|dur*|g||<n|||Wn&ty`|j|||fYn0dSr@)rgetrrr)r;rindexststoragestoredrrr store_indexzs    zDiffBuilder.store_indexcCsz"|j||}|r |WSWn\ty~|j|}tt|dddD]*}||d|krN||dYSqNYn0dS)Nrrhr)rrpoprrranger)r;rrrrirrr take_indexs  zDiffBuilder.take_indexcCs,|j}|d}|||g|d<|d<|dS)Nrrr)r;r]rZlastrrrrszDiffBuilder.insertcCs*|\}}}||d<||d<g|dd<dS)Nrrr)r;rZ link_prevZ link_next_rrrr.s zDiffBuilder.removeccs.|j}|d}||ur*|dV|d}qdSNrr)r;startrcurrrrr iter_froms  zDiffBuilder.iter_fromccs.|j}|d}||ur*|dV|d}qdSrr)r;rrrrrrDs  zDiffBuilder.__iter__ccs|j}|d}||ur|d|ur|d|dd}}|j|jkrt|tkrt|tkrtd|j|jddjV|dd}q|djV|d}qdS)Nrrr0rr)rrcrr4r5r6r\)r;rrZop_firstZ op_secondrrrrSs&       zDiffBuilder.executec Cs||t}|dur|d}t|jtkrL||D]}||j|j|_q4|||j t ||krt d|j t ||d}| |n.t dt |||d}| |}|||tdS)Nrr1r]rrbr/r)r _ST_REMOVErrrkrryrbr.rc _path_joinr7rr5r_ST_ADD) r;rbritemrr]vnew_op new_indexrrr _item_addeds*    zDiffBuilder._item_addedc Cstdt||d}||t}||}|dur|d}t|jtkrj||D]}| |j |j|_qR| ||j |j krt d|j |j d}||d<q| |n|||tdS)Nr.rrr1r)r4rrrrrrrkrrzrbr.rcr7rr) r;rbrrrrrr]rrrr _item_removeds*      zDiffBuilder._item_removedcCs |tdt|||ddS)Nr0r)rr6r)r;rbrrrrr_item_replaceds zDiffBuilder._item_replacedc Cst|}t|}||}||}|D]}||t|||q,|D]}||t|||qL||@D]}|||||||qpdSr@)setkeysrrmrrR) r;rbr+r,Zsrc_keysZdst_keysZ added_keysZ removed_keysrrrr_compare_dictss   zDiffBuilder._compare_dictsc Cst|t|}}t||}t||}t|D]}||kr||||} } | | krXq.qt| trt| tr|t||| | qt| trt| tr| t||| | q| ||| | ||| q.||kr| ||||q.| ||||q.dSr@) rmaxminrr!rrrr_compare_listsrr) r;rbr+r,Zlen_srcZlen_dstZmax_lenZmin_lenroldnewrrrr s*     zDiffBuilder._compare_listscCsr||kr dSt|tr6t|tr6|t||||n8t|tr`t|tr`|t||||n||||dSr@)r!rrrrrr)r;rbrr+r,rrrrR's  zDiffBuilder._compare_valuesN)r r r r<rrrr.rrDrSrrrrrrRrrrrrQrs  rQcCs,|dur |S|dt|ddddS)Nrg~z~0z~1)rmr0rwrrrr7sr)F)3rZ __future__rrr3 functoolsinspect itertoolsrVsysZ jsonpointerrrrrcollections.abcrr ImportErrorZunicoderm __author__ __version__Z __website__Z __license__ version_infobytesr" Exceptionr rrAssertionErrorrr partialloadsrNr)r-objectr#rar4r5r6r7r8r9rQrrrrr!sT      %&)2$SF