
    ztf                    h   U d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZ ddlmZmZmZ ddl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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* d	dl+m,Z, d	dl-m.Z.m/Z/m0Z0m1Z1m2Z2 er'd	dl3m4Z4 d	dl-m5Z5 eee6   ge6f   Z7ee6e6ge6f   Z8e!e7e8f   Z9g dZ: e;       Z< e de      Z= ej|                         Z?ed   Z@ eAe@j                        ZCdZDdeEd<    G d d      ZF G d d      ZG e       ZH e*d       G d d             ZI G d d       ZJ G d! d"      ZKd4d#ZL e ed$ej                  %       ed&ej                  %      g      ZO ed'      d5d(       ZPd6d)ZQd7d*ZR	 d8	 	 	 	 	 d9d,ZS	 d:	 	 	 	 	 	 	 d;d-ZTd<d.ZUd=d/ZVd0ZWd>d1ZXd+eEd2<   d?d3ZYy)@a+  The main Signal class and SignalInstance class.

A note on the "reemission" parameter in Signal and SignalInstances.  This controls the
behavior of the signal when a callback emits the signal.

Since it can be a little confusing, take the following example of a Signal that emits an
integer.  We'll connect three callbacks to it, two of which re-emit the same signal with
a different value:

```python
from psygnal import SignalInstance

# a signal that emits an integer
sig = SignalInstance((int,), reemission="...")


def cb1(value: int) -> None:
    print(f"calling cb1 with: {value}")
    if value == 1:
        # cb1 ALSO triggers an emission of the value 2
        sig.emit(2)


def cb2(value: int) -> None:
    print(f"calling cb2 with: {value}")
    if value == 2:
        # cb2 ALSO triggers an emission of the value 3
        sig.emit(3)


def cb3(value: int) -> None:
    print(f"calling cb3 with: {value}")


sig.connect(cb1)
sig.connect(cb2)
sig.connect(cb3)
sig.emit(1)
```

with `reemission="queued"` above: you see a breadth-first pattern:
ALL callbacks are called with the first emitted value, before ANY of them are called
with the second emitted value (emitted by the first connected callback  cb1)

```
calling cb1 with: 1
calling cb2 with: 1
calling cb3 with: 1
calling cb1 with: 2
calling cb2 with: 2
calling cb3 with: 2
calling cb1 with: 3
calling cb2 with: 3
calling cb3 with: 3
```

with `reemission='immediate'` signals emitted by callbacks are immediately processed by
all callbacks in a deeper level, before returning back to the original loop level to
call the remaining callbacks with the original value.

```
calling cb1 with: 1
calling cb1 with: 2
calling cb2 with: 2
calling cb1 with: 3
calling cb2 with: 3
calling cb3 with: 3
calling cb3 with: 2
calling cb2 with: 1
calling cb3 with: 1
```

with `reemission='latest'`, just as with 'immediate', signals emitted by callbacks are
immediately processed by all callbacks in a deeper level.  But in this case, the
remaining callbacks in the current level are never called with the original value.

```
calling cb1 with: 1
calling cb1 with: 2
calling cb2 with: 2
calling cb1 with: 3
calling cb2 with: 3
calling cb3 with: 3
# cb2 is never called with 1
# cb3 is never called with 1 or 2
```

The real-world scenario in which this usually arises is an EventedModel or dataclass.
Evented models emit signals on `setattr`:


```python
class MyModel(EventedModel):
    x: int = 1


m = MyModel(x=1)
print("starting value", m.x)


@m.events.x.connect
def ensure_at_least_20(val: int):
    print("trying to set to", val)
    m.x = max(val, 20)


m.x = 5
print("ending value", m.x)
```

```
starting value 1
trying to set to 5
trying to set to 20
ending value 20
```

With EventedModel.__setattr__, you can easily end up with some complicated recursive
behavior if you connect an on-change callback that also sets the value of the model. In
this case `reemission='latest'` is probably the most appropriate, as it will prevent
the callback from being called with the original (now-stale) value.  But one can
conceive of other scenarios where `reemission='immediate'` or `reemission='queued'`
might be more appropriate.  Qt's default behavior, for example, is similar to
`immediate`, but can also be configured to be like `queued` by changing the
connection type (in that case, depending on threading).
    )annotationsN)deque)contextmanagersuppress)	lru_cachepartialreduce)	Parameter	Signatureisclass)TYPE_CHECKINGAnyCallableClassVarContextManagerFinalIterableIteratorLiteralNoReturnTypeTypeVarUnioncastget_args
get_originget_type_hintsoverload   )EmitLoopError)
mypyc_attr)QueuedCallback)StrongFunctionWeakCallbackWeakSetattrWeakSetitemweak_callbackEmissionInfo)RefErrorChoice)SignalSignalInstance	_compiledF)bound)	immediatequeuedlatest-onlyr0   ReemissionValDEFAULT_REEMISSIONc                  `    e Zd ZU dZdZded<   dZded<   dZded<   edd	       Z	edd
       Z
y)ReemissionModez%Enumeration of reemission strategies.r0   r   	IMMEDIATEr1   QUEUEDr2   LATESTc                    t        |       j                         } | t        j                         vr2t	        ddj                  t        j                                d|       | S )Nz)Invalid reemission value. Must be one of z, z. Not )strlowerr6   _members
ValueErrorjoin)values    Y/var/www/html/software/conda/envs/higlass/lib/python3.12/site-packages/psygnal/_signal.pyvalidatezReemissionMode.validate   s`    E
  "//11;99^44678uiI      c                     t         S N)VALID_REEMISSION rC   rA   r=   zReemissionMode._members   s    rC   N)r@   r;   returnr;   )rH   zset[str])__name__
__module____qualname____doc__r7   __annotations__r8   r9   staticmethodrB   r=   rG   rC   rA   r6   r6      sI    /"Iu"FE!FE!     rC   r6   c                     e Zd ZU dZdZded<   dddded	 	 	 	 	 	 	 	 	 	 	 	 	 dd	Zedd
       Z	ddZ
