
    
3jB                     t   S SK r S SKrS SKJr  S SKJr  \R                  " \5      rSr	Sr
 " S S5      r\" S5      r\" S	5      r " S
 S\5      r " S S\5      rS rS\	4r\" SS9\4S j5       rS"S jrS rS rS"S jrS r\S4S jrS"S jr\S4S jr\ R8                  " S5      rS r " S S 5      rS! r g)#    N)literal_eval)	lru_cacheGETATTRGETc                   0    \ rS rSrSrS rS rS rS rSr	g)	_WildcardToken   zSentinel object for wildcard path tokens.

Using a dedicated class (instead of plain strings) ensures that a literal
dict key ``'*'`` (parsed from ``root['*']``) is never confused with the
wildcard ``*`` (parsed from ``root[*]``).
c                     Xl         g N_symbol)selfsymbols     G/home/wildlama/miniconda3/lib/python3.13/site-packages/deepdiff/path.py__init___WildcardToken.__init__   s        c                     U R                   $ r   r   r   s    r   __repr___WildcardToken.__repr__   s    ||r   c                 b    [        U[        5      =(       a    U R                  UR                  :H  $ r   )
isinstancer   r   )r   others     r   __eq___WildcardToken.__eq__   s!    %0RT\\U]]5RRr   c                 0    [        SU R                  45      $ )Nr   )hashr   r   s    r   __hash___WildcardToken.__hash__   s    %t||455r   r   N)
__name__
__module____qualname____firstlineno____doc__r   r   r   r   __static_attributes__ r   r   r   r      s    S6r   r   ***c                       \ rS rSrSrg)PathExtractionError$   r'   Nr!   r"   r#   r$   r&   r'   r   r   r+   r+   $       r   r+   c                       \ rS rSrSrg)RootCanNotBeModified(   r'   Nr-   r'   r   r   r0   r0   (   r.   r   r0   c                    U(       d  g UR                  S5      (       d  US;   a6  US:X  a  [        O[        nU R                  US:X  a  [        O[
        U45        g SnSU;   d  SU;   a  SnO [        U5      nSnU(       a  US	   US
   :X  a  US	   S;   a  USS
 nUS:X  a  [        O[        nU R                  X45        g g ! [        [        4 a    Sn N[f = f)N__)r(   r)   .r(   F   𝆺𝅥𝅯\Tr      "'   )	
startswithr   r   appendSINGLE_WILDCARDMULTI_WILDCARDr   
ValueErrorSyntaxError)elementseleminsideactionremove_quotess        r   _add_to_elementsrG   ,   s    ??4   ; &#W3FOO_QWXYT>TT\ M%#D) % T!WR0T!W
5J2;D"cMs'/ !$ , % $%s   -C CCrooti   )maxsizec                    [        U [        [        45      (       a  U $ / nU(       a  UR                  U5        SnSnSnU SS n / nSnSnU  GH  n	US:X  a  X9-  nOU	S;   a2  X9-  nU(       a  X:w  d!  U(       + nU(       a  U	nO[	        X#U5        SnSnOU(       a  X9-  nOU	S:X  a8  US:X  a  [	        X#U5        SnSnOUS:X  a  X9-  nOSnUR                  S5        SnOrU	S:X  a%  US:X  a  X9-  nOaUS:X  a  [	        X#U5        SnOLSnSnOGU	S	:X  a=  U(       a  US
   S:X  a  UR                  5         U(       a  X9-  nO[	        X#U5        SnSnOX9-  nU	nGM     U(       a  [	        X#U5        [        U5      $ )a&  
Given a path, it extracts the elements that form the path and their relevant most likely retrieval action.

    >>> from deepdiff import _path_to_elements
    >>> path = "root[4.3].b['a3']"
    >>> _path_to_elements(path, root_element=None)
    [(4.3, 'GET'), ('b', 'GETATTR'), ('a3', 'GET')]
 FN   r5   r8   [r4   ]r7   )r   tuplelistr=   rG   pop)
pathroot_elementrB   rC   rD   	prev_charbracketsinside_quotes
quote_usedchars
             r   _path_to_elementsrY   M   s    $&&H%DFI8DHMJLDZLD Z%7$1 1 !%J$XV<D!#JLDS[} 83$S[}3 8S[HRLC/ 8LD	a b 0?r   c                     U H7  u  p4[        U5        U[        :X  a  X   n M   U[        :X  d  M,  [        X5      n M9     U $ r   )
check_elemr   r   getattr)objrB   next_elementrC   rE   s        r   _get_nested_objr_      s=    "4S=)Cw#$C # Jr   c                 \    U[        U 5      S-
  :  a  0 $ [        U[        5      (       a  / $ 0 $ )Nr;   )lenr   int)rB   rC   indexr^   s       r   _guess_typerd      s/    s8}q  	,$$	Ir   c                     [        U [        5      (       a9  U R                  S5      (       a"  U R                  S5      (       a  [	        S5      eg g g )Nr3   z+traversing dunder attributes is not allowed)r   strr<   endswithr@   )rC   s    r   r[   r[      sC    $!6!64==;N;NFGG <O!6r   c           
         S nS nU n[        U5       HB  u  nu  px[        U5        U n	U[        :X  a   X   n U	nOU[        :X  a  [        X5      n U	nUnUnMD     U $ ! [         a    [	        XXb5      X'   X   n U	n N*[
         a    [        U [        5      (       ai  [        U[        5      (       aT  U[        U 5      :  aE  U R                  S /U[        U 5      -
  -  5        U R                  [	        XXb5      5        U S   n U	n N[        U [        5      (       aM  [        U 5      S:X  a>  U(       a7  U[	        XXb5      0n U[        :X  a  XU'   O[        U[        U5      U 5        X   n  GNf = f)Nr7   r   )	enumerater[   r   KeyErrorrd   
IndexErrorr   rP   rb   ra   extendr=   setattrrf   r   r\   )
r]   rB   r^   	prev_elemprev_actionprev_objrc   rC   rE   	_prev_objs
             r   _get_nested_obj_and_forcerr      s^   IKH!*8!4~4	S=$i$( w#$C H	= "5> J1  %'L	i$ $c4((Zc-B-BtsSVxGWJJvC9:JJ{85OPb'C(HT**s3x1}  XU!QRC"c).1+#i.#>)C$s   AE':BE'A"E'&E'c                 ,    [        USS9n[        X5      $ )a  
Get the item from obj based on path.

Example:

    >>> from deepdiff import extract
    >>> obj = {1: [{'2': 'b'}, 3], 2: [4, 5]}
    >>> path = "root[1][0]['2']"
    >>> extract(obj, path)
    'b'

Note that you can use extract in conjunction with DeepDiff results
or even with the search and :ref:`deepsearch_label` modules. For example:

    >>> from deepdiff import grep
    >>> obj = {1: [{'2': 'b'}, 3], 2: [4, 5]}
    >>> result = obj | grep(5)
    >>> result
    {'matched_values': ['root[2][1]']}
    >>> result['matched_values'][0]
    'root[2][1]'
    >>> path = result['matched_values'][0]
    >>> extract(obj, path)
    5


.. note::
    Note that even if DeepDiff tried gives you a path to an item in a set,
    there is no such thing in Python and hence you will get an error trying
    to extract that item from a set.
    If you want to be able to get items from sets, use the SetOrdered module
    to generate the sets.
    In fact Deepdiff uses SetOrdered as a dependency.

    >>> from deepdiff import grep, extract
    >>> obj = {"a", "b"}
    >>> obj | grep("b")
    Set item detected in the path.'set' objects do NOT support indexing. But DeepSearch will still report a path.
    {'matched_values': SetOrdered(['root[0]'])}
    >>> extract(obj, 'root[0]')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "deepdiff/deepdiff/path.py", line 126, in extract
        return _get_nested_obj(obj, elements)
      File "deepdiff/deepdiff/path.py", line 84, in _get_nested_obj
        obj = obj[elem]
    TypeError: 'set' object is not subscriptable
    >>> from orderly_set import SetOrdered
    >>> obj = SetOrdered(["a", "b"])
    >>> extract(obj, 'root[0]')
    'a'

NrS   )rY   r_   )r]   rR   rB   s      r   extractru      s    l !D9H3))r   Fc                     [        XS9n[        U5      nU(       a  [        U5        USL a  U Vs/ s H  oDS   PM	     sn$ U Vs/ s H  oDS   US   S.PM     sn$ s  snf s  snf )aC  
Parse a path to a format that is machine readable

**Parameters**

path : A string
The path string such as "root[1][2]['age']"

root_element: string, default='root'
    What the root is called in the path.

include_actions: boolean, default=False
    If True, we return the action required to retrieve the item at each element of the path.  

**Examples**

    >>> from deepdiff import parse_path
    >>> parse_path("root[1][2]['age']")
    [1, 2, 'age']
    >>> parse_path("root[1][2]['age']", include_actions=True)
    [{'element': 1, 'action': 'GET'}, {'element': 2, 'action': 'GET'}, {'element': 'age', 'action': 'GET'}]
    >>>
    >>> parse_path("root['joe'].age")
    ['joe', 'age']
    >>> parse_path("root['joe'].age", include_actions=True)
    [{'element': 'joe', 'action': 'GET'}, {'element': 'age', 'action': 'GETATTR'}]

rt   Fr   r;   )elementrE   )rY   iternext)rR   rS   include_actionsresultis        r   
parse_pathr}     sh    < t?F&\FV%$%f!f%%7=>v!!!-v>> &>s   AA!c                 D   SU ;   nSU ;   nU(       aZ  U(       aS  U(       dL  / nU  H+  nUS;   a  UR                  S5        UR                  U5        M-     SSR                  U5      -   S-   nU$ U(       a  SU  S3nU$ U(       a  SU  S3nU$ Uc  U OUR                  U 5      nU$ )Nr:   r9   r8   r5   rK   )r=   joinformat)param	quote_str	has_quotehas_double_quote	new_paramrX   r{   s          r   stringify_elementr   9  s    uIe|%i	Dz!  (T"  rwwy))C/ M 
UG1
 M	 
UG1 M $+1A1A%1HMr   z'{}'c                    U (       d  US   $ US   /nSn U S   S   [         [        1;   a  SnU(       d'  U  Vs/ s H
  oU[         4PM     n nU S   S   US   4U S'   U  Hd  u  pg[        U[        5      (       a  U[         :X  a  [        Xb5      nU[         :X  a  UR                  SU S35        MP  UR                  SU 35        Mf     SR                  U5      $ ! [        [        [        4 a     Nf = fs  snf )	zX
Gets the path as an string.

For example [1, 2, 'age'] should become
root[1][2]['age']
r   Fr;   TrM   rN   r4   rK   )
r   r   rj   rk   	TypeErrorr   rf   r   r=   r   )rR   rS   r   r{   has_actionsr|   rw   rE   s           r   stringify_pathr   L  s     A1oFK71:#w'K "&'$QC$'71:|A/Qgs###';GS=MMAgYa.)MMAgY-(   776? j),  (s   C C2C/.C/z\[\*\*?\]|\.\*\*?(?=[.\[]|$)c                 >    [        [        R                  U 5      5      $ )z<Check if a path string contains wildcard segments (* or **).)bool_WILDCARD_REsearch)rR   s    r   path_has_wildcardr   q  s    ##D)**r   c                   <    \ rS rSrSrS rS rS rS rS r	S r
S	rg
)GlobPathMatcheriv  a  Pre-compiled matcher for a single glob pattern path.

Parses a pattern like ``root['users'][*]['password']`` into segments
and matches concrete path strings against it.

``*`` matches exactly one path segment (any key, index, or attribute).
``**`` matches zero or more path segments.
c                 D    Xl         [        US[        4S9nUSS  U l        g )NrH   rt   r;   )original_patternrY   r   _pattern)r   pattern_pathrB   s      r   r   GlobPathMatcher.__init__  s&     ,$\@QR r   c                 N    [        US[        4S9SS nU R                  USS0 SS9$ )z:Return True if *path_string* matches this pattern exactly.rH   rt   r;   Nr   Fallow_extra_targetrY   r   _match_segmentsr   path_stringtargets      r   matchGlobPathMatcher.match  s8    ";fg=NOPQPRS##FAq"#OOr   c                     [        US[        4S9SS n0 nU R                  USSUSS9=(       d    U R                  USS0 5      $ )zReturn True if *path_string* matches OR is an ancestor of a potential match.

This is needed for ``include_paths``: we must not prune a path that
could lead to a matching descendant.
rH   rt   r;   Nr   Fr   )rY   r   r   _could_match_descendant)r   r   r   memos       r   match_or_is_ancestor$GlobPathMatcher.match_or_is_ancestor  s\     #;fg=NOPQPRS$$VQ4E$R B//1bA	Cr   c                 N    [        US[        4S9SS nU R                  USS0 SS9$ )zReturn True if *path_string* matches OR is a descendant of a matching path.

Equivalent to: the pattern matches some prefix of *path_string*.
rH   rt   r;   Nr   Tr   r   r   s      r   match_or_is_descendant&GlobPathMatcher.match_or_is_descendant  s:    
 #;fg=NOPQPRS##FAq"#NNr   c                    X#4nXd;   a  XF   $ U R                   n[        U5      n[        U5      n	X):  a  X8:  a  Xr   S   n
U
[        L a;  [        X8S-   5       H$  nU R	                  XS-   XU5      (       d  M   SXF'     g   SXF'   gU
[
        L a  US-  nUS-  nOXU   S   :w  a  SXF'   gUS-  nUS-  nX):  a  X8:  a  M  X):  a(  Xr   S   [        L a  US-  nX):  a  Xr   S   [        L a  M  U(       a  X):H  nOX):H  =(       a    X8:H  nXU'   U$ )u   Recursive segment matcher with backtracking for ``**``.

``memo`` is a per-top-level-call dict keyed by ``(pi, ti)`` so each
state is computed at most once — turns the worst case from
exponential to ``O(len(pattern) * len(target))``.
r   r;   TF)r   ra   r?   ranger   r>   )r   r   pitir   r   keypattern
target_lenpattern_lenpat_elemkr{   s                r   r   GlobPathMatcher._match_segments  s?    h;9--[
'l2?{1~H>)r>2A++FFAEWXX$(	# 3 "	_,aabz!}, %DI aa% 2?* 7;q>^#C!GB 7;q>^#C &F&;2+;FS	r   c                    X#4nXT;   a  XE   $ U R                   nU[        U5      :X  a  U[        U5      :  nXtU'   U$ U[        U5      :  a  SXE'   gXb   S   nU[        L a3  U R                  XS-   X45      =(       d    U R                  XUS-   U5      nOLU[        L a  U R                  XS-   US-   U5      nO)XU   S   :w  a  SXE'   gU R                  XS-   US-   U5      nXtU'   U$ )zECheck if *target* is a prefix that could lead to a match deeper down.Fr   r;   )r   ra   r?   r   r>   )	r   r   r   r   r   r   r   r{   r   s	            r   r   'GlobPathMatcher._could_match_descendant  s   h;9--V#g,&FIMWDI;q>~%22662L P55f"q&$O (11&q&"q&$OF":a=(!	11&q&"q&$OFS	r   )r   r   N)r!   r"   r#   r$   r%   r   r   r   r   r   r   r&   r'   r   r   r   r   v  s)    %P
	CO+Zr   r   c                 T    U (       d  gU  Vs/ s H  n[        U5      PM     sn$ s  snf )zCompile a list of glob pattern strings into GlobPathMatcher objects.

Returns a list of ``GlobPathMatcher`` or ``None`` if *paths* is empty/None.
N)r   )pathsps     r   compile_glob_pathsr     s'    
 (-.1OA...s   %r   )!reloggingastr   	functoolsr   	getLoggerr!   loggerr   r   r   r>   r?   r@   r+   r0   rG   DEFAULT_FIRST_ELEMENTrY   r_   rd   r[   rr   ru   r}   r   r   compiler   r   r   r   r'   r   r   <module>r      s    	   			8	$
6 6( !%%	* 		: 	(<  )  :)> H HVH
#L7*t #8 $?N& '<v > zz+
o od/r   