B
    0d-                 @   s\  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e jde j	d f Z
e je j	e je j	ge j	e j	e jf f ZddlmZmZmZmZ ddd	d
dddddddddgZdd Zdd Zeee eej dd Zd(e
eee je j dddZd)ddZdd	 Zdd Zd*d dZd!d
 Zd+d#dZG d$d dZ d%d Z!d&d Z"d'd Z#dS ),    N   )_uarray.)Dispatchable.)BackendNotImplementedError	_Function_SkipBackendContext_SetBackendContextset_backendset_global_backendskip_backendregister_backendclear_backendscreate_multimethodgenerate_multimethodr   r   r   wrap_single_convertorall_of_typemark_asc          
   C   s^   dd l }y|| }t||}|S  ttfk
rX } zddlm} ||W d d }~X Y nX d S )Nr   )UnpicklingError)	importlibimport_modulegetattrImportErrorAttributeErrorpickler   )mod_nameqnamer   modulefuncer    r   M/var/www/html/venv/lib/python3.7/site-packages/scipy/_lib/_uarray/_backend.pyunpickle_function&   s    

r!   c             C   sh   t | dd }t | dd }yt||}W n tjk
r@   d }Y nX || k	r\td| |t||ffS )N
__module____qualname__z/Can't pickle {}: it's not the same object as {})r   r!   r   r   PicklingErrorformat)r   r   r   testr   r   r    pickle_function3   s    
r'   c                 s    fdd}|S )ao  
    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                s   t | f S )N)r   )a)argskwargsr   r    wrapperV   s    z#create_multimethod.<locals>.wrapperr   )r)   r*   r+   r   )r)   r*   r    r   H   s    )argument_extractorargument_replacerdomaindefaultc             C   s,   t | \}}}t| |||||}t|| 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.backend.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)r,   r-   r.   r/   kw_defaultsarg_defaultsoptsZua_funcr   r   r    r   \   s    =Fc             C   s^   y| j d||f S  tk
r*   i | _ Y n tk
r<   Y nX 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onlyctxr   r   r    r	      s    
c             C   sN   y
| j d S  tk
r$   i | _ Y n tk
r6   Y nX 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)r7   r   r8   r   )r9   r<   r   r   r    r      s    


c             C   s   t | }i }g }t }xZ|j D ]L\}}|jt jjk	rD|j||< |jt jj	t jj
fkrf||j || q$W |t||fS )N)inspect	signaturer6   
parametersitemsr/   	ParameteremptykindPOSITIONAL_ONLYPOSITIONAL_OR_KEYWORDappendaddtuple)fsigr3   r4   r5   kvr   r   r    r0      s    

r0   c             C   s   t | || dS )a>  
    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.

    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
   )r9   r:   r;   r   r   r    r
      s    c             C   s   t |  dS )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   )r9   r   r   r    r     s    Tc             C   s   t | || dS )ap  
    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 the 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   )r.   
registeredglobalsr   r   r    r     s    c               @   s.   e Zd ZdZd
ddZdd Zdd ZeZd	S )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.
    Tc             C   s   || _ || _|| _d S )N)valuetype	coercible)selfrP   dispatch_typerR   r   r   r    __init__Y  s    zDispatchable.__init__c             C   s   | j | jf| S )N)rQ   rP   )rS   indexr   r   r    __getitem__^  s    zDispatchable.__getitem__c             C   s   d t| j| j| jS )Nz<{0}: type={1!r}, value={2!r}>)r%   rQ   __name__rP   )rS   r   r   r    __str__a  s    zDispatchable.__str__N)T)rX   r"   r#   __doc__rU   rW   rY   __repr__r   r   r   r    r   =  s
   
c             C   s   t jt| d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>
    )rT   )r1   partialr   )rT   r   r   r    r   i  s    
c                s    fd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                s   t   fdd}|S )Nc                 s    | |}t  fdd|D S )Nc             3   s&   | ]}t |tst| n|V  qd S )N)
isinstancer   ).0arg)arg_typer   r    	<genexpr>  s   z<all_of_type.<locals>.outer.<locals>.inner.<locals>.<genexpr>)rI   )r)   r*   Zextracted_args)r`   r   r   r    inner  s    

z)all_of_type.<locals>.outer.<locals>.inner)r1   wraps)r   rb   )r`   )r   r    outer  s    
zall_of_type.<locals>.outerr   )r`   rd   r   )r`   r    r   v  s    c                s   t   fdd}|S )z
    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                sB   g }x8| D ]0} |j |j|o |j}|tkr0tS || q
W |S )N)rP   rQ   rR   NotImplementedrG   )Zdispatchablesr:   Z	converteddc)convert_singler   r    __ua_convert__  s    
z-wrap_single_convertor.<locals>.__ua_convert__)r1   rc   )rh   ri   r   )rh   r    r     s    	)N)FF)FF)TF)$typingr>   r1    r   copyregatexitr   CallableTupleZArgumentExtractorTypeDictZArgumentReplacerTyper   r   r   r   __all__r!   r'   registerZclear_all_globalsr   strOptionalr   r	   r   r0   r
   r   r   r   r   r   r   r   r   r   r    <module>   sN   $F


,