eddd       Ze	 d	 	 	 	 	 dd       Z	 d	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ	 d	 	 	 	 	 ddZeedd              Zedd       Zedd       Zy) r+   a[  Declares a signal emitter on a class.

    This is class implements the [descriptor
    protocol](https://docs.python.org/3/howto/descriptor.html#descriptorhowto)
    and is designed to be used as a class attribute, with the supported signature types
    provided in the constructor:

    ```python
    from psygnal import Signal


    class MyEmitter:
        changed = Signal(int)


    def receiver(arg: int):
        print("new value:", arg)


    emitter = MyEmitter()
    emitter.changed.connect(receiver)
    emitter.changed.emit(1)  # prints 'new value: 1'
    ```

    !!! note

        in the example above, `MyEmitter.changed` is an instance of `Signal`,
        and `emitter.changed` is an instance of `SignalInstance`.  See the
        documentation on [`SignalInstance`][psygnal.SignalInstance] for details
        on how to connect to and/or emit a signal on an instance of an object
        that has a `Signal`.


    Parameters
    ----------
    *types : Type[Any] | Signature
        A sequence of individual types, or a *single* [`inspect.Signature`][] object.
    description : str
        Optional descriptive text for the signal.  (not used internally).
    name : str | None
        Optional name of the signal. If it is not specified then the name of the
        class attribute that is bound to the signal will be used. default None
    check_nargs_on_connect : bool
        Whether to check the number of positional args against `signature` when
        connecting a new callback. This can also be provided at connection time using
        `.connect(..., check_nargs=True)`. By default, `True`.
    check_types_on_connect : bool
        Whether to check the callback parameter types against `signature` when
        connecting a new callback. This can also be provided at connection time using
        `.connect(..., check_types=True)`. By default, `False`.
    reemission : Literal["immediate", "queued", "latest-only"] | None
        Determines the order and manner in which connected callbacks are invoked when a
        callback re-emits a signal. Default is `"immediate"`.

        * `"immediate"`: Signals emitted by callbacks are immediately processed in a
            deeper emission loop, before returning to process signals emitted at the
            current level (after all callbacks in the deeper level have been called).

        * `"queued"`: Signals emitted by callbacks are enqueued for emission after the
            current level of emission is complete. This ensures *all* connected
            callbacks are called with the first emitted value, before *any* of them are
            called with values emitted while calling callbacks.

        * `"latest-only"`: Signals emitted by callbacks are immediately processed in a
            deeper emission loop, and remaining callbacks in the current level are never
            called with the original value.
    NzClassVar[SignalInstance | None]_current_emitter TF)descriptionnamecheck_nargs_on_connectcheck_types_on_connect
reemissionc               4   || _         || _        || _        || _        || _        t
        | _        i | _        |rJt        |d   t              r7|d   | _
        t        |      dkD  rt        j                  d|dd   d       y y t        t        d|       | _
        y )Nr   r   zdOnly a single argument is accepted when directly providing a `Signature`.  These args were ignored:    
stacklevelztuple[Type[Any], ...])_namerR   _check_nargs_on_connect_check_types_on_connect_reemissionr,   _signal_instance_class_signal_instance_cache
isinstancer   
_signaturelenwarningswarn_build_signaturer   )selfrR   rS   rT   rU   rV   typess          rA   __init__zSignal.__init__#  s     
&'=$'=$%<J#AC#Za)4#AhDO5zA~??DQRykK   /5Le0TUDOrC   c                    | j                   S )z8[Signature][inspect.Signature] supported by this Signal.rb   rg   s    rA   	signaturezSignal.signature?       rC   c                ,    | j                   || _         yy)zASet name of signal when declared as a class attribute on `owner`.Nr[   )rg   ownerrS   s      rA   __set_name__zSignal.__set_name__D  s    ::DJ rC   c                     y rE   rG   rg   instancerq   s      rA   __get__zSignal.__get__I  s    QTrC   c                     y rE   rG   rt   s      rA   rv   zSignal.__get__L  s     rC   c                   || S t        |      | j                  v r| j                  t        |         S | j                  |      }	 t        |t	        d| j
                        |       |S # t        $ r | j                  ||       Y |S w xY w)ag  Get signal instance.

        This is called when accessing a Signal instance.  If accessed as an
        attribute on the class `owner`, instance, will be `None`.  Otherwise,
        if `instance` is not None, we're being accessed on an instance of `owner`.

            class Emitter:
                signal = Signal()

            e = Emitter()

            E.signal  # instance will be None, owner will be Emitter
            e.signal  # instance will be e, owner will be Emitter

        Returns
        -------
        Signal or SignalInstance
            Depending on how this attribute is accessed.
        r;   )idr`   _create_signal_instancesetattrr   r[   AttributeError_cache_signal_instance)rg   ru   rq   signal_instances       rA   rv   zSignal.__get__Q  s    , Kh<4666..r(|<<66x@	C Hd5$**5G   	C ''/B	Cs   !A) )BBc                    t        |      }|| j                  |<   t        t              5  t	        j
                  || j                  j                  |d       ddd       y# 1 sw Y   yxY w)z(Cache a signal instance on the instance.N)ry   r`   r   	TypeErrorweakreffinalizepop)rg   ru   r~   obj_ids       rA   r}   zSignal._cache_signal_instancez  s_     H.=##F+i  	VXt'B'B'F'FPTU	V 	V 	Vs   -A  A)c                    | j                  | j                  ||xs | j                  | j                  | j                  | j
                        S )Nru   rS   rT   rU   rV   )r_   rm   r[   r\   r]   r^   )rg   ru   rS   s      rA   rz   zSignal._create_signal_instance  sM     **NN##'#?#?#'#?#?'' + 
 	
rC   c              #  d   K   | j                   |c}| _         	 d || _         y# || _         w xY ww)zJContext that sets the sender on a receiver object while emitting a signal.NrP   )clsemitterpreviouss      rA   	_emittingzSignal._emitting  s5      *-)=)=w&#&	,#+C 8C s   0$ 0	-0c                    | j                   S )a  Return currently emitting `SignalInstance`, if any.

        This will typically be used in a callback.

        Examples
        --------
        ```python
        from psygnal import Signal


        def my_callback():
            source = Signal.current_emitter()
        ```
        r   r   s    rA   current_emitterzSignal.current_emitter  s      ###rC   c                0    t        | j                  dd      S )zfReturn currently emitting object, if any.

        This will typically be used in a callback.
        ru   N)getattrrP   r   s    rA   senderzSignal.sender  s     s++Z>>rC   )rh   ztype[Any] | SignaturerR   r;   rS   
str | NonerT   boolrU   r   rV   r3   rH   NonerH   r   )rq   	type[Any]rS   r;   rH   r   rE   )ru   r   rq   type[Any] | NonerH   r+   )ru   r   rq   r   rH   r,   )ru   r   rq   r   rH   zSignal | SignalInstance)ru   r   r~   r,   rH   r   )ru   r   rS   r   rH   r,   )r   r,   rH   zIterator[None])rH   zSignalInstance | NonerH   r   )rI   rJ   rK   rL   rP   rM   r4   ri   propertyrm   rr   r   rv   r}   rz   classmethodr   r   r   r   rG   rC   rA   r+   r+      sy   BL 9=5<
 '+',$6V%V V 	V
 !%V !%V "V 
V8  
 T T7;$4	 
 8<''$4'	 'RVV.<V	V 15



#-

	

 ,  , $ $" ? ?rC   r+   T)allow_interpreted_subclassesc            	         e Zd ZU dZdZded<   dZded<   dZded<   efddd	de	d
	 	 	 	 	 	 	 	 	 	 	 	 	 d5dZ
