
    sgO              
          d dl Z d dlZd dlZd dlZddlmZ d dlZd dlZd dlZddlm	Z	m
Z
mZmZmZ g dZe j                  ded   f   Ze j                  eeegeeef   f   Zd Zd	 Zd
 Zd Zd Z ej                  e
e        ej                  ej                  e        ej                  ee        ej                  ee       d Zej4                  d        Zej4                  d        Zd Z	 d(dededede j>                  e j                     fdZ d)dZ!d Z"d Z#d)dddZ$d Z%d*dZ& G d d       Z'd! Z(d" Z)d# Z*d$ Z+ddd%d&Z,ddd%d'Z-y)+    N   )_uarray)BackendNotImplementedError	_Function_SkipBackendContext_SetBackendContext_BackendState)set_backendset_global_backendskip_backendregister_backenddetermine_backenddetermine_backend_multiclear_backendscreate_multimethodgenerate_multimethodr   r   Dispatchablewrap_single_convertorwrap_single_convertor_instanceall_of_typemark_as	set_state	get_statereset_stater	   r   r   .)r   .c                     dd l }	 |j                  |       }|j                  d      }|}|D ]  }t        ||      } |t	        j
                  ||      }|S # t        t        f$ r}ddlm	} ||d }~ww xY w)Nr   .)UnpicklingError)
	importlibimport_modulesplitgetattrtypes
MethodTypeImportErrorAttributeErrorpickler   )	mod_nameqnameself_r   modulefuncqer   s	            N/var/www/html/venv/lib/python3.12/site-packages/scipy/_lib/_uarray/_backend.pyunpickle_functionr/   0   s    %((2C  	$A4#D	$ ##D%0D( %*1$%s   AA A4&	A//A4c                     t        | dd       }t        | dd       }t        | dd       }	 t        |||      }|| urt        j                  d|  d|       t        |||ffS # t        j                  $ r d }Y Aw xY w)N
__module____qualname____self__zCan't pickle z: it's not the same object as )r!   r/   r&   r   PicklingError)r+   r'   r(   r)   tests        r.   pickle_functionr6   D   s    t\40HD.$/ED*d+E 5%8 4""D6!?vF
 	
 x666 !! s   A   A87A8c                 V    t         j                  j                  | j                         fS N)r   r	   	_unpickle_pickle)states    r.   pickle_stater<   V   s      **EMMO;;    c                 .    t         | j                         fS r8   )r   r:   ctxs    r.   pickle_set_backend_contextrA   Z   s    s{{},,r=   c                 .    t         | j                         fS r8   )r   r:   r?   s    r.   pickle_skip_backend_contextrC   ^   s    --r=   c                  *    t        j                         S )z
    Returns an opaque object containing the current state of all the backends.

    Can be used for synchronization between threads/processes.

    See Also
    --------
    set_state
        Sets the state returned by this function.
    )r   r    r=   r.   r   r   h   s     r=   c               #   d   K   t        t                     5  d ddd       y# 1 sw Y   yxY ww)z
    Returns a context manager that resets all state once exited.

    See Also
    --------
    set_state
        Context manager that sets the backend state.
    get_state
        Gets a state to be set by this context manager.
    N)r   r   rE   r=   r.   r   r   v   s)      
