a d�GZ–_ã@sÆdZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl m Z m Z dZ dZzddlmZmZWn&eyšddlmZmZeZYn0dZdZd Zd Ze jd kr¾eefZGd d „d eƒZGdd„deƒZGdd„deƒZGdd„dee ƒZ!dd„Z"ej#ej$e"d�Z%d0dd„Z&dd„Z'Gdd„de(ƒZ)Gdd„de(ƒ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)Ú JsonPointerÚJsonPointerExceptioné)ÚMutableMappingÚMutableSequenceu 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<t t¡}|D]\}}|| |¡qtdd„| ¡DƒƒS)z'Convert duplicate keys values to lists.css.|]&\}}|t|ƒdkr |dn|fVqdS)rrN)Úlen)Ú.0ÚkeyÚvaluesrrrÚ csÿzmultidict..)Ú collectionsÚ defaultdictÚlistÚappendÚdictÚitems)Z ordered_pairsZmdictrÚvaluerrrÚ multidict\s   ýr )Zobject_pairs_hookFcCs*t|tƒrt |¡}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_stringÚapply)ÚdocÚpatchÚin_placerrrÚ apply_patchos  r)cCs 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ÚdstrrrÚ make_patch”sr-c@sŒeZdZdZdd„Zdd„Zdd„ZeZdd „Zd d „Z d d „Z dd„Z e dd„ƒZ e ddd„ƒZdd„Zedd„ƒZd dd„Zdd„ZdS)!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)ÚremoveÚaddÚreplaceÚmoveÚtestÚcopy)r'ÚRemoveOperationÚ AddOperationÚReplaceOperationÚ MoveOperationÚ TestOperationÚ CopyOperationÚ operations)Úselfr'rrrÚ__init__×súzJsonPatch.__init__cCs| ¡S)zstr(self) -> self.to_string())Ú to_string©r;rrrÚ__str__ãszJsonPatch.__str__cCs t|jƒS©N)Úboolr'r>rrrÚ__bool__çszJsonPatch.__bool__cCs t|jƒSr@)Úiterr'r>rrrÚ__iter__ìszJsonPatch.__iter__cCstt|jƒƒSr@)ÚhashÚtupleÚ_opsr>rrrÚ__hash__ïszJsonPatch.__hash__cCst|tƒsdS|j|jkS©NF)r!r#rG©r;ÚotherrrrÚ__eq__òs zJsonPatch.__eq__cCs ||k Sr@rrJrrrÚ__ne__÷szJsonPatch.__ne__cCst|ƒ}||ƒS)z¸Creates 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_valuesrÚexecute)rOr+r,Ú optimizationZbuilderÚopsrrrr*s zJsonPatch.from_diffcCs t |j¡S)z!Returns patch set as JSON string.)ÚjsonÚdumpsr'r>rrrr=!szJsonPatch.to_stringcCstt|j|jƒƒSr@)rFÚmapÚ_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`. )r3ÚdeepcopyrGr%)r;Úobjr(Ú operationrrrr%)s    zJsonPatch.applycCsTd|vrtdƒ‚|d}t|tƒs*tdƒ‚||jvrBtd |¡ƒ‚|j|}||ƒS)NÚopz&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^eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Ze d d „ƒZ e dd„ƒZ e j dd„ƒZ dS)ÚPatchOperationz'A single operation inside a JSON Patch.cCs |d|_t|jƒ|_||_dS)NÚpath)ÚlocationrÚpointerr\)r;r\rrrr<Qs  zPatchOperation.__init__cCs tdƒ‚dS)zAAbstract method that applies patch operation to specified object.z!should implement patch operation.N)ÚNotImplementedError)r;r[rrrr%VszPatchOperation.applycCstt|j ¡ƒƒSr@)rEÚ frozensetr\rr>rrrrHZszPatchOperation.__hash__cCst|tƒsdS|j|jkSrI)r!rar\rJrrrrL]s zPatchOperation.__eq__cCs ||k Sr@rrJrrrrMbszPatchOperation.__ne__cCsd |jjdd…¡S)Nú/éÿÿÿÿ)ÚjoinrdÚpartsr>rrrrbeszPatchOperation.pathcCs6zt|jjdƒWSty0|jjdYS0dS)Nrh)ÚintrdrjÚ ValueErrorr>rrrris zPatchOperation.keycCs*t|ƒ|jjd<|jj|_|j|jd<dS)Nrhrb)Ústrrdrjrbrcr\)r;rrrrrps N) r r r rr<r%rHrLrMr`rbrÚsetterrrrrraNs  rac@s(eZdZdZdd„Zdd„Zdd„ZdS) 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}')rdÚto_lastÚKeyErrorÚ IndexErrorr^r)r;r[ÚsubobjÚpartÚexÚmsgrrrr%zs  zRemoveOperation.applycCs0|j|kr,|j|kr$|jd7_n|d8}|S©Nr©rbr©r;rbrrrrÚ_on_undo_remove„s   zRemoveOperation._on_undo_removecCs0|j|kr,|j|kr$|jd8_n|d8}|SrvrwrxrrrÚ _on_undo_addŒs   zRemoveOperation._on_undo_addN©r r r rr%ryrzrrrrr4ws r4c@s(eZdZdZdd„Zdd„Zdd„ZdS) r5z,Adds an object property or an array element.c CsÎz|jd}Wn,ty:}ztdƒ‚WYd}~n d}~00|j |¡\}}t|tƒr–|dkrj| |¡qÊ|t|ƒks~|dkrˆt dƒ‚qÊ|  ||¡n4t|t ƒr¸|dur®|}qÊ|||<nt d  t|ƒ¡ƒ‚|S)Nrú/The operation does not contain a 'value' memberú-rzcan't insert outside of listúinvalid document type {0})r\rprrdror!rrrrÚinsertrÚ TypeErrorr^Útype)r;r[rrtrrrsrrrr%˜s&ÿ     zAddOperation.applycCs0|j|kr,|j|kr$|jd7_n|d7}|Srvrwrxrrrry¶s   zAddOperation._on_undo_removecCs0|j|kr,|j|kr$|jd8_n|d7}|Srvrwrxrrrrz¾s   zAddOperation._on_undo_addNr{rrrrr5•sr5c@s(eZdZdZdd„Zdd„Zdd„ZdS) r6z=Replaces an object property or an array element by new value.c CsÄz|jd}Wn,ty:}ztdƒ‚WYd}~n d}~00|j |¡\}}|durX|St|tƒr€|t|ƒksv|dkr¸tdƒ‚n8t|t ƒr¦||vr¸d  |¡}t|ƒ‚nt d  t |ƒ¡ƒ‚|||<|S)Nrr|rzcan't replace outside of listz'can't replace non-existent object '{0}'r~) r\rprrdror!rrrrr^r€r�)r;r[rrtrrrsrurrrr%Ês&ÿ     zReplaceOperation.applycCs|Sr@rrxrrrryäsz ReplaceOperation._on_undo_removecCs|Sr@rrxrrrrzçszReplaceOperation._on_undo_addNr{rrrrr6Çsr6c@sNeZdZdZdd„Zedd„ƒZedd„ƒZejdd„ƒZd d „Z d d „Z d S)r7z=Moves an object property or an array element to new location.c Csòzt|jdƒ}Wn,ty>}ztdƒ‚WYd}~n d}~00| |¡\}}z ||}Wn4ttfyŽ}ztt|ƒƒ‚WYd}~n d}~00|j|krž|St |t ƒr¼|j  |¡r¼tdƒ‚t d|jddœƒ  |¡}td|j|dœƒ  |¡}|S)NÚfromú.The operation does not contain a 'from' memberz(Cannot move values into its own childrenr.©r]rbr/©r]rbr)rr\rprrorqrrmrdr!rÚcontainsr4r%r5rc©r;r[Úfrom_ptrrtrrrsrrrrr%îs>ÿ "   ÿþýýüzMoveOperation.applycCs"t|jdƒ}d |jdd…¡S)Nr‚rgrh)rr\rirj©r;rˆrrrÚ from_pathszMoveOperation.from_pathcCs@t|jdƒ}zt|jdƒWSty:|jdYS0dS©Nr‚rh)rr\rkrjr€r‰rrrÚfrom_keys  zMoveOperation.from_keycCs,t|jdƒ}t|ƒ|jd<|j|jd<dSr‹)rr\rmrjrb)r;rrˆrrrrŒscCs\|j|kr,|j|kr$|jd7_n|d8}|j|krX|j|krP|jd7_n|d7}|Srv©rŠrŒrbrrxrrrry#s    zMoveOperation._on_undo_removecCs\|j|kr,|j|kr$|jd8_n|d8}|j|krX|j|krP|jd8_n|d7}|Srvr�rxrrrrz0s    zMoveOperation._on_undo_addN) r r r rr%r`rŠrŒrnryrzrrrrr7ës"    r7c@seZdZdZdd„ZdS)r8z!Test value by specified location.c CsÊz0|j |¡\}}|dur |}n|j ||¡}Wn0ty`}ztt|ƒƒ‚WYd}~n d}~00z|jd}Wn,tyœ}ztdƒ‚WYd}~n d}~00||krÆd}t|  |t |ƒ|t |ƒ¡ƒ‚|S)Nrr|z0{0} ({1}) is not equal to tested value {2} ({3})) rdroÚwalkrrrmr\rprr^r�)r;r[rrrsÚvalrtrrurrrr%As&"ÿÿzTestOperation.applyN©r r r rr%rrrrr8>sr8c@seZdZdZdd„ZdS)r9zA Copies an object property or an array element to a new location c Cs²zt|jdƒ}Wn,ty>}ztdƒ‚WYd}~n d}~00| |¡\}}zt ||¡}Wn4ttfy”}ztt |ƒƒ‚WYd}~n d}~00t d|j |dœƒ  |¡}|S)Nr‚rƒr/r…) rr\rprror3rZrqrrmr5rcr%r‡rrrr%\s&ÿ"ýüzCopyOperation.applyNr�rrrrr9Ysr9c@s|eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dd„Z dd„Z dd„Zdd„Zdd„ZdS)rQcCs4iig|_ggg|_g|_}||dg|dd…<dSr@)Ú index_storageÚindex_storage2Ú_DiffBuilder__root)r;Úrootrrrr<ts   zDiffBuilder.__init__cCsfz:|j|}| |¡}|dur*|g||<n|| |¡Wn&ty`|j| ||f¡Yn0dSr@)r‘Úgetrr€r’)r;rÚindexÚstÚstorageÚstoredrrrÚ store_indexzs    zDiffBuilder.store_indexcCs„z"|j| |¡}|r | ¡WSWn\ty~|j|}tt|ƒdddƒD]*}||d|krN| |¡dYSqNYn0dS)Nrrhr)r‘r•Úpopr€r’Úranger)r;rr—r™r˜ÚirrrÚ take_index†s  zDiffBuilder.take_indexcCs,|j}|d}|||g|d<|d<|dS)Nrr©r“)r;r]r”Zlastrrrr’szDiffBuilder.insertcCs*|\}}}||d<||d<g|dd…<dS)Nrrr)r;r–Z link_prevZ link_nextÚ_rrrr.˜s zDiffBuilder.removeccs.|j}|d}||ur*|dV|d}qdS©NrérŸ)r;Ústartr”ÚcurrrrrÚ iter_fromžs  zDiffBuilder.iter_fromccs.|j}|d}||ur*|dV|d}qdSr¡rŸ)r;r”r¤rrrrD¥s  zDiffBuilder.__iter__ccs |j}|d}||urœ|d|ur†|d|dd}}|j|jkr†t|ƒtkr†t|ƒtkr†td|j|jddœƒjV|dd}q|djV|d}qdS)Nrr¢r0rr…)r“rcr�r4r5r6r\)r;r”r¤Zop_firstZ op_secondrrrrS¬s&   ÿ þý   zDiffBuilder.executec Cs¼| |t¡}|durŠ|d}t|jƒtkrL| |¡D]}| |j|j¡|_q4| |¡|j t ||ƒkr¸t d|j t ||ƒdœƒ}|  |¡n.t dt ||ƒ|dœƒ}|  |¡}| ||t¡dS)Nr¢r1©r]r‚rbr/r…)ržÚ _ST_REMOVEr�rrkr¥ryrbr.rcÚ _path_joinr7rr5ršÚ_ST_ADD) r;rbrÚitemr–r]ÚvÚnew_opÚ new_indexrrrÚ _item_addedÀs*  ý ý zDiffBuilder._item_addedc Cs¼tdt||ƒdœƒ}| |t¡}| |¡}|durª|d}t|jƒtkrj| |¡D]}|  |j |j¡|_qR|  |¡|j |j kržt d|j |j dœƒ}||d<q¸|  |¡n| ||t¡dS)Nr.r„r¢r1r¦)r4r¨ržr©rr�rrkr¥rzrbr.rcr7ršr§) r;rbrrªr¬r–r­r]r«rrrÚ _item_removedÙs*þ    ý  zDiffBuilder._item_removedcCs | tdt||ƒ|dœƒ¡dS)Nr0r…)rr6r¨)r;rbrrªrrrÚ_item_replacedõs ýzDiffBuilder._item_replacedc Cs’t| ¡ƒ}t| ¡ƒ}||}||}|D]}| |t|ƒ||¡q,|D]}| |t|ƒ||¡qL||@D]}| ||||||¡qpdSr@)ÚsetÚkeysr¯rmr®rR) r;rbr+r,Zsrc_keysZdst_keysZ added_keysZ removed_keysrrrrÚ_compare_dictsüs   zDiffBuilder._compare_dictsc Csþt|ƒt|ƒ}}t||ƒ}t||ƒ}t|ƒD]Ê}||krÊ||||} } | | krXq.qøt| tƒr‚t| tƒr‚| t||ƒ| | ¡qøt| tƒr¬t| tƒr¬|  t||ƒ| | ¡qø|  ||| ¡|  ||| ¡q.||kræ|  ||||¡q.|  ||||¡q.dSr@) rÚmaxÚminrœr!rr³r¨rÚ_compare_listsr¯r®) r;rbr+r,Zlen_srcZlen_dstZmax_lenZmin_lenrÚoldÚnewrrrr¶ s*    ÿ ÿzDiffBuilder._compare_listscCsr||kr dSt|tƒr6t|tƒr6| t||ƒ||¡n8t|tƒr`t|tƒr`| t||ƒ||¡n| |||¡dSr@)r!rr³r¨rr¶r°)r;rbrr+r,rrrrR's ÿ ÿzDiffBuilder._compare_valuesN)r r r r<ršržrr.r¥rDrSr®r¯r°r³r¶rRrrrrrQrs  rQcCs,|dur |S|dt|ƒ dd¡ dd¡S)Nrgú~z~0z~1)rmr0rwrrrr¨7sr¨)F)3rZ __future__rrr3Ú functoolsÚinspectÚ itertoolsrVÚsysZ jsonpointerrrr©r§Úcollections.abcrrÚ ImportErrorZunicodermÚ __author__Ú __version__Z __website__Z __license__Ú version_infoÚbytesr"Ú Exceptionr rrÚAssertionErrorrr ÚpartialÚloadsrNr)r-Úobjectr#rar4r5r6r7r8r9rQr¨rrrrÚ!sT      %&)2$SF