ed6d       Zed7d       Zed8d       Zed9d       Zd9dZedddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d:d       Zedddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d;d       Z	 d<dddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d=dZd>dZd?dZd@dAdZefddd	 	 	 	 	 	 	 	 	 	 	 dBdZ	 d@	 	 	 	 	 	 	 dCdZefddd	 	 	 	 	 	 	 	 	 	 	 dDdZ	 d@	 	 	 	 	 	 	 dEdZ	 	 	 	 	 	 dFd ZdGdHd!ZdId"ZdJdKd#ZdLd$Z dMd%Z!ddd&	 	 	 	 	 	 	 dNd'Z"ddd&	 	 	 	 	 	 	 dNd(Z#dOd)Z$dPd*Z%dPd+Z&dPd,Z'dQdRd-Z(dPd.Z)dSd/Z*dPd0Z+defdTd1Z,def	 	 	 	 	 dUd2Z-dVd3Z.dWd4Z/y)Xr,   a  A signal instance (optionally) bound to an object.

    In most cases, users will not create a `SignalInstance` directly -- instead
    creating a [Signal][psygnal.Signal] class attribute.  This object will be
    instantiated by the `Signal.__get__` method (i.e. the descriptor protocol),
    when a `Signal` instance is accessed from an *instance* of a class with `Signal`
    attribute.

    However, it is the `SignalInstance` that you will most often be interacting
    with when you access the name of a `Signal` on an instance -- so understanding
    the `SignalInstance` API is key to using psygnal.

    ```python
    class Emitter:
        signal = Signal()


    e = Emitter()

    # when accessed on an *instance* of Emitter,
    # the signal attribute will be a SignalInstance
    e.signal

    # This is what you will use to connect your callbacks
    e.signal.connect(some_callback)
    ```

    Parameters
    ----------
    signature : Signature | None
        The signature that this signal accepts and will emit, by default `Signature()`.
    instance : Any
        An object to which this signal is bound. Normally this will be provided by the
        `Signal.__get__` method (see above).  However, an unbound `SignalInstance`
        may also be created directly. by default `None`.
    name : str | None
        An optional name for this signal.  Normally this will be provided by the
        `Signal.__get__` method. by default `None`
    check_nargs_on_connect : bool
        Whether to check the number of positional args against `signature` when
        connecting a new callback. This can also be provided at connection time using
        `.connect(..., check_nargs=True)`. By default, `True`.
    check_types_on_connect : bool
        Whether to check the callback parameter types against `signature` when
        connecting a new callback. This can also be provided at connection time using
        `.connect(..., check_types=True)`. By default, `False`.
    reemission : Literal["immediate", "queued", "latest-only"] | None
        See docstring for [`Signal`][psygnal.Signal] for details.
        By default, `"immediate"`.

    Raises
    ------
    TypeError
        If `signature` is neither an instance of `inspect.Signature`, or a `tuple`
        of types.
    Fr   _is_blocked
_is_pausedNz/ClassVar[Callable[[EmissionInfo], None] | None]_debug_hookTr   c                  t        |t        t        f      r	t        | }nt        |t              st        d      t        j                  |      | _        || _	        | j                  |      | _        g | _        || _        || _        || _        g | _        d| _        d| _        t'        j(                         | _        t-               | _        d| _        d| _        |  | j                  t        j4                  k(  r| j6                  | _        d| _         y | j                  t        j:                  k(  r| j<                  | _        d| _         y | j>                  | _        d| _         y )NzU`signature` must be either a sequence of types, or an instance of `inspect.Signature`Fr   )!ra   listtuplerf   r   r   r6   rB   r^   r[   _instance_ref	_instance_args_queuerb   r\   r]   _slotsr   r   	threadingRLock_lockr   _emit_queue_recursion_depth_max_recursion_depthr8   _run_emit_loop_queued_run_emit_loop_innerr9   _run_emit_loop_latest_only_run_emit_loop_immediate_priority_in_use)rg   rm   ru   rS   rT   rU   rV   s          rA   ri   zSignalInstance.__init__  s:    i$/()4IIy12 
 *22:>
#'#5#5h#?(*#'=$'=$*,!& %__&
).%&)*!~444(,(B(BD% !& !6!66(,(G(GD%
 !& )-(E(ED% !&rC   c                b      d S 	 t        j                         S # t        $ r  fdcY S w xY w)Nc                      y rE   rG   rG   rC   rA   <lambda>z.SignalInstance._instance_ref.<locals>.<lambda>(      rC   c                      S rE   rG   ru   s   rA   r   z.SignalInstance._instance_ref.<locals>.<lambda>.  s    8 rC   )r   refr   r   s   `rA   r   zSignalInstance._instance_ref%  s8    	$;;x(( 	$##	$s    ..c                    | j                   S )z-Signature supported by this `SignalInstance`.rk   rl   s    rA   rm   zSignalInstance.signature0  rn   rC   c                "    | j                         S )z(Object that emits this `SignalInstance`.)r   rl   s    rA   ru   zSignalInstance.instance5  s     ~~rC   c                "    | j                   xs dS )zName of this `SignalInstance`.rQ   rp   rl   s    rA   rS   zSignalInstance.name:  s     zzRrC   c                    | j                   rd| j                   nd}| j                  d| j                  nd}dt        |       j                   | | dS )zReturn repr. rQ   z on <>)r[   ru   typerI   )rg   rS   ru   s      rA   __repr__zSignalInstance.__repr__?  sX    %)ZZ4::.!R/3}}/HT$--*+b4:&&'vhZq99rC   .)threadcheck_nargscheck_typesuniquemax_argson_ref_errorpriorityc                    y rE   rG   )rg   r   r   r   r   r   r   r   s           rA   connectzSignalInstance.connectE  s     rC   c                    y rE   rG   )	rg   slotr   r   r   r   r   r   r   s	            rA   r   zSignalInstance.connectR  s     rC   re   r   c                     j                    j                  ||f	 	 	 	 	 	 	 d fd}	||	S  |	|      S )a  Connect a callback (`slot`) to this signal.

        `slot` is compatible if:

        * it requires no more than the number of positional arguments emitted by this
          `SignalInstance`.  (It *may* require less)
        * it has no *required* keyword arguments (keyword only arguments that have
          no default).
        * if `check_types` is `True`, the parameter types in the callback signature must
          match the signature of this `SignalInstance`.

        This method may be used as a decorator.

        ```python
        @signal.connect
        def my_function(): ...
        ```

        !!!important
            If a signal is connected with `thread != None`, then it is up to the user
            to ensure that `psygnal.emit_queued` is called, or that one of the backend
            convenience functions is used (e.g. `psygnal.qt.start_emitting_from_queue`).
            Otherwise, callbacks that are connected to signals that are emitted from
            another thread will never be called.

        Parameters
        ----------
        slot : Callable
            A callable to connect to this signal.  If the callable accepts less
            arguments than the signature of this slot, then they will be discarded when
            calling the slot.
        check_nargs : Optional[bool]
            If `True` and the provided `slot` requires more positional arguments than
            the signature of this Signal, raise `TypeError`. by default `True`.
        thread: Thread | Literal["main", "current"] | None
            If `None` (the default), this slot will be invoked immediately when a signal
            is emitted, from whatever thread emitted the signal. If a thread object is
            provided, then the callback will only be immediately invoked if the signal
            is emitted from that thread.  Otherwise, the callback will be added to a
            queue. **Note!**, when using the `thread` parameter, the user is responsible
            for calling `psygnal.emit_queued()` in the corresponding thread, otherwise
            the slot will never be invoked. (See note above). (The strings `"main"` and
            `"current"` are also accepted, and will be interpreted as the
            `threading.main_thread()` and `threading.current_thread()`, respectively).
        check_types : Optional[bool]
            If `True`, An additional check will be performed to make sure that types
            declared in the slot signature are compatible with the signature
            declared by this signal, by default `False`.
        unique : Union[bool, str, None]
            If `True`, returns without connecting if the slot has already been
            connected.  If the literal string "raise" is passed to `unique`, then a
            `ValueError` will be raised if the slot is already connected.
            By default `False`.
        max_args : Optional[int]
            If provided, `slot` will be called with no more more than `max_args` when
            this SignalInstance is emitted.  (regardless of how many arguments are
            emitted).
        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
            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.

        Raises
        ------
        TypeError
            If a non-callable object is provided.
        ValueError
            If the provided slot fails validation, either due to mismatched positional
            argument requirements, or failed type checking.
        ValueError
            If `unique` is `True` and `slot` has already been connected.
        c                   t        |       st        d|        
j                  5  r| 
v rdk(  rt        d      | cd d d        S d }r&|$
j	                  | 
j
                        \  }}}|rd}r>|xs t        |       }t        | 
j
                  |      sd| d}
j                  | |       t        | |
j                  |	      }t        |      }
j                  |       d d d        | S # 1 sw Y   | S xY w)	Nz'Cannot connect to non-callable object: raisezUSlot already connect. Use `connect(..., unique=False)` to allow duplicate connectionsignorez- Slot types z do not match types in signal.r   r   r   r   )r   )callabler   r   r>   _check_nargsrm   _parameter_types_match_raise_connection_errorr'   _try_discardr"   _append_slot)r   r   _on_ref_errslot_sigisqtextracbr   r   r   rg   r   r   s          rA   _wrapperz(SignalInstance.connect.<locals>._wrapper  s+   
 D>"I$ PQQ &ddl((=   & & .2H$4/3/@/@t~~/V,Hh&.':9T?H1$Q"/z9W X44T5A"%!..!,% %'6:B!!"%;&< K=&< Ks   C7	B$C77D)r   r.   r   
