
    Vi-                     *   S SK r S SK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  SSK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 S\5      rS r " S S\5      rS rg! \ a    \r NSf = f)    N)pprint)make_sentinel   )Tglom	GlomErrorformat_invocationbbreprUnregisteredTargetMODE)GROUPtarget_iterACC_TREECUR_AGG_MISSINGc                       \ rS rSrSrSrg)	FoldError   zbError raised when Fold() is called on non-iterable
targets, and possibly other uses in the future. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       a/home/james-whalen/.local/share/pipx/venvs/semgrep/lib/python3.13/site-packages/glom/reduction.pyr   r      s
    7r   r   c                   P    \ rS rSrSr\R                  4S jrS rS r	S r
S rSrg	)
Fold   a  The `Fold` specifier type is glom's building block for reducing
iterables in data, implementing the classic `fold
<https://en.wikipedia.org/wiki/Fold_(higher-order_function)>`_
from functional programming, similar to Python's built-in
:func:`reduce`.

Args:
   subspec: A spec representing the target to fold, which must be
      an iterable, or otherwise registered to 'iterate' (with
      :func:`~glom.register`).
   init (callable): A function or type which will be invoked to
      initialize the accumulator value.
   op (callable): A function to call on the accumulator value and
      every value, the result of which will become the new
      accumulator value. Defaults to :func:`operator.iadd`.

Usage is as follows:

   >>> target = [set([1, 2]), set([3]), set([2, 4])]
   >>> result = glom(target, Fold(T, init=frozenset, op=frozenset.union))
   >>> result == frozenset([1, 2, 3, 4])
   True

Note the required ``spec`` and ``init`` arguments. ``op`` is
optional, but here must be used because the :class:`set` and
:class:`frozenset` types do not work with addition.

