o
    tfQ                     @  s  U 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
 d dl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rWd dlZd d	lmZmZ ed
 Zded< ddgZedZedZ d=ddZ!ddddd dd>d'dZ"G d(d dee  Z#d?d,d-Z$edd.G d/d0 d0e#Z%G d1d2 d2e#Z&G d3d4 d4e#Z'G d5d6 d6e#Z(G d7d8 d8e#Z)G d9d: d:eZ*G d;d< d<e#Z+dS )@    )annotationsN)partial)BuiltinMethodTypeFunctionType
MethodTypeMethodWrapperType)TYPE_CHECKINGAnyCallableGenericLiteralProtocolTypeVarcast)warn   )
mypyc_attr)	TypeAlias	TypeGuard)raiser   ignorer   RefErrorChoiceweak_callbackWeakCallback_T_Robjr	   returnTypeGuard[toolz.curry]c                 C  s$   t jd}|du rdS t| |jS )z+Return True if obj is a toolz.curry object.toolzNF)sysmodulesget
isinstancecurry)r   tz r&   _/var/www/html/software/conda/envs/catlas/lib/python3.10/site-packages/psygnal/_weak_callback.py_is_toolz_curry    s   r(   Tr   )max_argsfinalizestrong_funcon_ref_errorprioritycb$Callable[..., _R] | WeakCallback[_R]argsr)   
int | Noner*   $Callable[[WeakCallback], Any] | Noner+   boolr,   r-   intWeakCallback[_R]c             
   G  s  t | tr| S d}t | tr| j| }| j}| j} t | tr4|r)t| ||||dS t| ||||||dS t | t	rtt
| dddkriz|d }W n tyX }	 ztd|	d}	~	ww td| j}
t|
|||||dS t| ||||||dS t | ttfr|rtd| tu rz
|dd	 \}
}W n ty }	 ztd
|	d}	~	ww t|
|||||dS t| |||||dS t| rt
| dd}|du rtdt|g|R ||||dS t| rt| ||||||dS tdt|  )a  Create a weakly-referenced callback.

    This function creates a weakly-referenced callback, with special considerations
    for many known callable types (functions, lambdas, partials, bound methods,
    partials on bound methods, builtin methods, etc.).

    NOTE: For the sake of least-surprise, an exception is made for functions and,
    lambdas, which are strongly-referenced by default.  See the `strong_func` parameter
    for more details.

    Parameters
    ----------
    cb : callable
        The callable to be called.
    *args
        Additional positional arguments to be passed to the callback (similar
        to functools.partial).
    max_args : int, optional
        The maximum number of positional arguments to pass to the callback.
        If provided, additional arguments passed to WeakCallback.cb will be ignored.
    finalize : callable, optional
        A callable that will be called when the callback is garbage collected.
        The callable will be passed the WeakCallback instance as its only argument.
    strong_func : bool, optional
        If True (default), a strong reference will be kept to the function `cb` if
        it is a function or lambda.  If False, a weak reference will be kept.  The
        reasoning for this is that functions and lambdas are very often defined *only*
        to be passed to this function, and would likely be immediately garbage
        collected if we weakly referenced them. If you would specifically like to
        *allow* the function to be garbage collected, set this to False.
    on_ref_error : {'raise', 'warn', 'ignore'}, optional
        What to do if a weak reference cannot be created.  If 'raise', a
        ReferenceError will be raised.  If 'warn' (default), a warning will be issued
        and a strong-reference will be used. If 'ignore' a strong-reference will be
        used (silently).
    priority : int, optional
        The priority of the callback.  This is used to determine the order in which
        callbacks are called when multiple are connected to the same signal.
        Higher priority callbacks are called first. Negative values are allowed.
        The default is 0.

    Returns
    -------
    WeakCallback
        A WeakCallback subclass instance appropriate for the given callable.
        The fast way to "call" the callback is to use the `cb` method, passing a
        single args tuple, it returns nothing.  A `__call__` method is also provided,
        that can be used to call the original function as usual.

    Examples
    --------
    ```python
        from psygnal._weak_callback import weak_callback

    class T:
        def greet(self, name):
            print("hello,", name)

    def _on_delete(weak_cb):
        print("deleting!")

    t = T()
    weak_cb = weak_callback(t.greet, finalize=_on_delete)

    weak_cb.cb(("world",))  # "hello, world"

    del t  # "deleting!"

    weak_cb.cb(("world",))  # ReferenceError
    ```
    N)r-   __name____setitem__r   z0WeakCallback.__setitem__ requires a key argumentSupportsSetitemz3MethodWrapperTypes do not support keyword arguments   z@setattr requires two arguments, an object and an attribute name._partialztoolz.curry object found without a '_partial' attribute. This version of toolz is not supported. Please open an issue at psygnal.)r)   r*   r,   r-   zunsupported type )r#   r   r   r0   keywordsfuncr   StrongFunctionWeakFunctionr   getattr