int | Noner   r*   rH   r.   )r\   r]   )
rg   r   r   r   r   r   r   r   r   r   s
   ` ````  ` rA   r   zSignalInstance.connect`  st    t 66K66K $,*6&	&	 &	 (&	 	&	 &	P  <x;Xd^;rC   c                X   | j                   s/|j                  s| j                  j                  |       yd| _         t	        | j                        D ]<  \  }}|j                  |j                  k  s | j                  j                  ||        y | j                  j                  |       y)zAppend a slot to the list of slots.

        Implementing this as a method allows us to override/extend it in subclasses.
        NT)r   r   r   append	enumerateinsert)rg   r   iss       rA   r   zSignalInstance._append_slot  s     $$==""4($(D! dkk* 	DAqzzDMM)""1d+	 	4 rC   c                    |dk(  r| j                   j                          yt        |t              r| j                   j	                  |       y| j                   j                  t        d|             y)z%Remove a slot from the list of slots.allr$   N)r   clearra   intr   remover   rg   r   s     rA   _remove_slotzSignalInstance._remove_slot  sN     5=KKc"KKOOD!KKtND9:rC   c                L    	 | j                  |       y# t        $ r |s Y yw xY w)a  Try to discard a callback from the list of slots.

        Parameters
        ----------
        callback : WeakCallback
            A callback to discard.
        missing_ok : bool, optional
            If `True`, do not raise an error if the callback is not found in the list.
        N)r   r>   )rg   callback
missing_oks      rA   r   zSignalInstance._try_discard  s/    	h' 	 	s    ##)r   r   c          	     <   |t         u rt        j                  dt        d       d}t	        ||      st        d| d|      | j                  5  t        ||t        d|      | j                  ||      }| j                  |       ddd       |S # 1 sw Y   S xY w)	a   Bind an object attribute to the emitted value of this signal.

        Equivalent to calling `self.connect(functools.partial(setattr, obj, attr))`,
        but with additional weakref safety (i.e. a strong reference to `obj` will not
        be retained). The return object can be used to
        [`disconnect()`][psygnal.SignalInstance.disconnect], (or you can use
        [`disconnect_setattr()`][psygnal.SignalInstance.disconnect_setattr]).

        Parameters
        ----------
        obj : object
            An object.
        attr : str
            The name of an attribute on `obj` that should be set to the value of this
            signal when emitted.
        maxargs : Optional[int]
            max number of positional args to accept
        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
            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
        -------
        Tuple
            (weakref.ref, name, callable).  Reference to the object, name of the
            attribute, and setattr closure.  Can be used to disconnect the slot.

        Raises
        ------
        ValueError
            If this is not a single-value signal
        AttributeError
            If `obj` has no attribute `attr`.

        Examples
        --------
        >>> class T:
        ...     sig = Signal(int)
        >>> class SomeObj:
        ...     x = 1
        >>> t = T()
        >>> my_obj = SomeObj()
        >>> t.sig.connect_setattr(my_obj, "x")
        >>> t.sig.emit(5)
        >>> assert my_obj.x == 5
        zThe default value of maxargs will change from `None` to `1` in version 0.11. To silence this warning, provide an explicit value for maxargs (`None` for current behavior, `1` for future behavior).rX   rY   NObject  has no attribute r   r   )_NULLrd   re   FutureWarninghasattrr|   r   r%   r   r   r   )rg   objattrmaxargsr   r   callers          rA   connect_setattrzSignalInstance.connect_setattr  s    | eMMR  GsD! 73%/A$!JKKZZ 		& lG4**)!F f%		& 		& s   7BBc                    | j                   5  t        ||d      }| j                  ||       ddd       y# 1 sw Y   yxY w)a  Disconnect a previously connected attribute setter.

        Parameters
        ----------
        obj : object
            An object.
        attr : str
            The name of an attribute on `obj` that was previously used for
            `connect_setattr`.
        missing_ok : bool
            If `False` and the provided `slot` is not connected, raises `ValueError`.
            by default `True`

        Raises
        ------
        ValueError
            If `missing_ok` is `True` and no attribute setter is connected.
        r   r   N)r   r%   r   )rg   r   r   r   r   s        rA   disconnect_setattrz!SignalInstance.disconnect_setattrr  s>    * ZZ 	.S$X>Bb*-	. 	. 	.s	   !7A c          	     8   |t         u rt        j                  dt        d       d}t	        |d      st        d| d      | j                  5  t        ||t        d|      | j                  ||	      }| j                  |       ddd       |S # 1 sw Y   S xY w)
a  Bind a container item (such as a dict key) to emitted value of this signal.

        Equivalent to calling `self.connect(functools.partial(obj.__setitem__, attr))`,
        but with additional weakref safety (i.e. a strong reference to `obj` will not
        be retained). The return object can be used to
        [`disconnect()`][psygnal.SignalInstance.disconnect], (or you can use
        [`disconnect_setitem()`][psygnal.SignalInstance.disconnect_setitem]).

        Parameters
        ----------
        obj : object
            An object.
        key : str
            Name of the key in `obj` that should be set to the value of this
            signal when emitted
        maxargs : Optional[int]
            max number of positional args to accept
        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
            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
        -------
        Tuple
            (weakref.ref, name, callable).  Reference to the object, name of the
            attribute, and setitem closure.  Can be used to disconnect the slot.

        Raises
        ------
        ValueError
            If this is not a single-value signal
        TypeError
            If `obj` does not support __setitem__.

        Examples
        --------
        >>> class T:
        ...     sig = Signal(int)
        >>> t = T()
        >>> my_obj = dict()
        >>> t.sig.connect_setitem(my_obj, "x")
        >>> t.sig.emit(5)
        >>> assert my_obj == {"x": 5}
        zThe default value of maxargs will change from `None` to `1` inversion 0.11. To silence this warning, provide an explicit value for maxargs (`None` for current behavior, `1` for future behavior).rX   rY   N__setitem__r    does not support __setitem__r   r   )r   rd   re   r   r   r   r   r&   r   r   r   )rg   r   keyr   r   r   r   s          rA   connect_setitemzSignalInstance.connect_setitem  s    x eMMR  GsM*gcU*GHIIZZ 		& lG4**)!F f%		& 		& s   7BBc                    t        |d      st        d| d      | j                  5  t        ||d      }| j	                  ||       ddd       y# 1 sw Y   yxY w)a  Disconnect a previously connected item setter.

        Parameters
        ----------
        obj : object
            An object.
        key : str
            The name of a key in `obj` that was previously used for
            `connect_setitem`.
        missing_ok : bool
            If `False` and the provided `slot` is not connected, raises `ValueError`.
            by default `True`

        Raises
        ------
        ValueError
            If `missing_ok` is `True` and no item setter is connected.
        r   r   r   r   r   N)r   r   r   r&   r   )rg   r   r  r   r   s        rA   disconnect_setitemz!SignalInstance.disconnect_setitem  s]    * sM*gcU*GHIIZZ 	2 cAFfj1	2 	2 	2s   !AAc                   	 t        |      }	 t	        |      \  }}|t        |j                        x}kD  rd| d| }| j                  ||       t        |t              rd|d	fS ||d	fS # t        $ r$}t        j                  | dd       Y d}~yd}~ww xY w# t        $ r%}t        |t              rt        | d      | d}~ww xY w)
a  Make sure slot is compatible with signature.

        Also returns the maximum number of arguments that we can pass to the slot

        Returns
        -------
        slot_sig : Signature | None
            The signature of the slot, or None if it could not be determined.
        maxargs : int | None
            The maximum number of arguments that we can pass to the slot.
        is_qt : bool
            Whether the slot is a Qt slot.
        z;. To silence this warning, connect with `check_nargs=False`rX   rY   N)NNFzM. (Note: prefer using positional args with functools.partials when possible).z- Slot requires at least z. positional arguments, but spec only provides T)_get_signature_possibly_qtr>   rd   re   _acceptable_posarg_rangera   r   rc   
parametersr   r;   )	rg   r   specr   eminargsr   n_spec_paramsr   s	            rA   r   zSignalInstance._check_nargs  s     	%1$7H	7AGW s4??';;m<+G9 555BOE  ((u5!(C0tMMhMM1  	%MM#TT %	%  	$( c 9 9  	s.   A* B *	B3BB	C# CCc                    t        |dt        |            }d|dt        |       d}||z  }|d| j                   z  }t        |      )NrI   zCannot connect slot z with signature: :
z

Accepted signature: )r   r;   rm   r>   )rg   r   r   rS   msgs        rA   r   z&SignalInstance._raise_connection_error)  sX    tZT3$TH,=io=NcRu)$..)9::orC   c                    | j                   5  t        |d      t        fdt        | j                        D        d      cddd       S # 1 sw Y   yxY w)zBGet index of `slot` in `self._slots`.  Return -1 if not connected.r   r   c              3  4   K   | ]  \  }}|k(  s|  y wrE   rG   ).0r   r   normeds      rA   	<genexpr>z-SignalInstance._slot_index.<locals>.<genexpr>6  s     Mtq!fMs   N)r   r'   nextr   r   )rg   r   r  s     @rA   _slot_indexzSignalInstance._slot_index0  sJ    ZZ 	S"4h?F My'=MrR		S 	S 	Ss   5AAc                    | j                   5  || j                  d       	 ddd       y| j                  |      }|dk7  r| j                  |       n|st        d|       ddd       y# 1 sw Y   yxY w)a  Disconnect slot from signal.

        Parameters
        ----------
        slot : callable, optional
            The specific slot to disconnect.  If `None`, all slots will be disconnected,
            by default `None`
        missing_ok : Optional[bool]
            If `False` and the provided `slot` is not connected, raises `ValueError.
            by default `True`

        Raises
        ------
        ValueError
            If `slot` is not connected and `missing_ok` is False.
        Nr   r  zslot is not connected: )r   r   r  r>   )rg   r   r   idxs       rA   