While :class:`~glom.Fold` is powerful, :class:`~glom.Flatten` and
:class:`~glom.Sum` are subtypes with more convenient defaults for
day-to-day use.
c                    Xl         X l        X0l        [        U5      (       d'  [	        SU R
                  R                  < SU< 35      e[        U5      (       d'  [	        SU R
                  R                  < SU< 35      eg )Nzexpected callable for z op param, not: z init param, not: )subspecinitopcallable	TypeError	__class__r   )selfr"   r#   r$   s       r   __init__Fold.__init__:   sj    	||!^^44b: ; ;~~!^^44d< = = r   c           
         SnU[            [        L a   UR                  [        5      c
  X[        '   SnU R                  [
        La  U[           " XR                  U5      nU(       a  U R                  X[           5      $  U R                  [        X5      5      $ ! [         aD  n[        SU R                  R                  < S[        U5      R                  < SU< S35      eS nAff = f)NFTz	can only z on iterable targets, not z type ())r   r   getr   r"   r   r   _aggr   _foldr   r   r   r'   r   type)r(   targetscopeis_agguts        r   glomitFold.glomitE   s    ;%EIIg$6$>!'NF<<q 4[u=F99V8_55	T::k&899! 	T#~~66V8M8MrS T T	Ts    B 
C($?C##C(c                 ^    U R                  5       U R                  p2U H  nU" X$5      nM     U$ Nr#   r$   r(   iteratorretr$   vs        r   r/   
Fold._foldV   s-    ))+twwRAS*C  
r   c                 d    X;  a  U R                  5       X '   U R                  X    U5      X '   X    $ r8   r9   )r(   r1   trees      r   r.   	Fold._agg^   s1    DJWWTZ0
zr   c                     U R                   R                  nSU R                  0nU R                  [        R
                  La  U R                  US'   [        XR                  4U[        S9$ )Nr#   r$   repr)	r'   r   r#   r$   operatoriaddr	   r"   r
   )r(   cnkwargss      r   __repr__Fold.__repr__d   sQ    ^^$$$))$77(--'77F4L ll_f6JJr   )r#   r$   r"   N)r   r   r   r   r   rE   rF   r)   r5   r/   r.   rI   r   r   r   r   r   r      s+    > *2 	=T"Kr   r   c                   :   ^  \ rS rSrSr\\4U 4S jjrS rSr	U =r
$ )Suml   a  The `Sum` specifier type is used to aggregate integers and other
numericals using addition, much like the :func:`sum()` builtin.

   >>> glom(range(5), Sum())
   10

Note that this specifier takes a callable *init* parameter like
its friends, so to change the start value, be sure to wrap it in a
callable::

   >>> glom(range(5), Sum(init=lambda: 5.0))
   15.0

To "sum" lists and other iterables, see the :class:`Flatten`
spec. For other objects, see the :class:`Fold` specifier type.

c                 F   > [         [        U ]  X[        R                  S9  g )Nr"   r#   r$   )superrL   r)   rE   rF   r(   r"   r#   r'   s      r   r)   Sum.__init__~   s    c4!'!Or   c                     U R                   R                  nU R                  [        L a  SOU R                  4nU R                  [
        La  SU R                  0O0 n[        XU[        S9$ )Nr   r#   rC   )r'   r   r"   r   r#   intr	   r
   r(   rG   argsrH   s       r   rI   Sum.__repr__   sS    ^^$$\\Q&rT\\O(,		(<&$))$" 6??r   r   )r   r   r   r   r   r   rT   r)   rI   r   __classcell__r'   s   @r   rL   rL   l   s!    "  !s P@ @r   rL   c                   6   ^  \ rS rSrSrSrU 4S jrS rSrU =r	$ )Count   zK
takes a count of how many values occurred

>>> glom([1, 2, 3], Count())
3
r   c                 >   > [         [        U ]  [        [        S S9  g )Nc                     U S-   $ )Nr   r   )curvals     r   <lambda> Count.__init__.<locals>.<lambda>   s    S1Wr   rO   )rP   r[   r)   r   rT   )r(   r'   s    r   r)   Count.__init__   s    eT#C$< 	$ 	>r   c                 4    SU R                   R                  -  $ )Nz%s())r'   r   )r(   s    r   rI   Count.__repr__   s    ////r   )
r   r   r   r   r   	__slots__r)   rI   r   rX   rY   s   @r   r[   r[      s     I>0 0r   r[   c                   F   ^  \ rS rSrSr\\4U 4S jjrU 4S jrS r	Sr
U =r$ )Flatten   a  The `Flatten` specifier type is used to combine iterables. By
default it flattens an iterable of iterables into a single list
containing items from all iterables.

>>> target = [[1], [2, 3]]
>>> glom(target, Flatten())
[1, 2, 3]

You can also set *init* to ``"lazy"``, which returns a generator
instead of a list. Use this to avoid making extra lists and other
collections during intermediate processing steps.
c                 |   > US:X  a  SU l         [        nOSU l         [        [        U ]  X[
        R                  S9  g )NlazyTFrO   )rk   listrP   rh   r)   rE   rF   rQ   s      r   r)   Flatten.__init__   s5    6>DIDDIgt%gX]]%Sr   c                    > U R                   (       a  [        R                  R                  U5      $ [        [
        U ]  U5      $ r8   )rk   	itertoolschainfrom_iterablerP   rh   r/   )r(   r;   r'   s     r   r/   Flatten._fold   s1    99??00::Wd)(33r   c                    U R                   R                  nU R                  [        L a  SOU R                  4n0 nU R                  (       a  SUS'   O"U R
                  [        La  U R
                  US'   [        XU[        S9$ )Nr   rk   r#   rC   )	r'   r   r"   r   rk   r#   rl   r	   r
   rU   s       r   rI   Flatten.__repr__   sf    ^^$$\\Q&rT\\O99#F6NYYd"!YYF6N 6??r   )rk   )r   r   r   r   r   r   rl   r)   r/   rI   r   rX   rY   s   @r   rh   rh      s&      !t T4
@ @r   rh   c                 j   UR                  S[        5      nUR                  S[        5      nUR                  SS5      nU(       a%  [        S[	        UR                  5       5      -  5      eUS:X  a  U $ US:  a  [        SU-  5      eU4nU[        SS	94US-
  -  -  nU[        US	94-  n[        X5      $ )
aN  At its most basic, ``flatten()`` turns an iterable of iterables
into a single list. But it has a few arguments which give it more
power:

Args:

   init (callable): A function or type which gives the initial
      value of the return. The value must support addition. Common
      values might be :class:`list` (the default), :class:`tuple`,
      or even :class:`int`. You can also pass ``init="lazy"`` to
      get a generator.
   levels (int): A positive integer representing the number of
      nested levels to flatten. Defaults to 1.
   spec: The glomspec to fetch before flattening. This defaults to the
      the root level of the object.

Usage is straightforward.

  >>> target = [[1, 2], [3], [4]]
  >>> flatten(target)
  [1, 2, 3, 4]

Because integers themselves support addition, we actually have two
levels of flattening possible, to get back a single integer sum:

  >>> flatten(target, init=int, levels=2)
  10

However, flattening a non-iterable like an integer will raise an
exception:

  >>> target = 10
  >>> flatten(target)
  Traceback (most recent call last):
  ...
  FoldError: can only Flatten on iterable targets, not int type (...)

By default, ``flatten()`` will add a mix of iterables together,
making it a more-robust alternative to the built-in
``sum(list_of_lists, list())`` trick most experienced Python
programmers are familiar with using:

  >>> list_of_iterables = [range(2), [2, 3], (4, 5)]
  >>> sum(list_of_iterables, [])
  Traceback (most recent call last):
  ...
  TypeError: can only concatenate list (not "tuple") to list

Whereas flatten() handles this just fine:

  >>> flatten(list_of_iterables)
  [0, 1, 2, 3, 4, 5]

The ``flatten()`` function is a convenient wrapper around the
:class:`Flatten` specifier type. For embedding in larger specs,
and more involved flattening, see :class:`Flatten` and its base,
:class:`Fold`.

specr#   levelsr   unexpected keyword args: %rr   zexpected levels >= 0, not %rrk   )r#   )	popr   rl   r&   sortedkeys
ValueErrorrh   r   )r1   rH   r"   r#   rw   rv   s         r   flattenr}      s    x jj#G::fd#DZZ!$F5v{{}8MMNN{z7&@AA:DW&!#vz22DW$!!Dr   c                   B   ^  \ rS rSrSr\\S4U 4S jjrS rS r	Sr
U =r$ )Mergei  a+  By default, Merge turns an iterable of mappings into a single,
merged :class:`dict`, leveraging the behavior of the
:meth:`~dict.update` method. The start state can be customized
with *init*, as well as the update operation, with *op*.

Args:
   subspec: The location of the iterable of mappings. Defaults to ``T``.
   init (callable): A type or callable which returns a base
      instance into which all other values will be merged.
   op (callable): A callable, which takes two arguments, and
      performs a merge of the second into the first. Can also be
      the string name of a method to fetch on the instance created
      from *init*. Defaults to ``"update"``.

.. note::

   Besides the differing defaults, the primary difference between
   :class:`Merge` and other :class:`Fold` subtypes is that its
   *op* argument is assumed to be a two-argument function which
   has no return value and modifies the left parameter
   in-place. Because the initial state is a new object created with
   the *init* parameter, none of the target values are modified.

Nc                    > Uc  Sn[        U[        5      (       a  U" 5       n[        [        U5      US 5      n[	        U5      (       d  [        SU< SU< 35      e[        [        U ]#  XUS9  g )NupdatezEexpected callable "op" arg or an "init" with an .update() method not z and rO   )	
isinstance
basestringgetattrr0   r%   r|   rP   r   r)   )r(   r"   r#   r$   	test_initr'   s        r   r)   Merge.__init__$  sj    :Bb*%%Ii"d3B||8:DB C CeT#G2#Fr   c                 ^    U R                  5       U R                  p2U H  nU" X$5        M     U$ r8   r9   r:   s        r   r/   Merge._fold/  s-     ))+twwRAsJ  
r   c                 d    X;  a  U R                  5       =o2U '   OX    nU R                  X15        U$ r8   r9   )r(   r1   r@   accs       r   r.   
Merge._agg:  s2    #yy{*Ct**C
r   r   )r   r   r   r   r   r   dictr)   r/   r.   r   rX   rY   s   @r   r   r     s&    0  !t 	G r   r   c                    UR                  S[        5      nUR                  S[        5      nUR                  SS5      nU(       a%  [        S[	        UR                  5       5      -  5      e[        X#U5      n[        X5      $ )aa  By default, ``merge()`` turns an iterable of mappings into a
single, merged :class:`dict`, leveraging the behavior of the
:meth:`~dict.update` method. A new mapping is created and none of
the passed mappings are modified.

>>> target = [{'a': 'alpha'}, {'b': 'B'}, {'a': 'A'}]
>>> res = merge(target)
>>> pprint(res)
{'a': 'A', 'b': 'B'}

Args:
   target: The list of dicts, or some other iterable of mappings.

The start state can be customized with the *init* keyword
argument, as well as the update operation, with the *op* keyword
argument. For more on those customizations, see the :class:`Merge`
spec.

rv   r#   r$   Nrx   )ry   r   r   r&   rz   r{   r   r   )r1   rH   r"   r#   r$   rv   s         r   merger   C  sj    ( jj#G::fd#D	D$	B5v{{}8MMNN#Dr   )rE   ro   r   boltons.typeutilsr   corer   r   r   r	   r
   r   r   groupingr   r   r   r   r   r   	NameErrorstrr   objectr   rL   r[   rh   r}   r   r   r   r   r   <module>r      s       + Y Y Y ; ;$
		 	OK6 OKd@$ @80D 0""@d "@JJZ5D 5pg	  Js   B BB