
    ij9                    l   U d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	m
Z
mZmZ ddlZddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ ddlmZ  ddl!m"Z" erdd	lm#Z# g d
Z$dZ%dZ&de'd<    ed      Z( ed      Z) ede*      Z+ G d de"      Z,d!dZ-e	 	 	 	 	 	 d"d       Z.e	 	 	 	 	 	 	 	 d#d       Z.	 d$	 	 	 	 	 	 	 d%dZ.e	 	 	 	 	 	 d"d       Z/e	 	 	 	 	 	 	 	 d#d       Z/	 d$	 	 	 	 	 	 	 d%dZ/e.Z0	 	 	 	 	 	 	 	 	 	 	 d&dZe	 d$dd	 	 	 	 	 d'd       Z1e	 	 	 	 	 	 d(d       Z1	 d$dd	 	 	 	 	 d)d Z1y)*a  Integration with :mod:`attrs`.

This module implements PyTree integration with :mod:`attrs` by providing :func:`field`,
:func:`define`, :func:`frozen`, and :func:`register_node` functions. The :func:`field` and
:func:`define` functions wrap the corresponding :mod:`attrs` functions with an additional
``pytree_node`` parameter for controlling which fields are tree children versus metadata.
The :func:`register_node` function allows registering existing :mod:`attrs` classes as pytree nodes.

The PyTree integration allows attrs classes to be flattened and unflattened recursively. The fields
are stored in a special attribute named ``__optree_attrs_fields__`` in the attrs class.

>>> import optree
... from optree.integrations import attrs
...
>>> @attrs.define(namespace='my_module')
... class Point:
...     x: float
...     y: float
...     z: float = 0.0
...
>>> point = Point(2.0, 6.0, 3.0)
>>> point
Point(x=2.0, y=6.0, z=3.0)
>>> # Flatten without specifying the namespace
>>> optree.tree_flatten(point)  # `Point`s are leaf nodes
([Point(x=2.0, y=6.0, z=3.0)], PyTreeSpec(*))
>>> # Flatten with the namespace
>>> optree.tree_flatten(point, namespace='my_module')
([2.0, 6.0, 3.0], PyTreeSpec(CustomTreeNode(Point[()], [*, *, *]), namespace='my_module'))
>>> treespec = optree.tree_structure(point, namespace='my_module')
>>> point == optree.tree_unflatten(treespec, [2.0, 6.0, 3.0])
True

.. versionadded:: 0.20.0
    )annotationsN)MappingProxyType)TYPE_CHECKINGAnyCallableTypeVaroverload)NOTHING	AttributeFactoryasdictastuple	cmp_using
convertersevolve
exceptionsfieldsfields_dictfiltershasresolve_typessettersvalidate
validators)
make_class)GetAttrEntry)ClassVar)
AttrsEntryfielddefinefrozenmutabler   register_noder
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __optree_attrs_fields__Tbool_PYTREE_NODE_DEFAULT_T_U_TypeT)boundc                  z    e Zd ZU dZdZded<   ded<   edd       Zedd       Zedd	       Z	edd
       Z
