U
    Š±Ëhd+  ã                   @   s’   d Z ddlZddlZddlZddlmZmZ ddlmZ dd„ Z	dd„ Z
d	d
„ Zdd„ ZG dd„ dƒZddd„Zdd„ Zdd„ Zddœdd„ZdS )zUseful utility decorators. é    N)ÚwrapsÚupdate_wrapper©Úsympy_deprecation_warningc                    sD   ddl m‰ ddlm‰  ddlm‰ tˆƒ‡ ‡‡‡‡fdd„ƒ}|S )z'A factory for ``threaded`` decorators. r   )Úsympify)Ú
MatrixBase)Úiterablec                    sÔ   t | ˆƒr |  ‡ ‡‡fdd„¡S ˆ| ƒrbz|  ‡ ‡‡fdd„| D ƒ¡W S  tk
r^   |  Y S X nnˆ| ƒ} ˆr’| jr’| j‡ ‡‡fdd„| jD ƒŽ S | jrÀ|  ˆ| jfˆ žˆŽˆ| jfˆ žˆŽ¡S ˆ| fˆ žˆŽS d S )Nc                    s   ˆ| fˆ žˆŽS ©N© )Úf©ÚargsÚfuncÚkwargsr
   ú=/tmp/pip-unpacked-wheel-6t8vlncq/sympy/utilities/decorator.pyÚ<lambda>   ó    z9threaded_factory.<locals>.threaded_func.<locals>.<lambda>c                    s   g | ]}ˆ|fˆ žˆŽ‘qS r
   r
   ©Ú.0r   r   r
   r   Ú
<listcomp>   s     z;threaded_factory.<locals>.threaded_func.<locals>.<listcomp>c                    s   g | ]}ˆ|fˆ žˆŽ‘qS r
   r
   r   r   r
   r   r      s     )	Ú
isinstanceZ	applyfuncÚ	__class__Ú	TypeErrorZis_Addr   Zis_RelationalÚlhsÚrhs)Úexprr   r   ©r   r   r   r   Úuse_add©r   r   r   Úthreaded_func   s    

ÿz'threaded_factory.<locals>.threaded_func)Z
sympy.corer   Zsympy.matricesr   Zsympy.utilities.iterablesr   r   )r   r   r   r
   r   r   Úthreaded_factory
   s    r    c                 C   s
   t | dƒS )aU  Apply ``func`` to sub--elements of an object, including :class:`~.Add`.

    This decorator is intended to make it uniformly possible to apply a
    function to all elements of composite objects, e.g. matrices, lists, tuples
    and other iterable containers, or just expressions.

    This version of :func:`threaded` decorator allows threading over
    elements of :class:`~.Add` class. If this behavior is not desirable
    use :func:`xthreaded` decorator.

    Functions using this decorator must have the following signature::

      @threaded
      def function(expr, *args, **kwargs):

    T©r    ©r   r
   r
   r   Úthreaded'   s    r#   c                 C   s
   t | dƒS )aX  Apply ``func`` to sub--elements of an object, excluding :class:`~.Add`.

    This decorator is intended to make it uniformly possible to apply a
    function to all elements of composite objects, e.g. matrices, lists, tuples
    and other iterable containers, or just expressions.

    This version of :func:`threaded` decorator disallows threading over
    elements of :class:`~.Add` class. If this behavior is not desirable
    use :func:`threaded` decorator.

    Functions using this decorator must have the following signature::

      @xthreaded
      def function(expr, *args, **kwargs):

    Fr!   r"   r
   r
   r   Ú	xthreaded;   s    r$   c                    s$   ddl ‰‡ ‡fdd„}t|ˆ ƒ}|S )zwAfter the function finishes, resets the value of ``mpmath.mp.dps`` to
    the value it had before the function was run.r   Nc                     s&   ˆj j}zˆ | |ŽW ¢S |ˆj _X d S r	   )ÚmpÚdps)r   r   r&   ©r   Úmpmathr
   r   Úfunc_wrapperT   s    z)conserve_mpmath_dps.<locals>.func_wrapper)r(   r   )r   r)   r
   r'   r   Úconserve_mpmath_dpsO   s    