disconnectzSignalInstance.disconnect8  s    " ZZ 
	C|!!%(	
	C 
	C ""4(Cby!!#& #:4&!ABB
	C 
	C 
	Cs   A,8A,,A5c                *    | j                  |      dk\  S )z#Return `True` if slot is connected.r   )r  r   s     rA   __contains__zSignalInstance.__contains__U  s    %**rC   c                ,    t        | j                        S )z!Return number of connected slots.)rc   r   rl   s    rA   __len__zSignalInstance.__len__Y  s    4;;rC   r   r   c               z   | j                   ry|r	  | j                  j                  |  |rmt	        d | j                  t        |D cg c]  }t        |       c}       s8t        d| j                   dt        d	 |D               d
| j                         | j                  r| j                  j                  |       yt        j                  "ddlm} t        j                   || |             | j!                  |       y# t        $ r'}t        d| d| d| j                   d|       |d}~ww xY wc c}w )a  Emit this signal with arguments `args`.

        !!! note

            `check_args` and `check_types` both add overhead when calling emit.

        Parameters
        ----------
        *args : Any
            These arguments will be passed when calling each slot (unless the slot
            accepts fewer arguments, in which case extra args will be discarded.)
        check_nargs : bool
            If `False` and the provided arguments cannot be successfully bound to the
            signature of this Signal, raise `TypeError`.  Incurs some overhead.
            by default False.
        check_types : bool
            If `False` and the provided arguments do not match the types declared by
            the signature of this Signal, raise `TypeError`.  Incurs some overhead.
            by default False.

        Raises
        ------
        TypeError
            If `check_nargs` and/or `check_types` are `True`, and the corresponding
            checks fail.
        NzCannot emit args z from signal z with signature r  c                      y rE   rG   rG   rC   rA   r   z%SignalInstance.emit.<locals>.<lambda>  r   rC   zTypes provided to 'z.emit' c              3  F   K   | ]  }t        |      j                    y wrE   )r   rI   )r  as     rA   r  z&SignalInstance.emit.<locals>.<genexpr>  s     8aa))8s   !z  do not match signal signature: r   r(   )r   rm   bindr   r   rf   r   rS   r   r   r   r   r,   r   _groupr)   _run_emit_loop)rg   r   r   argsr
  r#  r)   s          rA   emitzSignalInstance.emit]  s=   : ###T* 5$..*:d<ST!W<S*T 
 %dii[84889 :"nn-/  ??##D)%%1,&&|D$'?@D!1  'v]4( C!!% 0A38  =Ts   D D8	D5"D00D5c               (     | j                   |||dS )z:Alias for `emit()`. But prefer using `emit()` for clarity.r  )r(  )rg   r   r   r'  s       rA   __call__zSignalInstance.__call__  s     tyy$K[QQrC   c           	        | j                   5  | j                  j                  |       t        | j                        dkD  r
	 d d d        y 	 | xj                  dz  c_        t        | j                  | j                        | _        t        j                  |       5  | j                          d d d        | xj                  dz  c_        | j                  dk  rd| _        d| _        | j                  j%                          	 d d d        y # 1 sw Y   _xY w# t        $ r!}t        d| j                  d|       |d }~wt        $ rd}t        |t              r|t        || | j                  dz
  | j                  | j                        j!                  |j"                        }||d }~ww xY w# | xj                  dz  c_        | j                  dk  rd| _        d| _        | j                  j%                          w xY w# 1 sw Y   y xY w)Nr   z$RecursionError when emitting signal z with args )excsignalrecursion_depthrV   