9;	   s   0$	0-0c              #      K   t               }t        j                  |        	 d t        j                  |d       y# t        j                  |d       w xY ww)z
    A context manager that sets the state of the backends to one returned by :obj:`get_state`.

    See Also
    --------
    get_state
        Gets a state to be set by this context manager.
    NT)r   r   r   )r;   	old_states     r.   r   r      sE      Ie+)T*)T*s    A> AAAc                        fd}|S )au  
    Creates a decorator for generating multimethods.

    This function creates a decorator that can be used with an argument
    extractor in order to generate a multimethod. Other than for the
    argument extractor, all arguments are passed on to
    :obj:`generate_multimethod`.

    See Also
    --------
    generate_multimethod
        Generates a multimethod.
    c                 "    t        | gi S r8   )r   )aargskwargss    r.   wrapperz#create_multimethod.<locals>.wrapper   s    #A7777r=   rE   )rL   rM   rN   s   `` r.   r   r      s    8 Nr=   argument_extractorargument_replacerdomaindefaultc                 l    t        |       \  }}}t        | |||||      }t        j                  ||       S )a  
    Generates a multimethod.

    Parameters
    ----------
    argument_extractor : ArgumentExtractorType
        A callable which extracts the dispatchable arguments. Extracted arguments
        should be marked by the :obj:`Dispatchable` class. It has the same signature
        as the desired multimethod.
    argument_replacer : ArgumentReplacerType
        A callable with the signature (args, kwargs, dispatchables), which should also
        return an (args, kwargs) pair with the dispatchables replaced inside the
        args/kwargs.
    domain : str
        A string value indicating the domain of this multimethod.
    default: Optional[Callable], optional
        The default implementation of this multimethod, where ``None`` (the default)
        specifies there is no default implementation.

    Examples
    --------
    In this example, ``a`` is to be dispatched over, so we return it, while marking it
    as an ``int``.
    The trailing comma is needed because the args have to be returned as an iterable.

    >>> def override_me(a, b):
    ...   return Dispatchable(a, int),

    Next, we define the argument replacer that replaces the dispatchables inside
    args/kwargs with the supplied ones.

    >>> def override_replacer(args, kwargs, dispatchables):
    ...     return (dispatchables[0], args[1]), {}

    Next, we define the multimethod.

    >>> overridden_me = generate_multimethod(
    ...     override_me, override_replacer, "ua_examples"
    ... )

    Notice that there's no default implementation, unless you supply one.

    >>> overridden_me(1, "a")
    Traceback (most recent call last):
        ...
    uarray.BackendNotImplementedError: ...

    >>> overridden_me2 = generate_multimethod(
    ...     override_me, override_replacer, "ua_examples", default=lambda x, y: (x, y)
    ... )
    >>> overridden_me2(1, "a")
    (1, 'a')

    See Also
    --------
    uarray
        See the module documentation for how to override the method by creating
        backends.
    )get_defaultsr   	functoolsupdate_wrapper)rO   rP   rQ   rR   kw_defaultsarg_defaultsoptsua_funcs           r.   r   r      sI    B '33E&F#KtG ##G-?@@r=   Fc                     	 | j                   d||f   S # t        $ r
 i | _         Y nt        $ r Y nw xY wt        | ||      }|| j                   d||f<   |S )a  
    A context manager that sets the preferred backend.

    Parameters
    ----------
    backend
        The backend to set.
    coerce
        Whether or not to coerce to a specific backend's types. Implies ``only``.
    only
        Whether or not this should be the last backend to try.

    See Also
    --------
    skip_backend: A context manager that allows skipping of backends.
    set_global_backend: Set a single, global backend for a domain.
    set)__ua_cache__r%   KeyErrorr   )backendcoerceonlyr@   s       r.   r
   r
      sm    $##E64$788 "!  Wfd
3C03G,-Js    111c                     	 | j                   d   S # t        $ r
 i | _         Y nt        $ r Y nw xY wt        |       }|| j                   d<   |S )a  
    A context manager that allows one to skip a given backend from processing
    entirely. This allows one to use another backend's code in a library that
    is also a consumer of the same backend.

    Parameters
    ----------
    backend
        The backend to skip.

    See Also
    --------
    set_backend: A context manager that allows setting of backends.
    set_global_backend: Set a single, global backend for a domain.
    skip)r]   r%   r^   r   )r_   r@   s     r.   r   r     s[     ##F++ "!  g
&C#&G Js    ...c                    t        j                  |       }i }g }t               }|j                  j	                         D ]  \  }}|j
                  t         j                  j                  ur|j
                  ||<   |j                  t         j                  j                  t         j                  j                  fv r|j                  |j
                         |j                  |        |t        |      |fS r8   )inspect	signaturer\   
parametersitemsrR   	ParameteremptykindPOSITIONAL_ONLYPOSITIONAL_OR_KEYWORDappendaddtuple)fsigrW   rX   rY   kvs          r.   rT   rT   5  s    


