
    Vi              	       t   S r SSKrSSKrSSKJr  SSKJr  SSKJr  SSKJ	r	J
r
JrJrJrJrJrJrJrJr  \" S5      r " S	 S
\	5      r " S S\\5      r " S S\5      r\" \SS5      r\" \S\R8                  \R:                  45      r\" SSRA                  \!" S \ 5       5      5      -  5      r"Sr#\R:                  " SS5        \#\$" S5      4-  r#\R:                  " SS5        \#\$" S5      4-  r# " S S\5      r&S r' " S S\5      r( " S S\(5      r) " S S\(5      r* " S S \(5      r+S!S"S#S$S%.r, " S& S'\5      r- " S( S)\5      r. " S* S+\5      r/\/" 5       r0 " S, S-\5      r1 " S. S/\5      r2S0 r3S1 r4S2 r5 " S3 S4\5      r6\" S55      r7 " S6 S7\5      r8 " S8 S9\	5      r9g! \% a     Nf = f! \% a     Nf = f):a  
.. versionadded:: 20.7.0

Sometimes you want to confirm that your target data matches your
code's assumptions. With glom, you don't need a separate validation
step, you can do these checks inline with your glom spec, using
:class:`~glom.Match` and friends.
    N)pprint)is_iterable)make_sentinel   )
	GlomErrorglomTMODEbbreprbbformatformat_invocationPathchain_childVal_MISSINGc                   2   ^  \ rS rSrSrU 4S jrS rSrU =r$ )
MatchError   z
Raised when a :class:`Match` or :data:`M` check fails.

>>> glom({123: 'a'}, Match({'id': int}))
Traceback (most recent call last):
...
MatchError: key 123 didn't match any of ['id']

c                 0   > [         [        U ]
  " U/UQ76   g N)superr   __init__)selffmtargs	__class__s      `/home/james-whalen/.local/share/pipx/venvs/semgrep/lib/python3.13/site-packages/glom/matching.pyr   MatchError.__init__%   s    j$(4t4    c                 T    U R                   S   U R                   SS  p![        U/UQ76 $ )Nr   r   )r   r   )r   r   r   s      r   get_messageMatchError.get_message(   s+    IIaL$))AB-T#d##r    )	__name__
__module____qualname____firstlineno____doc__r   r!   __static_attributes____classcell__r   s   @r   r   r      s    5$ $r   r   c                   2   ^  \ rS rSrSrU 4S jrS rSrU =r$ )TypeMatchError-   a  :exc:`MatchError` subtype raised when a
:class:`Match` fails a type check.

>>> glom({'id': 'a'}, Match({'id': int}))
Traceback (most recent call last):
...
TypeMatchError: error raised while processing.
 Target-spec trace, with error detail (most recent last):
 - Target: {'id': 'a'}
 - Spec: Match({'id': <type 'int'>})
 - Spec: {'id': <type 'int'>}
 - Target: 'a'
 - Spec: int
TypeMatchError: expected type int, not str
c                 .   > [         [        U ]  SX!5        g )Nz,expected type {0.__name__}, not {1.__name__})r   r-   r   )r   actualexpectedr   s      r   r   TypeMatchError.__init__>   s    nd,:H	Nr   c                 N    [        U R                  S   U R                  S   5      $ )N   r   )r-   r   r   s    r   __copy__TypeMatchError.__copy__B   s!     diilDIIaL99r   r#   )	r$   r%   r&   r'   r(   r   r6   r)   r*   r+   s   @r   r-   r-   -   s     N: :r   r-   c                   <    \ rS rSrSr\4S jrS rS rS r	S r
Srg	)
MatchH   af
  glom's ``Match`` specifier type enables a new mode of glom usage:
pattern matching.  In particular, this mode has been designed for
nested data validation.

Pattern specs are evaluated as follows:

  1. Spec instances are always evaluated first
  2. Types match instances of that type
  3. Instances of :class:`dict`, :class:`list`, :class:`tuple`,
     :class:`set`, and :class:`frozenset` are matched recursively
  4. Any other values are compared for equality to the target with
     ``==``

By itself, this allows to assert that structures match certain
patterns, and may be especially familiar to users of the `schema`_
library.

For example, let's load some data::

  >>> target = [
  ... {'id': 1, 'email': 'alice@example.com'},
  ... {'id': 2, 'email': 'bob@example.com'}]

A :class:`Match` pattern can be used to ensure this data is in its expected form:

  >>> spec = Match([{'id': int, 'email': str}])

This ``spec`` succinctly describes our data structure's pattern
Specifically, a :class:`list` of :class:`dict` objects, each of
which has exactly two keys, ``'id'`` and ``'email'``, whose values are
an :class:`int` and :class:`str`, respectively. Now,
:func:`~glom.glom` will ensure our ``target`` matches our pattern
``spec``:

  >>> result = glom(target, spec)
  >>> assert result == \
  ... [{'id': 1, 'email': 'alice@example.com'}, {'id': 2, 'email': 'bob@example.com'}]

With a more complex :class:`Match` spec, we can be more precise:

  >>> spec = Match([{'id': And(M > 0, int), 'email': Regex('[^@]+@[^@]+')}])

:class:`~glom.And` allows multiple conditions to be applied.
:class:`~glom.Regex` evaluates the regular expression against the
target value under the ``'email'`` key.  In this case, we take a
simple approach: an email has exactly one ``@``, with at least one
character before and after.