ddZy)r   z%A path entry class for attrs classes. zClassVar[tuple[()]]	__slots__z	str | intentryc               N    t        d | j                  j                  D              S )zGet all field names.c              3  4   K   | ]  }|j                     y wN)name.0as     n/var/www/html/emotional.easysim.app/public_html/venv/lib/python3.12/site-packages/optree/integrations/attrs.py	<genexpr>z$AttrsEntry.fields.<locals>.<genexpr>   s     ?QVV?   tupletype__attrs_attrs__selfs    r6   r   zAttrsEntry.fields   s     ?TYY%>%>???    c               N    t        d | j                  j                  D              S )zGet the init field names.c              3  N   K   | ]  }|j                   s|j                    y wr1   )initr2   r3   s     r6   r7   z)AttrsEntry.init_fields.<locals>.<genexpr>   s     I!&&QVVIs   %%r9   r=   s    r6   init_fieldszAttrsEntry.init_fields   s     ITYY%>%>IIIr?   c                   t        | j                  t              r| j                  | j                     S | j                  S )zGet the field name.)
isinstancer.   intrC   r=   s    r6   r   zAttrsEntry.field   s1     djj#&##DJJ//zzr?   c                   | j                   S )zGet the attribute name.)r   r=   s    r6   r2   zAttrsEntry.name   s     zzr?   c               h    | j                   j                   d| j                  d| j                  dS )z)Get the representation of the path entry.z(field=z, type=))	__class____name__r   r;   r=   s    r6   __repr__zAttrsEntry.__repr__   s/    ..))*'$**wtyymSTUUr?   N)returnztuple[str, ...])rM   str)rK   
__module____qualname____doc__r-   __annotations__propertyr   rC   r   r2   rL   r,   r?   r6   r   r      sn    /%'I"'@ @ J J    Vr?   r   c                    | j                  dd      }t        | j                  dd      xs i       }||j                  dt              }||d<   | j                  dd      }|s|rt	        dt
         d      t        j                  dd|i| S )	a  Field factory for :func:`define`.

    This factory function is used to define the fields in an attrs class. It is similar to
    :func:`attrs.field`, but with an additional ``pytree_node`` parameter. If ``pytree_node`` is
    :data:`True` (default), the field will be considered a child node in the PyTree structure which
    can be recursively flattened and unflattened. Otherwise, the field will be considered as PyTree
    metadata.

    Setting ``pytree_node`` in the field factory is equivalent to setting a key ``'pytree_node'`` in
    ``metadata``. The ``pytree_node`` value can be accessed using ``field.metadata['pytree_node']``.
    If ``pytree_node`` is :data:`None`, the value ``metadata.get('pytree_node', True)`` will be
    used.

    .. note::
        If a field is considered a child node, it must be included in the argument list of the
        :meth:`__init__` method, i.e., passes ``init=True`` in the field factory.

    Args:
        pytree_node (bool or None, optional): Whether the field is a PyTree node.
        **kwargs (optional): Optional keyword arguments passed to :func:`attrs.field`.

    Returns:
        The field defined using the provided arguments with ``metadata['pytree_node']`` set.

    .. versionadded:: 0.20.0
    pytree_nodeNmetadatarB   TzN`pytree_node=True` is not allowed for non-init fields. Please explicitly set `'.field(init=False, pytree_node=False)`.r,   )popdictgetr&   	TypeErrorrK   attrsr   )kwargsrU   rV   rB   s       r6   r   r      s    6 **]D1KFJJz406B7Hll=2FG)H]::fd#DK&&.Z/VX
 	

 ;;33F33r?   c                     y r1   r,   	namespacer]   s     r6   r    r           
 "%r?   c                   y r1   r,   clsr`   r]   s      r6   r    r            r?   c                  | 	dfd}|S t        j                  |       st        dt         d| d      t	        j
                  | fi } t        |       S )a6  Attrs class decorator with PyTree integration.

    This is a wrapper around :func:`attrs.define` that also registers the class as a pytree node.

    Args:
        cls (type or None, optional): The class to decorate. If :data:`None`, return a decorator.
        namespace (str): The registry namespace used for the PyTree registration.
        **kwargs (optional): Optional keyword arguments passed to :func:`attrs.define`.

    Returns:
        type or callable: The decorated class with PyTree integration or decorator function.

    .. versionadded:: 0.20.0
    c                     t        | fdiS )Nr`   )r    )rd   r]   r`   s    r6   	decoratorzdefine.<locals>.decorator   s    #==f==r?   @z-.define() can only be used with classes, not .r`   rd   r)   rM   r)   )inspectisclassr[   rK   r\   r    r#   )rd   r`   r]   rh   s    `` r6   r    r       sa    * {	> ??3!H:%RSVRYYZ[\\