emit_queuer   )r   r   r   rc   r   maxr   r+   r   r   RecursionErrorrS   	Exceptionra   r    r^   with_traceback__traceback__r   )rg   r'  r
  cb_errloop_errs        rA   r&  zSignalInstance._run_emit_loop  s   ZZ #	)##D)4##$q(#	) #	))%%*%,/--t/D/D-) %%d+ 0--/0( %%*%((A-01D-,-D)  &&(G#	) #	)0 0! $''+yym;tfF   +fm4 L($($9$9A$=#//#// !.!5!56  F*+ %%*%((A-01D-,-D)  &&(G#	) #	)sc   5G?ADD
,D4AG?
D	D	F+D;;F+AF&&F++F..AG<<G??Hc                |    | j                   j                         }| j                  D ]  }|j                  |        y rE   )r   popleftr   r   rg   r'  r   s      rA   r   z'SignalInstance._run_emit_loop_immediate  s4    '')kk 	FIIdO	rC   c                    | j                   j                         x| _        }| j                  D ]5  }| j                  | j
                  k  r y || _        |j                  |       7 y rE   )r   r8  _argsr   r   r   _callerr   r9  s      rA   r   z)SignalInstance._run_emit_loop_latest_only  s[     ,,4466
Tkk 	F$$t'@'@@ !DLIIdO	rC   c                   d}|t        | j                        k  rr| j                  |   }| j                  D ]5  }|j                  |       t        | j                        t        kD  s1t
         |dz  }|t        | j                        k  rqy y )Nr   r   )rc   r   r   r   RECURSION_LIMITr1  )rg   r   r'  r   s       rA   r   z$SignalInstance._run_emit_loop_queued  s    #d&&''##A&D++ )		$t''(?:(() FA #d&&''rC   c                    d| _         y)zBlock this signal from emitting.

        NOTE: the `exclude` argument is only for SignalGroup subclass, but we
        have to include it here to make mypyc happy.
        TNr   )rg   excludes     rA   blockzSignalInstance.block  s      rC   c                    d| _         y)z)Unblock this signal, allowing it to emit.FNr@  rl   s    rA   unblockzSignalInstance.unblock  s
     rC   c                    t        |       S )a  Context manager to temporarily block this signal.

        Useful if you need to temporarily block all emission of a given signal,
        (for example, to avoid a recursive signal loop)

        Examples
        --------
        ```python
        class MyEmitter:
            changed = Signal()

            def make_a_change(self):
                self.changed.emit()

        obj = MyEmitter()

        with obj.changed.blocked()
            obj.make_a_change()  # will NOT emit a changed signal.
        ```
        )_SignalBlockerrl   s    rA   blockedzSignalInstance.blocked  s    * d##rC   c                    d| _         y)zPause all emission and collect *args tuples from emit().

        args passed to `emit` will be collected and re-emitted when `resume()` is
        called. For a context manager version, see `paused()`.
        TN)r   rl   s    rA   pausezSignalInstance.pause  s     rC   c                H   d| _         t        | dd      syt        | j                        dk(  r| j                  j                          y|t        t        j                  |      j                        dk(  r t        d|      | j                        }nBt        d|      }|t        u rt        || j                        }nt        || j                  |      }| j                  |       n"| j                  D ]  }| j                  |        | j                  j                          y)a  Resume (unpause) this signal, emitting everything in the queue.

        Parameters
        ----------
        reducer : Callable | None
            A optional function to reduce the args collected while paused into a single
            emitted group of args.  If not provided, all emissions will be re-emitted
            as they were collected when the signal is resumed. May be:

            - a function that takes two args tuples and returns a single args tuple.
              This will be passed to `functools.reduce` and is expected to reduce all
              collected/emitted args into a single tuple.
              For example, three `emit(1)` events would be reduced and re-emitted as
              follows: `self.emit(*functools.reduce(reducer, [(1,), (1,), (1,)]))`
            - a function that takes a single argument (an iterable of args tuples) and
              returns a tuple (the reduced args). This will be *not* be passed to
              `functools.reduce`. If `reducer` is a function that takes a single
              argument, `initial` will be ignored.
        initial: any, optional
            initial value to pass to `functools.reduce`

        Examples
        --------
        >>> class T:
        ...     sig = Signal(int)
        >>> t = T()
        >>> t.sig.pause()
        >>> t.sig.emit(1)
        >>> t.sig.emit(2)
        >>> t.sig.emit(3)
        >>> t.sig.resume(lambda a, b: (a[0].union(set(b)),), (set(),))
        >>> # results in t.sig.emit({1, 2, 3})
        Fr   Nr   r   ReducerOneArgReducerTwoArgs)r   r   rc   r   r   r   inspectrm   r  r   r   r	   r&  )rg   reducerinitialr'  s       rA   resumezSignalInstance.resume
  s    D   t]D1t{{q ""$7$$W-889Q>5tOW5d6F6FG/9e#!'4+;+;<D!'4+;+;WED%(( *##D)* rC   c                    t        | ||      S )a  Context manager to temporarily pause this signal.

        Parameters
        ----------
        reducer : Callable | None
            A optional function to reduce the args collected while paused into a single
            emitted group of args.  If not provided, all emissions will be re-emitted
            as they were collected when the signal is resumed. May be:

            - a function that takes two args tuples and returns a single args tuple.
              This will be passed to `functools.reduce` and is expected to reduce all
              collected/emitted args into a single tuple.
              For example, three `emit(1)` events would be reduced and re-emitted as
              follows: `self.emit(*functools.reduce(reducer, [(1,), (1,), (1,)]))`
            - a function that takes a single argument (an iterable of args tuples) and
              returns a tuple (the reduced args). This will be *not* be passed to
              `functools.reduce`. If `reducer` is a function that takes a single
              argument, `initial` will be ignored.
        initial: any, optional
            initial value to pass to `functools.reduce`

        Examples
        --------
        >>> with obj.signal.paused(lambda a, b: (a[0].union(set(b)),), (set(),)):
        ...     t.sig.emit(1)
        ...     t.sig.emit(2)
        ...     t.sig.emit(3)
        >>> # results in obj.signal.emit({1, 2, 3})
        )_SignalPauser)rg   rN  rO  s      rA   pausedzSignalInstance.pausedD  s    @ T7G44rC   c                J   d}|D ci c]  }|t        | |       }}| j                         |d<   | j                  D cg c]  }t        |t              s| c}|d<   t        | j                        t        |d         kD  rt        j                  dd       |S c c}w c c}w )z)Return dict of current state, for pickle.)rb   r[   r   r   r   r\   r]   r   r   r^   r   r   r   r   zJPickling a SignalInstance does not copy connected weakly referenced slots.rX   rY   )r   r   r   ra   r#   rc   rd   re   )rg   attrsr   ddxs        rA   __getstate__zSignalInstance.__getstate__f  s    
 5::DdGD$''::..*;#';;Pa*Q2OP8t{{c"X,//MM 	 ;Ps   BB B c                   |j                         D ].  \  }}|dk(  r| j                  |      | _        "t        | ||       0 t	        j
                         | _        | j                  t        j                  k(  r| j                  | _        y| j                  t        j                  k(  r| j                  | _        y| j                  | _        y)zRestore state from pickle.r   N)itemsr   r   r{   r   r   r   r^   r6   r8   r   r   r9   r   r   )rg   statekvs       rA   __setstate__zSignalInstance.__setstate__  s     KKM 	$DAqK!%!3!3A!6a#		$
 __&