Finally, :attr:`~glom.M` is our stand-in for the current target
we're matching against, allowing us to perform in-line comparisons
using Python's native greater-than operator (as well as
others). We apply our :class:`Match` pattern as before::

  >>> assert glom(target, spec) == \
  ... [{'id': 1, 'email': 'alice@example.com'}, {'id': 2, 'email': 'bob@example.com'}]

And as usual, upon a successful match, we get the matched result.

.. note::

   For Python 3.6+ where dictionaries are ordered, keys in the target
   are matched against keys in the spec in their insertion order.

.. _schema: https://github.com/keleshev/schema

Args:
   spec: The glomspec representing the pattern to match data against.
   default: The default value to be returned if a match fails. If not
     set, a match failure will raise a :class:`MatchError`.

c                     Xl         X l        g r   )specdefault)r   r<   r=   s      r   r   Match.__init__   s    	r   c                     [         U[        '    U[           " XR                  U5      nU$ ! [         a$    U R
                  [        L a  e U R
                  n U$ f = fr   )_glom_matchr
   r   r<   r   r=   r   )r   targetscoperets       r   glomitMatch.glomit   sY    !d	+fii7C
 
	  	||x',,C
		s   + *AAc                     [        X5      $ )zA convenience function a :class:`Match` instance which returns the
matched value when *target* matches, or raises a
:exc:`MatchError` when it does not.

Args:
  target: Target value or data structure to match against.

Raises:
  glom.MatchError

)r   r   rA   s     r   verifyMatch.verify   s     F!!r   c                 <     [        X5        g! [         a     gf = f)zA convenience method on a :class:`Match` instance, returns
``True`` if the *target* matches, ``False`` if not.

>>> Match(int).matches(-1.0)
False

Args:
   target: Target value or data structure to match against.
FT)r   r   rG   s     r   matchesMatch.matches   s(    	   		s    
c                 d    U R                   R                  < S[        U R                  5      < S3$ N())r   r$   r   r<   r5   s    r   __repr__Match.__repr__   s     >>22F4994EFFr   )r=   r<   N)r$   r%   r&   r'   r(   r   r   rD   rH   rK   rQ   r)   r#   r   r   r9   r9   H   s(    FN &. " Gr   r9   	fullmatchz'func' must be one of %s, c              #   \   #    U  H"  o=(       a    UR                   =(       d    S v   M$     g7f)NoneN)r$   ).0es     r   	<genexpr>rY      s     
?!%v%s   *,r#    r   c                   2    \ rS rSrSrSrSS jrS rS rSr	g)	Regex   z
checks that target is a string which matches the passed regex pattern

raises MatchError if there isn't a match; returns Target if match