,,s
%f
%C	22r?   c                     y r1   r,   r_   s     r6   r!   r!     ra   r?   c                   y r1   r,   rc   s      r6   r!   r!     re   r?   c              f    |j                  dd       |j                  dd       t        | fd|i|S )a)  Frozen attrs class decorator with PyTree integration.

    This is a convenience wrapper around :func:`define` with ``frozen=True``.

    Args:
        cls (type or None, optional): The class to decorate. If :data:`None`, return a decorator.
        namespace (str): The registry namespace used for the PyTree registration.
        **kwargs (optional): Optional keyword arguments passed to :func:`attrs.define`.

    Returns:
        type or callable: The decorated class with PyTree integration or decorator function.

    .. versionadded:: 0.20.0
    r!   T
on_setattrNr`   )
setdefaultr    rc   s      r6   r!   r!     s9    * h%
lD)#55f55r?   c              6    t        | |fi |}t        ||      S )a^  Create a new attrs class and register it as a pytree node.

    This is a wrapper around :func:`attrs.make_class` that also registers the class as a pytree
    node.

    Args:
        name (str): The name for the new class.
        attrs: A list of names or a dictionary of mappings of names to :func:`attrs.field` calls.
        namespace (str): The registry namespace used for the PyTree registration.
        **kwargs (optional): Optional keyword arguments passed to :func:`attrs.make_class`.

    Returns:
        type: A new attrs class registered as a pytree node.

    .. versionadded:: 0.20.0
    rk   )_attrs_make_classr#   )r2   r\   r`   r]   rd   s        r6   r   r   3  s"    0 D%
