
    ViK$                     6   S r SSKJr  SSK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  \" S5      rS\l         \" S	5      rS
\l         S 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\5      r " S S\5      rg)z
Group mode
    )divisionN)make_sentinel   )	glomMODESKIPSTOPTargetRegistryPathTBadSpec_MISSINGACC_TREEz
tree of accumulators for aggregation;
structure roughly corresponds to the result,
but is not 1:1; instead the main purpose is to ensure
data is kept until the Group() finishes executing
CUR_AGGaq  
the spec which is currently performing aggregation --
useful for specs that want to work in either "aggregate"
mode, or "spec" mode depending on if they are in Group mode
or not; this sentinel in the Scope allows a spec to decide
if it is "closest" to the Group and so should behave
like an aggregate, or if it is further away and so should
have normal spec behavior.
c           
          U[            R                  SX[           S9n U" U 5      nU$ ! [         a>  n[	        SU R
                  R                  < S[        U[           6 < SU< S35      eS nAff = f)Niterate)pathz&failed to iterate on instance of type z at z (got ))r
   get_handlerr   	Exception	TypeError	__class____name__)targetscoper   iteratores        `/home/james-whalen/.local/share/pipx/venvs/semgrep/lib/python3.13/site-packages/glom/grouping.pytarget_iterr   !   s{    N#//	6d/TGN6? O  N!++44dE$K6H!M N 	NNs   * 
A29A--A2c                   *    \ rS rSrSrS rS rS rSrg)Group,   aV  supports nesting grouping operations --
think of a glom-style recursive boltons.iterutils.bucketize

the "branches" of a Group spec are dicts;
the leaves are lists, or an Aggregation object
an Aggregation object is any object that defines the
method agg(target, accumulator)

For example, here we get a map of even and odd counts::

>>> glom(range(10), Group({lambda x: x % 2: T}))
{0: 8, 1: 9}

And here we create a `"bucketized"
<https://boltons.readthedocs.io/en/latest/iterutils.html#boltons.iterutils.bucketize>`_
map of even and odd numbers::

>>> glom(range(10), Group({lambda x: x % 2: [T]}))
{0: [0, 2, 4, 6, 8], 1: [1, 3, 5, 7, 9]}

target is the current target, accumulator is a dict
maintained by Group mode

unlike Iter(), Group() converts an iterable target
into a single result; Iter() converts an iterable
target into an iterable result