variables captures in regex are added to the scope so they can
be used by downstream processes
)flagsfunc
match_funcpatternNc                    U[         ;  a  [        e[        R                  " X5      nU[        R                  L a  UR                  nOjU[        R
                  L a  UR
                  nOJ[        (       a  UR                  nO2[        R                  " SR                  U5      U5      nUR                  nX#sU l	        U l
        XQsU l        U l        g )Nz(?:{})\Z)_RE_VALID_FUNCS_RE_FUNC_ERRORrecompilematchsearch_RE_FULLMATCHrS   formatr^   r_   r`   ra   )r   ra   r^   r_   regexr`   s         r   r   Regex.__init__   s    &  

7*288JRYYJ}"__


;#5#5g#>F"[[
 %
DI(2%r   c                     [        U5      [        ;  a  [        S[        U5      [        5      eU R                  U5      nU(       d  [        SU R                  5      eUR                  UR                  5       5        U$ )Nz3{0!r} not valid as a Regex target -- expected {1!r}z"target did not match pattern {0!r})type	_RE_TYPESr   r`   ra   update	groupdictr   rA   rB   rg   s       r   rD   Regex.glomit   sd    <y(EtF|U^` `'A4<<PPU__&'r   c                    S[        U R                  5      -   nU R                  (       a  US[        U R                  5      -   -  nU R                  b  USU R                  R                  -   -  nUS-  nU R
                  R                  U-   $ )NrO   z, flags=z, func=rP   )r   ra   r^   r_   r$   r   )r   r   s     r   rQ   Regex.__repr__   su    VDLL))::J

!333D99 I		 2 222D~~&&--r   )r   N)
r$   r%   r&   r'   r(   	__slots__r   rD   rQ   r)   r#   r   r   r\   r\      s     ;I<".r   r\   c                     U [         L a  [        U 5      $ [        U [        5      (       a  S[	        U 5      -   S-   $ [	        U 5      $ rN   )Mrepr
isinstance_MExprr   childs    r   _bool_child_reprr~      s>    zE{	E6	"	"VE]"S((%=r   c                   >    \ rS rSrS rS rS rS rS rS r	S r
S	rg
)_Booli  c                    Xl         U(       d.  [        SR                  U R                  R                  5      5      eUR                  S[        5      U l        U(       a%  [        S[        UR                  5       5      -  5      eg )Nz need at least one operand for {}r=   zgot unexpected kwargs: %r)children
ValueErrorrj   r   r$   popr   r=   	TypeErrorlistkeys)r   r   kws      r   r   _Bool.__init__  sg     ?FF'') * *vvi27$rwwy/IJJ r   c                     [        X5      $ r   Andr   others     r   __and___Bool.__and__      4r   c                     [        X5      $ r   Orr   s     r   __or___Bool.__or__      $r   c                     [        U 5      $ r   Notr5   s    r   
__invert___Bool.__invert__      4yr   c                      U R                  X5      $ ! [         a#    U R                  [        La  U R                  s $ e f = fr   )_glomitr   r=   r   r   rA   rB   s      r   rD   _Bool.glomit  s>    	<<.. 	||8+||#	s    )A A c                     [        U R                  S   [        [        45      (       a  g[	        U R                  S   5      [
        [        [        4;   a  U R                  S   R                  5       $ g)zshould this Or() repr as M |?r   TF)	rz   r   _MTyper{   rn   r   r   r   _m_reprr5   s    r   r   _Bool._m_repr"  sY     dmmA&(899a !c2s^3==#++--r   c                    U R                    Vs/ s H  n[        U5      PM     nnU R                  5       (       a=  U R                  [        L a*  SR                  U R                  5      R                  U5      $ U R                  [        La'  UR                  S[        U R                  5      -   5        U R                  R                  S-   SR                  U5      -   S-   $ s  snf )Nz {} zdefault=rO   rT   rP   )r   r~   r   r=   r   rj   OPjoinappendry   r   r$   )r   cchild_reprss      r   rQ   _Bool.__repr__+  s    48MMBMq'*MB<<>>dllh6==)..{;;<<x'zD,>>?~~&&,tyy/EEKK Cs   C )r   r=   N)r$   r%   r&   r'   r   r   r   r   rD   r   rQ   r)   r#   r   r   r   r     s'    K Lr   r   c                   ,    \ rS rSrSrSrSrS rS rSr	g)	r   i4  zz
Applies child specs one after the other to the target; if none of the
specs raises `GlomError`, returns the last result.
&r   c                 P    UnU R                    H  nU[           " XU5      nM     U$ r   )r   r   )r   rA   rB   resultr}   s        r   r   And._glomit<  s*    ]]E4[6F #r   c                 .    [        U R                  U4-   6 $ r   )r   r   r   s     r   r   And.__and__C  s    T]]eX-//r   r#   N)
r$   r%   r&   r'   r(   r   rv   r   r   r)   r#   r   r   r   r   4  s     
BI0r   r   c                   ,    \ rS rSrSrSrSrS rS rSr	g)	r   iH  z
Tries to apply the first child spec to the target, and return the result.
If `GlomError` is raised, try the next child spec until there are no
all child specs have been tried, then raise `MatchError`.
|r   c                     U R                   S S  H  n U[           " XU5      s  $    U[           " XR                   S   U5      $ ! [         a     MB  f = f)N)r   r   r   )r   rA   rB   r}   s       r   r   
Or._glomitQ  s]    ]]3B'ET{6%88 (
 T{6==#4e<<  s   A
AAc                 .    [        U R                  U4-   6 $ r   )r   r   r   s     r   r   	Or.__or__Y  s    DMMUH,..r   r#   N)
r$   r%   r&   r'   r(   r   rv   r   r   r)   r#   r   r   r   r   H  s    
 
BI=/r   r   c                   4    \ rS rSrSrSrS rS rS rS r	Sr
g)	r   i^  z
Inverts the *child*. Child spec will be expected to raise
:exc:`GlomError` (or subtype), in which case the target will be returned.

If the child spec does not raise :exc:`GlomError`, :exc:`MatchError`
will be raised.
r|   c                     Xl         g r   r|   )r   r}   s     r   r   Not.__init__h  s    
r   c                      U[            " XR                  U5        [        SU R                  5      e! [         a    Us $ f = f)Nzchild shouldn't have passed)r   r}   r   r   s      r   rD   
Not.glomitk  sD    	G$K

E2 94::FF  	M	s   2 A Ac                     [        U R                  [        [        45      (       a  g[	        U R                  5      [
        [        [        4;  a  gU R                  R                  5       $ )NTF)	rz   r}   r   r{   rn   r   r   r   r   r5   s    r   r   Not._m_reprs  sH    djj66"233

CS>1zz!!##r   c                     U R                   [        L a  gU R                  5       (       a  S[        U R                   5      -   S-   $ S[        U R                   5      -   S-   $ )Nz~Mz~(rP   zNot()r}   rx   r   r   r5   s    r   rQ   Not.__repr__z  sM    ::?<<>>&,,s22tzz**S00r   N)r$   r%   r&   r'   r(   rv   r   rD   r   rQ   r)   r#   r   r   r   r   ^  s#     IG$1r   r   z==z!=z>=z<=)=!glc                   R    \ rS rSrSrSrS rS rS rS r	S r
S	 rS
 rS rS rSrg)	_MSubspeci  z8used by MType.__call__ to wrap a sub-spec for comparisonr<   c                     Xl         g r   r<   r   r<   s     r   r   _MSubspec.__init__  s    	r   c                     [        U SU5      $ Nr   r{   r   s     r   __eq___MSubspec.__eq__      dC''r   c                     [        U SU5      $ Nr   r   r   s     r   __ne___MSubspec.__ne__  r   r   c                     [        U SU5      $ N>r   r   s     r   __gt___MSubspec.__gt__  r   r   c                     [        U SU5      $ N<r   r   s     r   __lt___MSubspec.__lt__  r   r   c                     [        U SU5      $ Nr   r   r   s     r   __ge___MSubspec.__ge__  r   r   c                     [        U SU5      $ Nr   r   r   s     r   __le___MSubspec.__le__  r   r   c                 6    S[        U R                  5      < S3$ )NzM(rP   )r   r<   r5   s    r   rQ   _MSubspec.__repr__  s     +--r   c                 v    U[            " XR                  U5      nU(       a  U$ [        SU R                  U5      e)Nz+expected truthy value from {0!r}, got {1!r})r   r<   r   rr   s       r   rD   _MSubspec.glomit  s3    dFIIu5MF		SXYYr   r   N)r$   r%   r&   r'   r(   rv   r   r   r   r   r   r   r   rQ   rD   r)   r#   r   r   r   r     s8    BI((((((.Zr   r   c                   @    \ rS rSrSrS rS r\rS rS r	S r
S rSrg	)
r{   i  lhsoprhsc                 .    XUsU l         U l        U l        g r   r   )r   r   r   r   s       r   r   _MExpr.__init__  s    &)s#$'48r   c                     [        X5      $ r   r   r   s     r   r   _MExpr.__and__  r   r   c                     [        X5      $ r   r   r   s     r   r   _MExpr.__or__  r   r   c                     [        U 5      $ r   r   r5   s    r   r   _MExpr.__invert__  r   r   c                 ~   U R                   U R                  U R                  pTnU[        L a  UnU[        L a  Un[	        U5      [
        L a  U[           " XR                  U5      n[	        U5      [
        L a  U[           " XR                  U5      nUS:H  =(       a    X5:H  =(       dl    US:H  =(       a    X5:g  =(       dU    US:H  =(       a    X5:  =(       d>    US:H  =(       a    X5:  =(       d'    US:H  =(       a    X5:  =(       d    US:H  =(       a    X5:*  nU(       a  U$ [        SU[        R                  XD5      U5      e)Nr   r   r   r   r   r   z{0!r} {1} {2!r})r   r   r   rx   rn   r   r   r<   r   	_M_OP_MAPget)r   rA   rB   r   r   r   matcheds          r   rD   _MExpr.glomit  s   xx$((!8C!8C9	!+fhh6C9	!+fhh6C3Y%3: '3Y%3:'3Y$39' 3Y$39' 3Y%3:	'
 3Y%3: 	 M*Cr1FLLr   c                     [         R                  U R                  U R                  5      nSR                  U R                  XR
                  5      $ )Nz{!r} {} {!r})r   r   r   rj   r   r   )r   r   s     r   rQ   _MExpr.__repr__  s5    ]]477DGG,$$TXXr88<<r   N)r$   r%   r&   r'   rv   r   r   __rand__r   r   rD   rQ   r)   r#   r   r   r{   r{     s-    $I3  HM,=r   r{   c                   h    \ rS rSrSrSrS rS rS rS r	S r
S	 rS
 rS r\rS rS rS rS rSrg)r   i  a  :attr:`~glom.M` is similar to :attr:`~glom.T`, a stand-in for the
current target, but where :attr:`~glom.T` allows for attribute and
key access and method calls, :attr:`~glom.M` allows for comparison
operators.

If a comparison succeeds, the target is returned unchanged.
If a comparison fails, :class:`~glom.MatchError` is thrown.

Some examples:

>>> glom(1, M > 0)
1
>>> glom(0, M == 0)
0
>>> glom('a', M != 'b') == 'a'
True

:attr:`~glom.M` by itself evaluates the current target for truthiness.
For example, `M | Val(None)` is a simple idiom for normalizing all falsey values to None:

>>> from glom import Val
>>> glom([0, False, "", None], [M | Val(None)])
[None, None, None, None]

For convenience, ``&`` and ``|`` operators are overloaded to
construct :attr:`~glom.And` and :attr:`~glom.Or` instances.

>>> glom(1.0, (M > 0) & float)
1.0

.. note::

   Python's operator overloading may make for concise code,
   but it has its limits.

   Because bitwise operators (``&`` and ``|``) have higher precedence
   than comparison operators (``>``, ``<``, etc.), expressions must
   be parenthesized.

   >>> M > 0 & float
   Traceback (most recent call last):
   ...
   TypeError: unsupported operand type(s) for &: 'int' and 'type'

   Similarly, because of special handling around ternary
   comparisons (``1 < M < 5``) are implemented via
   short-circuiting evaluation, they also cannot be captured by
   :data:`M`.

r#   c                     [        U[        [        5      5      (       d!  [        S[        U5      R                  -  5      e[        U5      $ )zDwrap a sub-spec in order to apply comparison operators to the resultz&M() only accepts T-style specs, not %s)rz   rn   r	   r   r$   r   r   s     r   __call___MType.__call__	  s:    $Q(( DtDzGZGZZ[[r   c                     [        U SU5      $ r   r   r   s     r   r   _MType.__eq__  r   r   c                     [        U SU5      $ r   r   r   s     r   r   _MType.__ne__  r   r   c                     [        U SU5      $ r   r   r   s     r   r   _MType.__gt__  r   r   c                     [        U SU5      $ r   r   r   s     r   r   _MType.__lt__  r   r   c                     [        U SU5      $ r   r   r   s     r   r   _MType.__ge__  r   r   c                     [        U SU5      $ r   r   r   s     r   r   _MType.__le__   r   r   c                     [        X5      $ r   r   r   s     r   r   _MType.__and__#  r   r   c                     [        X5      $ r   r   r   s     r   r   _MType.__or__(  r   r   c                     [        U 5      $ r   r   r5   s    r   r   _MType.__invert__+  r   r   c                     g)Nrx   r#   r5   s    r   rQ   _MType.__repr__.  s    r   c                 ,    U(       a  U$ [        SU5      e)Nz{0!r} not truthy)r   )r   rA   r<   s      r   rD   _MType.glomit1  s    M+V44r   N)r$   r%   r&   r'   r(   rv   r  r   r   r   r   r   r   r   r  r   r   rQ   rD   r)   r#   r   r   r   r     sR    1d I((((((  H5r   r   c                   4    \ rS rSrSrSr\4S jrS rS r	Sr
g)	Optionali;  a  Used as a :class:`dict` key in a :class:`~glom.Match()` spec,
marks that a value match key which would otherwise be required is
optional and should not raise :exc:`~glom.MatchError` even if no
keys match.

For example::

  >>> spec = Match({Optional("name"): str})
  >>> glom({"name": "alice"}, spec)
  {'name': 'alice'}
  >>> glom({}, spec)
  {}
  >>> spec = Match({Optional("name", default=""): str})
  >>> glom({}, spec)
  {'name': ''}

)keyr=   c                     [        U5      [        [        4;   a  [        S5      e[	        U5        [        U5      S:w  a  [        SR                  U5      5      eXsU l        U l	        g )Nzdouble wrapping of Optionalr   z4Optional() keys must be == match constants, not {!r})
rn   Requiredr  r   hash_precedencer   rj   r   r=   )r   r   r=   s      r   r   Optional.__init__O  sY    98,,9::S	sq SZZ[^_``!$$,r   c                 P    XR                   :w  a  [        SXR                   5      eU$ )Nztarget {0} != spec {1})r   r   r   s      r   rD   Optional.glomitW  s#    XX5vxxHHr   c                 d    U R                   R                  < S[        U R                  5      < S3$ rN   r   r$   r   r   r5   s    r   rQ   Optional.__repr__\       >>22F4884DEEr   )r=   r   N)r$   r%   r&   r'   r(   rv   r   r   rD   rQ   r)   r#   r   r   r  r  ;  s!    " #I$, .
Fr   r  c                   (    \ rS rSrSrSrS rS rSrg)r"  i`  a6  Used as a :class:`dict` key in :class:`~glom.Match()` mode, marks
that a key which might otherwise not be required should raise
:exc:`~glom.MatchError` if the key in the target does not match.

For example::

  >>> spec = Match({object: object})

This spec will match any dict, because :class:`object` is the base
type of every object::

  >>> glom({}, spec)
  {}

``{}`` will also match because match mode does not require at
least one match by default. If we want to require that a key
matches, we can use :class:`~glom.Required`::

  >>> spec = Match({Required(object): object})
  >>> glom({}, spec)
  Traceback (most recent call last):
  ...
  MatchError: error raised while processing.
   Target-spec trace, with error detail (most recent last):
   - Target: {}
   - Spec: Match({Required(object): <type 'object'>})
   - Spec: {Required(object): <type 'object'>}
  MatchError: target missing expected keys Required(object)

Now our spec requires at least one key of any type. You can refine
the spec by putting more specific subpatterns inside of
:class:`~glom.Required`.

r   c                     [        U5      [        [        4;   a  [        S5      e[	        U5        [        U5      S:X  a  [        S[        U5      -   5      eXl        g )Nzdouble wrapping of Requiredr   z)== match constants are already required: )	rn   r"  r  r   r#  r$  r   r   r   )r   r   s     r   r   Required.__init__  sN    98,,9::S	sq H6RU;VWWr   c                 d    U R                   R                  < S[        U R                  5      < S3$ rN   r)  r5   s    r   rQ   Required.__repr__  r+  r   N)	r$   r%   r&   r'   r(   rv   r   rQ   r)   r#   r   r   r"  r"  `  s    !D IFr   r"  c                 4   [        U 5      [        [        4;   a  U R                  n [        U 5      [        [
        4;   a-  U (       d  g[        U  Vs/ s H  n[        U5      PM     sn5      $ [        U [         5      (       a  g[        U S5      (       a  ggs  snf )z
in a dict spec, target-keys may match many
spec-keys (e.g. 1 will match int, M > 0, and 1);
therefore we need a precedence for which order to try
keys in; higher = later
r   r4   rD   r   )
rn   r"  r  r   tuple	frozensetmaxr$  rz   hasattr)rg   items     r   r$  r$    s|     E{x**		E{ui((%8%$K%%899%uh 9s   Bc                    [        U [        5      (       d  [        [        U 5      [        5      eUn[        R
                  S:  a  [        U[        S9nU Vs1 s H:  n[        U5      S:X  a  [        U5      [        Ld  [        U5      [        L d  M8  UiM<     nnU Vs0 s HC  n[        U5      [        L d  M  UR                  [        Ld  M,  UR                  UR                  _ME     nnU R                  5        Hz  u  pGU He  n[        U5      [        L a  UR                  n	OUn	 U[           " XIU5      nU[           " XqU   [        U5      5      Xd'   UR!                  U5          Mn     [%        SXC5      e   U(       a5  [%        SSR'                  U V
s/ s H  n
[)        U
5      PM     sn
5      5      eU$ s  snf s  snf ! ["         a     M  f = fs  sn
f )N)      r-  r   z#key {0!r} didn't match any of {1!r}z!target missing expected keys: {0}rT   )rz   dictr-   rn   sysversion_infosortedr$  r  r"  r=   r   r   itemsr   r   discardr   r   r   r   )rA   r<   rB   	spec_keysr   requiredr   valmaybe_spec_keyspec_keyrs              r   _handle_dictrG    s   fd##T&\400I
& 9+6	 " sq T#Yh%>9  	y  "
 )2B(19  	%([[%@ 		  B LLN'NN#x/)--)Dk#7 $Dk#N/C[QVEWX  0 ( BCSS! #" <dii\dHe\dWXPQ\dHe>fggM5"B   Ifs6   7F6F6F;8F;F;&G G 
GGc           	         [        U[        5      (       a(  [        X5      (       d  [        [        U 5      U5      e U $ [        U[        5      (       a  [	        XU5      $ [        U[
        [        [        45      (       a  [        U [        U5      5      (       d  [        [        U 5      [        U5      5      e/ nU  H[  nU H$  n UR                  U[           " XEU5      5          M+     U (       a'  U(       d   [        SU [        U5      R                  5      eWe   [        U5      [
        La  [        U5      " U5      $ U$ [        U[        5      (       a  [        U [        5      (       d  [        [        U 5      [        5      e[        U 5      [        U5      :w  a  [        SX5      e/ n[        X5       H$  u  pUR                  U[           " XU5      5        M&     [        U5      $ [!        U5      (       a(   U" U 5      (       a  U $  [        SUR                  U 5      eX:w  a  [        SX5      eU $ ! [         a  nUn S nAGM  S nAff = f! ["         a  n[        SUR                  X5      eS nAff = f)Nz{0!r} does not match empty {1}z{0!r} does not match {1!r}z1{0}({1!r}) did not validate (got exception {2!r})z/{0}({1!r}) did not validate (non truthy return))rz   rn   r-   r;  rG  r   setr4  r   r   r   r   r$   r3  lenzipcallable	Exception)
rA   r<   rB   r   r7  r}   rX   
last_error
sub_targetsub_specs
             r   r@   r@     s5   $&'' ft44 (Z MW 
D$		F%00	D4i0	1	1&$t*-- ftDz::D#MM%+d5"AB  $$8&$t*BUBUW W !   :T!:f%%	D%	 	 &%(( fu55v;#d)#96HH$'$5 JMM%+jEBC %6V}	$	_F|| 
 =t}}fV 	V	5vDDMA ! #!"J#2  	_CT]]TZ_ _	_s0   H17I 1
I	;II	
I2I--I2c                   0    \ rS rSrSr\4S jrS rS rSr	g)Switchi  a	  The :class:`Switch` specifier type routes data processing based on
matching keys, much like the classic switch statement.

Here is a spec which differentiates between lowercase English
vowel and consonant characters:

  >>> switch_spec = Match(Switch([(Or('a', 'e', 'i', 'o', 'u'), Val('vowel')),
  ...                             (And(str, M, M(T[2:]) == ''), Val('consonant'))]))

The constructor accepts a :class:`dict` of ``{keyspec: valspec}``
or a list of items, ``[(keyspec, valspec)]``. Keys are tried
against the current target in order. If a keyspec raises
:class:`GlomError`, the next keyspec is tried.  Once a keyspec
succeeds, the corresponding valspec is evaluated and returned.
Let's try it out:

  >>> glom('a', switch_spec)
  'vowel'
  >>> glom('z', switch_spec)
  'consonant'

If no keyspec succeeds, a :class:`MatchError` is raised. Our spec
only works on characters (strings of length 1). Let's try a
non-character, the integer ``3``:

  >>> glom(3, switch_spec)
  Traceback (most recent call last):
  ...
  glom.matching.MatchError: error raised while processing, details below.
   Target-spec trace (most recent last):
   - Target: 3
   - Spec: Match(Switch([(Or('a', 'e', 'i', 'o', 'u'), Val('vowel')), (And(str, M, (M(T[2:]) == '')), Val('...
   + Spec: Switch([(Or('a', 'e', 'i', 'o', 'u'), Val('vowel')), (And(str, M, (M(T[2:]) == '')), Val('conson...
   |\ Spec: Or('a', 'e', 'i', 'o', 'u')
   ||\ Spec: 'a'
   ||X glom.matching.MatchError: 3 does not match 'a'
   ||\ Spec: 'e'
   ||X glom.matching.MatchError: 3 does not match 'e'
   ||\ Spec: 'i'
   ||X glom.matching.MatchError: 3 does not match 'i'
   ||\ Spec: 'o'
   ||X glom.matching.MatchError: 3 does not match 'o'
   ||\ Spec: 'u'
   ||X glom.matching.MatchError: 3 does not match 'u'
   |X glom.matching.MatchError: 3 does not match 'u'
   |\ Spec: And(str, M, (M(T[2:]) == ''))
   || Spec: str
   |X glom.matching.TypeMatchError: expected type str, not int
  glom.matching.MatchError: no matches for target in Switch


.. note::

   :class:`~glom.Switch` is one of several *branching* specifier
   types in glom. See ":ref:`branched-exceptions`" for details on
   interpreting its exception messages.

A *default* value can be passed to the spec to be returned instead
of raising a :class:`MatchError`.

.. note::

  Switch implements control flow similar to the switch statement
  proposed in `PEP622 <https://www.python.org/dev/peps/pep-0622/>`_.

c                 L   [        U5      [        L a  [        UR                  5       5      n[        U5      [        La#  [	        SR                  [        U5      5      5      eXl        X l        U(       d1  [        SU R                  R                  < SU R                  < 35      eg )Nz\expected cases argument to be of format {{keyspec: valspec}} or [(keyspec, valspec)] not: {}zexpected at least one case in z, got: )rn   r;  r   r?  r   rj   casesr=   r   r   r$   )r   rT  r=   s      r   r   Switch.__init__>  s    ;$'E;d"3396$u+3FH H 
  $ 7 7E F Fr   c                 2   U R                    H/  u  p4 U[           " XU5        U[           " X[        U5      5      s  $    U R                  [
        La  U R                  $ [        SU R                  R                  -  5      e! [         a  n S nAM  S nAff = f)Nzno matches for target in %s)	rT  r   r   r   r=   r   r   r   r$   )r   rA   rB   keyspecvalspecges         r   rD   Switch.glomitO  s     $

GdFU3 ;vE0BCC !+ <<x'<<6$..:Q:QQRR  s   B
BBc                 d    U R                   R                  < S[        U R                  5      < S3$ rN   )r   r$   r   rT  r5   s    r   rQ   Switch.__repr__Z  s     >>22F4::4FGGr   )rT  r=   N)
r$   r%   r&   r'   r(   r   r   rD   rQ   r)   r#   r   r   rR  rR    s    AD '/ "	SHr   rR  RAISEc                   F    \ rS rSrSr\4S jr " S S\5      rS r	S r
Srg	)
Checkia  a  Check objects are used to make assertions about the target data,
and either pass through the data or raise exceptions if there is a
problem.

If any check condition fails, a :class:`~glom.CheckError` is raised.

Args:

   spec: a sub-spec to extract the data to which other assertions will
      be checked (defaults to applying checks to the target itself)
   type: a type or sequence of types to be checked for exact match
   equal_to: a value to be checked for equality match ("==")
   validate: a callable or list of callables, each representing a
      check condition. If one or more return False or raise an
      exception, the Check will fail.
   instance_of: a type or sequence of types to be checked with isinstance()
   one_of: an iterable of values, any of which can match the target ("in")
   default: an optional default value to replace the value when the check fails
            (if default is not specified, GlomCheckError will be raised)

Aside from *spec*, all arguments are keyword arguments. Each
argument, except for *default*, represent a check
condition. Multiple checks can be passed, and if all check
conditions are left unset, Check defaults to performing a basic
truthy check on the value.

c                    Xl         [        U5      U l        UR                  S[        5      U l        SS jnS nUR                  SU(       a  [        OU5      nUR                  S[        5      nUR                  S[        5      nUR                  S[        5      nUR                  S[        5      n	U(       a  [        S	UR                  5       -  5      eU" SS
[        U5      U l
        U" SSS US5      U l        U" SSS US5      U l        U[        La  U4U l        U	[        La  [        S5      e g U	[        La;  [        U	5      (       d  [        SU	-  5      eU	(       d  [        SU	< 35      eXl        g SU l        g )Nr=   c           	          U[         L a  g[        U5      (       d  U4nO!U(       d  U(       d  [        SU < SU< 35      eU H'  nU" U5      (       a  M  [        SU < SU< SU< 35      e   U$ )Nr#   z	expected z. argument to contain at least one value, not: z argument to be z, not: )r   r   r   )namecondr_   rC  can_be_emptyvs         r   _get_arg_val$Check.__init__.<locals>._get_arg_val  sm    hs##f /3S": ; ;Aww$(,dA&7 8 8  Jr   c                     [        U 5      $ r   )bool)rC  s    r   truthyCheck.__init__.<locals>.truthy  s    9r   validatern   instance_ofequal_toone_ofz unexpected keyword arguments: %rrL  za typec                 "    [        U [        5      $ r   rz   rn   xs    r   <lambda> Check.__init__.<locals>.<lambda>  s    *Q2Er   Fc                 "    [        U [        5      $ r   rq  rr  s    r   rt  ru    s    Jq$,?r   zIexpected "one_of" argument to be unset when "equal_to" argument is passedz3expected "one_of" argument to be iterable , not: %rz6expected "one_of" to contain at least one value, not: r#   )T)r<   r;  _orig_kwargsr   r]  r=   r   r   r   rL  
validatorsrm  typesvalsr   r   )
r   r<   kwargsrf  rj  rl  type_argrm  rn  ro  s
             r   r   Check.__init__  s}   	 Lzz)U3	"	 ::jf(&I::fh/jj9::j(3Hh/>NOO&z:xR'x(E{TY[!&("?5R
 8#!DIX% !A B B & 	 8#v&&  ".06"7 8 8 :@"C D DI 	 DIr   c                       \ rS rSrSrSrg)Check._ValidationErrori  z%for internal use inside of Check onlyr#   N)r$   r%   r&   r'   r(   r)   r#   r   r   _ValidationErrorr    s    /r   r  c           	         Un/ nU R                   [        La  U[           " XR                   U5      nU R                  (       a  [	        U5      U R                  ;  a  U R
                  [        La  U R
                  $ UR                  S[        U R                  5      S:X  a  U R                  S   R                  O.[        U R                   Vs/ s H  oUR                  PM     sn5      < S[	        U5      R                  < 35        U R                  (       a  XR                  ;  a  U R
                  [        La  U R
                  $ [        U R                  5      S:X  a/  UR                  SR                  U R                  S   U5      5        O+UR                  SR                  U R                  U5      5        U R                  (       a8  [        U R                  5       H  u  pg U" U5      nUSL a  U R                  eM!     U R$                  (       a  ['        XR$                  5      (       d  U R
                  [        La  U R
                  $ UR                  S[        U R$                  5      S:X  a  U R$                  S   R                  O.[        U R$                   Vs/ s H  oUR                  PM     sn5      < S[	        U5      R                  < 35        U(       a  [)        X@U[*           5      eU$ s  snf ! [          a  n	S[#        US	S 5      -  =(       d    S
U-  n
[	        U	5      U R                  L a'  U R
                  [        La  U R
                  s S n	A	s  $ OU
SU	-  -  n
UR                  U
5         S n	A	GM  S n	A	ff = fs  snf )Nzexpected type to be r   r   z, found type zexpected {}, found {}zexpected one of {}, found {}Fz$expected %r check to validate targetr$   z#%sz (got exception: %r)zexpected instance of z, found instance of )r<   r	   r   ry  rn   r=   r]  r   rJ  r$   r3  rz  rj   rx  	enumerater  rM  getattrrm  rz   
CheckErrorr   )r   rA   rB   rC   errsti	validatorresrX   msgs              r   rD   Check.glomit  s   99A4[E:F::$v,djj8||5(||#KK36tzz?a3GA//#$DAZZ$DEFf..0 1
 99yy0||5(||#499~"3::499Q<PQ:AA$))VTU?? )$// :%#F+Ce|"333 $ !; Jv7G7G$H$H ||5(||#KK9<T=M=M9NRS9S))!,55#9I9I$J9IAZZ9I$JKLf..0 1
 Tt55
Q %E" ! %A$Y
DAB QFKai Aw$"7"77<<u4#'<</ 5 599KK$$%$ %Ks1   K2$K7N7
NAM<NM<<Nc                     U R                   R                  nU R                  [        La  U R                  4OSn[	        XU R
                  [        S9$ )Nr#   )ry   )r   r$   r<   r	   r   rw  r   )r   cnposargss      r   rQ   Check.__repr__  s>    ^^$$"&))1"4499," d.?.?fMMr   )rw  r=   rm  r<   ry  rx  rz  N)r$   r%   r&   r'   r(   r	   r   rM  r  rD   rQ   r)   r#   r   r   r_  r_  a  s*    >  6p9 2hNr   r_  c                   0    \ rS rSrSrS rS rS rS rSr	g)	r  i  a  This :exc:`GlomError` subtype is raised when target data fails to
pass a :class:`Check`'s specified validation.

An uncaught ``CheckError`` looks like this::

   >>> target = {'a': {'b': 'c'}}
   >>> glom(target, {'b': ('a.b', Check(type=int))})
   Traceback (most recent call last):
   ...
   CheckError: target at path ['a.b'] failed check, got error: "expected type to be 'int', found type 'str'"

If the ``Check`` contains more than one condition, there may be
more than one error message. The string rendition of the
``CheckError`` will include all messages.

You can also catch the ``CheckError`` and programmatically access
messages through the ``msgs`` attribute on the ``CheckError``
instance.

c                 (    Xl         X l        X0l        g r   )msgs	check_objpath)r   r  checkr  s       r   r   CheckError.__init__  s    		r   c                 N   SU R                   -  nU R                  R                  [        La  USU R                  R                  < 3-  n[	        U R
                  5      S:X  a  USU R
                  S   < 3-  nU$ US[	        U R
                  5      < SU R
                  < 3-  nU$ )Nztarget at path %s failed check,z subtarget at r   z got error: r   z got z	 errors: )r  r  r<   r	   rJ  r  )r   r  s     r   r!   CheckError.get_message  s    /$));>>a')<)<>>Ctyy>Qtyy|55C 
 3tyy>499EEC
r   c                 d    [        U 5      " U R                  U R                  U R                  5      $ r   )rn   r  r  r  r5   s    r   r6   CheckError.__copy__  s!    Dz$))T^^TYY??r   c                     U R                   R                  nU< SU R                  < SU R                  < SU R                  < S3$ )NrO   rT   rP   )r   r$   r  r  r  )r   r  s     r   rQ   CheckError.__repr__  s,    ^^$$#%tyy$..$))LLr   )r  r  r  N)
r$   r%   r&   r'   r(   r   r!   r6   rQ   r)   r#   r   r   r  r    s    (
@Mr   r  ):r(   re   r<  r   boltons.iterutilsr   boltons.typeutilsr   corer   r   r	   r
   r   r   r   r   r   r   r   r   r   r-   objectr9   r  ri   rI  rh   rg   rc   r   r   r>  rd   ro   rn   rM  r\   r~   r   r   r   r   r   r   r{   r   rx   r  r"  r$  rG  r@   rR  r]  r_  r  r#   r   r   <module>r     s
   
 
  ) + g g g $$ $$:Z :6uGF uGp K.}dBIIrxx@A6$))

?
??;A B C 		xxST#YL y	xxST#YL y-.F -.b*LF *LZ0% 0(/ /,!1% !1H T48	 Z  ZF)=V )=X`5V `5F H"Fv "FJ.Fv .Fb(!H/d`HV `HF 	gSNF SNl*M *Ma  $   $ s$   2F" F. "F+*F+.F76F7