r*   c                   @   s"   e Zd ZdZdd„ Zddd„ZdS )Úno_attrs_in_subclassaE  Don't 'inherit' certain attributes from a base class

    >>> from sympy.utilities.decorator import no_attrs_in_subclass

    >>> class A(object):
    ...     x = 'test'

    >>> A.x = no_attrs_in_subclass(A, A.x)

    >>> class B(A):
    ...     pass

    >>> hasattr(A, 'x')
    True
    >>> hasattr(B, 'x')
    False

    c                 C   s   || _ || _d S r	   )Úclsr   )Úselfr,   r   r
   r
   r   Ú__init__r   s    zno_attrs_in_subclass.__init__Nc                 C   s2   || j kr*t| jdƒr$| j ||¡S | jS t‚d S )NÚ__get__)r,   Úhasattrr   r/   ÚAttributeError)r-   ÚinstanceÚownerr
   r
   r   r/   v   s
    
zno_attrs_in_subclass.__get__)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r.   r/   r
   r
   r
   r   r+   _   s   r+   c                    sr   i ‰ | dk	r| ˆ d< |dk	r$|ˆ d< |dk	r4|ˆ d< |dk	rD|ˆ d< |dk	rT|ˆ d< ‡ fdd„‰‡ ‡fd	d
„}|S )a­  
    Adds metadata about the dependencies which need to be met for doctesting
    the docstrings of the decorated objects.

    ``exe`` should be a list of executables

    ``modules`` should be a list of modules

    ``disable_viewers`` should be a list of viewers for :func:`~sympy.printing.preview.preview` to disable

    ``python_version`` should be the minimum Python version required, as a tuple
    (like ``(3, 0)``)
    NZexecutablesÚmodulesÚdisable_viewersÚpython_versionÚground_typesc                     sT   ddl m} m}m} |ƒ }||d ƒ}z|jf ˆ Ž W n | k
rJ   Y dS X dS d S )Nr   )ÚDependencyErrorÚSymPyDocTestsÚPyTestReporterTF)Zsympy.testing.runtestsr<   r=   r>   Z_check_dependencies)r<   r=   r>   ÚrÚt)Údependenciesr
   r   Ú	skiptests™   s    
z%doctest_depends_on.<locals>.skiptestsc                    s6   ˆ | _ ˆ| _t | ¡r2t| | j ƒ| _t| | jƒ| _| S r	   )Z_doctest_depends_onZ__doctest_skip__ÚinspectÚisclassr+   Z_doctest_depdends_on)Úfn©rA   rB   r
   r   Údepends_on_deco¤   s    
 ÿ ÿz+doctest_depends_on.<locals>.depends_on_decor
   )Zexer8   r9   r:   r;   rG   r
   rF   r   Údoctest_depends_on~   s    rH   c                 C   st   t | tjƒr| j}| j}n4t | ttƒtfƒrBtj| j j	}| j}nt
d|  ƒ‚d|krb|g|d< n|d  |¡ | S )aå  
    Append ``obj``'s name to global ``__all__`` variable (call site).

    By using this decorator on functions or classes you achieve the same goal
    as by filling ``__all__`` variables manually, you just do not have to repeat
    yourself (object's name). You also know if object is public at definition
    site, not at some random location (where ``__all__`` was set).

    Note that in multiple decorator setup (in almost all cases) ``@public``
    decorator must be applied before any other decorators, because it relies
    on the pointer to object's global namespace. If you apply other decorators
    first, ``@public`` may end up modifying the wrong namespace.

    Examples
    ========

    >>> from sympy.utilities.decorator import public

    >>> __all__ # noqa: F821
    Traceback (most recent call last):
    ...
    NameError: name '__all__' is not defined

    >>> @public
    ... def some_function():
    ...     pass

    >>> __all__ # noqa: F821
    ['some_function']

    z&expected a function or a class, got %sÚ__all__)r   ÚtypesÚFunctionTypeÚ__globals__r4   ÚtypeÚsysr8   r5   Ú__dict__r   Úappend)ÚobjÚnsÚnamer
   r
   r   Úpublic²   s     rT   c                    s0   dˆj  ‰ tƒ ‰tˆƒ‡ ‡‡fdd„ƒ}t|ƒS )zÍProperty decorator that caches the value of potentially expensive
    ``propfunc`` after the first evaluation. The cached value is stored in
    the corresponding property name with an attached underscore.Ú_c                    s,   t | ˆ ˆƒ}|ˆkr(ˆ| ƒ}t| ˆ |ƒ |S r	   )ÚgetattrÚsetattr)r-   Úval©ÚattrnameÚpropfuncÚsentinelr
   r   Úaccessorê   s
    z"memoize_property.<locals>.accessor)r4   Úobjectr   Úproperty)r[   r]   r
   rY   r   Úmemoize_propertyã   s
    