A
CKL5D$$& 199G--333YYKN66--33
 
 		* l+T11r=   )try_lastc                4    t        j                  | |||       y)ae  
    This utility method replaces the default backend for permanent use. It
    will be tried in the list of backends automatically, unless the
    ``only`` flag is set on a backend. This will be the first tried
    backend outside the :obj:`set_backend` context manager.

    Note that this method is not thread-safe.

    .. warning::
        We caution library authors against using this function in
        their code. We do *not* support this use-case. This function
        is meant to be used only by users themselves, or by a reference
        implementation, if one exists.

    Parameters
    ----------
    backend
        The backend to register.
    coerce : bool
        Whether to coerce input types when trying this backend.
    only : bool
        If ``True``, no more backends will be tried if this fails.
        Implied by ``coerce=True``.
    try_last : bool
        If ``True``, the global backend is tried after registered backends.

    See Also
    --------
    set_backend: A context manager that allows setting of backends.
    skip_backend: A context manager that allows skipping of backends.
    N)r   r   )r_   r`   ra   ru   s       r.   r   r   G  s    @ wh?r=   c                 .    t        j                  |        y)a0  
    This utility method sets registers backend for permanent use. It
    will be tried in the list of backends automatically, unless the
    ``only`` flag is set on a backend.

    Note that this method is not thread-safe.

    Parameters
    ----------
    backend
        The backend to register.
    N)r   r   )r_   s    r.   r   r   j  s     W%r=   Tc                 2    t        j                  | ||       y)al  
    This utility method clears registered backends.

    .. warning::
        We caution library authors against using this function in
        their code. We do *not* support this use-case. This function
        is meant to be used only by users themselves.

    .. warning::
        Do NOT use this method inside a multimethod call, or the
        program is likely to crash.

    Parameters
    ----------
    domain : Optional[str]
        The domain for which to de-register backends. ``None`` means
        de-register for all domains.
    registered : bool
        Whether or not to clear registered backends. See :obj:`register_backend`.
    globals : bool
        Whether or not to clear global backends. See :obj:`set_global_backend`.

    See Also
    --------
    register_backend : Register a backend globally.
    set_global_backend : Set a global backend.
    N)r   r   )rQ   
registeredglobalss      r.   r   r   z  s    8 6:w7r=   c                   (    e Zd ZdZddZd Zd ZeZy)r   a  
    A utility class which marks an argument with a specific dispatch type.


    Attributes
    ----------
    value
        The value of the Dispatchable.

    type
        The type of the Dispatchable.

    Examples
    --------
    >>> x = Dispatchable(1, str)
    >>> x
    <Dispatchable: type=<class 'str'>, value=1>

    See Also
    --------
    all_of_type
        Marks all unmarked parameters of a function.

    mark_as
        Allows one to create a utility function to mark as a given type.
    c                 .    || _         || _        || _        y r8   )valuetype	coercible)selfr}   dispatch_typer   s       r.   __init__zDispatchable.__init__  s    
!	"r=   c                 8    | j                   | j                  f|   S r8   )r~   r}   )r   indexs     r.   __getitem__zDispatchable.__getitem__  s    		4::&u--r=   c                 h    dt        |       j                   d| j                   d| j                  dS )N<z: type=z, value=>)r~   __name__r}   )r   s    r.   __str__zDispatchable.__str__  s1    4:&&'wtyym8DJJ>QRSSr=   N)T)r   r1   r2   __doc__r   r   r   __repr__rE   r=   r.   r   r     s    6#
.T Hr=   r   c                 8    t        j                  t        |       S )z
    Creates a utility function to mark something as a specific type.

    Examples
    --------
    >>> mark_int = mark_as(int)
    >>> mark_int(1)
    <Dispatchable: type=<class 'int'>, value=1>
    r   )rU   partialr   r   s    r.   r   r     s     \GGr=   c                       fd}|S )a$  
    Marks all unmarked arguments as a given type.

    Examples
    --------
    >>> @all_of_type(str)
    ... def f(a, b):
    ...     return a, Dispatchable(b, int)
    >>> f('a', 1)
    (<Dispatchable: type=<class 'str'>, value='a'>,
     <Dispatchable: type=<class 'int'>, value=1>)
    c                 F     t        j                          fd       }|S )Nc                  <     | i |}t        fd|D              S )Nc              3   Z   K   | ]"  }t        |t              st        |      n| $ y wr8   
isinstancer   ).0argarg_types     r.   	<genexpr>z<all_of_type.<locals>.outer.<locals>.inner.<locals>.<genexpr>  s6        "#|4 S(+   (+)rp   )rL   rM   extracted_argsr   r+   s      r.   innerz)all_of_type.<locals>.outer.<locals>.inner  s.    !4262N  *	  r=   rU   wraps)r+   r   r   s   ` r.   outerzall_of_type.<locals>.outer  s%    			 
	 r=   rE   )r   r   s   ` r.   r   r     s     Lr=   c                 B     t        j                          fd       }|S )
    Wraps a ``__ua_convert__`` defined for a single element to all elements.
    If any of them return ``NotImplemented``, the operation is assumed to be
    undefined.

    Accepts a signature of (value, type, coerce).
    c                     g }| D ]O  } |j                   |j                  |xr |j                        }|t        u rt        c S |j	                  |       Q |S r8   r}   r~   r   NotImplementedrn   )dispatchablesr`   	converteddcconvert_singles        r.   __ua_convert__z-wrap_single_convertor.<locals>.__ua_convert__  sZ    	 	 Aqww0F1;;GAN"%%Q	  r=   r   r   r   s   ` r.   r   r     (     __^$
 %
 r=   c                 B     t        j                          fd       }|S )r   c                     g }|D ]P  } | |j                   |j                  |xr |j                        }|t        u rt        c S |j	                  |       R |S r8   r   )r   r   r`   r   r   r   r   s         r.   r   z6wrap_single_convertor_instance.<locals>.__ua_convert__  s\    	 	 AtQWWafff6LMAN"%%Q	  r=   r   r   s   ` r.   r   r     r   r=   )ra   r`   c                h    t        | ||      f}t        j                  |||      }t        |||      S )a	  Set the backend to the first active backend that supports ``value``

    This is useful for functions that call multimethods without any dispatchable
    arguments. You can use :func:`determine_backend` to ensure the same backend
    is used everywhere in a block of multimethod calls.

    Parameters
    ----------
    value
        The value being tested
    dispatch_type
        The dispatch type associated with ``value``, aka
        ":ref:`marking <MarkingGlossary>`".
    domain: string
        The domain to query for backends and set.
    coerce: bool
        Whether or not to allow coercion to the backend's types. Implies ``only``.
    only: bool
        Whether or not this should be the last backend to try.

    See Also
    --------
    set_backend: For when you know which backend to set

    Notes
    -----

    Support is determined by the ``__ua_convert__`` protocol. Backends not
    supporting the type must return ``NotImplemented`` from their
    ``__ua_convert__`` if they don't support input of that type.

    Examples
    --------

    Suppose we have two backends ``BackendA`` and ``BackendB`` each supporting
    different types, ``TypeA`` and ``TypeB``. Neither supporting the other type:

    >>> with ua.set_backend(ex.BackendA):
    ...     ex.call_multimethod(ex.TypeB(), ex.TypeB())
    Traceback (most recent call last):
        ...
    uarray.BackendNotImplementedError: ...

    Now consider a multimethod that creates a new object of ``TypeA``, or
    ``TypeB`` depending on the active backend.

    >>> with ua.set_backend(ex.BackendA), ua.set_backend(ex.BackendB):
    ...         res = ex.creation_multimethod()
    ...         ex.call_multimethod(res, ex.TypeA())
    Traceback (most recent call last):
        ...
    uarray.BackendNotImplementedError: ...

    ``res`` is an object of ``TypeB`` because ``BackendB`` is set in the
    innermost with statement. So, ``call_multimethod`` fails since the types
    don't match.

    Instead, we need to first find a backend suitable for all of our objects.

    >>> with ua.set_backend(ex.BackendA), ua.set_backend(ex.BackendB):
    ...     x = ex.TypeA()
    ...     with ua.determine_backend(x, "mark", domain="ua_examples"):
    ...         res = ex.creation_multimethod()
    ...         ex.call_multimethod(res, x)
    TypeA

    r`   ra   )r   r   r   r
   )r}   r   rQ   ra   r`   r   r_   s          r.   r   r      s9    H "%?AM''vFGwvD99r=   c                *   d|v r&|j                  d      t        fd| D              } n(t        |       } t        d | D              st        d      t	        |      dk7  rt        d|       t        j                  || |      }t        |||      S )a	  Set a backend supporting all ``dispatchables``

    This is useful for functions that call multimethods without any dispatchable
    arguments. You can use :func:`determine_backend_multi` to ensure the same
    backend is used everywhere in a block of multimethod calls involving
    multiple arrays.

    Parameters
    ----------
    dispatchables: Sequence[Union[uarray.Dispatchable, Any]]
        The dispatchables that must be supported
    domain: string
        The domain to query for backends and set.
    coerce: bool
        Whether or not to allow coercion to the backend's types. Implies ``only``.
    only: bool
        Whether or not this should be the last backend to try.
    dispatch_type: Optional[Any]
        The default dispatch type associated with ``dispatchables``, aka
        ":ref:`marking <MarkingGlossary>`".

    See Also
    --------
    determine_backend: For a single dispatch value
    set_backend: For when you know which backend to set

    Notes
    -----

    Support is determined by the ``__ua_convert__`` protocol. Backends not
    supporting the type must return ``NotImplemented`` from their
    ``__ua_convert__`` if they don't support input of that type.

    Examples
    --------

    :func:`determine_backend` allows the backend to be set from a single
    object. :func:`determine_backend_multi` allows multiple objects to be
    checked simultaneously for support in the backend. Suppose we have a
    ``BackendAB`` which supports ``TypeA`` and ``TypeB`` in the same call,
    and a ``BackendBC`` that doesn't support ``TypeA``.

    >>> with ua.set_backend(ex.BackendAB), ua.set_backend(ex.BackendBC):
    ...     a, b = ex.TypeA(), ex.TypeB()
    ...     with ua.determine_backend_multi(
    ...         [ua.Dispatchable(a, "mark"), ua.Dispatchable(b, "mark")],
    ...         domain="ua_examples"
    ...     ):
    ...         res = ex.creation_multimethod()
    ...         ex.call_multimethod(res, a, b)
    TypeA

    This won't call ``BackendBC`` because it doesn't support ``TypeA``.

    We can also use leave out the ``ua.Dispatchable`` if we specify the
    default ``dispatch_type`` for the ``dispatchables`` argument.

    >>> with ua.set_backend(ex.BackendAB), ua.set_backend(ex.BackendBC):
    ...     a, b = ex.TypeA(), ex.TypeB()
    ...     with ua.determine_backend_multi(
    ...         [a, b], dispatch_type="mark", domain="ua_examples"
    ...     ):
    ...         res = ex.creation_multimethod()
    ...         ex.call_multimethod(res, a, b)
    TypeA

    r   c              3   Z   K   | ]"  }t        |t              r|nt        |       $ y wr8   r   )r   r   	disp_types     r.   r   z*determine_backend_multi.<locals>.<genexpr>  s.      
 A|,A,q)2LL
r   c              3   <   K   | ]  }t        |t                y wr8   r   )r   r   s     r.   r   z*determine_backend_multi.<locals>.<genexpr>  s     F1:a.Fs   z6dispatchables must be instances of uarray.Dispatchabler   z'Received unexpected keyword arguments: r   )poprp   all	TypeErrorlenr   r   r
   )r   rQ   ra   r`   rM   r_   r   s         @r.   r   r   j  s    L & JJ/	 
"
 

 m,FFFTUU
6{aA&JKK''vFGwvD99r=   r8   )FF)TF).typingr"   re   rU    r   copyregr&   
contextlibr   r   r   r   r	   __all__Callablerp   ArgumentExtractorTypedictArgumentReplacerTyper/   r6   r<   rA   rC   r   contextmanagerr   r   r   strOptionalr   r
   r   rT   r   r   r   r   r   r   r   r   r   r   rE   r=   r.   <module>r      s           2 U3F-G(GH 
D%%t,, %(7$<-. y/ * w$$l 3 !#= > "$? @   + +"2 15	KA-KA+KA KA __V__-	KA\<82$ @e  @F& 8>' 'T
H<22 =A G:V $(V:r=   