IndexError	TypeErrorr   __self__WeakSetitem
WeakMethodr   r   NotImplementedErrorsetattrWeakSetattrWeakBuiltinr(   r   callabletype)r.   r)   r*   r+   r,   r-   r0   kwargskeyer   attrZ
cb_partialr&   r&   r'   r   &   s   
P



	c                   @  s   e Zd ZdZ			d1d2ddZd3d4ddZd5ddZd6ddZd7d d!Z	d8d9d&d'Z	d:d)d*Z
ed;d+d,Zed;d-d.Zd:d/d0ZdS )<r   a  Abstract Base Class for weakly-referenced callbacks.

    Do not instantiate this class directly, use the `weak_callback` function instead.
    The main public-facing methods of all subclasses are:

        cb(args: tuple[Any, ...] = ()) -> None: special fast callback method, args only.
        dereference() -> Callable[..., _R] | None: return strong dereferenced callback.
        __call__(*args: Any, **kwargs: Any) -> _R: call original callback
        __eq__: compare two WeakCallback instances for equality
        object_key: static method that returns a unique key for an object.

    NOTE: can't use ABC here because then mypyc and PySide2 don't play nice together.
    Nr   r   r   r	   r)   r1   r,   r   r-   r4   r   Nonec                 C  sT   t || _t|dd pd| _t|dd| _t || _|| _d| _	|| _
|| _d S )N
__module__ __qualname__T)r   
object_key_keyr?   _obj_module_obj_qualnameobject_repr_object_repr	_max_args_alive_on_ref_errorr-   )selfr   r)   r,   r-   r&   r&   r'   __init__   s   
zWeakCallback.__init__r&   r0   tuple[Any, ...]c                 C     t  )zICall the callback with `args`. Args will be spread when calling the func.rE   r\   r0   r&   r&   r'   r.         zWeakCallback.cbCallable[..., _R] | Nonec                 C  r_   )z,Return the original object, or None if dead.r`   r\   r&   r&   r'   dereference   rb   zWeakCallback.dereferencekwdsr   c                 O  s>   |   }|d u rtd| jd ur|d | j }||i |S )Nzcallback is dead)re   ReferenceErrorrY   )r\   r0   rf   r<   r&   r&   r'   __call__   s   
zWeakCallback.__call__otherobjectr3   c                 C  s   t |tr| j|jkS tS N)r#   r   rT   NotImplemented)r\   ri   r&   r&   r'   __eq__   s   
zWeakCallback.__eq__r   r*   r2   Callable[[], _T | None]c                   st   |d u rd nt | |}zt |W S  ty9   | jdkr | jdkr.td ddd d fd	d
}| Y S w )Nr   r   zfailed to create weakref for z, returning strong refr9   )
stacklevelr   r   c                     s    S rk   r&   r&   r   r&   r'   _strong_ref  s   z*WeakCallback._try_ref.<locals>._strong_ref)r   r   )_kill_and_finalizeweakrefrefrA   r[   r   )r\   r   r*   _cbrq   r&   rp   r'   _try_ref   s   