r`   é   )Ú
stacklevelc                   s   ||dœ‰ ‡ ‡‡fdd„}|S )aš  
    Mark a function as deprecated.

    This decorator should be used if an entire function or class is
    deprecated. If only a certain functionality is deprecated, you should use
    :func:`~.warns_deprecated_sympy` directly. This decorator is just a
    convenience. There is no functional difference between using this
    decorator and calling ``warns_deprecated_sympy()`` at the top of the
    function.

    The decorator takes the same arguments as
    :func:`~.warns_deprecated_sympy`. See its
    documentation for details on what the keywords to this decorator do.

    See the :ref:`deprecation-policy` document for details on when and how
    things should be deprecated in SymPy.

    Examples
    ========

    >>> from sympy.utilities.decorator import deprecated
    >>> from sympy import simplify
    >>> @deprecated("""    ... The simplify_this(expr) function is deprecated. Use simplify(expr)
    ... instead.""", deprecated_since_version="1.1",
    ... active_deprecations_target='simplify-this-deprecation')
    ... def simplify_this(expr):
    ...     """
    ...     Simplify ``expr``.
    ...
    ...     .. deprecated:: 1.1
    ...
    ...        The ``simplify_this`` function is deprecated. Use :func:`simplify`
    ...        instead. See its documentation for more information. See
    ...        :ref:`simplify-this-deprecation` for details.
    ...
    ...     """
    ...     return simplify(expr)
    >>> from sympy.abc import x
    >>> simplify_this(x*(x + 1) - x**2) # doctest: +SKIP
    <stdin>:1: SymPyDeprecationWarning:
    <BLANKLINE>
    The simplify_this(expr) function is deprecated. Use simplify(expr)
    instead.
    <BLANKLINE>
    See https://docs.sympy.org/latest/explanation/active-deprecations.html#simplify-this-deprecation
    for details.
    <BLANKLINE>
    This has been deprecated since SymPy version 1.1. It
    will be removed in a future version of SymPy.
    <BLANKLINE>
      simplify_this(x)
    x

    See Also
    ========
    sympy.utilities.exceptions.SymPyDeprecationWarning
    sympy.utilities.exceptions.sympy_deprecation_warning
    sympy.utilities.exceptions.ignore_warnings
    sympy.testing.pytest.warns_deprecated_sympy

    )Údeprecated_since_versionÚactive_deprecations_targetc                    sR   t ˆ dƒr.G ‡‡‡‡ fdd„dˆ ƒ}ˆ j|_n tˆ ƒ‡‡‡‡ fdd„ƒ}ˆ |_|S )NÚ__mro__c                       sP   e Zd Z”jZ”jZ”Zd”jkr6‡ ‡‡‡fdd„Zn‡ ‡‡‡fdd„Z‡  ZS )ú9deprecated.<locals>.deprecated_decorator.<locals>.wrapperÚ__new__c                    s(   t ˆfˆdˆi—Ž tƒ j| f|ž|ŽS ©Nrb   )r   Úsuperrg   )r,   r   r   ©r   Údecorator_kwargsÚmessagerb   r
   r   rg   >  s    zAdeprecated.<locals>.deprecated_decorator.<locals>.wrapper.__new__c                    s&   t ˆfˆdˆi—Ž tƒ j||Ž d S rh   )r   ri   r.   )r-   r   r   rj   r
   r   r.   B  s    zBdeprecated.<locals>.deprecated_decorator.<locals>.wrapper.__init__)	r4   r5   r6   r7   Ú_sympy_deprecated_funcrO   rg   r.   Ú__classcell__r
   ©rk   rl   rb   Úwrapped)r   r   Úwrapper9  s   
rq   c                     s   t ˆfˆ dˆi—Ž ˆ| |ŽS rh   r   r   ro   r
   r   rq   G  s    rf   )r0   r4   r   rm   )rp   rq   ©rk   rl   rb   )rp   r   Údeprecated_decorator7  s    

z(deprecated.<locals>.deprecated_decoratorr
   )rl   rc   rd   rb   rs   r
   rr   r   Ú
deprecatedõ   s
    @ÿrt   )NNNNN)r7   rN   rJ   rC   Ú	functoolsr   r   Zsympy.utilities.exceptionsr   r    r#   r$   r*   r+   rH   rT   r`   rt   r
   r
   r
   r   Ú<module>   s$       ÿ
41ÿ