26
2C	22r?   rk   c                   y r1   r,   rd   r`   s     r6   r#   r#   O  s     "%r?   c                   y r1   r,   rw   s     r6   r#   r#   X  s     r?   c                  ddl m}  |u st         t              r"t	        d       dk(  rt	        d      d c t	        d       d fd}|S t        j                         st        d	 d
      t        j                         st         d      t         j                  v rt        d j                   d      |urt        t              st        dd
      dk(  r|t        t         dd      dd      s1t        j                  d j                  dt         dt         d       i }i t        j"                         D ]z  }|j$                  j'                  dt(              r<|j*                  s t        d|j,                  dt         d      |||j,                  <   _|j*                  sl||j,                  <   | t/        |      t/        d |j1                         D              t3        |      }t3              }t5         t        ||f       	 	 	 	 d!fd}d" fd}	ddl m}
  |
 ||	t8                S )#a3  Register an existing attrs class as a pytree node.

    This function takes an existing :func:`attrs.define`-decorated class and registers it as a
    pytree node. It can be used as a direct function call or as a decorator.

    Fields with ``metadata['pytree_node']`` set to :data:`True` (or not set, defaulting to
    :data:`True`) are treated as children, while init fields with ``metadata['pytree_node']`` set
    to :data:`False` are treated as metadata.

    Usage::

        # Direct function call
        register_node(Point, namespace='my-namespace')

        # As a decorator
        @register_node(namespace='my-namespace')
        @attrs.define
        class Point:
            x: float
            y: float

    Args:
        cls (type, optional): An existing attrs-decorated class. If :data:`None`, return a
            decorator.
        namespace (str): The registry namespace used for the PyTree registration.

    Returns:
        type or callable: The same class, now registered as a pytree node, or a decorator function.

    .. versionadded:: 0.20.0
    r   )__GLOBAL_NAMESPACENz?Cannot specify `namespace` when the first argument is a string. z(The namespace cannot be an empty string.z<Must specify `namespace` when the first argument is a class.c                   t        |       S )Nrk   )r#   rw   s    r6   rh   z register_node.<locals>.decorator  s     	::r?   zExpected a class, got rj   z! is not an attrs-decorated class.zCannot register z! as a pytree node more than once.z$The namespace must be a string, got __attrs_props__
added_initTzAttrs class zn does not use an attrs-generated `__init__` (for example, `init=False`). `tree_unflatten()` may fail because `z>.register_node()` reconstructs instances with `cls(**kwargs)`.   )
stacklevelrU   zPyTree node field z> must be included in `__init__()`. Or you can explicitly set `rW   c              3  4   K   | ]  }|j                     y wr1   )aliasr3   s     r6   r7   z register_node.<locals>.<genexpr>  s     GQWWGr8   c               |     t         fdD              }t         fdj                         D              }||fS )Nc              3  6   K   | ]  }t        |        y wr1   )getattr)r4   r2   objs     r6   r7   z6register_node.<locals>.flatten_func.<locals>.<genexpr>  s     Md+Ms   c              3  b   K   | ]&  }|j                   t        |j                        f ( y wr1   )r   r   r2   )r4   r5   r   s     r6   r7   z6register_node.<locals>.flatten_func.<locals>.<genexpr>  s%     [Q!''73#78[s   ,/)r:   values)r   childrenrV   children_field_namesmetadata_fieldss   `  r6   flatten_funcz#register_node.<locals>.flatten_func  s=     M8LMM[/BXBXBZ[[#777r?   c               `    t        t        |            }|j                  |         di |S )Nr,   )rY   zipupdate)rV   r   r]   children_aliasesrd   s      r6   unflatten_funcz%register_node.<locals>.unflatten_func  s-    c*H56h}V}r?   )register_pytree_node)path_entry_typer`   rl   )r   r'   rM   zCtuple[tuple[_U, ...], tuple[tuple[str, Any], ...], tuple[str, ...]])rV   ztuple[tuple[str, Any], ...]r   ztuple[_U, ...]rM   r'   )optree.registryrz   rE   rN   
ValueErrorrm   rn   r[   r\   r   _FIELDS__dict__rK   r   warningswarnUserWarningr   rV   rZ   r&   rB   r2   r:   r   r   setattrr   r   )rd   r`   GLOBAL_NAMESPACErh   children_fieldsr5   children_fields_proxymetadata_fields_proxyr   r   r   r   r   r   s   ``         @@@r6   r#   r#   a  sv   L G
*S#"6 ^__"9GHHsYWXX
{	; ??30q9::99S>3'!BCDD#,,s||n,MN
 	
 ((Is1K>ym1MNNB$	73 148,M3<<* + zWY 	
 OO\\# 	(::>>-)=>66(
 322:;bd  '(OAFF#VV&'OAFF#	( !1Go.D.D.FGG,_=,_=C02GHI
8
8

8
 5" Jr?   )r]   r   rM   r   )r`   rN   r]   r   rM   Callable[[_TypeT], _TypeT])rd   r)   r`   rN   r]   r   rM   r)   r1   )rd   z_TypeT | Noner`   rN   r]   r   rM   #_TypeT | Callable[[_TypeT], _TypeT])
r2   rN   r\   r   r`   rN   r]   r   rM   r;   )rd   
str | Noner`   r   rM   r   )rd   r)   r`   rN   rM   r)   )rd   z_TypeT | str | Noner`   r   rM   r   )2rQ   
__future__r   rm   r   typesr   typingr   r   r   r   r	   r\   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   ru   optree.accessorsr   r   __all__r   r&   rR   r'   r(   r;   r)   r   r   r    r!   r"   r#   r,   r?   r6   <module>r      s  "N #   " B B     & 2 ) < $! d ! T]T]		&V VD(4V 
%% %  	% 
% 
	 	
   
  3	 3 	 3
  3 ) 3F 
%% %  	% 
% 
	 	
   
 6	6 	6
 6 )64  3
33
 3 3 
38 
% !	%	% 	%
  % 
% 
	 	
  
  $} !	}	} 	}
 )}r?   