c                     Xl         g Nspec)selfr&   s     r   __init__Group.__init__I       	    c                 6   [         U[        '   S U[        '   0 U[        '   [	        U R
                  5      [        [        4;   a  [	        U R
                  5      " 5       nOS n[        X5       H*  nX2[           " X@R
                  U5      p5U[        L d  M(  Us  $    U$ r$   )GROUPr   r   r   typer&   dictlistr   r   r	   )r'   r   r   rettlasts         r   glomitGroup.glomitL   s~    dgh 		?tTl*tyy/#CCV+A4[IIu=#d{ , 
r+   c                 V    U R                   R                  nU< SU R                  < S3$ N(r   )r   r   r&   )r'   cns     r   __repr__Group.__repr__^   s     ^^$$tyy))r+   r%   N)	r   
__module____qualname____firstlineno____doc__r(   r4   r:   __static_attributes__ r+   r   r!   r!   ,   s    8$*r+   r!   c                   ^ ^ UU 4S jnT[            n[        [        USS5      5      (       a  UR                  T U5      $ [        U5      (       a  U" T 5      $ [	        U5      nU[
        [        4;  a  [        SU< 35      e[        U5      n XF   nU[
        L a  SnUR                  5        H  u  pUR                  U	S5      [        L a  M   U" U	5      nU[        L a  SnM5  U[        L a
  [        XI'   MH  X;  a  0 XK'   XK   T[         '   U" U
5      nU[        L a
  [        XI'   Mw  SnU[        Ld  M  XU'   M     U(       a  [        $ U$ U[        L a`  U HX  n
[	        U
5      [
        L a  [        SU-  5      eU" U
5      nU[        L a  [        s  $ U[        Ld  MG  UR                  U5        MZ     U$ [        SR!                  U5      5      e! [         a    U" 5       =otU'    GNQf = f)	z?
Group mode dispatcher; also sentinel for current mode = group
c                 &   > T[            " TU T5      $ r$   )r   )r&   r   r   s    r   <lambda>GROUP.<locals>.<lambda>g   s    5;vtU;r+   aggNz>Group mode expected dict, list, callable, or aggregator, not: TFz:dicts within lists are not allowed while in Group mode: %rz'{} not a valid spec type for Group mode)r   callablegetattrrF   r.   r/   r0   r   idKeyErroritemsgetr	   r   append
ValueErrorformat)r   r&   r   recursetree
_spec_type_spec_idaccdonekeyspecvalspeckeyresults   ` `          r   r-   r-   c   s    <G?DeT*++xx%%	$F|dJ$%047 8 	8$xH,n T $

Gxx&$.'"Cd{d{ $~	"iE(OW%F~ $DT!!C) !-* K
	t	GG}$ ACGH I IW%F~T!

6"  

>EEjQ
RRQ  ,)|+8n,s   G G$#G$c                   (    \ rS rSrSrSrS rS rSrg)First   zC
holds onto the first value

>>> glom([1, 2, 3], Group(First()))
1
rA   c                 ,    X;  a
  [         X '   U$ [         $ r$   )r	   r'   r   rQ   s      r   rF   	First.agg   s    DJMr+   c                 4    SU R                   R                  -  $ Nz%s()r   r   r'   s    r   r:   First.__repr__       ////r+   N	r   r<   r=   r>   r?   	__slots__rF   r:   r@   rA   r+   r   r[   r[      s     I0r+   r[   c                   (    \ rS rSrSrSrS rS rSrg)Avg   zy
takes the numerical average of all values;
raises exception on non-numeric value

>>> glom([1, 2, 3], Group(Avg()))
2.0
rA   c                      X    nUS==   U-  ss'   US==   S-  ss'   US   US   -  $ ! [          a    SS/=o2U '    N9f = f)Ng        r   r   )rJ   )r'   r   rQ   avg_accs       r   rF   Avg.agg   s_    	,jG 	
f

a
qzGAJ&&  	,$'8+G4j	,s   + A A c                 4    SU R                   R                  -  $ ra   rb   rc   s    r   r:   Avg.__repr__   re   r+   Nrf   rA   r+   r   ri   ri      s     I'0r+   ri   c                   (    \ rS rSrSrSrS rS rSrg)Max   zz
takes the maximum of all values;
raises exception on values that are not comparable

>>> glom([1, 2, 3], Group(Max()))
3
rA   c                 ,    X;  d  XU    :  a  XU '   X    $ r$   rA   r^   s      r   rF   Max.agg        vT
2Jzr+   c                 4    SU R                   R                  -  $ ra   rb   rc   s    r   r:   Max.__repr__   re   r+   Nrf   rA   r+   r   rq   rq           I
0r+   rq   c                   (    \ rS rSrSrSrS rS rSrg)Min   zz
takes the minimum of all values;
raises exception on values that are not comparable

>>> glom([1, 2, 3], Group(Min()))
1
rA   c                 ,    X;  d  XU    :  a  XU '   X    $ r$   rA   r^   s      r   rF   Min.agg   ru   r+   c                 4    SU R                   R                  -  $ ra   rb   rc   s    r   r:   Min.__repr__   re   r+   Nrf   rA   r+   r   rz   rz      rx   r+   rz   c                   .    \ rS rSrSrSrS rS rS rSr	g)Sample   a  takes a random sample of the values

>>> glom([1, 2, 3], Group(Sample(2)))  # doctest: +SKIP
[1, 3]
>>> glom(range(5000), Group(Sample(2)))  # doctest: +SKIP
[272, 2901]

The advantage of this over :func:`random.sample` is that this can
take an arbitrarily-sized, potentially-very-long streaming input
and returns a fixed-size output. Note that this does not stream
results out, so your streaming input must have finite length.
sizec                     Xl         g r$   r   )r'   r   s     r   r(   Sample.__init__   r*   r+   c                     X;  a  S/ /X '   X    u  p4[        U5      U R                  :  a  UR                  U5        O*[        R                  " SU5      nXPR                  :  a  XU'   X    S==   S-  ss'   U$ )Nr   r   )lenr   rM   randomrandint)r'   r   rQ   num_seensampleposs         r   rF   
Sample.agg  sp     RDJ:v;"MM&!..H-CYY$s
1r+   c                 R    U R                   R                  < SU R                  < S3$ r7   )r   r   r   rc   s    r   r:   Sample.__repr__  s    >>22DII>>r+   N)
r   r<   r=   r>   r?   rg   r(   rF   r:   r@   rA   r+   r   r   r      s     I?r+   r   c                   4    \ rS rSrSrSr\4S jrS rS r	Sr
g)Limiti  a  
Limits the number of values passed to sub-accumulator

>>> glom([1, 2, 3], Group(Limit(2)))
[1, 2]

To override the default untransformed list output, set the subspec kwarg:

>>> glom(range(10), Group(Limit(3, subspec={(lambda x: x % 2): [T]})))
{0: [0, 2], 1: [1]}

You can even nest Limits in other ``Group`` specs:

>>> glom(range(10), Group(Limit(5, {(lambda x: x % 2): Limit(2)})))
{0: [0, 2], 1: [1, 3]}

)nsubspecc                 <    U[         L a  [        /nXl        X l        g r$   )r   r   r   r   )r'   r   r   s      r   r(   Limit.__init__*  s    hcGr+   c                    U[            [        La  [        S5      eU[           nX;  a  S0 /X0'   X0   S   U[        '   X0   S==   S-  ss'   X0   S   U R                  :  a  [
        $ U[           " XR                  U5      $ )Nz Limit() only valid in Group moder   r   )r   r-   r   r   r   r	   r   r   )r'   r   r   rQ   s       r   r4   Limit.glomit0  s    ;e#<==XRDJ*Q-h
1:a=466!KT{6<<77r+   c                 n    U R                   R                  < SU R                  < SU R                  < S3$ )Nr8   z, r   )r   r   r   r   rc   s    r   r:   Limit.__repr__<  s!    #~~66MMr+   N)r   r<   r=   r>   r?   rg   r   r(   r4   r:   r@   rA   r+   r   r   r     s!    " !I"* 
8Nr+   r   )r?   
__future__r   r   boltons.typeutilsr   corer   r   r   r	   r
   r   r   r   r   r   r   r   objectr!   r-   r[   ri   rq   rz   r   r   rA   r+   r   <module>r      s       + T T T $  	
"4*F 4*n9Sx0F 0&0& 000& 0&0& 0&"?V "?L'NF 'Nr+   