zWeakCallback._try_refstrc                 C  s   | j  d| j S N.)rU   rV   rd   r&   r&   r'   	slot_repr     zWeakCallback.slot_reprc                 C  s   t | dr/t| j}t| j}t|ddpd}t|ddpd}t| ddp&d}| d| }nt| }t| ddp:d}t| ddpBd}| d| dt| S )	zReturn a unique key for an object.

        This includes information about the object's type, module, and id. It has
        considerations for bound methods (which would otherwise have a different id
        for each instance).
        rB   r6   NrQ   rP   ry   :@)hasattridrB   rJ   r?   hex)r   obj_id	owner_cls	type_namemodulemethod_nameobj_namer&   r&   r'   rS     s   


zWeakCallback.object_keyc                 C  s   t | dd}t| dr6t| j}t |ddpd}t | ddpd}|dkr&|S t |dd}| d| d| S t | ddrD| d| j S t t| ddrV| dt| j S t| S )	z%Return a human-readable repr for obj.rP   rQ   rB   Nr6   builtinsrR   ry   )r?   r~   rJ   rB   rR   repr)r   r   r   r   Z
type_qnamer&   r&   r'   rW   )  s   

zWeakCallback.object_reprc                 C  s   d| j j d| j dS )N<z on >)	__class__r6   rX   rd   r&   r&   r'   __repr__>  s   zWeakCallback.__repr__)Nr   r   )
r   r	   r)   r1   r,   r   r-   r4   r   rO   r&   r0   r^   r   rO   )r   rc   )r0   r	   rf   r	   r   r   )ri   rj   r   r3   rk   )r   r   r*   r2   r   rn   r   rw   )r   r	   r   rw   )r6   rP   rR   __doc__r]   r.   re   rh   rm   rv   rz   staticmethodrS   rW   r   r&   r&   r&   r'   r      s$    


	
wcbCallable[[WeakCallback], Any]'Callable[[weakref.ReferenceType], None]c                   s   d fdd}|S )N_weakref.ReferenceTyper   rO   c                   s   j rd_   d S d S )NF)rZ   )r   r*   r   r&   r'   ru   E  s   z_kill_and_finalize.<locals>._cb)r   r   r   rO   r&   )r   r*   ru   r&   r   r'   rr   B  s   rr   )Zserializablec                      sX   e Zd ZdZ					d!d" fddZd#d$ddZd%ddZd&ddZd'dd Z  Z	S )(r=   z+Wrapper around a strong function reference.Nr&   r   r   r   r
   r)   r1   r0   r^   rK   dict[str, Any] | Noner,   r   r-   r4   r   rO   c                   sR   t  |||| || _|| _|pi | _|r'| j g |R dd| _d S d S N)z ...))superr]   _f_args_kwargsrX   replace)r\   r   r)   r0   rK   r,   r-   r   r&   r'   r]   Q  s   	
"zStrongFunction.__init__c                 C  s:   | j d ur|d | j  }| jg | j|R i | j d S rk   )rY   r   r   r   ra   r&   r&   r'   r.   b  s   
"zStrongFunction.cbc                 C  s.   | j s| jrt| jg| j R i | jS | jS rk   )r   r   r   r   rd   r&   r&   r'   re   g  s   zStrongFunction.dereferencedict[str, Any]c                   s   d} fdd|D S )N)rT   rY   rZ   r[   r   r   r   c                   s   i | ]}|t  |qS r&   )r?   ).0krd   r&   r'   
<dictcomp>n  s    z/StrongFunction.__getstate__.<locals>.<dictcomp>r&   )r\   Zatrr&   rd   r'   __getstate__l  s   zStrongFunction.__getstate__statedictc                 C  s"   |  D ]
\}}t| || qd S rk   )itemsrF   )r\   r   r   vr&   r&   r'   __setstate__p  s   zStrongFunction.__setstate__Nr&   Nr   r   )r   r
   r)   r1   r0   r^   rK   r   r,   r   r-   r4   r   rO   r   r   )r   r
   )r   r   )r   r   r   rO   )
r6   rP   rR   r   r]   r.   re   r   r   __classcell__r&   r&   r   r'   r=   M  s    

r=   c                      sF   e Zd ZdZ						dd fddZddddZd ddZ  ZS )!r>   z)Wrapper around a weak function reference.Nr&   r   r   r   r
   r)   r1   r0   r^   rK   r   r*   Callable | Noner,   r   r-   r4   r   rO   c                   sZ   t  |||| | ||| _|| _|pi | _|r+| j g |R dd| _d S d S r   )r   r]   rv   r   r   r   rX   r   r\   r   r)   r0   rK   r*   r,   r-   r   r&   r'   r]   x  s   