~444(,(B(BD%!6!66(,(G(GD%(,(E(ED%rC   )rm   zSignature | tupleru   r   rS   r   rT   r   rU   r   rV   r3   rH   r   )ru   r   rH   zCallable[[], Any]r   r   )rH   r;   )r   4threading.Thread | Literal['main', 'current'] | Noner   bool | Noner   r`  r   
bool | strr   r   r   r*   r   r   rH   zCallable[[F], F])r   r.   r   r_  r   r`  r   r`  r   ra  r   r   r   r*   r   r   rH   r.   rE   )r   zF | Noner   r_  r   r`  r   r`  r   ra  r   r   r   r*   r   r   rH   zCallable[[F], F] | F)r   r$   rH   r   )r   z#Literal['all'] | int | WeakCallbackrH   r   T)r   r$   r   r   rH   r   )r   objectr   r;   r   int | None | objectr   r*   r   r   rH   WeakCallback[None])r   rc  r   r;   r   r   rH   r   )r   rc  r  r;   r   rd  r   r*   r   r   rH   re  )r   rc  r  r;   r   r   rH   r   )r   r   r	  r   rH   z)tuple[Signature | None, int | None, bool])rQ   )r   r   r   r;   rH   r   )r   r   rH   r   )NT)r   zCallable | Noner   r   rH   r   )r   r   rH   r   )rH   r   )r'  r   r   r   r   r   rH   r   )r'  ztuple[Any, ...]rH   r   rH   r   rG   )rA  Iterable[str | SignalInstance]rH   r   )rH   ContextManager[None])rN  ReducerFunc | NonerO  r   rH   r   )rN  rj  rO  r   rH   ri  )rH   dict)r[  rk  rH   r   )0rI   rJ   rK   rL   r   rM   r   r   _empty_signaturer4   ri   rN   r   r   rm   ru   rS   r   r   r   r   r   r   r   r   r   r  r  r   r   r  r  r  r  r(  r*  r&  r   r   r   rB  rD  rG  rI  rP  rS  rX  r^  rG   rC   rA   r,   r,     s   7r KJCGK@G (8)& '+',$6)&$)& 	)&
 )& !%)& !%)& ")& 
)&V $ $          :  HK#&#& #'*
 E
 !	

 !
 
 
 %
 
 

 
 
 HK#&#& #'* E	
 ! !   %  
  G< HL#'#'"#'-G<G< E	G<
 !G< !G< G< G< %G< G< 
G<R!0;( (-	U (.UU U %	U %U U 
Up :>..!$.26.	.: (-	T (.TT T %	T %T T 
Tn 9=22 #2152	28*N*N$-*N	2*NXSC:+ 
 /4;";"'+;"BF;"	;"| /4RR'+RBFR	R$)L
 !$. 48 8!v -1 5) 5;> 5	 5D8FrC   r,   c                  6    e Zd ZdZ	 d	 	 	 	 	 ddZddZd	dZy)
rF  z.Context manager to block and unblock a signal.c                B    || _         || _        |j                  | _        y rE   )_signal_excluder   _was_blocked)rg   r-  rA  s      rA   ri   z_SignalBlocker.__init__  s      "..rC   c                P    | j                   j                  | j                         y )N)rA  )ro  rB  rp  rl   s    rA   	__enter__z_SignalBlocker.__enter__  s    4==1rC   c                R    | j                   s| j                  j                          y y rE   )rq  ro  rD  rg   r'  s     rA   __exit__z_SignalBlocker.__exit__  s       LL  " !rC   Nrg  )r-  r,   rA  rh  rH   r   rf  r'  r   rH   r   rI   rJ   rK   rL   ri   rs  rv  rG   rC   rA   rF  rF    s3    8 QS/$//M/	/2#rC   rF  c                  8    e Zd ZdZ	 	 	 	 	 	 	 	 ddZddZddZy)	rR  z-Context manager to pause and resume a signal.c                P    |j                   | _        || _        || _        || _        y rE   )r   _was_pausedro  _reducer_initial)rg   r-  rN  rO  s       rA   ri   z_SignalPauser.__init__  s'     ",,rC   c                8    | j                   j                          y rE   )ro  rI  rl   s    rA   rs  z_SignalPauser.__enter__  s    rC   c                ~    | j                   s1| j                  j                  | j                  | j                         y y rE   )r{  ro  rP  r|  r}  ru  s     rA   rv  z_SignalPauser.__exit__  s,    LLt}}=  rC   N)r-  r,   rN  rj  rO  r   rH   r   rf  rw  rx  rG   rC   rA   rR  rR    s4    7 $ /A LO 	 >rC   rR  c                    	 t        j                  |       S # t        $ r]}t        t              5  t        j
                  |       st        |       cd d d        cY d }~S 	 d d d        ||# 1 sw Y   ||xY wd }~ww xY wrE   )rM  rm   r>   r   r2  ismethod	_stub_sig)r   r
  s     rA   rm   rm     ss      %% i  	&##C( ~	& 	&(	& Q	& Q	s7    	A=A8 A*	A8A=A8*A5	/	A88A=r'  rS   kindkwargs)maxsizec           	        ddl }t        t        | dd            t        u rt        | dd      dk(  st        |       t        u rt        S | |j
                  u rt        dt        j                        t        dt        j                  d	
      t        dt        j                  d
      t        dt        j                  d
      t        dt        j                  d
      g}t        |      S t        d      )z0Called as a backup when inspect.signature fails.r   N__self__rI   r(  r@   r  sepr   )rS   r  defaultend
fileflushFzunknown object)builtinsr   r   r,   _ANYSIGprintr
   VAR_POSITIONALKEYWORD_ONLYr   r>   )r   r  paramss      rA   r  r    s     
 	WS*d+,>CT*f4	cn	$  hnn7)A)AB5y'='=sK5y'='=tL6	(>(>M7)?)?O
   
%
&&rC   c            	         t        |       D cg c]$  \  }}t        d| t        j                  |      & }}}t        |      S c c}}w )Np)rS   r  
annotation)r   r
   POSITIONAL_ONLYr   )rh   r   tr  s       rA   rf   rf     sQ     e$Aq 	1#wY%>%>1MF  V	s   )Ac                6    t        |       }|t        |       S |S rE   )_guess_qtsignal_signaturerm   )r   sigs     rA   r  r    s!     $D
)C!k9T?2s2rC   r   c                   t        | t              rXd| vrt        d|       | j                  dd      d   j                  dd      d   }|r|j	                  d      dz   ndx}}||fS d}d}d}t
        j                  t
        j                  h}| j                  j                         D ]  }	|	j                  |v r(|	j                  t
        j                  u r|dz  }3|dz  }9|	j                  t
        j                  u rd}X|	j                  t
        j                  u su|	j                  t
        j                  u s|st        d	|         ||rd
fS ||z   fS )a  Return tuple of (min, max) accepted positional arguments.

    Parameters
    ----------
    sig : Signature
        Signature object to evaluate
    forbid_required_kwarg : Optional[bool]
        Whether to allow required KEYWORD_ONLY parameters. by default True.

    Returns
    -------
    arg_range : Tuple[int, int]
        minimum, maximum number of acceptable positional arguments

    Raises
    ------
    ValueError
        If the signature has a required keyword_only parameter and
        `forbid_required_kwarg` is `True`.
    (z&Unrecognized string signature format: r   )r   ,FTz2Unsupported KEYWORD_ONLY parameters in signature: N)ra   r;   r>   splitcountr
   r  POSITIONAL_OR_KEYWORDr  valuesr  r  emptyr  r  )
r  forbid_required_kwarginnerr  r   requiredoptionalposargs_unlimited_pos_requiredparams
             rA   r  r    sW   . #sc>EcWMNN		#q!!$**321549EKK,q0q@'HH..	0O0OPM&&( Y::&}}	/AAZZ9333 $JJ)0000%QRUQVWXXY /dIIX5HIIrC   c                   |xs t        |       }d}t        |j                  j                         |j                  j                               D ]p  \  }}|j                  }||j
                  u r!t        |t              r(|t        |       }|j                  |j                        }t        ||j                        rp y y)a  Return True if types in `function` signature match those in `spec`.

    Parameters
    ----------
    function : Callable
        A function to validate
    spec : Signature
        The Signature against which the `function` should be validated.
    func_sig : Signature, optional
        Signature for `function`, if `None`, signature will be inspected.
        by default None

    Returns
    -------
    bool
        True if the parameter types match.
    NFT)rm   zipr  r  r  r  ra   r;   r   getrS   _is_subclass)functionr	  func_sigfsig
func_hintsf_param
spec_paramf_annos           rA   r   r   8  s    ( *y*D"J"4??#9#9#;T__=S=S=UV ##TZZfc"!+H5
^^GLL1FFJ$9$9: rC   c                    t        |       s.t        |       t        u rt        fdt	        |       D              S t        |       S )z.Variant of issubclass with support for unions.c              3  6   K   | ]  }t        |        y wrE   )
issubclass)r  r   rights     rA   r  z_is_subclass.<locals>.<genexpr>b  s     @A:a'@s   )r   r   r   anyr   r  )leftr  s    `rA   r  r  _  s8    4=Z-6@$@@@dE""rC   c                   t        |       }d|j                  v rt        d| j                        S t	        | dd      }|dk(  r t        d| j
                  j                        S |dk(  r:|j                  j                  d      rt        | j
                  j                        S d|j                  v r$d	t	        |d
d      v rt        | j                        S y)zReturn string signature if `obj` is a SignalInstance or Qt emit method.

    This is a bit of a hack, but we found no better way:
    https://stackoverflow.com/q/69976089/1631624
    https://bugreports.qt.io/browse/PYSIDE-1713
    pyqtBoundSignalr;   rK   rQ   zpyqtBoundSignal.emitzSignalInstance.emitbuiltinr,   QtCorerJ   N)	r   rI   r   r-  r   r  
startswith_ridiculously_call_emitr(  )r   type_qualnames      rA   r  r  f  s     IEENN*E3::&&sNB/H))E3<<..// ((U^^-F-Fy-Q 's||'8'8995>>)h'|R; / 'sxx00rC   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   c                    	  | t           y# t        $ rG}dt        |      v r0t        |      j                  d      d   j	                         cY d}~S Y d}~yd}~ww xY w)zACall SignalInstance emit() to get the signature from err message.zonly acceptsr   N)_CRAZY_ARGSr   r;   r  strip)r   r
  s     rA   r  r    s[    ;   ;SV#q6<</288:: $;s   	 	A7AAAr-   c                V    | dk(  rt        t        d      S t        dt        d|       )Nr-   __mypyc_attrs__zmodule r   )r   r+   r|   rI   )rS   s    rA   __getattr__r    s1    {v011
78,.@I
JJrC   )r   r   rH   zinspect.Signature)r   r   rH   r   )rh   r   rH   r   )r   r   rH   Signature | strrb  )r  r  r  r   rH   ztuple[int, int | None]rE   )r  r   r	  r   r  zSignature | NonerH   r   )r  r   r  r   rH   r   )r   r   rH   r   )r   r   rH   r   )rS   r;   rH   r   )ZrL   
__future__r   rM  sysr   rd   r   collectionsr   
contextlibr   r   	functoolsr   r   r	   r
   r   r   typingr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   _exceptionsr    _mypycr!   _queuer"   _weak_callbackr#   r$   r%   r&   r'   r%  r)   r*   r   rK  rL  ReducerFunc__all__rc  r   r.   getrecursionlimitr>  r3   set__args__rF   r4   rM   r6   r+   rl  r,   rF  rR  rm   r  VAR_KEYWORDr  r  rf   r  r  r   r  r  r  r  r  rG   rC   rA   <module>r     s   }~ #  
     / 0 0 1 1    * '  "  $. huo.56Muene34N~56K 4Cx '#'')<=}--. $/ M /
   ,[? [?| ;  .TF TF /TFn# #$> >. vI$<$<=xi&;&;< 4' '6&3 9=0J	0J150J0Jh GK$$'$3C$	$N#8 
 KrC   