Ticket #11115: 11115_flat.patch

File 11115_flat.patch, 98.2 KB (added by jdemeyer, 9 years ago)
  • module_list.py

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1305526656 -7200
    # Node ID 1be94e1beaae845273fa8b6363e86be660222c9f
    # Parent  9ef16f06aa8195b4bf587c9ebee85f3b2ba4f8b9
    Cython version of cached_method and friends (relative to #11298, #9138).
    Make cached_in_parent methods work for the element class of categories,
    including cached_in_parent methods
    Provide lazy attributes for all parents.
    Lazy atributes and cached methods for elements without attribute assignment.
    Pickling of cached functions.
    Reviewer patch: removed out-of-date commented-out code and typos in docstrings.
    
    diff --git a/module_list.py b/module_list.py
    a b  
    10151015    Extension('sage.misc.bitset',
    10161016              sources = ['sage/misc/bitset.pyx']),
    10171017
     1018    Extension('sage.misc.cachefunc',
     1019              sources = ['sage/misc/cachefunc.pyx']),
     1020
    10181021    Extension('sage.misc.citation',
    10191022              sources = ['sage/misc/citation.pyx']),
    10201023
  • sage/combinat/sf/dual.py

    diff --git a/sage/combinat/sf/dual.py b/sage/combinat/sf/dual.py
    a b  
    178178       
    179179        EXAMPLES::
    180180       
    181             sage: e = SFAElementary(QQ)
     181            sage: e = SFAElementary(QQ['t'])
    182182            sage: f = e.dual_basis()
    183183            sage: f._precompute(0)
    184184            sage: f._precompute(1)
  • new file sage/misc/cachefunc.pxd

    diff --git a/sage/misc/cachefunc.pxd b/sage/misc/cachefunc.pxd
    new file mode 100644
    - +  
     1cdef class CachedFunction(object):
     2    cdef public str __name__
     3    cdef public str __module__
     4    cdef object _argument_fixer
     5    cdef public object _fix_to_pos
     6    cdef public object f
     7    # cache is not always of type "dict"!
     8    cdef public object cache
     9    cdef tuple _default_key
     10    cpdef get_cache(self)
     11    cpdef clear_cache(self)
     12
     13cdef class CachedMethod
     14
     15cdef class CachedMethodCaller(CachedFunction):
     16    cdef public object _instance
     17    cdef public bint _inst_in_key
     18    cdef public CachedMethod _cachedmethod
     19
     20cdef class CachedMethodCallerNoArgs(CachedFunction):
     21    cdef public object _instance
     22
     23cdef class CachedMethod(object):
     24    cdef str _cache_name
     25    cdef CachedFunction _cachedfunc
     26    cpdef dict _get_instance_cache(self, inst)
     27
  • (a) a/sage/misc/cachefunc.py vs. (b) b/sage/misc/cachefunc.pyx

    diff --git a/sage/misc/cachefunc.py b/sage/misc/cachefunc.pyx
    rename from sage/misc/cachefunc.py
    rename to sage/misc/cachefunc.pyx
    a b  
    1 """
     1r"""
    22Cached Functions and Methods
    33
    44AUTHORS:
     
    88- Willem Jan Palenstijn (add CachedMethodCaller for binding cached
    99  methods to instances).
    1010- Tom Boothby (added DiskCachedFunction).
    11 - Simon King (improved performance, more doctests).
     11- Simon King (improved performance, more doctests, cython version,
     12  added CachedMethodCallerNoArgs).
     13
     14EXAMPLES:
     15
     16By trac ticket #11115, cached functions and methods are now also
     17available in Cython code. The following examples cover various ways
     18of usage.
     19
     20Python functions::
     21
     22    sage: @cached_function
     23    ... def test_pfunc(x):
     24    ...     '''
     25    ...     Some documentation
     26    ...     '''
     27    ...     return -x
     28    ...
     29    sage: test_pfunc(5) is test_pfunc(5)
     30    True
     31
     32Unfortunately, cython functions do not allow arbitrary
     33decorators. However, one can wrap a Cython function and
     34turn it into a cached function, by trac ticket #11115.
     35We need to provide the name that the wrapped method or
     36function should have, since otherwise the name of the
     37original function would be used::
     38
     39    sage: cython('''cpdef test_funct(x): return -x''')
     40    sage: wrapped_funct = cached_function(test_funct, name='wrapped_funct')
     41    sage: wrapped_funct
     42    Cached version of <built-in function test_funct>
     43    sage: wrapped_funct.__name__
     44    'wrapped_funct'
     45    sage: wrapped_funct(5)
     46    -5
     47    sage: wrapped_funct(5) is wrapped_funct(5)
     48    True
     49
     50We can proceed similarly for cached methods of Cython classes,
     51provided that they allow attribute assignment or have a public
     52attribute ``__cached_methods`` of type ``<dict>``. Since trac ticket
     53#11115, this is the case for all classes inheriting from
     54:class:`~sage.structure.parent.Parent`::
     55
     56    sage: cython_code = ['cpdef test_meth(self,x):',
     57    ... '    "some doc for a wrapped cython method"',
     58    ... '    return -x',
     59    ... 'from sage.all import cached_method',
     60    ... 'from sage.structure.parent cimport Parent',
     61    ... 'cdef class MyClass(Parent):',
     62    ... '    wrapped_method = cached_method(test_meth,name="wrapped_method")']
     63    sage: cython('\n'.join(cython_code))
     64    sage: O = MyClass()
     65    sage: O.wrapped_method
     66    Cached version of <built-in function test_meth>
     67    sage: O.wrapped_method.__name__
     68    'wrapped_method'
     69    sage: O.wrapped_method(5)
     70    -5
     71    sage: O.wrapped_method(5) is O.wrapped_method(5)
     72    True
     73
     74By trac ticket #11115, even if a parent does not allow attribute
     75assignment, it can inherit a cached method from the parent class of a
     76category (previously, the cache would have been broken)::
     77
     78    sage: cython_code = ["from sage.all import cached_method, cached_in_parent_method, Category",
     79    ... "class MyCategory(Category):",
     80    ... "    @cached_method",
     81    ... "    def super_categories(self):",
     82    ... "        return [Objects()]",
     83    ... "    class ElementMethods:",
     84    ... "        @cached_method",
     85    ... "        def element_cache_test(self):",
     86    ... "            return -self",
     87    ... "        @cached_in_parent_method",
     88    ... "        def element_via_parent_test(self):",
     89    ... "            return -self",
     90    ... "    class ParentMethods:",
     91    ... "        @cached_method",
     92    ... "        def one(self):",
     93    ... "            return self.element_class(self,1)",
     94    ... "        @cached_method",
     95    ... "        def invert(self, x):",
     96    ... "            return -x"]
     97    sage: cython('\n'.join(cython_code))
     98    sage: C = MyCategory()
     99
     100In order to keep the memory footprint of elements small, it was
     101decided to not support the same freedom of using cached methods
     102for elements: If an instance of a class derived from
     103:class:`~sage.structure.element.Element` does not allow attribute
     104assignment, then a cached method inherited from the category of
     105its parent will break, as in the class ``MyBrokenElement`` below.
     106
     107However, there is a class :class:`~sage.structure.element.ElementWithCachedMethod`
     108that has generally a slower attribute access, but fully supports
     109cached methods. We remark, however, that cached methods are
     110*much* faster if attribute access works. So, we expect that
     111:class:`~sage.structure.element.ElementWithCachedMethod` will
     112hardly by used.
     113::
     114
     115    sage: cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod",
     116    ... "cdef class MyBrokenElement(Element):",
     117    ... "    cdef public object x",
     118    ... "    def __init__(self,P,x):",
     119    ... "        self.x=x",
     120    ... "        Element.__init__(self,P)",
     121    ... "    def __neg__(self):",
     122    ... "        return MyBrokenElement(self.parent(),-self.x)",
     123    ... "    def _repr_(self):",
     124    ... "        return '<%s>'%self.x",
     125    ... "    def __hash__(self):",
     126    ... "        return hash(self.x)",
     127    ... "    def __cmp__(left, right):",
     128    ... "        return (<Element>left)._cmp(right)",
     129    ... "    def __richcmp__(left, right, op):",
     130    ... "        return (<Element>left)._richcmp(right,op)",
     131    ... "    cdef int _cmp_c_impl(left, Element right) except -2:",
     132    ... "        return cmp(left.x,right.x)",
     133    ... "    def raw_test(self):",
     134    ... "        return -self",
     135    ... "cdef class MyElement(ElementWithCachedMethod):",
     136    ... "    cdef public object x",
     137    ... "    def __init__(self,P,x):",
     138    ... "        self.x=x",
     139    ... "        ElementWithCachedMethod.__init__(self,P)",
     140    ... "    def __neg__(self):",
     141    ... "        return MyElement(self.parent(),-self.x)",
     142    ... "    def _repr_(self):",
     143    ... "        return '<%s>'%self.x",
     144    ... "    def __hash__(self):",
     145    ... "        return hash(self.x)",
     146    ... "    def __cmp__(left, right):",
     147    ... "        return (<Element>left)._cmp(right)",
     148    ... "    def __richcmp__(left, right, op):",
     149    ... "        return (<Element>left)._richcmp(right,op)",
     150    ... "    cdef int _cmp_c_impl(left, Element right) except -2:",
     151    ... "        return cmp(left.x,right.x)",
     152    ... "    def raw_test(self):",
     153    ... "        return -self",
     154    ... "from sage.structure.parent cimport Parent",
     155    ... "cdef class MyParent(Parent):",
     156    ... "    Element = MyElement"]
     157    sage: cython('\n'.join(cython_code))
     158    sage: P = MyParent(category=C)
     159    sage: ebroken = MyBrokenElement(P,5)
     160    sage: e = MyElement(P,5)
     161
     162The cached methods inherited by the parent works::
     163
     164    sage: P.one()
     165    <1>
     166    sage: P.one() is P.one()
     167    True
     168    sage: P.invert(e)
     169    <-5>
     170    sage: P.invert(e) is P.invert(e)
     171    True
     172
     173The cached methods inherited by ``MyElement`` works::
     174
     175    sage: e.element_cache_test()
     176    <-5>
     177    sage: e.element_cache_test() is e.element_cache_test()
     178    True
     179    sage: e.element_via_parent_test()
     180    <-5>
     181    sage: e.element_via_parent_test() is e.element_via_parent_test()
     182    True
     183
     184The other element class can only inherit a ``cached_in_parent_method``, since
     185the cache is stored in the parent. In fact, equal elements share the cache,
     186even if they are of different types::
     187
     188    sage: e == ebroken
     189    True
     190    sage: type(e) == type(ebroken)
     191    False
     192    sage: ebroken.element_via_parent_test() is e.element_via_parent_test()
     193    True
     194
     195However, the cache of the other inherited method breaks, although the method
     196as such works::
     197
     198    sage: ebroken.element_cache_test()
     199    <-5>
     200    sage: ebroken.element_cache_test() is ebroken.element_cache_test()
     201    False
     202
     203The cache can be emptied::
     204
     205    sage: a = test_pfunc(5)
     206    sage: test_pfunc.clear_cache()
     207    sage: a is test_pfunc(5)
     208    False
     209    sage: a = P.one()
     210    sage: P.one.clear_cache()
     211    sage: a is P.one()
     212    False   
     213
     214Since ``e`` and ``ebroken`` share the cache, when we empty it for one element
     215it is empty for the other as well::
     216
     217    sage: b = ebroken.element_via_parent_test()
     218    sage: e.element_via_parent_test.clear_cache()
     219    sage: b is ebroken.element_via_parent_test()
     220    False
     221
     222Introspection works::
     223
     224    sage: from sage.misc.edit_module import file_and_line
     225    sage: from sage.misc.sageinspect import sage_getdoc, sage_getfile, sage_getsource
     226    sage: print sage_getdoc(test_pfunc)
     227       Some documentation
     228    sage: print sage_getdoc(O.wrapped_method)
     229    some doc for a wrapped cython method
     230    <BLANKLINE>
     231    sage: print sage_getsource(O.wrapped_method)
     232    cpdef test_meth(self,x):
     233        "some doc for a wrapped cython method"
     234        return -x
     235
     236It is a very common special case to cache a method that has no
     237arguments. In that special case, the time needed to access the cache
     238can be drastically reduced by using a special implementation. The
     239cached method decorator automatically determines which implementation
     240ought to be chosen. A typical example is
     241:meth:`sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal.gens`
     242(no arguments) versus
     243:meth:`sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal.groebner_basis`
     244(several arguments)::
     245
     246    sage: P.<a,b,c,d> = QQ[]
     247    sage: I = P*[a,b]
     248    sage: I.gens()
     249    [a, b]
     250    sage: I.gens() is I.gens()
     251    True
     252    sage: I.groebner_basis()
     253    [a, b]
     254    sage: I.groebner_basis() is I.groebner_basis()
     255    True
     256    sage: type(I.gens)
     257    <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     258    sage: type(I.groebner_basis)
     259    <type 'sage.misc.cachefunc.CachedMethodCaller'>
    12260
    13261"""
    14262########################################################################
    15263#       Copyright (C) 2008 William Stein <wstein@gmail.com>
    16264#                          Mike Hansen <mhansen@gmail.com>
     265#                     2011 Simon King <simon.king@uni-jena.de>
    17266#
    18267#  Distributed under the terms of the GNU General Public License (GPL)
    19268#
     
    21270########################################################################
    22271from function_mangling import ArgumentFixer
    23272import os
    24 
    25 class CachedFunction(object):
     273from sage.misc.sageinspect import sage_getfile, sage_getsourcelines
     274
     275def _cached_function_unpickle(module,name):
     276    """
     277    Unpickling of cached functions.
     278
     279    NOTE:
     280
     281    Pickling and unpickling of cached functions is by importing
     282    from the module in which the function is defined.
     283
     284    INPUT:
     285
     286    - ``module``: A string, describing the module to import the
     287      function from.
     288    - ``name``: A string, name of the to-be-imported cached function.
     289
     290    EXAMPLE::
     291
     292        sage: type(cunningham_prime_factors)
     293        <type 'sage.misc.cachefunc.CachedFunction'>
     294        sage: loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest
     295        True
     296
     297    """
     298    return getattr(__import__(module, fromlist=['']),name)
     299
     300cdef class CachedFunction(object):
    26301    """
    27302    Create a cached version of a function, which only recomputes
    28303    values it hasn't already computed. Synonyme: ``cached_function``
    29304
     305    INPUT:
     306
     307    - ``f`` -- a function
     308    - ``name`` (optional string) -- name that the cached version
     309      of ``f`` should be provided with.
     310
    30311    If ``f`` is a function, do either ``g = CachedFunction(f)``
    31312    or ``g = cached_function(f)`` to make a cached version of ``f``,
    32313    or put ``@cached_function`` right before the definition of ``f``
     
    71352        'foo'
    72353
    73354    """
    74     def __init__(self, f, classmethod=False):
     355    def __init__(self, f, classmethod=False, name=None):
    75356        """
    76357        Create a cached version of a function, which only recomputes
    77         values it hasn't already computed.
     358        values it hasn't already computed. A custom name can be
     359        provided by an optional argument "name".
    78360
    79361        If f is a function, do either g = CachedFunction(f) to make
    80362        a cached version of f, or put @CachedFunction right before
    81         the definition of f (i.e., use Python decorators)::
     363        the definition of f (i.e., use Python decorators, but then
     364        the optional argument ``name`` can not be used)::
    82365
    83366            @CachedFunction
    84367            def f(...):
     
    91374            sage: g = CachedFunction(number_of_partitions)
    92375            sage: g.__name__
    93376            'number_of_partitions'
    94             sage: 'partitions' in g.__doc__
     377            sage: 'partitions' in sage.misc.sageinspect.sage_getdoc(g)
    95378            True
    96379            sage: g(5)
    97380            7
     
    106389            True
    107390
    108391        """
    109         self._common_init(f, ArgumentFixer(f,classmethod=classmethod))
     392        self._common_init(f, ArgumentFixer(f,classmethod=classmethod), name=name)
    110393        self.cache = {}
    111394
    112     def _common_init(self, f, argumentfixer):
     395    def _common_init(self, f, argument_fixer, name=None):
    113396        """
    114397        Perform initialization common to CachedFunction and CachedMethodCaller.
    115398
     
    118401            sage: @cached_function
    119402            ... def test_cache(x):
    120403            ...     return -x
    121             sage: hasattr(test_cache, '_argumentfixer')  # indirect doctest
     404            sage: test_cache._fix_to_pos is not None  # indirect doctest
    122405            True
     406
    123407        """
    124408        self.f = f
     409        if name is not None:
     410            self.__name__ = name
     411        elif hasattr(f, "func_name"):
     412            self.__name__ = f.func_name
     413        else:
     414            self.__name__ = f.__name__
     415        self.__module__ = f.__module__
     416        if argument_fixer is not None: # it is None for CachedMethodCallerNoArgs
     417            self._argument_fixer = argument_fixer
     418            self._fix_to_pos = argument_fixer.fix_to_pos
     419
     420    def __reduce__(self):
     421        """
     422        Pickling of cached functions.
     423
     424        TEST::
     425
     426            sage: type(cunningham_prime_factors)
     427            <type 'sage.misc.cachefunc.CachedFunction'>
     428            sage: loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest
     429            True
     430
     431        """
     432        return _cached_function_unpickle, (self.__module__, self.__name__)
     433
     434    #########
     435    ## Introspection
     436    ##
     437    ## We provide some methods explicitly, and
     438    ## forward other questions to the cached function.
     439
     440    def _sage_doc_(self):
     441        """
     442        Provide documentation for the cached function.
     443
     444        A cached function shall inherit the documentation
     445        from the function that is wrapped, not from the
     446        documentation of the wrapper.
     447
     448        TEST::
     449
     450            sage: P.<x,y> = QQ[]
     451            sage: I = P*[x,y]
     452            sage: from sage.misc.sageinspect import sage_getdoc
     453            sage: print sage_getdoc(I.groebner_basis) # indirect doctest
     454               Return the reduced Groebner basis of this ideal.
     455            ...
     456               ALGORITHM: Uses Singular, Magma (if available), Macaulay2 (if
     457               available), or a toy implementation.
     458
     459        """
     460        f = self.f
    125461        if hasattr(f, "func_doc"):
    126             self.__doc__ = f.func_doc
    127         if hasattr(f, "func_name"):
    128             self.__name__ = f.func_name
    129         self.__module__ = f.__module__
    130         self._argumentfixer = argumentfixer
     462            try:
     463                sourcelines = sage_getsourcelines(f)
     464            except IOError:
     465                sourcelines = None
     466            if sourcelines is not None:
     467                import os
     468                SAGE_ROOT = os.environ['SAGE_ROOT']
     469                filename = sage_getfile(f)
     470                # The following is a heuristics to get
     471                # the file name of the cached function
     472                # or method
     473                if filename.startswith(SAGE_ROOT+'/devel/sage/'):
     474                    filename = filename[len(SAGE_ROOT+'/devel/sage/'):]
     475                elif 'site-packages/' in filename:
     476                    filename = filename.split('site-packages/',1)[1]
     477                file_info = "File: %s (starting at line %d)"%(filename,sourcelines[1])
     478                doc = file_info+(f.func_doc or '')
     479            else:
     480                doc = f.func_doc
     481        else:
     482            doc = f.__doc__
     483        return doc
    131484
    132485    def _sage_src_(self):
    133486        """
     
    144497        from sage.misc.sageinspect import sage_getsource
    145498        return sage_getsource(self.f)
    146499
     500    def _sage_src_lines_(self):
     501        r"""
     502        Returns the list of source lines and the first line number
     503        of the wrapped function.
     504
     505        TEST::
     506
     507            sage: P.<x,y> = QQ[]
     508            sage: I = P*[x,y]
     509            sage: from sage.misc.sageinspect import sage_getsourcelines
     510            sage: l = "        elif algorithm == 'macaulay2:gb':\n"
     511            sage: l in sage_getsourcelines(I.groebner_basis)[0] # indirect doctest
     512            True
     513
     514        """
     515        from sage.misc.sageinspect import sage_getsourcelines
     516        return sage_getsourcelines(self.f)
     517
     518    def _sage_argspec_(self):
     519        """
     520        Return the argspec of the wrapped function or method.
     521
     522        This was implemented in trac ticket #11115.
     523
     524        EXAMPLE::
     525
     526            sage: P.<x,y> = QQ[]
     527            sage: I = P*[x,y]
     528            sage: from sage.misc.sageinspect import sage_getargspec
     529            sage: sage_getargspec(I.groebner_basis)   # indirect doctest
     530            ArgSpec(args=['self', 'algorithm', 'deg_bound', 'mult_bound', 'prot'],
     531            varargs='args', keywords='kwds', defaults=('', None, None,
     532            False))
     533
     534        """
     535        from sage.misc.sageinspect import sage_getargspec
     536        return sage_getargspec(self.f)
     537
    147538    def __call__(self, *args, **kwds):
    148539        """
    149540        Return value from cache or call the wrapped function,
     
    155546            sage: a = g(5)
    156547            sage: g.get_cache()
    157548            {((5, None, 'default'), ()): 7}
    158             sage: a = g(10^5)
     549            sage: a = g(10^5)   # indirect doctest
    159550            sage: a == number_of_partitions(10^5)
    160551            True
    161552            sage: a is g(10^5)
     
    166557        """
    167558        # We shortcut a common case of no arguments
    168559        if args or kwds:
    169             k = self._argumentfixer.fix_to_pos(*args, **kwds)
     560            k = self._fix_to_pos(*args, **kwds)
    170561        else:
    171             try:
     562            if self._default_key is not None:
    172563                k = self._default_key
    173             except AttributeError:
    174                 k = self._default_key = self._argumentfixer.fix_to_pos()
     564            else:
     565                k = self._default_key = self._fix_to_pos()
     566
    175567        try:
    176             return self.cache[k]
     568            return (<dict>self.cache)[k]
    177569        except KeyError:
    178570            w = self.f(*args, **kwds)
    179571            self.cache[k] = w
    180572            return w
    181573
    182     def get_cache(self):
     574    cpdef get_cache(self):
    183575        """
    184576        Returns the cache dictionary.
    185577
     
    214606            sage: a.f.is_in_cache(3,y=0)
    215607            True
    216608        """
    217         return self._argumentfixer.fix_to_pos(*args, **kwds) in self.cache
     609        return self._fix_to_pos(*args, **kwds) in (<dict>self.cache)
    218610
    219611    def set_cache(self, value, *args, **kwds):
    220612        """
     
    244636            sage: g(5)         # todo: not implemented
    245637            19
    246638        """
    247         self.cache[self._argumentfixer.fix_to_pos(*args, **kwds)] = value
     639        (<dict>self.cache)[self._fix_to_pos(*args, **kwds)] = value
    248640
    249641    def get_key(self, *args, **kwds):
    250642        """
     
    264656            sage: foo.get_key(x=3)
    265657            ((3,), ())
    266658        """
    267         return self._argumentfixer.fix_to_pos(*args, **kwds)
     659        return self._fix_to_pos(*args, **kwds)
    268660
    269661    def __repr__(self):
    270662        """
    271663        EXAMPLES::
    272664
    273665            sage: g = CachedFunction(number_of_partitions)
    274             sage: g
     666            sage: g     # indirect doctest
    275667            Cached version of <function number_of_partitions at 0x...>
    276668        """
    277669        try:
     
    279671        except AttributeError:
    280672            return "Cached version of a method (pending reassignment)"
    281673
    282     def clear_cache(self):
     674    cpdef clear_cache(self):
    283675        """
    284676        Clear the cache dictionary.
    285677
     
    293685            sage: g.get_cache()
    294686            {}
    295687        """
    296         cache = self.cache
     688        cdef object cache = self.cache
    297689        for key in cache.keys():
    298690            del cache[key]
    299691
    300692    def precompute(self, arglist, num_processes=1):
    301693        """
    302 
    303694        Cache values for a number of inputs.  Do the computation
    304695        in parallel, and only bother to compute values that we
    305696        haven't already cached.
     
    311702            ...     l = [p for p,e in factor(n) if p != 2]
    312703            ...     return len(l)
    313704            sage: oddprime_factors.precompute(range(1,100), 4)
    314             sage: oddprime_factors(25) is oddprime_factors(25)
    315             True
     705            sage: oddprime_factors.cache[(25,),()]
     706            1
    316707        """
    317708        from sage.parallel.decorate import parallel, normalize_input
    318709        P = parallel(num_processes)(self.f)
    319         cache = self.cache
    320         get_key = self._argumentfixer.fix_to_pos
    321         new = lambda x: not cache.has_key(get_key(*x[0],**x[1]))
     710        has_key = self.cache.has_key
     711        get_key = self._fix_to_pos
     712        new = lambda x: not has_key(get_key(*x[0],**x[1]))
    322713        arglist = filter(new, map(normalize_input, arglist))
    323714        for ((args,kwargs), val) in P(arglist):
    324715            self.set_cache(val, *args, **kwargs)
     
    326717
    327718cached_function = CachedFunction
    328719
    329 class CachedMethodPickle:
     720class CachedMethodPickle(object):
    330721    """
    331722    This class helps to unpickle cached methods.
    332723
     
    339730    since functions can not be pickled, currently. Therefore,
    340731    we replace the actual cached method by a place holder,
    341732    that kills itself as soon as any attribute is requested.
    342     Then, the original cached attribute is reinstated.
     733    Then, the original cached attribute is reinstated. But the
     734    cached values are in fact saved.
    343735
    344736    EXAMPLE::
    345737
    346738        sage: R.<x, y, z> = PolynomialRing(QQ, 3)
    347739        sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
    348740        sage: I.groebner_basis()
    349         [y^5*z^3 - 1/4*x^2*z^6 + 1/2*x*y*z^6 + 1/4*y^2*z^6, x^2*y*z^3 - x*y^2*z^3 + 2*y^3*z^3 + z^6, x*y^3 + y^4 + x*z^3, x^3 + y^3 + z^3]
     741        [y^5*z^3 - 1/4*x^2*z^6 + 1/2*x*y*z^6 + 1/4*y^2*z^6,
     742         x^2*y*z^3 - x*y^2*z^3 + 2*y^3*z^3 + z^6,
     743         x*y^3 + y^4 + x*z^3, x^3 + y^3 + z^3]
    350744        sage: I.groebner_basis
    351745        Cached version of <function groebner_basis at 0x...>
    352746
     
    368762        sage: J.groebner_basis() == I.groebner_basis()
    369763        True
    370764
     765    TESTS:
     766
     767    Since Trac Ticket #11115, there is a special implementation for
     768    cached methods that don't take arguments::
     769
     770        sage: P.<a,b,c,d> = QQ[]
     771        sage: I = P*[a,b]
     772        sage: type(I.gens)
     773        <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     774        sage: type(I.groebner_basis)
     775        <type 'sage.misc.cachefunc.CachedMethodCaller'>
     776
     777    We demonstrate that both implementations can be pickled and
     778    preserve the cache. For that purpose, we assign nonsense to the
     779    cache. Of course, it is a very bad idea to override the cache in
     780    that way.  So, please don't try this at home::
     781
     782        sage: I.groebner_basis.set_cache('foo',algorithm='singular')
     783        sage: I.groebner_basis(algorithm='singular')
     784        'foo'
     785        sage: I.gens.set_cache('bar')
     786        sage: I.gens()
     787        'bar'
     788        sage: J = loads(dumps(I))
     789        sage: J.gens()
     790        'bar'
     791        sage: J.groebner_basis(algorithm='singular')
     792        'foo'
     793
     794    Anyway, the cache will be automatically reconstructed after
     795    clearing it::
     796
     797        sage: J.gens.clear_cache()
     798        sage: J.gens()
     799        [a, b]
     800        sage: J.groebner_basis.clear_cache()
     801        sage: J.groebner_basis(algorithm='singular')
     802        [a, b]
     803
    371804    AUTHOR:
    372805
    373806    - Simon King (2011-01)
    374807    """
    375     def __init__(self, inst, name):
     808    def __init__(self, inst, name, cache=None):
    376809        """
    377810        INPUT:
    378811
     
    390823        """
    391824        self._instance = inst
    392825        self._name = name
     826        self._cache = cache
    393827    def __repr__(self):
    394828        """
    395829        TEST::
     
    402836            Pickle of the cached method "groebner_basis"
    403837        """
    404838        return 'Pickle of the cached method "%s"'%self._name
     839    def __reduce__(self):
     840        """
     841        This class is a pickle. However, sometimes, pickles
     842        need to be pickled another time.
     843
     844        TEST::
     845
     846            sage: PF = WeylGroup(['A',3]).pieri_factors()
     847            sage: a = PF.an_element()
     848            sage: a.bruhat_lower_covers()
     849            [[0 1 0 0]
     850            [0 0 1 0]
     851            [1 0 0 0]
     852            [0 0 0 1], [0 1 0 0]
     853            [1 0 0 0]
     854            [0 0 0 1]
     855            [0 0 1 0], [1 0 0 0]
     856            [0 0 1 0]
     857            [0 0 0 1]
     858            [0 1 0 0]]
     859            sage: b = loads(dumps(a))
     860            sage: b.bruhat_lower_covers
     861            Pickle of the cached method "bruhat_lower_covers"
     862
     863        When we now pickle ``b``, the pickle of the cached method
     864        needs to be taken care of::
     865
     866            sage: c = loads(dumps(b))  # indirect doctest
     867            sage: c.bruhat_lower_covers
     868            Pickle of the cached method "bruhat_lower_covers"
     869            sage: c.bruhat_lower_covers()
     870            [[0 1 0 0]
     871            [0 0 1 0]
     872            [1 0 0 0]
     873            [0 0 0 1], [0 1 0 0]
     874            [1 0 0 0]
     875            [0 0 0 1]
     876            [0 0 1 0], [1 0 0 0]
     877            [0 0 1 0]
     878            [0 0 0 1]
     879            [0 1 0 0]]
     880
     881        """
     882        return CachedMethodPickle,(self._instance,self._name,self._cache)
     883    def __call__(self,*args,**kwds):
     884        """
     885        The purpose of this call method is to kill ``self`` and to
     886        replace it by an actual :class:`CachedMethodCaller`. The last
     887        thing that ``self`` does before disappearing is to call the
     888        :class:`CachedMethodCaller` and return the result.
     889
     890        EXAMPLE::
     891
     892            sage: P.<a,b,c,d> = QQ[]
     893            sage: I = P*[a,b]
     894            sage: I.gens
     895            Cached version of <function gens at 0x...>
     896            sage: J = loads(dumps(I))
     897            sage: J.gens
     898            Pickle of the cached method "gens"
     899            sage: J.gens()   # indirect doctest
     900            [a, b]
     901            sage: J.gens
     902            Cached version of <function gens at 0x...>
     903
     904        """
     905        self._instance.__dict__.__delitem__(self._name)
     906        CM = getattr(self._instance,self._name)
     907        if self._cache is not None:
     908            if isinstance(CM, CachedMethodCallerNoArgs):
     909                CM.cache = self._cache
     910            else:
     911                for k,v in self._cache:
     912                    CM.cache[k] = v
     913        return CM(*args,**kwds)
     914       
    405915    def __getattr__(self,s):
    406916        """
    407917        TEST::
     
    432942
    433943        """
    434944        self._instance.__dict__.__delitem__(self._name)
    435         return getattr(getattr(self._instance,self._name),s)
    436 
    437 class CachedMethodCaller(CachedFunction):
     945        CM = getattr(self._instance,self._name)
     946        if self._cache is not None:
     947            if isinstance(CM, CachedMethodCallerNoArgs):
     948                CM.cache = self._cache
     949            else:
     950                for k,v in self._cache:
     951                    CM.cache[k] = v
     952        return getattr(CM,s)
     953
     954cdef class CachedMethodCaller(CachedFunction):
    438955    """
    439956    Utility class that is used by :class:`CachedMethod` to bind a
    440957    cached method to an instance.
    441958
     959    NOTE:
     960
     961    Since Trac Ticket #11115, there is a special implementation
     962    :class:`CachedMethodCallerNoArgs` for methods that do not take
     963    arguments.
     964
    442965    EXAMPLE::
    443966
    444967        sage: class A:
     
    449972        sage: a.bar
    450973        Cached version of <function bar at 0x...>
    451974        sage: type(a.bar)
    452         <class 'sage.misc.cachefunc.CachedMethodCaller'>
     975        <type 'sage.misc.cachefunc.CachedMethodCaller'>
    453976        sage: a.bar(2) is a.bar(x=2)
    454977        True
    455978
    456979    """
    457     def __init__(self, cachedmethod, inst, cache=None, inst_in_key=False):
     980    def __init__(self, CachedMethod cachedmethod, inst, cache=None, inst_in_key=False, name=None):
    458981        """
    459982        EXAMPLES::
    460983
     
    462985            ...       def __init__(self, x):
    463986            ...           self._x = x
    464987            ...       @cached_method
    465             ...       def f(self):
     988            ...       def f(self,*args):
    466989            ...           return self._x^2
    467990            ...
    468991            sage: a = Foo(2)
     
    474997            {((), ()): 4}
    475998        """
    476999        # initialize CachedFunction, but re-use the ArgumentFixer
    477         self._common_init(cachedmethod._cachedfunc.f, cachedmethod._cachedfunc._argumentfixer)
     1000        self._common_init(cachedmethod._cachedfunc.f, cachedmethod._cachedfunc._argument_fixer, name=name)
    4781001        self.cache = {} if cache is None else cache
    4791002        self._instance = inst
    4801003        self._inst_in_key = inst_in_key
     
    5001023            Cached version of <function groebner_basis at 0x...>
    5011024
    5021025        """
    503         return CachedMethodPickle,(self._instance,self.__name__)
     1026#        if hasattr(self._instance,self._cachedmethod._cache_name):
     1027#            return CachedMethodPickle,(self._instance,self.__name__)
     1028        if isinstance(self._cachedmethod, CachedInParentMethod) or hasattr(self._instance,self._cachedmethod._cache_name):
     1029            return CachedMethodPickle,(self._instance,self.__name__)
     1030        return CachedMethodPickle,(self._instance,self.__name__,self.cache.items())
     1031
     1032    def _instance_call(self, *args, **kwds):
     1033        """
     1034        Call the cached method without using the cache.
     1035
     1036        EXAMPLE::
     1037
     1038            sage: P.<a,b,c,d> = QQ[]
     1039            sage: I = P*[a,b]
     1040            sage: I.groebner_basis()
     1041            [a, b]
     1042            sage: I.groebner_basis._instance_call() is I.groebner_basis()
     1043            False
     1044            sage: I.groebner_basis._instance_call() == I.groebner_basis()
     1045            True
     1046
     1047        """
     1048        return self._cachedmethod._instance_call(self._instance, *args, **kwds)
    5041049
    5051050    def __call__(self, *args, **kwds):
    5061051        """
     
    5421087            2
    5431088        """
    5441089        # We shortcut a common case of no arguments
    545         if args or kwds:
    546             k = self.get_key(*args, **kwds)
     1090        # and we avoid calling another python function,
     1091        # although that means to duplicate code.
     1092        cdef int lenargs
     1093        cdef int nargs
     1094        cdef tuple k
     1095        cdef dict cache = self.cache
     1096        if kwds:
     1097            if self._inst_in_key:
     1098                k = (self._instance,self._fix_to_pos(*args, **kwds))
     1099            else:
     1100                k = self._fix_to_pos(*args, **kwds)
    5471101        else:
    548             try:
     1102            if args:
     1103                lenargs = len(args)
     1104                nargs = self._argument_fixer._nargs
     1105                if self._inst_in_key:
     1106                    if lenargs>=nargs:
     1107                        k = (self._instance,(args,()))
     1108                    else:
     1109                        k = (self._instance,(<tuple>args+(<tuple>self._argument_fixer._default_tuple)[-nargs+lenargs:],()))
     1110                else:
     1111                    if lenargs>=nargs:
     1112                        k = (args,())
     1113                    else:
     1114                        k = (<tuple>args+(<tuple>self._argument_fixer._default_tuple)[-nargs+lenargs:],())
     1115            elif self._default_key is not None:
    5491116                k = self._default_key
    550             except AttributeError:
    551                 k = self._default_key = self.get_key()
     1117            else:
     1118                if self._inst_in_key:
     1119                    k = self._default_key = (self._instance,self._fix_to_pos())
     1120                else:
     1121                    k = self._default_key = self._fix_to_pos()
    5521122        try:
    553             return self.cache[k]
     1123            return cache[k]
    5541124        except KeyError:
    5551125            w = self._cachedmethod._instance_call(self._instance, *args, **kwds)
    556             self.cache[k] = w
     1126            cache[k] = w
    5571127            return w
    5581128
    5591129    def get_key(self, *args, **kwds):
     
    5991169
    6001170        """
    6011171        if self._inst_in_key:
    602             return (self._instance,self._argumentfixer.fix_to_pos(*args,**kwds))
    603         return self._argumentfixer.fix_to_pos(*args,**kwds)
    604 
    605     def __get__(self, inst, cls=None):
    606         """
     1172            return (self._instance,self._fix_to_pos(*args,**kwds))
     1173        return self._fix_to_pos(*args,**kwds)
     1174
     1175    def __get__(self, inst, cls): #cls=None):
     1176        r"""
    6071177        Get a :class:`CachedMethodCaller` bound to a specific
    6081178        instance of the class of the cached method.
    6091179
     
    6141184        return value of ``CachedMethod.__get__`` with
    6151185        ``inst==None``.
    6161186
     1187        This getter attempts to assign a bound method as an
     1188        attribute to the given instance. If this is not
     1189        possible (for example, for some extension classes),
     1190        it is attempted to find an attribute ``__cached_methods``,
     1191        and store/retrieve the bound method there. In that
     1192        way, cached methods can be implemented for extension
     1193        classes deriving from :class:`~sage.structure.parent.Parent`
     1194        and :class:`~sage.structure.element.Element`.
     1195
    6171196        TESTS:
    6181197
    6191198        Due to the separate ``__get__`` method, it is possible
     
    6521231            sage: b2.f._instance is b2
    6531232            True
    6541233
     1234        An extension class can inherit a cached method from the
     1235        parent or element class of a category (trac ticket #11115).
     1236        See :class:`CachedMethodCaller` for examples.
     1237
    6551238        """
    656         Caller = CachedMethodCaller(self._cachedmethod, inst, cache=self._cachedmethod._get_instance_cache(inst), inst_in_key=self._inst_in_key)
     1239        # This is for Parents or Elements that do not allow attribute assignment
    6571240        try:
    658             setattr(inst,self._cachedmethod._cachedfunc.f.__name__, Caller)
     1241            return (<dict>inst.__cached_methods).__getitem__(self._cachedmethod._cachedfunc.__name__)
     1242        except (AttributeError,TypeError,KeyError):
     1243            pass
     1244        Caller = CachedMethodCaller(self._cachedmethod, inst, cache=self._cachedmethod._get_instance_cache(inst), inst_in_key=self._inst_in_key, name=self._cachedmethod._cachedfunc.__name__)
     1245        try:
     1246            setattr(inst,self._cachedmethod._cachedfunc.__name__, Caller)
     1247            return Caller
     1248        except AttributeError,msg:
     1249            pass
     1250        try:
     1251            if inst.__cached_methods is None:
     1252                inst.__cached_methods = {self._cachedmethod._cachedfunc.__name__ : Caller}
     1253            else:
     1254                (<dict>inst.__cached_methods).__setitem__(self._cachedmethod._cachedfunc.__name__, Caller)
     1255        except AttributeError,msg:
     1256            pass
     1257        return Caller
     1258
     1259cdef class CachedMethodCallerNoArgs(CachedFunction):
     1260    """
     1261    Utility class that is used by :class:`CachedMethod` to bind a
     1262    cached method to an instance, in the case of a method that does
     1263    not accept any arguments except ``self``.
     1264
     1265    NOTE:
     1266
     1267    The return value ``None`` would not be cached. So, if you have
     1268    a method that does not accept arguments and may return ``None``
     1269    after a lengthy computation, then ``@cached_method`` should not
     1270    be used.
     1271
     1272    EXAMPLE::
     1273
     1274        sage: P.<a,b,c,d> = QQ[]
     1275        sage: I = P*[a,b]
     1276        sage: I.gens
     1277        Cached version of <function gens at 0x...>
     1278        sage: type(I.gens)
     1279        <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1280        sage: I.gens is I.gens
     1281        True
     1282        sage: I.gens() is I.gens()
     1283        True
     1284
     1285    AUTHOR:
     1286
     1287    - Simon King (2011-04)
     1288    """
     1289    def __init__(self, inst, f, cache=None, name=None):
     1290        """
     1291        EXAMPLES::
     1292
     1293            sage: class Foo:
     1294            ...       def __init__(self, x):
     1295            ...           self._x = x
     1296            ...       @cached_method
     1297            ...       def f(self):
     1298            ...           return self._x^2
     1299            ...
     1300            sage: a = Foo(2)
     1301            sage: print a.f.get_cache()
     1302            None
     1303            sage: a.f()
     1304            4
     1305            sage: a.f.get_cache()
     1306            4
     1307
     1308        """
     1309        # initialize CachedFunction
     1310        if isinstance(f,basestring):
     1311            try:
     1312                F = getattr(inst.__class__,f)
     1313            except AttributeError:
     1314                 F = getattr(inst,f)
     1315            if isinstance(F,CachedFunction):
     1316                f = F.f
     1317            else:
     1318                f = F
     1319        self._common_init(f, None, name=name)
     1320        # This is for unpickling a CachedMethodCallerNoArgs out
     1321        # of an old CachedMethodCaller:
     1322        cachename = '_cache__' + self.__name__
     1323        if hasattr(inst, cachename):
     1324            # This is for data that are pickled in an old format
     1325            CACHE = getattr(inst, cachename)
     1326            if len(CACHE)>1:
     1327                raise TypeError, "Apparently you are opening a pickle in which '%s' was a method accepting arguments"%name
     1328            if len(CACHE)==1:
     1329                self.cache = CACHE.values()[0]
     1330            else:
     1331                self.cache = cache
     1332            delattr(inst, cachename)
     1333        else:
     1334            self.cache = cache  # None means: the underlying method will be called
     1335        self._instance = inst
     1336
     1337    def __reduce__(self):
     1338        """
     1339        Since functions can not be pickled, the cached method caller
     1340        is pickled by a :class:`CachedMethodPickle`, that replaces
     1341        itself by an actual :class:`CachedMethodCallerNoArgs` as soon
     1342        as it is asked to do anything.
     1343
     1344        TEST::
     1345
     1346            sage: P.<a,b,c,d> = QQ[]
     1347            sage: I = P*[a,b]
     1348            sage: I.gens()
     1349            [a, b]
     1350            sage: I.gens
     1351            Cached version of <function gens at 0x...>
     1352            sage: J = loads(dumps(I))
     1353            sage: J.gens
     1354            Pickle of the cached method "gens"
     1355            sage: J.gens.cache
     1356            [a, b]
     1357            sage: J.gens
     1358            Cached version of <function gens at 0x...>
     1359
     1360        """
     1361        return CachedMethodPickle,(self._instance,self.__name__,self.cache)
     1362
     1363    def _instance_call(self):
     1364        """
     1365        Call the cached method without using the cache.
     1366
     1367        EXAMPLE::
     1368
     1369            sage: P.<a,b,c,d> = QQ[]
     1370            sage: I = P*[a,b]
     1371            sage: I.gens()
     1372            [a, b]
     1373            sage: I.gens._instance_call() is I.gens()
     1374            False
     1375            sage: I.gens._instance_call() == I.gens()
     1376            True
     1377
     1378        """
     1379        return self.f(self._instance)
     1380
     1381    def __call__(self):
     1382        """
     1383        Call the cached method.
     1384
     1385        EXAMPLE::
     1386
     1387            sage: P.<a,b,c,d> = QQ[]
     1388            sage: I = P*[a,b]
     1389            sage: I.gens()    # indirect doctest
     1390            [a, b]
     1391            sage: I.gens() is I.gens()
     1392            True
     1393
     1394        """
     1395        if self.cache is None:
     1396            f = self.f
     1397            self.cache = f(self._instance)
     1398        return self.cache
     1399
     1400    def set_cache(self, value):
     1401        """
     1402        Override the cache with a specific value.
     1403
     1404        NOTE:
     1405
     1406        ``None`` is not suitable for a cached value. It would be
     1407        interpreted as an empty cache, forcing a new computation.
     1408
     1409        EXAMPLES::
     1410
     1411            sage: P.<a,b,c,d> = QQ[]
     1412            sage: I = P*[a,b]
     1413            sage: I.gens()
     1414            [a, b]
     1415            sage: I.gens.set_cache('bar')
     1416            sage: I.gens()
     1417            'bar'
     1418
     1419        The cache can be emptied and thus the original value will
     1420        be reconstructed::
     1421
     1422            sage: I.gens.clear_cache()
     1423            sage: I.gens()
     1424            [a, b]
     1425
     1426        The attempt to assign ``None`` to the cache fails::
     1427
     1428            sage: I.gens.set_cache(None)
     1429            sage: I.gens()
     1430            [a, b]
     1431
     1432        """
     1433        self.cache = value
     1434
     1435    cpdef clear_cache(self):
     1436        r"""
     1437        Clear the cache dictionary.
     1438
     1439        EXAMPLES::
     1440
     1441            sage: P.<a,b,c,d> = QQ[]
     1442            sage: I = P*[a,b]
     1443            sage: I.gens()
     1444            [a, b]
     1445            sage: I.gens.set_cache('bar')
     1446            sage: I.gens()
     1447            'bar'
     1448
     1449        The cache can be emptied and thus the original value will
     1450        be reconstructed::
     1451
     1452            sage: I.gens.clear_cache()
     1453            sage: I.gens()
     1454            [a, b]
     1455
     1456        """
     1457        self.cache = None
     1458
     1459    def is_in_cache(self):
     1460        """
     1461        Answers whether the return value is already in the cache.
     1462
     1463        NOTE:
     1464
     1465        Recall that a cached method without arguments can not cache
     1466        the return value ``None``.
     1467
     1468        EXAMPLE::
     1469
     1470            sage: P.<x,y> = QQ[]
     1471            sage: I = P*[x,y]
     1472            sage: I.gens.is_in_cache()
     1473            False
     1474            sage: I.gens()
     1475            [x, y]
     1476            sage: I.gens.is_in_cache()
     1477            True
     1478
     1479        """
     1480        return self.cache is not None
     1481
     1482    def __get__(self, inst, cls): #cls=None):
     1483        """
     1484        Get a :class:`CachedMethodCallerNoArgs` bound to a specific
     1485        instance of the class of the cached method.
     1486
     1487        NOTE:
     1488
     1489        :class:`CachedMethodCallerNoArgs` has a separate ``__get__``
     1490        since the categories framework creates and caches the
     1491        return value of ``CachedMethod.__get__`` with
     1492        ``inst==None``.
     1493
     1494        This getter attempts to assign a bound method as an
     1495        attribute to the given instance. If this is not
     1496        possible (for example, for some extension classes),
     1497        it is attempted to find an attribute ``__cached_methods``,
     1498        and store/retrieve the bound method there. In that
     1499        way, cached methods can be implemented for extension
     1500        classes deriving from :class:`~sage.structure.parent.Parent`
     1501        and :class:`~sage.structure.element.Element`.
     1502
     1503        TESTS:
     1504
     1505        Due to the separate ``__get__`` method, it is possible
     1506        to define a cached method in one class and use it as
     1507        an attribute of another class.
     1508
     1509            sage: class Foo:
     1510            ...       def __init__(self, n):
     1511            ...           self.__n = n
     1512            ...       @cached_method
     1513            ...       def f(self):
     1514            ...           return self.__n^2
     1515            ...
     1516            sage: class Bar:
     1517            ...       f = Foo.f
     1518            ...
     1519            sage: b1 = Bar()
     1520            sage: b2 = Bar()
     1521
     1522        The :class:`CachedMethod` is replaced by an instance of
     1523        :class:`CachedMethodCallerNoArgs` that is set as an
     1524        attribute. Hence, we have::
     1525
     1526            sage: b1.f is b1.f
     1527            True
     1528            sage: type(b1.f)
     1529            <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1530
     1531        Any instance of ``Bar`` gets its own instance of
     1532        :class:`CachedMethodCaller``::
     1533
     1534            sage: b1.f is b2.f
     1535            False
     1536 
     1537        The method caller knows the instance that it belongs
     1538        to::
     1539
     1540            sage: Foo.f._instance is None
     1541            True
     1542            sage: b1.f._instance is b1
     1543            True
     1544            sage: b2.f._instance is b2
     1545            True
     1546
     1547        """
     1548        # This is for Parents or Elements that do not allow attribute assignment
     1549        try:
     1550            return (<dict>inst.__cached_methods).__getitem__(self.__name__)
     1551        except (AttributeError,TypeError,KeyError),msg:
     1552            pass
     1553        Caller = CachedMethodCallerNoArgs(inst, self.f, name=self.__name__)
     1554        try:
     1555            setattr(inst,self.__name__, Caller)
     1556            return Caller
    6591557        except AttributeError:
    6601558            pass
     1559        try:
     1560            if inst.__cached_methods is None:
     1561                inst.__cached_methods = {self.__name__ : Caller}
     1562            else:
     1563                (<dict>inst.__cached_methods).__setitem__(self.__name__, Caller)
     1564        except AttributeError,msg:
     1565            pass
    6611566        return Caller
    6621567
    663 class CachedMethod(object):
     1568cdef class CachedMethod(object):
    6641569    """
    6651570    A decorator that creates a cached version of an instance
    6661571    method of a class.
     
    6811586
    6821587    The example shows that the actual computation
    6831588    takes place only once, and that the result is
    684     identic for equivalent input::
     1589    identical for equivalent input::
    6851590   
    6861591        sage: res = a.f(3, 2); res
    6871592        computing
     
    6911596        sage: a.f(3) is res
    6921597        True
    6931598
     1599    Note, however, that the :class:`CachedMethod` is replaced by a
     1600    :class:`CachedMethodCaller` or :class:`CachedMethodCallerNoArgs`
     1601    as soon as it is bound to an instance or class::
     1602
     1603        sage: P.<a,b,c,d> = QQ[]
     1604        sage: I = P*[a,b]
     1605        sage: type(I.__class__.gens)
     1606        <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1607
     1608    So, you would hardly ever see an instance of this class alive.
    6941609    """
    695     def __init__(self, f):
     1610    def __init__(self, f, name=None):
    6961611        """
    6971612        EXAMPLES::
    6981613
     
    7021617            ...       @cached_method
    7031618            ...       def f(self,n):
    7041619            ...           return self._x^n
     1620            ...       @cached_method
     1621            ...       def f0(self):
     1622            ...           return self._x^2
    7051623            ...
    7061624            sage: a = Foo(2)
    7071625            sage: a.f(2)
    7081626            4
    709 
    710         The computations in method ``f`` are
    711         stored in a dictionary assigned to the
    712         instance ``a``::
     1627            sage: a.f0()
     1628            4
     1629
     1630        The computations in method ``f`` are tried to store in a
     1631        dictionary assigned to the instance ``a``::
    7131632
    7141633            sage: hasattr(a, '_cache__f')
    7151634            True
     
    7211640        of the ``CachedMethodCaller``::
    7221641
    7231642            sage: type(a.f)
    724             <class 'sage.misc.cachefunc.CachedMethodCaller'>
     1643            <type 'sage.misc.cachefunc.CachedMethodCaller'>
    7251644            sage: a.f.cache is a._cache__f
    7261645            True
    7271646
     1647        Note that if the instance ``a`` would not accept attribute
     1648        assignment, the computations would still be cached in
     1649        ``a.f.cache``, and they would in fact be preserved when
     1650        pickling.
     1651
     1652        The cached method ``f0`` accepts no arguments, which allows
     1653        for an improved way of caching: By an attribute of the cached
     1654        method itsel. This cache is *only* available in that way, i.e.,
     1655        it is not additionally stored as an attribute of ``a``::
     1656
     1657            sage: type(a.f0)
     1658            <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1659            sage: a.f0.cache
     1660            4
     1661            sage: sorted(dir(a))
     1662            ['__doc__', '__init__', '__module__', '_cache__f', '_x', 'f', 'f0']
     1663
    7281664        """
    729         self._cache_name = '_cache__' + f.__name__
    730         self._cachedfunc = CachedFunction(f, classmethod=True)
    731         self._argument_fix_to_pos = self._cachedfunc._argumentfixer.fix_to_pos
     1665        self._cache_name = '_cache__' + (name or f.__name__)
     1666        self._cachedfunc = CachedFunction(f, classmethod=True, name=name)
    7321667
    7331668    def _instance_call(self, inst, *args, **kwds):
    7341669        """
     
    7451680            ...       def __init__(self, x):
    7461681            ...           self._x = x
    7471682            ...       @cached_method
    748             ...       def f(self):
    749             ...           return self._x^2
     1683            ...       def f(self,n=2):
     1684            ...           return self._x^n
    7501685            ...
    7511686            sage: a = Foo(2)
    7521687            sage: a.f()
    7531688            4
    7541689
    755         Usually, a cached meth is indeed cached::
     1690        Usually, a cached method is indeed cached::
    7561691
    7571692            sage: a.f() is a.f()
    7581693            True
    7591694
    760         However, when it becomes necessary, one can call
    761         it without using the cache::
    762 
    763             sage: a.f._cachedmethod._instance_call(a) is a.f()
     1695        However, when it becomes necessary, one can call it without
     1696        using the cache. Note that ``a.f`` is an instance of
     1697        :class:`CachedMethodCaller`.  But its
     1698        :meth:`CachedMethodCaller._instance_call` relies on this
     1699        method, so, we have an indirect doctest::
     1700
     1701            sage: a.f._instance_call() is a.f() # indirect doctest
    7641702            False
    765             sage: a.f._cachedmethod._instance_call(a) == a.f()
     1703            sage: a.f._instance_call() == a.f()
    7661704            True
    7671705
    768         It is also possible to call the method with a
    769         different instance::
    770 
    771             sage: b = Foo(3)
    772             sage: b.f()
    773             9
    774             sage: a.f._cachedmethod._instance_call(b)
    775             9
    776 
    7771706        """
    7781707        return self._cachedfunc.f(inst, *args, **kwds)
    7791708
    780     def _get_instance_cache(self, inst):
     1709    cpdef dict _get_instance_cache(self, inst):
    7811710        """
    7821711        Returns the cache dictionary.
    7831712
     
    7871716            ...       def __init__(self, x):
    7881717            ...           self._x = x
    7891718            ...       @cached_method
    790             ...       def f(self):
    791             ...           return self._x^2
     1719            ...       def f(self,n=2):
     1720            ...           return self._x^n
    7921721            ...
    7931722            sage: a = Foo(2)
    7941723            sage: a.f()
    7951724            4
    796             sage: a.f._cachedmethod._get_instance_cache(a)
    797             {((), ()): 4}
     1725
     1726        Note that we can not provide a direct test, since ``a.f`` is
     1727        an instance of :class:`CachedMethodCaller`.  But during its
     1728        initialisation, this method was called in order to provide the
     1729        cached method caller with its cache, and, if possible, assign
     1730        it to an attribute of ``a``.  So, the following is an indirect
     1731        doctest::
     1732
     1733            sage: a.f.get_cache()    # indirect doctest
     1734            {((2,), ()): 4}
     1735            sage: a._cache__f
     1736            {((2,), ()): 4}
     1737
    7981738        """
    7991739        try:
    8001740            return inst.__dict__.setdefault(self._cache_name, {})
    8011741        except AttributeError:
    8021742            return {}
    8031743
    804     def __get__(self, inst, cls=None):
     1744    def __get__(self, inst, cls): #cls=None):
    8051745        """
    8061746        Get a CachedMethodCaller bound to this specific instance of
    8071747        the class of the cached method.
     
    8121752            ...       @cached_method
    8131753            ...       def f(self):
    8141754            ...           return 1
     1755            ...       @cached_method
     1756            ...       def g(self, x,n=3):
     1757            ...           return x^n
     1758            ...
    8151759            sage: a = Foo()
    8161760            sage: type(a.f)
    817             <class 'sage.misc.cachefunc.CachedMethodCaller'>
    818 
    819         By trac ticket #8611, the CachedMethodCaller is set as
    820         an attribute of the instance ``a``, replacing the original
    821         cached attribute. Therefore, the ``__get__`` method will
    822         be used only once, which saves much time. Hence, we have::
     1761            <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1762            sage: type(a.g)
     1763            <type 'sage.misc.cachefunc.CachedMethodCaller'>
     1764
     1765        By trac ticket #8611, it is attempted to set the
     1766        CachedMethodCaller as an attribute of the instance ``a``,
     1767        replacing the original cached attribute. Therefore, the
     1768        ``__get__`` method will be used only once, which saves much
     1769        time. Hence, we have::
    8231770 
    8241771            sage: a.f is a.f
    8251772            True
     1773            sage: a.g is a.g
     1774            True
    8261775
    8271776        """
    828         Caller = CachedMethodCaller(self, inst, cache=self._get_instance_cache(inst))
     1777        # This is for Parents or Elements that do not allow attribute assignment:
    8291778        try:
    830             setattr(inst,self._cachedfunc.f.__name__, Caller)
    831         except AttributeError,msg:
     1779            name = self._cachedfunc.__name__
     1780        except AttributeError:
     1781            name = self.__name__
     1782        try:
     1783            return (<dict>inst.__cached_methods).__getitem__(name)
     1784        except (AttributeError,TypeError,KeyError),msg:
     1785            pass
     1786        # Apparently we need to construct the caller.
     1787        # Since we have an optimized version for functions that do not accept arguments,
     1788        # we need to analyse the argspec
     1789        f = (<CachedFunction>self._cachedfunc).f
     1790        from sage.misc.sageinspect import sage_getargspec
     1791        args, varargs, keywords, defaults = sage_getargspec(f)
     1792        if varargs is None and keywords is None and len(args)<=1:
     1793            Caller = CachedMethodCallerNoArgs(inst, f, name=name)
     1794        else:
     1795            Caller = CachedMethodCaller(self, inst,
     1796            cache=self._get_instance_cache(inst), name=name)
     1797        try:
     1798            setattr(inst,name, Caller)
     1799            return Caller
     1800        except AttributeError:
     1801            pass
     1802        try:
     1803            if inst.__cached_methods is None:
     1804                inst.__cached_methods = {name : Caller}
     1805            else:
     1806                (<dict>inst.__cached_methods).__setitem__(name, Caller)
     1807        except AttributeError:
    8321808            pass
    8331809        return Caller
    8341810
     
    8421818
    8431819cached_method = CachedMethod
    8441820
    845 class CachedInParentMethod(CachedMethod):
    846     """
     1821cdef class CachedInParentMethod(CachedMethod):
     1822    r"""
    8471823    A decorator that creates a cached version of an instance
    8481824    method of a class.
    8491825
     
    8551831
    8561832    This way of caching works only if
    8571833
    858     - the instances *have* a parent,
    859     - the parent allows assignment of attributes, and
     1834    - the instances *have* a parent, and
    8601835    - the instances are hashable (they are part of the cache key).
    8611836
    8621837    NOTE:
    8631838
    864     For proper behavior, the method must be a pure function
    865     (no side effects). Arguments to the method must be hashable.
    866 
    867     EXAMPLES::
    868 
    869         sage: class MyParent(Parent):
    870         ...       pass
    871         ...
    872         sage: class Foo:
    873         ...       def __init__(self, x):
    874         ...           self._x = x
    875         ...       _parent = MyParent()
    876         ...       def parent(self):
    877         ...           return self._parent
    878         ...       def __eq__(self, other):
    879         ...           return self._x^2 == other._x^2
    880         ...       def __hash__(self):
    881         ...           return hash(self._x^2)
    882         ...       def __repr__(self):
    883         ...           return 'My %s'%self._x
    884         ...       @cached_in_parent_method
    885         ...       def f(self):
    886         ...           return self._x^3
    887         ...
    888         sage: a = Foo(2)
    889         sage: a.f()
    890         8
    891         sage: a.f.get_cache()   #indirect doctest
    892         {(My 2, ((), ())): 8}
    893 
    894     Since the key for the cache depends on equality of
    895     the instances, we obtain *identical* result for
    896     *equal* instances - even though in this particular
    897     example the result of the method should be different
    898     for ``a`` and ``b``::
    899 
    900         sage: b = Foo(-2)
    901         sage: a is not b
    902         True
    903         sage: a == b
    904         True
    905         sage: b.f() is a.f()
    906         True
    907 
    908     Non-equal instances do not share the result of
    909     the cached method, but they do share the cache::
    910 
    911         sage: c = Foo(3)
    912         sage: c.f()
    913         27
    914         sage: c.f.get_cache() is a.f.get_cache() #indirect doctest
    915         True
    916 
    917     Note that the cache is also available as an
    918     attribute of the cached method, which speeds
    919     up internal computations::
    920 
    921         sage: a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c)
    922         True
     1839    For proper behavior, the method must be a pure function (no side
     1840    effects). If this decorator is used on a method, it will have
     1841    identical output on equal elements. This is since the element is
     1842    part of the hash key. Arguments to the method and the instance
     1843    it is assigned to must be hashable.
     1844
     1845    Examples can be found at :mod:`~sage.misc.cachefunc`.
     1846
    9231847    """
    924     def __init__(self, f):
     1848
     1849    def __init__(self, f, name=None):
    9251850        """
    9261851        Constructs a new method with cache stored in the parent of the instance.
    9271852
     
    9541879            sage: a.parent()._cache__element_f is a.f.cache
    9551880            True
    9561881        """
    957         self._cache_name = '_cache__' + 'element_' + f.__name__
    958         self._cachedfunc = CachedFunction(f, classmethod=True)
    959         self._argument_fix_to_pos = self._cachedfunc._argumentfixer.fix_to_pos
    960 
    961     def _get_instance_cache(self, inst):
     1882        self._cache_name = '_cache__' + 'element_' + (name or f.__name__)
     1883        self._cachedfunc = CachedFunction(f, classmethod=True, name=name)
     1884
     1885    cpdef dict _get_instance_cache(self, inst):
    9621886        """
    9631887        Returns the cache dictionary, which is stored in the parent.
    9641888
     
    10191943            True
    10201944
    10211945        """
     1946        if inst is None:
     1947            return {}
    10221948        try:
    1023             return inst.parent().__dict__.setdefault(self._cache_name, {})
     1949            P = inst.parent()
     1950            return P.__dict__.setdefault(self._cache_name, {})
    10241951        except AttributeError:
    1025             return {}
    1026 
    1027     def __get__(self, inst, cls=None):
     1952            pass
     1953        if not hasattr(P,'__cached_methods'):
     1954            raise TypeError, "The parent of this element does not allow attribute assignment\n    and does not descend from the Parent base class.\n    Can not use CachedInParentMethod."
     1955        if P.__cached_methods is None:
     1956            P.__cached_methods = {}
     1957        return (<dict>P.__cached_methods).setdefault(self._cache_name, {})
     1958
     1959    def __get__(self, inst, cls): #cls=None):
    10281960        """
    10291961        Get a CachedMethodCaller bound to this specific instance of
    10301962        the class of the cached-in-parent method.
    10311963        """
    10321964        Caller = CachedMethodCaller(self, inst, cache=self._get_instance_cache(inst), inst_in_key=True)
    10331965        try:
    1034             setattr(inst,self._cachedfunc.f.__name__, Caller)
     1966            setattr(inst,self._cachedfunc.__name__, Caller)
    10351967        except AttributeError:
    10361968            pass
    10371969        return Caller
     
    11742106            ((1,), (('a', 1),))
    11752107            ((1, 2), ())
    11762108        """
    1177         from sage.structure.sage_object import load
    1178 
    1179         for f in self.file_list():
    1180             if f[-9:] == '.key.sobj':
    1181                  yield load(f)
     2109        return self.keys().__iter__()
    11822110
    11832111    def keys(self):
    11842112        """
     
    11962124            sage: K.sort(); print K
    11972125            [((), ()), ((1,), (('a', 1),)), ((1, 2), ())]
    11982126        """
    1199         return [k for k in self]
     2127        cdef list K = []
     2128        from sage.structure.sage_object import load
     2129        for f in self.file_list():
     2130            if f[-9:] == '.key.sobj':
     2131                K.append(load(f))
     2132        return K
    12002133
    12012134    def _filename(self, key):
    12022135        """
     
    12182151            foo-1_2
    12192152        """
    12202153        a,k = key
    1221         kwdstr = '_'.join('%s-%s'%x for x in k)
    1222         argstr = '_'.join('%s'%x for x in a)
     2154        kwdstr = '_'.join(['%s-%s'%x for x in k])
     2155        argstr = '_'.join(['%s'%x for x in a])
    12232156        if kwdstr and argstr:
    12242157            keystr = kwdstr + '.' + argstr
    12252158        else:
     
    14252358        return DiskCachedFunction(f, self._dir, memory_cache = self._memory_cache)
    14262359
    14272360class ClearCacheOnPickle(object):
    1428     """
    1429     This class implements an appropriate __getstate__ method that
     2361    r"""
     2362    This class implements an appropriate ``__getstate__`` method that
    14302363    clears the cache of the methods (see @cached_method) before
    14312364    passing them on to the caller, typically the pickle and copy modules.
    14322365
    1433     The implemented __getstate__ method calls the __getstate__ methods
    1434     of classes later in the method resolution order. Therefore,
    1435     classes which wants this behaviour should inherit first from this
    1436     one.
     2366    The implemented ``__getstate__`` method calls the ``__getstate__``
     2367    methods of classes later in the method resolution
     2368    order. Therefore, classes which want this behaviour should inherit
     2369    first from this one.
     2370
     2371    EXAMPLE:
     2372
     2373    In the following example, we create a Python class that inherits
     2374    from multivariate polynomial ideals, but does not pickle cached
     2375    values.  We provide the definition in Cython, however, since
     2376    interactive Cython definitions provide introspection by trac
     2377    ticket #9976, whereas Python definitions don't.
     2378    ::
     2379
     2380        sage: P.<a,b,c,d> = QQ[]
     2381        sage: I = P*[a,b]
     2382        sage: classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle',
     2383        ...    'from sage.all import QQ',
     2384        ...    'P = QQ["a","b","c","d"]; I = P*[P.gen(0),P.gen(1)]',
     2385        ...    'class MyClass(ClearCacheOnPickle,I.__class__):',
     2386        ...    '    def __init__(self,ring,gens):',
     2387        ...    '        I.__class__.__init__(self,ring,gens)',
     2388        ...    '    def __getnewargs__(self):',
     2389        ...    '        return (self._Ideal_generic__ring,self._Ideal_generic__gens)']
     2390        sage: cython('\n'.join(classdef))
     2391
     2392    We destroy the cache of two methods of ``I`` on purpose
     2393    (demonstrating that the two different implementations of cached
     2394    methods are correctly dealt with).  Pickling ``I`` preserves the
     2395    cache::
     2396
     2397        sage: I.gens.set_cache('bar')
     2398        sage: I.groebner_basis.set_cache('foo',algorithm='singular')
     2399        sage: J = loads(dumps(I))
     2400        sage: J.gens()
     2401        'bar'
     2402        sage: J.groebner_basis(algorithm='singular')
     2403        'foo'
     2404
     2405    However, if we have an ideal that additionally descends from
     2406    :class:`ClearCacheOnPickle`, the carefully corrupted cache is not
     2407    pickled::
     2408
     2409        sage: A = MyClass(P,[a,b])
     2410        sage: A
     2411        Ideal (a, b) of Multivariate Polynomial Ring in a, b, c, d over Rational Field
     2412        sage: A.gens.set_cache('foo')
     2413        sage: A.groebner_basis.set_cache('bar',algorithm='singular')
     2414        sage: A.gens()
     2415        'foo'
     2416        sage: A.groebner_basis(algorithm='singular')
     2417        'bar'
     2418        sage: B = loads(dumps(A))
     2419        sage: B.gens()
     2420        [a, b]
     2421        sage: B.groebner_basis(algorithm='singular')
     2422        [a, b]
     2423        sage: A.gens()
     2424        'foo'
    14372425
    14382426    """
    14392427    def __getstate__(self):
     2428        r"""
     2429        The idea is to remove that might provide a cache to some cached method
     2430        from the return value of the ``__getstate__`` method.
     2431
     2432        EXAMPLE:
     2433
     2434        In the following example, we create a Python class that
     2435        inherits from multivariate polynomial ideals, but clears the
     2436        cache as well.
     2437
     2438            sage: P.<a,b,c,d> = QQ[]
     2439            sage: I = P*[a,b]
     2440
     2441        We destroy the cache of two methods if ``I`` on purpose
     2442        (demonstrating that the two different implementations of cached
     2443        methods are correctly dealt with).  Pickling ``I`` preserves the
     2444        cache::
     2445
     2446            sage: I.gens.set_cache('bar')
     2447            sage: I.groebner_basis.set_cache('foo',algorithm='singular')
     2448            sage: J = loads(dumps(I))
     2449            sage: J.gens()
     2450            'bar'
     2451            sage: J.groebner_basis(algorithm='singular')
     2452            'foo'
     2453
     2454        However, if we do the same with a class that additionally
     2455        descends from :class:`ClearCacheOnPickle`, the cache is not
     2456        pickled. We provide the definition in Cython, however, since
     2457        interactive Cython definitions provide introspection by trac
     2458        ticket #9976, whereas Python definitions don't.
     2459        ::
     2460
     2461            sage: classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle',
     2462            ...    'from sage.all import QQ',
     2463            ...    'from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal',
     2464            ...    'class MyClass(ClearCacheOnPickle,MPolynomialIdeal):',
     2465            ...    '    def __init__(self,ring,gens):',
     2466            ...    '        MPolynomialIdeal.__init__(self,ring,gens)',
     2467            ...    '    def __getnewargs__(self):',
     2468            ...    '        return (self._Ideal_generic__ring,self._Ideal_generic__gens)']
     2469            sage: cython('\n'.join(classdef))
     2470            sage: A = MyClass(P,[a,b])
     2471            sage: A
     2472            Ideal (a, b) of Multivariate Polynomial Ring in a, b, c, d over Rational Field
     2473            sage: A.gens.set_cache('foo')
     2474            sage: A.groebner_basis.set_cache('bar',algorithm='singular')
     2475            sage: A.gens()
     2476            'foo'
     2477            sage: A.groebner_basis(algorithm='singular')
     2478            'bar'
     2479            sage: B = loads(dumps(A))
     2480            sage: B.gens()
     2481            [a, b]
     2482            sage: B.groebner_basis(algorithm='singular')
     2483            [a, b]
     2484            sage: A.gens()
     2485            'foo'
     2486           
     2487        And here is why the example works::
     2488
     2489            sage: ST = I.__getstate__(); ST[0],sorted(ST[1].items())
     2490            (Monoid of ideals of Multivariate Polynomial Ring in a, b, c, d over Rational Field, [('_Ideal_generic__gens', (a, b)), ('_Ideal_generic__ring', Multivariate Polynomial Ring in a, b, c, d over Rational Field), ('_cache__groebner_basis', {(('singular', None, None, False), ()): 'foo'}), ('gens', Cached version of <function gens at 0x...>), ('groebner_basis', Cached version of <function groebner_basis at 0x...>)])
     2491            sage: ST = A.__getstate__(); ST[0],sorted(ST[1].items())
     2492            (Monoid of ideals of Multivariate Polynomial Ring in a, b, c, d over Rational Field, [('_Ideal_generic__gens', (a, b)), ('_Ideal_generic__ring', Multivariate Polynomial Ring in a, b, c, d over Rational Field)])
     2493
    14402494        """
    1441         """
    1442         return dict( (key, value) for (key, value) in super(ClearCacheOnPickle, self).__getstate__().iteritems() if not (type(key) == str and key[0:8] == '_cache__') )
     2495        OrigState = super(ClearCacheOnPickle, self).__getstate__()
     2496        def clear_list(T):
     2497            L = []
     2498            for x in T:
     2499                if isinstance(x,list):
     2500                    L.append(clear_list(x))
     2501                elif isinstance(x,tuple):
     2502                    L.append(clear_tuple(x))
     2503                elif isinstance(x,dict):
     2504                    L.append(clear_dict(x))
     2505                elif not isinstance(x,CachedFunction):
     2506                    L.append(x)
     2507            return L
     2508        def clear_tuple(T):
     2509            return tuple(clear_list(T))
     2510        def clear_dict(T):
     2511            D = {}
     2512            for key,value in T.iteritems():
     2513                if not ((type(key) == str and key[0:8] == '_cache__') or
     2514                            isinstance(value,CachedFunction)):
     2515                    if isinstance(value,list):
     2516                        D[key] = clear_list(value)
     2517                    elif isinstance(value,tuple):
     2518                        D[key] = clear_tuple(value)
     2519                    elif isinstance(value,dict):
     2520                        D[key] = clear_dict(value)
     2521                    else:
     2522                        D[key] = value
     2523            return D
     2524        if isinstance(OrigState,tuple):
     2525            return clear_tuple(OrigState)
     2526        if isinstance(OrigState,list):
     2527            return clear_list(OrigState)
     2528        if isinstance(OrigState,dict):
     2529            return clear_dict(OrigState)
     2530        return OrigState
  • sage/misc/function_mangling.pyx

    diff --git a/sage/misc/function_mangling.pyx b/sage/misc/function_mangling.pyx
    a b  
    109109        ...      def __init__(self, x = 1):
    110110        ...         self.x = x
    111111        sage: af = ArgumentFixer(one.__init__.im_func, classmethod=True)
    112         sage: af.fix_to_pos()
    113         ((1,), ())
    114         sage: af.fix_to_named()
    115         ((), (('x', 1),))
    116     """       
    117     cdef dict _defaults
    118     cdef int _ndefault, _nargs
    119     cdef tuple _arg_names
    120     cdef object f
    121     cdef bint _classmethod
    122     def __init__(self, f, classmethod = False):
    123         """
    124         INPUT:
    125 
    126         - ``f`` -- a function
    127         - ``classmethod`` (optional bool, default ``False``) --
    128           tells whether ``f`` is supposed to be a method of a class
    129 
    130         NOTE:
    131 
    132         Currently, we need to assume that ``f`` is a Python function, not
    133         a Cython function. This is since some essential arguments are not
    134         available from Cython functions.
    135 
    136         TESTS::
    137 
    138             sage: from sage.misc.function_mangling import ArgumentFixer
    139             sage: def f(a,b,m=1,n=2): return a*m+b*n
    140             sage: a = ArgumentFixer(f, classmethod=False)
    141             sage: a.fix_to_pos(a=31,b=2,n=3)
    142             ((31, 2, 1, 3), ())
    143             sage: a = ArgumentFixer(f, classmethod=True)
    144             sage: a.fix_to_pos(a=31,b=2,n=3)
    145             ((2, 1, 3), (('a', 31),))
     112        sage: af.fix_to_pos(1,2,3,a=31,b=2,n=3)
     113        ((1, 2, 3), (('a', 31), ('b', 2), ('n', 3)))
    146114
    147115        """
    148         defaults = f.func_defaults
     116
     117    cdef public object f
     118    cdef public int _ndefault
     119    cdef public int _nargs
     120    cdef tuple _arg_names
     121    cdef bint _classmethod
     122    cdef dict _defaults
     123    cdef public tuple _default_tuple
     124    def __init__(self, f, classmethod = False):
     125        from sage.misc.sageinspect import sage_getargspec
     126        arg_names, varargs, varkw, defaults = sage_getargspec(f)
    149127        if defaults is None:
    150             defaults = []
     128            self._default_tuple = defaults = ()
     129        else:
     130            self._default_tuple = tuple(defaults)
    151131
    152         code = f.func_code
     132        #code = f.func_code
    153133
    154134        self.f = f
    155135        self._ndefault = len(defaults)
    156136        if classmethod:
    157             self._nargs = code.co_argcount-1
    158             self._arg_names = code.co_varnames[1:self._nargs+1]
     137            self._nargs = len(arg_names)-1 #code.co_argcount-1
     138            self._arg_names = tuple(arg_names[1:]) #code.co_varnames[1:self._nargs+1]
    159139        else:
    160             self._nargs = code.co_argcount
    161             self._arg_names = code.co_varnames[:self._nargs]
     140            self._nargs = len(arg_names) #code.co_argcount
     141            self._arg_names = tuple(arg_names) #code.co_varnames[:self._nargs]
    162142        self._classmethod = classmethod
    163143
    164         default_map = {}
     144        cdef dict default_map
     145        self._defaults = default_map = {}
    165146        for k,v in zip(self._arg_names[-self._ndefault:], defaults):
    166147            default_map[k] = v
    167         self._defaults = default_map
    168148
    169149    def __repr__(self):
    170150        """
     
    248228            ARGS.append((k,kwargs_[k]))
    249229        return tuple(extra_args), tuple(ARGS)
    250230
    251     def fix_to_pos(self, *args, **kwargs):
     231    cpdef tuple defaults_to_pos(self, tuple Args):
     232        cdef int lenargs = len(Args)
     233        cdef int nargs = self._nargs
     234        if lenargs>=nargs:
     235            return Args, ()
     236        return Args+self._default_tuple[-nargs+lenargs:],()
     237
     238    def fix_to_pos(self, *args, **kwds):
    252239        """
    253240        Normalize the arguments with a preference for positional arguments.
    254241
    255242        INPUT:
    256243
    257         - any positional and named arguments.
     244        Any positional or named arguments
    258245
    259246        OUTPUT:
    260247
     
    264251 
    265252        where `n_1, ... , n_m` are the names of the arguments and
    266253        `v_1, ..., v_m` are the values passed in; and `e_1, ..., e_k`
    267         are the unnamed arguments.  We minimize `m`.
     254        are the unnamed arguments. We minimize `m`.
    268255
    269256        The commands
    270257        ::
     
    295282            sage: do_something(1,2,3,4,5,6,f=14,e=16)
    296283            1 2 3 (4, 5, 6) {'e': 16, 'f': 14}
    297284        """
     285        cdef tuple Args = args
     286        cdef dict kwargs = kwds
     287        cdef int lenargs = len(Args)
     288        cdef int nargs = self._nargs
     289        cdef tuple arg_names = self._arg_names
     290        cdef dict defaults = self._defaults
    298291        # a shortpath for the case of no named arguments:
    299292        if not kwargs:
     293            if lenargs>=nargs:
     294                return args, ()
    300295            # we take the given arguments, plus the default arguments
    301             return tuple(list(args)+[self._defaults[k] for k in self._arg_names[len(args):]]),()
    302         cdef tuple arg_names = self._arg_names
    303         cdef int lenargs = len(args)
    304         cdef list ARGS = []
    305         cdef dict defaults = self._defaults
    306         cdef dict kwargs_ = dict(kwargs)
     296            return Args+self._default_tuple[-nargs+lenargs:],() #tuple(list(Args)+[defaults[k] for k in arg_names[lenargs:]]),()
     297        cdef list Largs = list(Args)
    307298        cdef int i
    308         for i from 0<=i<self._nargs:
    309             if i >= lenargs:
    310                 name = arg_names[i]
    311                 if name in kwargs_:
    312                     val = kwargs_[name]
    313                     del kwargs_[name]
    314                 else:
    315                     val = defaults[name]
     299        for i from lenargs<=i<nargs:
     300        #for name,val in defaults.iteritems():
     301            # in addition to the positional arguments, we take the
     302            # ones with default values, unless they are overridded by
     303            # the named arguments.
     304            name = arg_names[i]
     305            if name in kwargs:
     306                val = kwargs[name]
     307                del kwargs[name]
    316308            else:
    317                 val = args[i]
    318             ARGS.append(val)
    319         ARGS+= args[self._nargs:]
    320         cdef list Items = kwargs_.items()
     309                val = defaults[name]
     310            Largs.append(val) #kwargs.pop(name,val))
     311        cdef list Items = kwargs.items()
    321312        Items.sort()
    322         return tuple(ARGS), tuple(Items) #(k,kwargs_[k]) for k in sorted(kwargs_.keys()))
     313        return tuple(Largs), tuple(Items) #(k,kwargs_[k]) for k in sorted(kwargs_.keys()))
    323314 
    324315
  • sage/misc/lazy_attribute.py

    diff --git a/sage/misc/lazy_attribute.py b/sage/misc/lazy_attribute.py
    a b  
    202202    second one brings up the code of this class, both being not very
    203203    useful.
    204204
    205     TESTS::
     205    TESTS:
    206206
    207207    .. rubric:: Partial support for old style classes
    208208
     
    301301        calculating x from y in B
    302302        1
    303303
    304     .. rubric:: lazy_attributes and cpdef functions
     304    .. rubric:: lazy_attributes and Cython
    305305
    306306    This attempts to check that lazy_attributes work with built-in
    307307    functions like cpdef methods::
     
    314314        sage: A().len
    315315        5
    316316
     317    Since #11115, extension classes derived from :class:`~sage.structure.parent.Parent`
     318    can inherit a lazy attribute, such as ``element_class``::
     319
     320        sage: cython_code = ["from sage.structure.parent cimport Parent",
     321        ... "from sage.structure.element cimport Element",
     322        ... "cdef class MyElement(Element): pass",
     323        ... "cdef class MyParent(Parent):",
     324        ... "    Element = MyElement"]
     325        sage: cython('\n'.join(cython_code))
     326        sage: P = MyParent(category=Rings())
     327        sage: P.element_class    # indirect doctest
     328        <type '...MyElement'>
     329
    317330    .. rubric:: About descriptor specifications
    318331
    319332    The specifications of descriptors (see 3.4.2.3 Invoking
     
    505518        """
    506519        if a is None: # when doing cls.x for cls a class and x a lazy attribute
    507520            return self
     521        try:
     522            # __cached_methods is supposed to be a public Cython attribute.
     523            # Apparently, these are *not* subject to name mangling.
     524            CM = getattr(a, '__cached_methods')
     525            if CM is None:
     526                CM = {}
     527                setattr(a, '__cached_methods', CM)
     528        except AttributeError,msg:
     529            CM = None
     530        if CM is not None:
     531            try:
     532                return CM[self.f.__name__]
     533            except KeyError:
     534                pass
    508535        result = self.f(a)
    509536        if result is NotImplemented:
    510537            # Workaround: we make sure that cls is the class
     
    515542                if self.f.__name__ in supercls.__dict__ and self is supercls.__dict__[self.f.__name__]:
    516543                    cls = supercls
    517544            return getattr(super(cls, a),self.f.__name__)
    518         setattr(a, self.f.__name__, result)
     545        try:
     546            setattr(a, self.f.__name__, result)
     547        except AttributeError:
     548            if CM is not None:
     549                CM[self.f.__name__] = result
     550                return result
     551            raise
    519552        return result
    520553
    521 
    522554class lazy_class_attribute(lazy_attribute):
    523555    """
    524556    A lazy class attribute for an class is like a usual class attribute,
  • sage/rings/ideal.py

    diff --git a/sage/rings/ideal.py b/sage/rings/ideal.py
    a b  
    3232import sage.rings.infinity
    3333from sage.structure.sequence import Sequence
    3434
    35 
    3635def Ideal(*args, **kwds):
    3736    r"""
    3837    Create the ideal in ring with given generators.
  • sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py

    diff --git a/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py b/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py
    a b  
    347347    def _Cartier_matrix_cached(self):
    348348        r"""
    349349        INPUT:
    350         - 'E' - Hyperelliptic Curve of the form `y^2 = f(x)` over a finite field, `\mathbb{F}_q`
     350
     351        - 'E' - Hyperelliptic Curve of the form `y^2 = f(x)` over a
     352          finite field, `\mathbb{F}_q`
    351353       
    352354        OUTPUT:
     355
    353356        - matrix(Fq,M)' The matrix $M = (c_(pi-j)), f(x)^((p-1)/2) = \sum c_i x^i$
    354357        - 'Coeff' List of Coeffs of F, this is needed for Hasse-Witt function.
    355358        - 'g' genus of the curve self, this is needed by a-number.
     
    564567            ValueError: so curve is not smooth
    565568
    566569        """
    567         #checking first that Cartier matrix is not already cached. Since it can be called by either Hasse_Witt or a_number
    568         #This way it does not matter which function is called first in the code.       
    569        
    570         A=self._Cartier_matrix_cached.get_cache()
    571         if len(A) !=0:
    572             if A.items()[-1][-1][-1]==self:
    573                 M,Coeffs,g, Fq, p,E = A.items()[-1][1];
    574             else:
    575                 A.clear()
    576                 M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
    577         else:
    578             A.clear()
    579             M, Coeffs,g, Fq, p, E = self._Cartier_matrix_cached()
     570        #checking first that Cartier matrix is not already cached. Since
     571        #it can be called by either Hasse_Witt or a_number.
     572        #This way it does not matter which function is called first
     573        #in the code.
     574        # Trac Ticket #11115: Why shall we waste time by studying
     575        # the cache manually? We only need to check whether the cached
     576        # data belong to self.
     577        M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
     578        if E!=self:
     579            self._Cartier_matrix_cached.clear_cache()
     580            M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
    580581        return M
    581582           
    582583    #This where Hasse_Witt is actually computed. This is either called by E.Hasse_Witt or p_rank
     
    643644        #is already computed it is stored in list A. If it was not cached (i.e. A is empty), we simply
    644645        #compute it. If it is cached then we need to make sure that we have the correct one. So check
    645646        #which curve does the matrix correspond to. Since caching stores a lot of stuff, we only check
    646         #the last entry in A. If it does not match, clear A and compute Cartier.     
    647         A=self._Cartier_matrix_cached.get_cache()
    648         if len(A) !=0:
    649             if A.items()[-1][-1][-1]==self:
    650                 M,Coeffs,g, Fq, p,E = A.items()[-1][1];
    651             else:
    652                 A.clear()
    653                 M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
    654         else:
    655             A.clear()
    656             M, Coeffs,g, Fq, p, E = self._Cartier_matrix_cached()
    657        
     647        #the last entry in A. If it does not match, clear A and compute Cartier.
     648        #
     649        #Since Trac Ticket #11115, there is a different cache for methods
     650        #that don't  accept arguments. Anyway, the easiest is to call
     651        #the cached method and simply see whether the data belong to self.
     652        M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
     653        if E!=self:
     654            self._Cartier_matrix_cached.clear_cache()
     655            M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
     656
    658657        #This compute the action of p^kth Frobenius  on list of coefficients       
    659658        def frob_mat(Coeffs, k):
    660659            a = p**k
     
    665664                mat.append(H);
    666665            return matrix(Fq,mat)
    667666   
    668        
    669    
    670667        #Computes all the different possible action of frobenius on matrix M and stores in list Mall       
    671668        Mall = [M] + [frob_mat(Coeffs,k) for k in range(1,g)]
    672669       
     
    727724
    728725       
    729726        """
    730         A=self._Hasse_Witt_cached.get_cache()
    731         if len(A) !=0:
    732             if A.items()[-1][-1][-1]==self:
    733                 N, E = A.items()[-1][1];
    734             else:
    735                 A.clear()
    736                 N, E= self._Hasse_Witt_cached()
    737         else:
    738             A.clear()
     727        # Since Trac Ticket #11115, there is a special
     728        # type of cached for those methods that don't
     729        # accept arguments. We want to get Hasse-Witt
     730        # from the cache - but apparently it could be
     731        # that the cached value does not belong to self.
     732        # So, the easiest is:
     733        N, E= self._Hasse_Witt_cached()
     734        if E!=self:
     735            self._Hasse_Witt_cached.clear_cache()
    739736            N, E= self._Hasse_Witt_cached()
    740737        return N
    741738
     
    775772        #compute it. If it is cached then we need to make sure that we have the correct one. So check
    776773        #which curve does the matrix correspond to. Since caching stores a lot of stuff, we only check
    777774        #the last entry in A. If it does not match, clear A and compute Cartier.     
    778 
    779         A=self._Cartier_matrix_cached.get_cache()
    780         if len(A) !=0:
    781             if A.items()[-1][-1][-1]==self:
    782                 M,Coeffs,g, Fq, p,E = A.items()[-1][1];
    783             else:
    784                 A.clear()
    785                 M,Coeffs,g, Fq, p,E= self._Cartier_matrix_cached()
    786         else:
    787             A.clear()
     775        # Since Trac Ticket #11115, there is a special cache for methods
     776        # that don't accept arguments. The easiest is: Call the cached
     777        # method, and test whether the last entry is self.
     778        M,Coeffs,g, Fq, p,E= self._Cartier_matrix_cached()
     779        if E != self:
     780            self._Cartier_matrix_cached.clear_cache()
    788781            M,Coeffs,g, Fq, p,E= self._Cartier_matrix_cached()
    789 
    790782        a=g-rank(M);
    791783        return a;
     784
    792785    def p_rank(self):
    793786        r"""
    794787        INPUT:
     
    816809            sage: E=HyperellipticCurve(x^29+1,0)
    817810            sage: E.p_rank()
    818811            0
    819 
    820 
    821 
    822      
    823812        """
    824813        #We use caching here since Hasse Witt is needed to compute p_rank. So if the Hasse Witt
    825814        #is already computed it is stored in list A. If it was not cached (i.e. A is empty), we simply
    826815        #compute it. If it is cached then we need to make sure that we have the correct one. So check
    827816        #which curve does the matrix correspond to. Since caching stores a lot of stuff, we only check
    828         #the last entry in A. If it does not match, clear A and compute Hasse Witt.     
    829        
    830         A=self._Hasse_Witt_cached.get_cache()
    831         if len(A) !=0:
    832             if A.items()[-1][-1][-1]==self:
    833                 N,E = A.items()[-1][1];
    834             else:
    835                 A.clear()
    836                 N,E= self._Hasse_Witt_cached()
    837         else:
    838             A.clear()
     817        #the last entry in A. If it does not match, clear A and compute Hasse Witt.
     818        # However, it seems a waste of time to manually analyse the cache
     819        # -- See Trac Ticket #11115
     820        N,E= self._Hasse_Witt_cached()
     821        if E!=self:
     822            self._Hasse_Witt_cached.clear_cache()
    839823            N,E= self._Hasse_Witt_cached()
    840 
    841 
    842        
    843824        pr=rank(N);
    844825        return pr
    845826       
  • sage/structure/element.pxd

    diff --git a/sage/structure/element.pxd b/sage/structure/element.pxd
    a b  
    2323    cpdef _act_on_(self, x, bint self_on_left)
    2424    cpdef _acted_upon_(self, x, bint self_on_left)
    2525   
    26    
     26cdef class ElementWithCachedMethod(Element):
     27    cdef public dict __cached_methods
     28
    2729cdef class ModuleElement(Element)       # forward declaration
    2830
    2931cdef class RingElement(ModuleElement)   # forward declaration
  • sage/structure/element.pyx

    diff --git a/sage/structure/element.pyx b/sage/structure/element.pyx
    a b  
    5050
    5151            MonoidElement
    5252                MultiplicativeGroupElement
     53        ElementWithCachedMethod
    5354
    5455
    5556How to Define a New Element Class
     
    959960    """
    960961    return IS_INSTANCE(x, ModuleElement)
    961962
     963cdef class ElementWithCachedMethod(Element):
     964    r"""
     965    An element class that fully supports cached methods.
     966
     967    NOTE:
     968
     969    The :class:`~sage.misc.cachefunc.cached_method` decorator provides
     970    a convenient way to automatically cache the result of a computation.
     971    Since trac ticket #11115, the cached method decorator applied to a
     972    method without optional arguments is faster than a hand-written cache
     973    in Python, and a cached method without any arguments (except ``self``)
     974    is actually faster than a Python method that does nothing more but
     975    to return ``1``. A cached method can also be inherited from the parent
     976    or element class of a category.
     977
     978    However, this holds true only if attribute assignment is supported.
     979    If you write an extension class in Cython that does not accept attribute
     980    assignment then a cached method inherited from the category will be
     981    slower (for :class:`~sage.structure.parent.Parent`) or the cache would
     982    even break (for :class:`Element`).
     983
     984    This class should be used if you write an element class, can not provide
     985    it with attribute assignment, but want that it inherits a cached method
     986    from the category. Under these conditions, your class should inherit
     987    from this class rather than :class:`Element`. Then, the cache will work,
     988    but certainly slower than with attribute assignment. Lazy attributes
     989    work as well.
     990
     991    EXAMPLE:
     992
     993    We define three element extension classes. The first inherits from
     994    :class:`Element`, the second from this class, and the third simply
     995    is a Python class. We also define a parent class and, in Python, a
     996    category whose element and parent classes define cached methods.
     997    ::
     998
     999        sage: cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod",
     1000        ... "cdef class MyBrokenElement(Element):",
     1001        ... "    cdef public object x",
     1002        ... "    def __init__(self,P,x):",
     1003        ... "        self.x=x",
     1004        ... "        Element.__init__(self,P)",
     1005        ... "    def __neg__(self):",
     1006        ... "        return MyBrokenElement(self.parent(),-self.x)",
     1007        ... "    def _repr_(self):",
     1008        ... "        return '<%s>'%self.x",
     1009        ... "    def __hash__(self):",
     1010        ... "        return hash(self.x)",
     1011        ... "    def __cmp__(left, right):",
     1012        ... "        return (<Element>left)._cmp(right)",
     1013        ... "    def __richcmp__(left, right, op):",
     1014        ... "        return (<Element>left)._richcmp(right,op)",
     1015        ... "    cdef int _cmp_c_impl(left, Element right) except -2:",
     1016        ... "        return cmp(left.x,right.x)",
     1017        ... "    def raw_test(self):",
     1018        ... "        return -self",
     1019        ... "cdef class MyElement(ElementWithCachedMethod):",
     1020        ... "    cdef public object x",
     1021        ... "    def __init__(self,P,x):",
     1022        ... "        self.x=x",
     1023        ... "        Element.__init__(self,P)",
     1024        ... "    def __neg__(self):",
     1025        ... "        return MyElement(self.parent(),-self.x)",
     1026        ... "    def _repr_(self):",
     1027        ... "        return '<%s>'%self.x",
     1028        ... "    def __hash__(self):",
     1029        ... "        return hash(self.x)",
     1030        ... "    def __cmp__(left, right):",
     1031        ... "        return (<Element>left)._cmp(right)",
     1032        ... "    def __richcmp__(left, right, op):",
     1033        ... "        return (<Element>left)._richcmp(right,op)",
     1034        ... "    cdef int _cmp_c_impl(left, Element right) except -2:",
     1035        ... "        return cmp(left.x,right.x)",
     1036        ... "    def raw_test(self):",
     1037        ... "        return -self",
     1038        ... "class MyPythonElement(MyBrokenElement): pass",
     1039        ... "from sage.structure.parent cimport Parent",
     1040        ... "cdef class MyParent(Parent):",
     1041        ... "    Element = MyElement"]
     1042        sage: cython('\n'.join(cython_code))
     1043        sage: cython_code = ["from sage.all import cached_method, cached_in_parent_method, Category",
     1044        ... "class MyCategory(Category):",
     1045        ... "    @cached_method",
     1046        ... "    def super_categories(self):",
     1047        ... "        return [Objects()]",
     1048        ... "    class ElementMethods:",
     1049        ... "        @cached_method",
     1050        ... "        def element_cache_test(self):",
     1051        ... "            return -self",
     1052        ... "        @cached_in_parent_method",
     1053        ... "        def element_via_parent_test(self):",
     1054        ... "            return -self",
     1055        ... "    class ParentMethods:",
     1056        ... "        @cached_method",
     1057        ... "        def one(self):",
     1058        ... "            return self.element_class(self,1)",
     1059        ... "        @cached_method",
     1060        ... "        def invert(self, x):",
     1061        ... "            return -x"]
     1062        sage: cython('\n'.join(cython_code))
     1063        sage: C = MyCategory()
     1064        sage: P = MyParent(category=C)
     1065        sage: ebroken = MyBrokenElement(P,5)
     1066        sage: e = MyElement(P,5)
     1067
     1068    The cached methods inherited by ``MyElement`` works::
     1069
     1070        sage: e.element_cache_test()
     1071        <-5>
     1072        sage: e.element_cache_test() is e.element_cache_test()
     1073        True
     1074        sage: e.element_via_parent_test()
     1075        <-5>
     1076        sage: e.element_via_parent_test() is e.element_via_parent_test()
     1077        True
     1078
     1079    The other element class can only inherit a
     1080    ``cached_in_parent_method``, since the cache is stored in the
     1081    parent. In fact, equal elements share the cache, even if they are
     1082    of different types::
     1083
     1084        sage: e == ebroken
     1085        True
     1086        sage: type(e) == type(ebroken)
     1087        False
     1088        sage: ebroken.element_via_parent_test() is e.element_via_parent_test()
     1089        True
     1090
     1091    However, the cache of the other inherited method breaks, although the method
     1092    as such works::
     1093
     1094        sage: ebroken.element_cache_test()
     1095        <-5>
     1096        sage: ebroken.element_cache_test() is ebroken.element_cache_test()
     1097        False
     1098
     1099    Since ``e`` and ``ebroken`` share the cache, when we empty it for one element
     1100    it is empty for the other as well::
     1101
     1102        sage: b = ebroken.element_via_parent_test()
     1103        sage: e.element_via_parent_test.clear_cache()
     1104        sage: b is ebroken.element_via_parent_test()
     1105        False
     1106
     1107    Note that the cache only breaks for elements that do no allow attribute assignment.
     1108    A Python version of ``MyBrokenElement`` therefore allows for cached methods::
     1109
     1110        sage: epython = MyPythonElement(P,5)
     1111        sage: epython.element_cache_test()
     1112        <-5>
     1113        sage: epython.element_cache_test() is epython.element_cache_test()
     1114        True
     1115
     1116    """
     1117    def __getattr__(self, name):
     1118        """
     1119        This getattr method ensures that cached methods and lazy attributes
     1120        can be inherited from the element class of a category.
     1121
     1122        NOTE:
     1123
     1124        The use of cached methods is demonstrated in the main doc string of
     1125        this class. Here, we demonstrate lazy attributes.
     1126
     1127        EXAMPLE::
     1128
     1129            sage: cython_code = ["from sage.structure.element cimport ElementWithCachedMethod",
     1130            ... "cdef class MyElement(ElementWithCachedMethod):",
     1131            ... "    cdef public object x",
     1132            ... "    def __init__(self,P,x):",
     1133            ... "        self.x=x",
     1134            ... "        ElementWithCachedMethod.__init__(self,P)",
     1135            ... "    def _repr_(self):",
     1136            ... "        return '<%s>'%self.x",
     1137            ... "from sage.structure.parent cimport Parent",
     1138            ... "cdef class MyParent(Parent):",
     1139            ... "    Element = MyElement",
     1140            ... "from sage.all import cached_method, lazy_attribute, Category",
     1141            ... "class MyCategory(Category):",
     1142            ... "    @cached_method",
     1143            ... "    def super_categories(self):",
     1144            ... "        return [Objects()]",
     1145            ... "    class ElementMethods:",
     1146            ... "        @lazy_attribute",
     1147            ... "        def my_lazy_attr(self):",
     1148            ... "            return 'lazy attribute of <%d>'%self.x"]
     1149            sage: cython('\n'.join(cython_code))
     1150            sage: C = MyCategory()
     1151            sage: P = MyParent(category=C)
     1152            sage: e = MyElement(P,5)
     1153            sage: e.my_lazy_attr
     1154            'lazy attribute of <5>'
     1155            sage: e.my_lazy_attr is e.my_lazy_attr
     1156            True
     1157
     1158        """
     1159        if name.startswith('__') and not name.endswith('_'):
     1160            raise AttributeError, AttributeErrorMessage(self, name)
     1161        try:
     1162            return self.__cached_methods[name]
     1163        except KeyError:
     1164            attr = getattr_from_other_class(self,
     1165                                        self._parent.category().element_class,
     1166                                        name)
     1167            self.__cached_methods[name] = attr
     1168            return attr
     1169        except TypeError:
     1170            attr = getattr_from_other_class(self,
     1171                                        self._parent.category().element_class,
     1172                                        name)
     1173            self.__cached_methods = {name : attr}
     1174            return attr
    9621175
    9631176cdef class ModuleElement(Element):
    9641177    """
    9651178    Generic element of a module.
    9661179    """
    967    
     1180
    9681181    ##################################################
    9691182    # Addition
    9701183    ##################################################   
  • sage/structure/parent.pxd

    diff --git a/sage/structure/parent.pxd b/sage/structure/parent.pxd
    a b  
    1717    cdef public _element_constructor
    1818    cdef public _convert_method_name
    1919    cdef public bint _element_init_pass_parent
     20    cdef public dict __cached_methods
    2021    cdef public _initial_coerce_list
    2122    cdef public _initial_action_list
    2223    cdef public _initial_convert_list
  • sage/structure/parent.pyx

    diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
    a b  
    262262        sage: getattr_from_other_class(1, A, "inc")()
    263263        2
    264264
    265     Caveat: lazy attributes don't work currently with extension types,
    266     with or without a __dict__:
     265    Caveat: lazy attributes work with extension types only
     266    if they allow attribute assignment or have a public attribute
     267    ``__cached_methods`` of type ``<dict>``. This condition
     268    is satisfied, e.g., by any class that is derived from
     269    :class:`Parent`::
    267270
    268271        sage: getattr_from_other_class(1, A, "lazy_attribute")
    269272        Traceback (most recent call last):
    270273        ...
    271274        AttributeError: 'sage.rings.integer.Integer' object has no attribute 'lazy_attribute'
     275
     276    The integer ring is a parent, so, lazy attributes work::
     277
    272278        sage: getattr_from_other_class(ZZ, A, "lazy_attribute")
    273         Traceback (most recent call last):
    274         ...
    275         AttributeError: 'sage.rings.integer_ring.IntegerRing_class' object has no attribute 'lazy_attribute'
     279        'Integer Ring'
    276280        sage: getattr_from_other_class(PolynomialRing(QQ, name='x', sparse=True).one(), A, "lazy_attribute")
    277281        '1'
    278282        sage: getattr_from_other_class(PolynomialRing(QQ, name='x', implementation="FLINT").one(), A, "lazy_attribute")
     
    283287    In general, descriptors are not yet well supported, because they
    284288    often do not accept to be cheated with the type of their instance::
    285289
    286 
    287290        sage: A.__weakref__.__get__(1)
    288291        Traceback (most recent call last):
    289292        ...
     
    810813        """
    811814        if (name.startswith('__') and not name.endswith('_')) or self._category is None:
    812815            raise AttributeError, AttributeErrorMessage(self, name)
    813         return getattr_from_other_class(self, self._category.parent_class, name)
     816        try:
     817            return self.__cached_methods[name]
     818        except KeyError:
     819            attr = getattr_from_other_class(self, self._category.parent_class, name)
     820            self.__cached_methods[name] = attr
     821            return attr
     822        except TypeError:
     823            attr = getattr_from_other_class(self, self._category.parent_class, name)
     824            self.__cached_methods = {name:attr}
     825            return attr
    814826
    815827    def __dir__(self):
    816828        """
  • sage/structure/parent_old.pyx

    diff --git a/sage/structure/parent_old.pyx b/sage/structure/parent_old.pyx
    a b  
    9696   
    9797    cpdef coerce_map_from_c(self, S):
    9898        """
    99         EXAMPLES:
    100           Check to make sure that we handle coerce maps from Python native types
    101           correctly.
     99        EXAMPLES::
     100
     101        Check to make sure that we handle coerce maps from Python
     102        native types correctly::
     103
    102104            sage: QQ['q,t'].coerce_map_from(int)
    103105            Composite map:
    104106              From: Set of Python objects of type 'int'