o
    2h                     @  s   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 dZejejdG dd dejee ZdS )z)PyTree integration with :mod:`functools`.    )annotationsN)TYPE_CHECKINGAnyCallableClassVar)Self)registry)GetAttrEntry)tree_reduce)CustomTreeNodeT)PyTreeEntrypartialreducec                   @  sh   e Zd ZU dZdZded< ded< ded< d	ed
< d!ddZd"ddZd#ddZd$ddZ	d%ddZ
d S )&_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   r   functools.partialreturnNonec                C  s
   || _ d S Nr   )selfr    r   K/var/www/html/chatgem/venv/lib/python3.10/site-packages/optree/functools.py__init__0      
z_HashablePartialShim.__init__r   kwargsc                O  s   | j |i |S r   r   )r   r   r!   r   r   r   __call__3   s   z_HashablePartialShim.__call__otherobjectboolc                C  s    t |tr| j|jkS | j|kS r   )
isinstancer   r   )r   r#   r   r   r   __eq__6   s   

z_HashablePartialShim.__eq__intc                C  
   t | jS r   )hashr   r   r   r   r   __hash__;   r    z_HashablePartialShim.__hash__strc                C  r)   r   )reprr   r+   r   r   r   __repr__>   r    z_HashablePartialShim.__repr__N)r   r   r   r   )r   r   r!   r   r   r   )r#   r$   r   r%   )r   r(   r   r-   )__name__
__module____qualname____doc__r   __annotations__r   r"   r'   r,   r/   r   r   r   r   r   '   s   
 



r   )	namespacec                      sv   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dZdddZ	dddZ
ed ddZ  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_TYPEr   r   r   c                  s~   t |tjr1|}t|}t|drJ dt j| |g|R i |}|j|_|j|_|j	|_	|S t j| |g|R 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__r   r   r;   |   s   zpartial.__new__r-   c                C  s`   t | jg}|dd | jD  |dd | j D  | jj d| jj dd	| dS )z@Return a string representation of the :class:`partial` instance.c                 s  s    | ]}t |V  qd S r   )r.   ).0xr   r   r   	<genexpr>   s    z#partial.__repr__.<locals>.<genexpr>c                 s  s"    | ]\}}| d |V  qdS )=Nr   )rA   kvr   r   r   rC      s     .(z, ))
r.   r   extendr   r   itemsr@   r2   r3   join)r   r   r   r   r   r/      s   $zpartial.__repr__Ntuple[tuple[tuple[T, ...], dict[str, T]], Callable[..., Any], tuple[str, str]]c                C  s   | j | jf| jdfS )z?Flatten the :class:`partial` instance to children and metadata.)r   r   )r   r   r   r+   r   r   r   tree_flatten   s   	zpartial.tree_flattenmetadatachildren"tuple[tuple[T, ...], dict[str, T]]c                C  s   |\}}| |g|R i |S )zEUnflatten the children and metadata into a :class:`partial` instance.r   )r<   rO   rP   r   r   r   r   r   tree_unflatten   s   zpartial.tree_unflatten)r   r   r   r   r   r   r   r   r0   )r   rM   )rO   r   rP   rQ   r   r   )r1   r2   r3   r4   r   r5   r	   r7   r;   r/   rN   classmethodrR   __classcell__r   r   r?   r   r   C   s   
 ,

)r4   
__future__r   r8   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   r   <module>   s(   