"zWeakFunction.__init__c                 C  sP   |   }|d u rtd| jd ur|d | j }|g | j|R i | j d S N)weakly-referenced object no longer exists)r   rg   rY   r   r   )r\   r0   fr&   r&   r'   r.     s   
 zWeakFunction.cbc                 C  s>   |   }|d u r
d S | js| jrt|g| jR i | jS |S rk   )r   r   r   r   )r\   r   r&   r&   r'   re     s   zWeakFunction.dereferenceNr&   NNr   r   )r   r
   r)   r1   r0   r^   rK   r   r*   r   r,   r   r-   r4   r   rO   r   r   )r   r   )r6   rP   rR   r   r]   r.   re   r   r&   r&   r   r'   r>   u  s    r>   c                      sP   e Zd ZdZ						d d! fddZd"ddZd#d$ddZd%ddZ  ZS )&rD   a  Wrapper around a method bound to a weakly-referenced object.

    Bound methods have a `__self__` attribute that holds a strong reference to the
    object they are bound to and a `__func__` attribute that holds a reference
    to the function that implements the method (on the class level)

    When `cb` is called here, it dereferences the two, and calls:
    `obj.__func__(obj.__self__, *args, **kwargs)`
    Nr&   r   r   r   r   r)   r1   r0   r^   rK   r   r*   r   r,   r   r-   r4   r   rO   c                   sl   t  |||| | |j|| _| |j|| _|| _|pi | _|r4| j	 g |R 
dd| _	d S d S r   )r   r]   rv   rB   _obj_ref__func__	_func_refr   r   rX   r   r   r   r&   r'   r]     s   

"zWeakMethod.__init__rw   c                 C  s2   |   }t|  dd}| j d|jj d| S )Nr6   z<method>ry   )r   r?   r   rU   r   rR   )r\   r   	func_namer&   r&   r'   rz     s   zWeakMethod.slot_reprc                 C  sb   |   }|  }|d u s|d u rtd| jd ur |d | j }||g| j|R i | j d S r   )r   r   rg   rY   r   r   )r\   r0   r   r<   r&   r&   r'   r.     s   
"zWeakMethod.cbMethodType | partial | Nonec                 C  s^   |   }|  }|d u s|d u rd S tt||}| js | jr-t|g| jR i | jS |S rk   )r   r   r   r   __get__r   r   r   )r\   r   r<   methodr&   r&   r'   re     s   zWeakMethod.dereferencer   )r   r   r)   r1   r0   r^   rK   r   r*   r   r,   r   r-   r4   r   rO   r   r   r   )r   r   	r6   rP   rR   r   r]   rz   r.   re   r   r&   r&   r   r'   rD     s    

rD   c                      sN   e Zd ZdZ					dd fddZd ddZd!d"ddZd#ddZ  ZS )$rH   a  Wrapper around a c-based method on a weakly-referenced object.

    Builtin/extension methods do have a `__self__` attribute (the object to which they
    are bound), but don't have a __func__ attribute, so we need to store the name of the
    method and look it up on the object when the callback is called.

    When `cb` is called here, it dereferences the object, and calls:
    `getattr(obj.__self__, obj.__name__)(*args, **kwargs)`
    Nr&   r   r   r   %MethodWrapperType | BuiltinMethodTyper)   r1   r0   r^   r*   r   r,   r   r-   r4   r   rO   c                   sZ   t  |||| | |j|| _|j| _|| _|r+| j g |R 	dd| _d S d S r   )
