Ticket #11734: trac11734_sage_wraps_no_sourceread.patch

File trac11734_sage_wraps_no_sourceread.patch, 6.5 KB (added by SimonKing, 10 years ago)

sage_wraps should only read source files when needed.

  • sage/misc/decorators.py

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1314173612 -7200
    # Node ID 78c0154cbd13c5ed3bb366c615570c5bc7b60a3b
    # Parent  24976595b88d846c39e9302c1fffc76173dadc7a
    #11734: sage_wraps should only read the sources if it is requested.
    
    diff --git a/sage/misc/decorators.py b/sage/misc/decorators.py
    a b  
    1010- Johan S. R. Nielsen (8 apr 2011) -- improve introspection on decorators.
    1111- Simon King (2011-05-26) -- improve introspection of sage_wraps. Put this
    1212  file into the reference manual.
     13- Simon King (2011-08-24) -- Do not read the sources of the wrapped function
     14  before they are requested.
    1315
    1416"""
    1517from functools import partial, update_wrapper, WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES
    1618from copy import copy
    17 from sage.misc.sageinspect import sage_getsource, sage_getsourcelines
     19from sage.misc.sageinspect import sage_getsource, sage_getsourcelines, sage_getargspec
    1820from sage.misc.misc import verbose, deprecation
    1921from inspect import ArgSpec
    2022
     23class _src_line_getter:
     24    """
     25    Stores a reference to an object and returns its source lines.
     26
     27    INPUT:
     28
     29    - ``f``, any object
     30
     31    EXAMPLE::
     32
     33        sage: from sage.misc.sageinspect import sage_getsourcelines
     34        sage: P.<x,y,z> = QQ[]
     35        sage: I = P*[x,y]
     36        sage: sage_getsourcelines(I.interreduced_basis) #indirect doctest
     37        (['    @singular_standard_options\n', '    @libsingular_standard_options\n',
     38        ...
     39        '        return ret\n'], ...)
     40
     41    """
     42    def __init__(self, f):
     43        r"""
     44        INPUT:
     45
     46        - ``f``, any object
     47
     48        EXAMPLE::
     49
     50            sage: cython('cpdef f(x): return x^2')
     51            sage: from sage.misc.decorators import _src_line_getter
     52            sage: g = _src_line_getter(f)
     53            sage: g()
     54            (['cpdef f(x): return x^2\n'], 6)
     55
     56        """
     57        self._f = f
     58    def __call__(self):
     59        r"""
     60        Return the source lines of the associated object.
     61
     62        EXAMPLE::
     63
     64            sage: cython('cpdef f(x): return x^2')
     65            sage: from sage.misc.decorators import _src_line_getter
     66            sage: g = _src_line_getter(f)
     67            sage: g()  #indirect doctest
     68            (['cpdef f(x): return x^2\n'], 6)
     69
     70        """
     71        return sage_getsourcelines(self._f)
     72
     73class _src_getter:
     74    r"""
     75    Stores a reference to an object and returns its source.
     76
     77    EXAMPLE::
     78
     79        sage: from sage.misc.sageinspect import sage_getsource
     80        sage: P.<x,y,z> = QQ[]
     81        sage: I = P*[x,y]
     82        sage: print sage_getsource(I.interreduced_basis)   #indirect doctest
     83        @singular_standard_options
     84        @libsingular_standard_options
     85        def interreduced_basis(self):
     86        ...
     87            ret = PolynomialSequence(R, ret, immutable=True)
     88            return ret
     89
     90    """
     91    def __init__(self, f):
     92        r"""
     93        INPUT:
     94
     95        - ``f``, any object
     96
     97        EXAMPLE::
     98
     99            sage: cython('cpdef f(x): return x^2')
     100            sage: from sage.misc.decorators import _src_getter
     101            sage: g = _src_getter(f)
     102            sage: g()
     103            'cpdef f(x): return x^2\n'
     104
     105        """
     106        self._f = f
     107    def __call__(self):
     108        r"""
     109        Return the sources of the associated object.
     110
     111        EXAMPLE::
     112
     113            sage: cython('cpdef f(x): return x^2')
     114            sage: from sage.misc.decorators import _src_getter
     115            sage: g = _src_getter(f)
     116            sage: g()   #indirect doctest
     117            'cpdef f(x): return x^2\n'
     118
     119        """
     120        return sage_getsource(self._f)
     121
     122class _argspec_getter:
     123    r"""
     124    Stores a reference to an object and returns its list of arguments.
     125
     126    EXAMPLE::
     127
     128        sage: from sage.misc.sageinspect import sage_getargspec
     129        sage: P.<x,y,z> = QQ[]
     130        sage: I = P*[x,y]
     131        sage: print sage_getargspec(I.interreduced_basis)   #indirect doctest
     132        ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
     133
     134    """
     135    def __init__(self, f):
     136        r"""
     137        INPUT:
     138
     139        - ``f``, any object
     140
     141        EXAMPLE::
     142
     143            sage: cython('cpdef f(x, bla, t={"hello":{1:"world"}}): return x^2')
     144            sage: from sage.misc.decorators import _argspec_getter
     145            sage: g = _argspec_getter(f)
     146            sage: g()
     147            ArgSpec(args=['x', 'bla', 't'], varargs=None, keywords=None, defaults=({'hello': {1: 'world'}},))
     148
     149        """
     150        self._f = f
     151    def __call__(self):
     152        r"""
     153        Return the arguments of the associated object.
     154
     155        EXAMPLE::
     156
     157            sage: cython('cpdef f(x, bla, t={"hello":{1:"world"}}): return x^2')
     158            sage: from sage.misc.decorators import _argspec_getter
     159            sage: g = _argspec_getter(f)
     160            sage: g()
     161            ArgSpec(args=['x', 'bla', 't'], varargs=None, keywords=None, defaults=({'hello': {1: 'world'}},))
     162
     163        """
     164        return sage_getargspec(self._f)
     165
    21166def sage_wraps(wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES):
    22167    r"""
    23168    Decorator factory which should be used in decorators for making sure that
     
    109254        4
    110255        sage: t.g.__doc__
    111256        'My little method'
     257
     258    Here, we test against a bug fixed in trac ticket #11734::
     259
     260        sage: def square(f):
     261        ...     @sage_wraps(f)
     262        ...     def new_f(x):
     263        ...         return f(x)*f(x)
     264        ...     return new_f
     265        ...
     266        sage: f = lambda x:x^2
     267        sage: g = square(f)
     268        sage: g(3)
     269        81
     270
    112271    """
    113272    #TRAC 9919: Workaround for bug in @update_wrapper when used with
    114273    #non-function callables.
     
    116275    #end workaround
    117276    def f(wrapper):
    118277        update_wrapper(wrapper, wrapped, assigned=assigned, updated=updated)
    119         wrapper._sage_src_=lambda: sage_getsource(wrapped)
    120         wrapper._sage_src_lines_=lambda: sage_getsourcelines(wrapped)
     278        wrapper._sage_src_ = _src_getter(wrapped)
     279        wrapper._sage_src_lines_ = _src_line_getter(wrapped)
    121280        #Getting the signature right in documentation by Sphinx (Trac 9976)
    122281        #The attribute _sage_argspec_() is read by Sphinx if present and used
    123282        #as the argspec of the function instead of using reflection.
    124         from sageinspect import sage_getargspec
    125         argspec = sage_getargspec(wrapped)
    126         wrapper._sage_argspec_ = lambda: argspec
     283        wrapper._sage_argspec_ = _argspec_getter(wrapped)
    127284        return wrapper
    128285    return f
    129286