
    0Vh                       d Z ddlmZ ddlZddlmZmZmZmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZmZ erdd
lmZ ddgZ G d d      Z ej0                  ej2                         G d dej4                  ee                Zy)z)PyTree integration with :mod:`functools`.    )annotationsN)TYPE_CHECKINGAnyCallableClassVar)Self)registry)GetAttrEntry)tree_reduce)CustomTreeNodeT)PyTreeEntrypartialreducec                  f    e Zd ZU dZdZded<   ded<   ded<   d	ed
<   ddZddZddZddZ	ddZ
y)_HashablePartialShimz_Object that delegates :meth:`__call__`, :meth:`__eq__`, and :meth:`__hash__` to another object.)argsfunckeywordspartial_funczClassVar[tuple[str, ...]]	__slots__Callable[..., Any]r   ztuple[Any, ...]r   zdict[str, Any]r   c                   || _         y Nr   )selfr   s     @/home/dcms/DCMS/lib/python3.12/site-packages/optree/functools.py__init__z_HashablePartialShim.__init__0   s
    /;    c               &     | j                   |i |S r   r   )r   r   kwargss      r   __call__z_HashablePartialShim.__call__3   s     t  $1&11r   c               r    t        |t              r| j                  |j                  k(  S | j                  |k(  S r   )
isinstancer   r   )r   others     r   __eq__z_HashablePartialShim.__eq__6   s5    e12$$(:(:::  E))r   c               ,    t        | j                        S r   )hashr   r   s    r   __hash__z_HashablePartialShim.__hash__;       D%%&&r   c               ,    t        | j                        S r   )reprr   r)   s    r   __repr__z_HashablePartialShim.__repr__>   r+   r   N)r   zfunctools.partialreturnNone)r   r   r!   r   r/   r   )r%   objectr/   bool)r/   intr/   str)__name__
__module____qualname____doc__r   __annotations__r   r"   r&   r*   r.    r   r   r   r   '   s;    i+WI(W

<2*
''r   r   )	namespacec                       e Zd ZU dZdZded<   ded<   ded<   d	ed
<   eZded<   d fdZddZ		 	 ddZ
e	 	 	 	 	 	 dd       Z xZS )r   a  A version of :func:`functools.partial` that works in pytrees.

    Use it for partial function evaluation in a way that is compatible with transformations,
    e.g., ``partial(func, *args, **kwargs)``.

    (You need to explicitly opt-in to this behavior because we did not want to give
    :func:`functools.partial` different semantics than normal function closures.)

    For example, here is a basic usage of :class:`partial` in a manner similar to
    :func:`functools.partial`:

    >>> import operator
    >>> import torch
    >>> add_one = partial(operator.add, torch.ones(()))
    >>> add_one(torch.tensor([[1, 2], [3, 4]]))
    tensor([[2., 3.],
            [4., 5.]])

    Pytree compatibility means that the resulting partial function can be passed as an argument
    within tree-map functions, which is not possible with a standard :func:`functools.partial`
    function:

    >>> def call_func_on_cuda(f, *args, **kwargs):
    ...     f, args, kwargs = tree_map(lambda t: t.cuda(), (f, args, kwargs))
    ...     return f(*args, **kwargs)
    ...
    >>> # doctest: +SKIP
    >>> tree_map(lambda t: t.cuda(), add_one)
    optree.functools.partial(<built-in function add>, tensor(1., device='cuda:0'))
    >>> call_func_on_cuda(add_one, torch.tensor([[1, 2], [3, 4]]))
    tensor([[2., 3.],
            [4., 5.]], device='cuda:0')

    Passing zero arguments to :class:`partial` effectively wraps the original function, making it a
    valid argument in tree-map functions:

    >>> # doctest: +SKIP
    >>> call_func_on_cuda(partial(torch.add), torch.tensor(1), torch.tensor(2))
    tensor(3, device='cuda:0')

    Had we passed :func:`operator.add` to ``call_func_on_cuda`` directly, it would have resulted in
    a :class:`TypeError` or :class:`AttributeError`.
    r;   zClassVar[tuple[()]]r   r   r   ztuple[T, ...]r   zdict[str, T]r   zClassVar[type[PyTreeEntry]]TREE_PATH_ENTRY_TYPEc               2   t        |t        j                        ri|}t        |      }t	        |d      rJ d       t        |   | |g|i |}|j                  |_        |j                  |_        |j                  |_	        |S t        |   | |g|i |S )z'Create a new :class:`partial` instance.r   z3shimmed function should not have a `func` attribute)
r$   	functoolsr   r   hasattrsuper__new__r   r   r   )clsr   r   r   original_funcout	__class__s         r   rC   zpartial.__new__|   s     dI--. M'6DtV,c.cc,'/#t?d?h?C%**DI%**DI)22DMJwsD<4<8<<r   c               V   t        | j                        g}|j                  d | j                  D               |j                  d | j                  j                         D               | j                  j                   d| j                  j                   ddj                  |       dS )z@Return a string representation of the :class:`partial` instance.c              3  2   K   | ]  }t        |        y wr   )r-   ).0xs     r   	<genexpr>z#partial.__repr__.<locals>.<genexpr>   s     /DG/s   c              3  0   K   | ]  \  }}| d |  yw)=Nr;   )rJ   kvs      r   rL   z#partial.__repr__.<locals>.<genexpr>   s     EVaqc1%LEs   .(z, ))
r-   r   extendr   r   itemsrG   r7   r8   join)r   r   s     r   r.   zpartial.__repr__   s    TYY /TYY//Et}}/B/B/DEE..++,Adnn.I.I-J!DIIVZOK\\]^^r   c               L    | j                   | j                  f| j                  dfS )z?Flatten the :class:`partial` instance to children and metadata.)r   r   )r   r   r   r)   s    r   tree_flattenzpartial.tree_flatten   s#     		4==)4996JJJr   c               $    |\  }} | |g|i |S )zEUnflatten the children and metadata into a :class:`partial` instance.r;   )rD   metadatachildrenr   r   s        r   tree_unflattenzpartial.tree_unflatten   s"     "h8/d/h//r   )r   r   r   r   r   r   r/   r   r4   )r/   zNtuple[tuple[tuple[T, ...], dict[str, T]], Callable[..., Any], tuple[str, str]])rZ   r   r[   z"tuple[tuple[T, ...], dict[str, T]]r/   r   )r6   r7   r8   r9   r   r:   r
   r>   rC   r.   rX   classmethodr\   __classcell__)rG   s   @r   r   r   C   s    
*X &(I"'

8D5D=$_	K
	K 0$0 50
 
0 0r   )r9   
__future__r   r@   typingr   r   r   r   typing_extensionsr   optreer	   optree.accessorsr
   
optree.opsr   r   optree.typingr   r   r   __all__r   register_pytree_node_class__GLOBAL_NAMESPACEr   r;   r   r   <module>ri      s    0 "  9 9 "  ) , + , ' '8 %$$x/J/JKe01e0 Le0r   