r   r]   rv   rB   r   r6   
_func_namer   rX   r   )r\   r   r)   r0   r*   r,   r-   r   r&   r'   r]     s   	"zWeakBuiltin.__init__rw   c                 C  s   |   }|jj d| j S rx   )r   r   rR   r   r\   r   r&   r&   r'   rz     s   zWeakBuiltin.slot_reprc                 C  sf   t |  | jd }|d u rtd| jd u r"|g | j|R   d S |g | j|d | j R   d S r   )r?   r   r   rg   rY   r   )r\   r0   r<   r&   r&   r'   r.     s   
"zWeakBuiltin.cb,MethodWrapperType | BuiltinMethodType | Nonec                 C  s   t |  | jd S rk   )r?   r   r   rd   r&   r&   r'   re     r{   zWeakBuiltin.dereferencer   )r   r   r)   r1   r0   r^   r*   r   r,   r   r-   r4   r   rO   r   r   r   )r   r   r   r&   r&   r   r'   rH     s    
	rH   c                      sL   e Zd ZdZ				dd  fddZd!ddZd"d#ddZd$ddZ  ZS )%rG   z9Caller to set an attribute on a weakly-referenced object.Nr   r   r   rj   rN   rw   r)   r1   r*   r   r,   r   r-   r4   r   rO   c                   V   t  |||| |  jd|d7  _| ||| _|| _|  jd|d7  _d S )Nz.__setattr__(r   , ...))r   r]   rT   rv   r   _attrrX   )r\   r   rN   r)   r*   r,   r-   r   r&   r'   r]     
   	zWeakSetattr.__init__c                 C  s    |   }d|jj d| jdS )Nzsetattr(z, r   )r   r   rR   r   r   r&   r&   r'   rz     s   zWeakSetattr.slot_reprr&   r0   r^   c                 C  s\   |   }|d u rtd| jd ur|d | j }t|| jt|dkr)|d  d S | d S Nr   r   r   )r   rg   rY   rF   r   lenr\   r0   r   r&   r&   r'   r.     s   
,zWeakSetattr.cbpartial | Nonec                 C  s"   |   }|d u r
d S tt|| jS rk   )r   r   rF   r   r   r&   r&   r'   re        zWeakSetattr.dereferenceNNr   r   )r   rj   rN   rw   r)   r1   r*   r   r,   r   r-   r4   r   rO   r   r   r   r   r   r   r&   r&   r   r'   rG         
rG   c                   @  s   e Zd Zd	ddZdS )
r8   rL   r	   valuer   rO   c                 C  s   d S rk   r&   )r\   rL   r   r&   r&   r'   r7   "  s    zSupportsSetitem.__setitem__N)rL   r	   r   r	   r   rO   )r6   rP   rR   r7   r&   r&   r&   r'   r8   !  s    r8   c                      sL   e Zd ZdZ				d d! fddZd"ddZd#d$ddZd%ddZ  ZS )&rC   z9Caller to call __setitem__ on a weakly-referenced object.Nr   r   r   r8   rL   r	   r)   r1   r*   r   r,   r   r-   r4   r   rO   c                   r   )N.__setitem__(r   r   )r   r]   rT   rv   r   _itemkeyrX   )r\   r   rL   r)   r*   r,   r-   r   r&   r'   r]   (  r   zWeakSetitem.__init__rw   c                 C  s   |   }|jj d| jdS )Nr   r   )r   r   rR   r   r   r&   r&   r'   rz   7  s   zWeakSetitem.slot_reprr&   r0   r^   c                 C  sR   |   }|d u rtd| jd ur|d | j }t|dkr"|d n||| j< d S r   )r   rg   rY   r   r   r   r&   r&   r'   r.   ;  s   
"zWeakSetitem.cbr   c                 C  s"   |   }|d u r
d S t|j| jS rk   )r   r   r7   r   r   r&   r&   r'   re   C  r   zWeakSetitem.dereferencer   )r   r8   rL   r	   r)   r1   r*   r   r,   r   r-   r4   r   rO   r   r   r   r   r   r&   r&   r   r'   rC   %  r   rC   )r   r	   r   r   )r.   r/   r0   r	   r)   r1   r*   r2   r+   r3   r,   r   r-   r4   r   r5   )r   r   r*   r   r   r   ),
__future__r   r    rs   	functoolsr   typesr   r   r   r   typingr   r	   r
   r   r   r   r   r   warningsr   Z_mypycr   r   Ztyping_extensionsr   r   r   __annotations____all__r   r   r(   r   r   rr   r=   r>   rD   rH   rG   r8   rC   r&   r&   r&   r'   <module>   sB    (

	 
~'&7,#