Ticket #11115: trac11115-cached_cython.patch

File trac11115-cached_cython.patch, 148.5 KB (added by SimonKing, 5 years ago)

Cythonized cached_method: Usable in Cython code, faster than handwritten Python cache. Special case for methods w/o arguments. Make ClearCacheOnPickle? usable. Lazy attributes

  • module_list.py

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1305526656 -7200
    # Node ID 1be94e1beaae845273fa8b6363e86be660222c9f
    # Parent  9ef16f06aa8195b4bf587c9ebee85f3b2ba4f8b9
    #11115: 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
    
    diff --git a/module_list.py b/module_list.py
    a b  
    997997    Extension('sage.misc.bitset',
    998998              sources = ['sage/misc/bitset.pyx']),
    999999
     1000    Extension('sage.misc.cachefunc',
     1001              sources = ['sage/misc/cachefunc.pyx']),
     1002
    10001003    Extension('sage.misc.citation',
    10011004              sources = ['sage/misc/citation.pyx']),
    10021005
  • 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
  • deleted file sage/misc/cachefunc.py

    diff --git a/sage/misc/cachefunc.py b/sage/misc/cachefunc.py
    deleted file mode 100644
    + -  
    1 """
    2 Cached Functions and Methods
    3 
    4 AUTHORS:
    5 
    6 - William Stein (inspired by conversation with Justin Walker).
    7 - Mike Hansen (added doctests and made it work with class methods).
    8 - Willem Jan Palenstijn (add CachedMethodCaller for binding cached
    9   methods to instances).
    10 - Tom Boothby (added DiskCachedFunction).
    11 - Simon King (improved performance, more doctests).
    12 
    13 """
    14 ########################################################################
    15 #       Copyright (C) 2008 William Stein <wstein@gmail.com>
    16 #                          Mike Hansen <mhansen@gmail.com>
    17 #
    18 #  Distributed under the terms of the GNU General Public License (GPL)
    19 #
    20 #                  http://www.gnu.org/licenses/
    21 ########################################################################
    22 from function_mangling import ArgumentFixer
    23 import os
    24 
    25 class CachedFunction(object):
    26     """
    27     Create a cached version of a function, which only recomputes
    28     values it hasn't already computed. Synonyme: ``cached_function``
    29 
    30     If ``f`` is a function, do either ``g = CachedFunction(f)``
    31     or ``g = cached_function(f)`` to make a cached version of ``f``,
    32     or put ``@cached_function`` right before the definition of ``f``
    33     (i.e., use Python decorators)::
    34 
    35         @cached_function
    36         def f(...):
    37             ....
    38 
    39     The inputs to the function must be hashable.
    40 
    41     EXAMPLES::
    42 
    43         sage: @cached_function
    44         ... def mul(x, y=2):
    45         ...     return x*y
    46         ...
    47         sage: mul(3)
    48         6
    49 
    50     We demonstrate that the result is cached, and that, moreover,
    51     the cache takes into account the various ways of providing
    52     default arguments::
    53 
    54         sage: mul(3) is mul(3,2)
    55         True
    56         sage: mul(3,y=2) is mul(3,2)
    57         True
    58 
    59     The user can clear the cache::
    60 
    61         sage: a = mul(4)
    62         sage: mul.clear_cache()
    63         sage: a is mul(4)
    64         False
    65 
    66     It is also possible to explicitly override the cache with
    67     a different value::
    68 
    69         sage: mul.set_cache('foo',5)
    70         sage: mul(5,2)
    71         'foo'
    72 
    73     """
    74     def __init__(self, f, classmethod=False):
    75         """
    76         Create a cached version of a function, which only recomputes
    77         values it hasn't already computed.
    78 
    79         If f is a function, do either g = CachedFunction(f) to make
    80         a cached version of f, or put @CachedFunction right before
    81         the definition of f (i.e., use Python decorators)::
    82 
    83             @CachedFunction
    84             def f(...):
    85                 ....
    86 
    87         The inputs to the function must be hashable.
    88 
    89         TESTS::
    90 
    91             sage: g = CachedFunction(number_of_partitions)
    92             sage: g.__name__
    93             'number_of_partitions'
    94             sage: 'partitions' in g.__doc__
    95             True
    96             sage: g(5)
    97             7
    98             sage: g.cache
    99             {((5, None, 'default'), ()): 7}
    100             sage: def f(t=1): print(t)
    101             sage: h = CachedFunction(f)
    102             sage: w = walltime()
    103             sage: h(); h(1); h(t=1)
    104             1
    105             sage: walltime(w) < 2
    106             True
    107 
    108         """
    109         self._common_init(f, ArgumentFixer(f,classmethod=classmethod))
    110         self.cache = {}
    111 
    112     def _common_init(self, f, argumentfixer):
    113         """
    114         Perform initialization common to CachedFunction and CachedMethodCaller.
    115 
    116         TESTS::
    117 
    118             sage: @cached_function
    119             ... def test_cache(x):
    120             ...     return -x
    121             sage: hasattr(test_cache, '_argumentfixer')  # indirect doctest
    122             True
    123         """
    124         self.f = f
    125         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
    131 
    132     def _sage_src_(self):
    133         """
    134         Returns the source code for the wrapped function.
    135 
    136         TESTS::
    137 
    138             sage: from sage.misc.sageinspect import sage_getsource
    139             sage: g = CachedFunction(number_of_partitions)
    140             sage: 'bober' in sage_getsource(g)  # indirect doctest
    141             True
    142 
    143         """
    144         from sage.misc.sageinspect import sage_getsource
    145         return sage_getsource(self.f)
    146 
    147     def __call__(self, *args, **kwds):
    148         """
    149         Return value from cache or call the wrapped function,
    150         caching the output.
    151 
    152         TESTS::
    153 
    154             sage: g = CachedFunction(number_of_partitions)
    155             sage: a = g(5)
    156             sage: g.get_cache()
    157             {((5, None, 'default'), ()): 7}
    158             sage: a = g(10^5)
    159             sage: a == number_of_partitions(10^5)
    160             True
    161             sage: a is g(10^5)
    162             True
    163             sage: a is number_of_partitions(10^5)
    164             False
    165 
    166         """
    167         # We shortcut a common case of no arguments
    168         if args or kwds:
    169             k = self._argumentfixer.fix_to_pos(*args, **kwds)
    170         else:
    171             try:
    172                 k = self._default_key
    173             except AttributeError:
    174                 k = self._default_key = self._argumentfixer.fix_to_pos()
    175         try:
    176             return self.cache[k]
    177         except KeyError:
    178             w = self.f(*args, **kwds)
    179             self.cache[k] = w
    180             return w
    181 
    182     def get_cache(self):
    183         """
    184         Returns the cache dictionary.
    185 
    186         EXAMPLES::
    187 
    188             sage: g = CachedFunction(number_of_partitions)
    189             sage: a = g(5)
    190             sage: g.get_cache()
    191             {((5, None, 'default'), ()): 7}
    192 
    193         """
    194         return self.cache
    195 
    196     def is_in_cache(self, *args, **kwds):
    197         """
    198         Checks if the argument list is in the cache.
    199 
    200         EXAMPLES::
    201 
    202             sage: class Foo:
    203             ...       def __init__(self, x):
    204             ...           self._x = x
    205             ...       @cached_method
    206             ...       def f(self, z, y=0):
    207             ...           return self._x*z+y
    208             ...
    209             sage: a = Foo(2)
    210             sage: a.f.is_in_cache(3)
    211             False
    212             sage: a.f(3)
    213             6
    214             sage: a.f.is_in_cache(3,y=0)
    215             True
    216         """
    217         return self._argumentfixer.fix_to_pos(*args, **kwds) in self.cache
    218 
    219     def set_cache(self, value, *args, **kwds):
    220         """
    221         Set the value for those args and keyword args
    222         Mind the unintuitive syntax (value first).
    223         Any idea on how to improve that welcome!
    224 
    225         EXAMPLES::
    226 
    227             sage: g = CachedFunction(number_of_partitions)
    228             sage: a = g(5)
    229             sage: g.get_cache()
    230             {((5, None, 'default'), ()): 7}
    231             sage: g.set_cache(17, 5)
    232             sage: g.get_cache()
    233             {((5, None, 'default'), ()): 17}
    234             sage: g(5)
    235             17
    236 
    237         DEVELOPER NOTE:
    238 
    239         Is there a way to use the following intuitive syntax?
    240 
    241         ::
    242 
    243             sage: g(5) = 19    # todo: not implemented
    244             sage: g(5)         # todo: not implemented
    245             19
    246         """
    247         self.cache[self._argumentfixer.fix_to_pos(*args, **kwds)] = value
    248 
    249     def get_key(self, *args, **kwds):
    250         """
    251         Returns the key in the cache to be used when args
    252         and kwds are passed in as parameters.
    253 
    254         EXAMPLES::
    255 
    256             sage: @cached_function
    257             ... def foo(x):
    258             ...    return x^2
    259             ...
    260             sage: foo(2)
    261             4
    262             sage: foo.get_key(2)
    263             ((2,), ())
    264             sage: foo.get_key(x=3)
    265             ((3,), ())
    266         """
    267         return self._argumentfixer.fix_to_pos(*args, **kwds)
    268 
    269     def __repr__(self):
    270         """
    271         EXAMPLES::
    272 
    273             sage: g = CachedFunction(number_of_partitions)
    274             sage: g
    275             Cached version of <function number_of_partitions at 0x...>
    276         """
    277         try:
    278             return "Cached version of %s"%self.f
    279         except AttributeError:
    280             return "Cached version of a method (pending reassignment)"
    281 
    282     def clear_cache(self):
    283         """
    284         Clear the cache dictionary.
    285 
    286         EXAMPLES::
    287 
    288             sage: g = CachedFunction(number_of_partitions)
    289             sage: a = g(5)
    290             sage: g.get_cache()
    291             {((5, None, 'default'), ()): 7}
    292             sage: g.clear_cache()
    293             sage: g.get_cache()
    294             {}
    295         """
    296         cache = self.cache
    297         for key in cache.keys():
    298             del cache[key]
    299 
    300     def precompute(self, arglist, num_processes=1):
    301         """
    302 
    303         Cache values for a number of inputs.  Do the computation
    304         in parallel, and only bother to compute values that we
    305         haven't already cached.
    306 
    307         EXAMPLES::
    308 
    309             sage: @cached_function
    310             ... def oddprime_factors(n):
    311             ...     l = [p for p,e in factor(n) if p != 2]
    312             ...     return len(l)
    313             sage: oddprime_factors.precompute(range(1,100), 4)
    314             sage: oddprime_factors(25) is oddprime_factors(25)
    315             True
    316         """
    317         from sage.parallel.decorate import parallel, normalize_input
    318         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]))
    322         arglist = filter(new, map(normalize_input, arglist))
    323         for ((args,kwargs), val) in P(arglist):
    324             self.set_cache(val, *args, **kwargs)
    325 
    326 
    327 cached_function = CachedFunction
    328 
    329 class CachedMethodPickle:
    330     """
    331     This class helps to unpickle cached methods.
    332 
    333     NOTE:
    334 
    335     Since trac ticket #8611, a cached method is an attribute
    336     of the instance (provided that it has a ``__dict__``).
    337     Hence, when pickling the instance, it would be attempted
    338     to pickle that attribute as well, but this is a problem,
    339     since functions can not be pickled, currently. Therefore,
    340     we replace the actual cached method by a place holder,
    341     that kills itself as soon as any attribute is requested.
    342     Then, the original cached attribute is reinstated.
    343 
    344     EXAMPLE::
    345 
    346         sage: R.<x, y, z> = PolynomialRing(QQ, 3)
    347         sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
    348         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]
    350         sage: I.groebner_basis
    351         Cached version of <function groebner_basis at 0x...>
    352 
    353     We now pickle and unpickle the ideal. The cached method
    354     ``groebner_basis`` is replaced by a placeholder::
    355 
    356         sage: J = loads(dumps(I))
    357         sage: J.groebner_basis
    358         Pickle of the cached method "groebner_basis"
    359 
    360     But as soon as any other attribute is requested from the
    361     placeholder, it replaces itself by the cached method, and
    362     the entries of the cache are actually preserved::
    363 
    364         sage: J.groebner_basis.is_in_cache()
    365         True
    366         sage: J.groebner_basis
    367         Cached version of <function groebner_basis at 0x...>
    368         sage: J.groebner_basis() == I.groebner_basis()
    369         True
    370 
    371     AUTHOR:
    372 
    373     - Simon King (2011-01)
    374     """
    375     def __init__(self, inst, name):
    376         """
    377         INPUT:
    378 
    379         - ``inst`` - some instance.
    380         - ``name`` (string) - usually the name of an attribute
    381           of ``inst`` to which ``self`` is assigned.
    382 
    383         TEST::
    384 
    385             sage: from sage.misc.cachefunc import CachedMethodPickle
    386             sage: P = CachedMethodPickle(1, 'foo')
    387             sage: P
    388             Pickle of the cached method "foo"
    389 
    390         """
    391         self._instance = inst
    392         self._name = name
    393     def __repr__(self):
    394         """
    395         TEST::
    396 
    397             sage: R.<x, y, z> = PolynomialRing(QQ, 3)
    398             sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
    399             sage: G = I.groebner_basis()
    400             sage: J = loads(dumps(I))
    401             sage: J.groebner_basis  #indirect doctest
    402             Pickle of the cached method "groebner_basis"
    403         """
    404         return 'Pickle of the cached method "%s"'%self._name
    405     def __getattr__(self,s):
    406         """
    407         TEST::
    408 
    409             sage: R.<x, y, z> = PolynomialRing(QQ, 3)
    410             sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
    411             sage: G = I.groebner_basis()
    412             sage: J = loads(dumps(I))
    413             sage: J.groebner_basis
    414             Pickle of the cached method "groebner_basis"
    415 
    416         If an attribute of name ``s`` is requested (say,
    417         ``is_in_cache``), the attribute ``self._name`` of
    418         ``self._instance`` is deleted. Then, the attribute
    419         of name ``s`` of the attribute ``self._name`` of
    420         ``self._instance`` is requested. Since ``self._name``
    421         is a cached method defined for the class of
    422         ``self._instance``, retrieving the just-deleted
    423         attribute ``self._name`` succeeds.
    424 
    425         In that way, the unpickling of the cached method is
    426         finally accomplished::
    427 
    428             sage: J.groebner_basis.is_in_cache()  #indirect doctest
    429             True
    430             sage: J.groebner_basis
    431             Cached version of <function groebner_basis at 0x...>
    432 
    433         """
    434         self._instance.__dict__.__delitem__(self._name)
    435         return getattr(getattr(self._instance,self._name),s)
    436 
    437 class CachedMethodCaller(CachedFunction):
    438     """
    439     Utility class that is used by :class:`CachedMethod` to bind a
    440     cached method to an instance.
    441 
    442     EXAMPLE::
    443 
    444         sage: class A:
    445         ...    @cached_method
    446         ...    def bar(self,x):
    447         ...        return x^2
    448         sage: a = A()
    449         sage: a.bar
    450         Cached version of <function bar at 0x...>
    451         sage: type(a.bar)
    452         <class 'sage.misc.cachefunc.CachedMethodCaller'>
    453         sage: a.bar(2) is a.bar(x=2)
    454         True
    455 
    456     """
    457     def __init__(self, cachedmethod, inst, cache=None, inst_in_key=False):
    458         """
    459         EXAMPLES::
    460 
    461             sage: class Foo:
    462             ...       def __init__(self, x):
    463             ...           self._x = x
    464             ...       @cached_method
    465             ...       def f(self):
    466             ...           return self._x^2
    467             ...
    468             sage: a = Foo(2)
    469             sage: a.f.get_cache()
    470             {}
    471             sage: a.f()
    472             4
    473             sage: a.f.get_cache()
    474             {((), ()): 4}
    475         """
    476         # initialize CachedFunction, but re-use the ArgumentFixer
    477         self._common_init(cachedmethod._cachedfunc.f, cachedmethod._cachedfunc._argumentfixer)
    478         self.cache = {} if cache is None else cache
    479         self._instance = inst
    480         self._inst_in_key = inst_in_key
    481         self._cachedmethod = cachedmethod
    482 
    483     def __reduce__(self):
    484         """
    485         The pickle of a :class:`CachedMethodCaller` unpickles
    486         to a :class:`CachedMethodPickle`, that is able to replace
    487         itself by a copy of the original :class:`CachedMethodCaller`.
    488 
    489         TEST::
    490 
    491             sage: R.<x, y, z> = PolynomialRing(QQ, 3)
    492             sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
    493             sage: G = I.groebner_basis()
    494             sage: J = loads(dumps(I))  #indirect doctest
    495             sage: J.groebner_basis
    496             Pickle of the cached method "groebner_basis"
    497             sage: J.groebner_basis.is_in_cache()
    498             True
    499             sage: J.groebner_basis
    500             Cached version of <function groebner_basis at 0x...>
    501 
    502         """
    503         return CachedMethodPickle,(self._instance,self.__name__)
    504 
    505     def __call__(self, *args, **kwds):
    506         """
    507         Call the cached method.
    508 
    509         TESTS::
    510 
    511             sage: class Foo:
    512             ...       @cached_method
    513             ...       def f(self, x,y=1):
    514             ...           return x+y
    515             ...
    516             sage: a = Foo()
    517             sage: a.f(1)  #indirect doctest
    518             2
    519 
    520         The result is cached, taking into account
    521         the three ways of providing (named) arguments::
    522 
    523             sage: a.f(5) is a.f(5,1)
    524             True
    525             sage: a.f(5) is a.f(5,y=1)
    526             True
    527             sage: a.f(5) is a.f(y=1,x=5)
    528             True
    529 
    530         We test that #5843 is fixed::
    531 
    532             sage: class Foo:
    533             ...       def __init__(self, x):
    534             ...           self._x = x
    535             ...       @cached_method
    536             ...       def f(self, y):
    537             ...           return self._x
    538             ...
    539             sage: a = Foo(2)
    540             sage: b = Foo(3)
    541             sage: a.f(b.f)
    542             2
    543         """
    544         # We shortcut a common case of no arguments
    545         if args or kwds:
    546             k = self.get_key(*args, **kwds)
    547         else:
    548             try:
    549                 k = self._default_key
    550             except AttributeError:
    551                 k = self._default_key = self.get_key()
    552         try:
    553             return self.cache[k]
    554         except KeyError:
    555             w = self._cachedmethod._instance_call(self._instance, *args, **kwds)
    556             self.cache[k] = w
    557             return w
    558 
    559     def get_key(self, *args, **kwds):
    560         """
    561         Convert arguments to the key for this instance's cache.
    562 
    563         EXAMPLES::
    564 
    565             sage: class Foo:
    566             ...       def __init__(self, x):
    567             ...           self._x = x
    568             ...       @cached_method
    569             ...       def f(self, y, z=0):
    570             ...           return self._x * y + z
    571             ...
    572             sage: a = Foo(2)
    573             sage: z = a.f(37)
    574             sage: k = a.f.get_key(37); k
    575             ((37, 0), ())
    576             sage: a.f.get_cache()[k] is z
    577             True
    578 
    579         Note that the method does not test whether there are
    580         too many arguments, or wrong argument names::
    581 
    582             sage: a.f.get_key(1,2,3,x=4,y=5,z=6)
    583             ((1, 2, 3), (('x', 4), ('y', 5), ('z', 6)))
    584 
    585         It does, however, take into account the different
    586         ways of providing named arguments, possibly with a
    587         default value::
    588 
    589             sage: a.f.get_key(5)
    590             ((5, 0), ())
    591             sage: a.f.get_key(y=5)
    592             ((5, 0), ())
    593             sage: a.f.get_key(5,0)
    594             ((5, 0), ())
    595             sage: a.f.get_key(5,z=0)
    596             ((5, 0), ())
    597             sage: a.f.get_key(y=5,z=0)
    598             ((5, 0), ())
    599 
    600         """
    601         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         """
    607         Get a :class:`CachedMethodCaller` bound to a specific
    608         instance of the class of the cached method.
    609 
    610         NOTE:
    611 
    612         :class:`CachedMethodCaller` has a separate ``__get__``
    613         since the categories framework creates and caches the
    614         return value of ``CachedMethod.__get__`` with
    615         ``inst==None``.
    616 
    617         TESTS:
    618 
    619         Due to the separate ``__get__`` method, it is possible
    620         to define a cached method in one class and use it as
    621         an attribute of another class.
    622 
    623             sage: class Foo:
    624             ...       @cached_method
    625             ...       def f(self, y):
    626             ...           return y - 1
    627             sage: class Bar:
    628             ...       f = Foo.f
    629             sage: b1 = Bar()
    630             sage: b2 = Bar()
    631 
    632         The :class:`CachedMethod` is replaced by an instance
    633         of :class:`CachedMethodCaller` that (by trac ticket
    634         #8611) is set as an attribute. Hence, we have::
    635 
    636             sage: b1.f is b1.f
    637             True
    638 
    639         Any instance of ``Bar`` gets its own instance of
    640         :class:`CachedMethodCaller``::
    641 
    642             sage: b1.f is b2.f
    643             False
    644  
    645         The method caller knows the instance that it belongs
    646         to::
    647 
    648             sage: Foo.f._instance is None
    649             True
    650             sage: b1.f._instance is b1
    651             True
    652             sage: b2.f._instance is b2
    653             True
    654 
    655         """
    656         Caller = CachedMethodCaller(self._cachedmethod, inst, cache=self._cachedmethod._get_instance_cache(inst), inst_in_key=self._inst_in_key)
    657         try:
    658             setattr(inst,self._cachedmethod._cachedfunc.f.__name__, Caller)
    659         except AttributeError:
    660             pass
    661         return Caller
    662 
    663 class CachedMethod(object):
    664     """
    665     A decorator that creates a cached version of an instance
    666     method of a class.
    667 
    668     NOTE:
    669 
    670     For proper behavior, the method must be a pure function
    671     (no side effects). Arguments to the method must be hashable.
    672 
    673     EXAMPLES::
    674 
    675         sage: class Foo(object):
    676         ...       @cached_method
    677         ...       def f(self, t, x=2):
    678         ...           print 'computing'
    679         ...           return t**x
    680         sage: a = Foo()
    681 
    682     The example shows that the actual computation
    683     takes place only once, and that the result is
    684     identic for equivalent input::
    685    
    686         sage: res = a.f(3, 2); res
    687         computing
    688         9
    689         sage: a.f(t = 3, x = 2) is res
    690         True
    691         sage: a.f(3) is res
    692         True
    693 
    694     """
    695     def __init__(self, f):
    696         """
    697         EXAMPLES::
    698 
    699             sage: class Foo:
    700             ...       def __init__(self, x):
    701             ...           self._x = x
    702             ...       @cached_method
    703             ...       def f(self,n):
    704             ...           return self._x^n
    705             ...
    706             sage: a = Foo(2)
    707             sage: a.f(2)
    708             4
    709 
    710         The computations in method ``f`` are
    711         stored in a dictionary assigned to the
    712         instance ``a``::
    713 
    714             sage: hasattr(a, '_cache__f')
    715             True
    716             sage: a._cache__f
    717             {((2,), ()): 4}
    718 
    719         As a shortcut, useful to speed up internal computations,
    720         the same dictionary is also available as an attribute
    721         of the ``CachedMethodCaller``::
    722 
    723             sage: type(a.f)
    724             <class 'sage.misc.cachefunc.CachedMethodCaller'>
    725             sage: a.f.cache is a._cache__f
    726             True
    727 
    728         """
    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
    732 
    733     def _instance_call(self, inst, *args, **kwds):
    734         """
    735         Call the cached method *without* using the cache.
    736 
    737         INPUT:
    738 
    739         - ``inst`` - an instance at which the method is to be called
    740         - Further positional or named arguments.
    741 
    742         EXAMPLES::
    743 
    744             sage: class Foo(object):
    745             ...       def __init__(self, x):
    746             ...           self._x = x
    747             ...       @cached_method
    748             ...       def f(self):
    749             ...           return self._x^2
    750             ...
    751             sage: a = Foo(2)
    752             sage: a.f()
    753             4
    754 
    755         Usually, a cached meth is indeed cached::
    756 
    757             sage: a.f() is a.f()
    758             True
    759 
    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()
    764             False
    765             sage: a.f._cachedmethod._instance_call(a) == a.f()
    766             True
    767 
    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 
    777         """
    778         return self._cachedfunc.f(inst, *args, **kwds)
    779 
    780     def _get_instance_cache(self, inst):
    781         """
    782         Returns the cache dictionary.
    783 
    784         TESTS::
    785 
    786             sage: class Foo:
    787             ...       def __init__(self, x):
    788             ...           self._x = x
    789             ...       @cached_method
    790             ...       def f(self):
    791             ...           return self._x^2
    792             ...
    793             sage: a = Foo(2)
    794             sage: a.f()
    795             4
    796             sage: a.f._cachedmethod._get_instance_cache(a)
    797             {((), ()): 4}
    798         """
    799         try:
    800             return inst.__dict__.setdefault(self._cache_name, {})
    801         except AttributeError:
    802             return {}
    803 
    804     def __get__(self, inst, cls=None):
    805         """
    806         Get a CachedMethodCaller bound to this specific instance of
    807         the class of the cached method.
    808 
    809         TESTS::
    810 
    811             sage: class Foo:
    812             ...       @cached_method
    813             ...       def f(self):
    814             ...           return 1
    815             sage: a = Foo()
    816             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::
    823  
    824             sage: a.f is a.f
    825             True
    826 
    827         """
    828         Caller = CachedMethodCaller(self, inst, cache=self._get_instance_cache(inst))
    829         try:
    830             setattr(inst,self._cachedfunc.f.__name__, Caller)
    831         except AttributeError,msg:
    832             pass
    833         return Caller
    834 
    835         # Note: a simpler approach to this would be
    836         # def caller(*args, **kwds):
    837         #     return self._instance_call(inst, *args, **kwds)
    838         # return caller
    839         # The disadvantage to this is that it does not provide
    840         # is_in_cache(), set_cache(), clear_cache(), ... methods.
    841 
    842 
    843 cached_method = CachedMethod
    844 
    845 class CachedInParentMethod(CachedMethod):
    846     """
    847     A decorator that creates a cached version of an instance
    848     method of a class.
    849 
    850     In contrast to :class:`CachedMethod`,
    851     the cache dictionary is an attribute of the parent of
    852     the instance to which the method belongs.
    853 
    854     ASSUMPTION:
    855 
    856     This way of caching works only if
    857 
    858     - the instances *have* a parent,
    859     - the parent allows assignment of attributes, and
    860     - the instances are hashable (they are part of the cache key).
    861 
    862     NOTE:
    863 
    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
    923     """
    924     def __init__(self, f):
    925         """
    926         Constructs a new method with cache stored in the parent of the instance.
    927 
    928         See also ``cached_method`` and ``cached_function``.
    929 
    930         EXAMPLES::
    931 
    932             sage: class MyParent(Parent):
    933             ...       pass
    934             sage: class Foo:
    935             ...       def __init__(self, x):
    936             ...           self._x = x
    937             ...       _parent = MyParent()
    938             ...       def parent(self):
    939             ...           return self._parent
    940             ...       @cached_in_parent_method  #indirect doctest
    941             ...       def f(self):
    942             ...           return self._x^2
    943             ...
    944             sage: a = Foo(2)
    945             sage: a.f()
    946             4
    947             sage: hasattr(a.parent(), '_cache__element_f')
    948             True
    949 
    950         For speeding up internal computations, this dictionary
    951         is also accessible as an attribute of the CachedMethodCaller
    952         (by trac ticket #8611)::
    953 
    954             sage: a.parent()._cache__element_f is a.f.cache
    955             True
    956         """
    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):
    962         """
    963         Returns the cache dictionary, which is stored in the parent.
    964 
    965         EXAMPLES::
    966 
    967             sage: class MyParent(Parent):
    968             ...       pass
    969             ...
    970             sage: class Foo:
    971             ...       def __init__(self, x):
    972             ...           self._x = x
    973             ...       _parent = MyParent()
    974             ...       def parent(self):
    975             ...           return self._parent
    976             ...       def __eq__(self, other):
    977             ...           return self._x^2 == other._x^2
    978             ...       def __hash__(self):
    979             ...           return hash(self._x^2)
    980             ...       def __repr__(self):
    981             ...           return 'My %s'%self._x
    982             ...       @cached_in_parent_method
    983             ...       def f(self):
    984             ...           return self._x^3
    985             ...
    986             sage: a = Foo(2)
    987             sage: a.f()
    988             8
    989             sage: a.f.get_cache()   #indirect doctest
    990             {(My 2, ((), ())): 8}
    991 
    992         Since the key for the cache depends on equality of
    993         the instances, we obtain *identical* result for
    994         *equal* instance - even though in this particular
    995         example the result is wrong::
    996 
    997             sage: b = Foo(-2)
    998             sage: a is not b
    999             True
    1000             sage: a == b
    1001             True
    1002             sage: b.f() is a.f()
    1003             True
    1004 
    1005         Non-equal instances do not share the result of
    1006         the cached method, but they do share the cache::
    1007 
    1008             sage: c = Foo(3)
    1009             sage: c.f()
    1010             27
    1011             sage: c.f.get_cache() is a.f.get_cache() #indirect doctest
    1012             True
    1013 
    1014         Note that the cache is also available as an
    1015         attribute of the cached method, which speeds
    1016         up internal computations::
    1017 
    1018             sage: a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c)
    1019             True
    1020 
    1021         """
    1022         try:
    1023             return inst.parent().__dict__.setdefault(self._cache_name, {})
    1024         except AttributeError:
    1025             return {}
    1026 
    1027     def __get__(self, inst, cls=None):
    1028         """
    1029         Get a CachedMethodCaller bound to this specific instance of
    1030         the class of the cached-in-parent method.
    1031         """
    1032         Caller = CachedMethodCaller(self, inst, cache=self._get_instance_cache(inst), inst_in_key=True)
    1033         try:
    1034             setattr(inst,self._cachedfunc.f.__name__, Caller)
    1035         except AttributeError:
    1036             pass
    1037         return Caller
    1038 
    1039 cached_in_parent_method = CachedInParentMethod
    1040 
    1041 class FileCache:
    1042     """
    1043     FileCache is a dictionary-like class which stores keys and
    1044     values on disk.  The keys take the form of a tuple (A,K)
    1045 
    1046     - A is a tuple of objects t where each t is an exact
    1047       object which is uniquely identified by a short string.
    1048 
    1049     - K is a tuple of tuples (s,v) where s is a valid
    1050       variable name and v is an exact object which is uniquely
    1051       identified by a short string with letters [a-zA-Z0-9-._]
    1052 
    1053     The primary use case is the DiskCachedFunction.  If
    1054     ``memory_cache == True``, we maintain a cache of objects seen
    1055     during this session in memory -- but we don't load them from
    1056     disk until necessary.  The keys and values are stored in a
    1057     pair of files:
    1058 
    1059     - ``prefix-argstring.key.sobj`` contains the ``key`` only,
    1060     - ``prefix-argstring.sobj`` contains the tuple ``(key,val)``
    1061 
    1062     where ``self[key] == val``.
    1063 
    1064     NOTE:
    1065 
    1066     We assume that each FileCache lives in its own directory.
    1067     Use **extreme** caution if you wish to break that assumption.
    1068     """
    1069     def __init__(self, dir, prefix = '', memory_cache = False):
    1070         """
    1071         EXAMPLES::
    1072 
    1073             sage: from sage.misc.cachefunc import FileCache
    1074             sage: dir = tmp_dir()
    1075             sage: FC = FileCache(dir, memory_cache = True)
    1076             sage: FC[((),())] = 1
    1077             sage: FC[((1,2),())] = 2
    1078             sage: FC[((),())]
    1079             1
    1080         """
    1081         if len(dir) == 0 or dir[-1] != '/':
    1082             dir += '/'
    1083         self._dir = dir
    1084         if not os.path.exists(dir):
    1085             os.mkdir(dir)
    1086 
    1087         self._prefix = prefix + '-'
    1088 
    1089         if memory_cache:
    1090             self._cache = {}
    1091         else:
    1092             self._cache = None
    1093 
    1094     def file_list(self):
    1095         """
    1096         Returns the list of files corresponding to self.
    1097 
    1098         EXAMPLES::
    1099 
    1100             sage: from sage.misc.cachefunc import FileCache
    1101             sage: dir = tmp_dir()
    1102             sage: FC = FileCache(dir, memory_cache = True, prefix='t')
    1103             sage: FC[((),())] = 1
    1104             sage: FC[((1,2),())] = 2
    1105             sage: FC[((1,),(('a',1),))] = 3
    1106             sage: for f in sorted(FC.file_list()): print f[len(dir):]
    1107             /t-.key.sobj
    1108             /t-.sobj
    1109             /t-1_2.key.sobj
    1110             /t-1_2.sobj
    1111             /t-a-1.1.key.sobj
    1112             /t-a-1.1.sobj
    1113         """
    1114         files = []
    1115         prefix = self._prefix
    1116         dir = self._dir
    1117         l = len(prefix)
    1118         for f in os.listdir(dir):
    1119             if f[:l] == prefix:
    1120                 files.append( dir + f )
    1121         return files
    1122 
    1123     def items(self):
    1124         """
    1125         Returns a list of tuples ``(k,v)`` where ``self[k] = v``.
    1126 
    1127         EXAMPLES::
    1128 
    1129             sage: from sage.misc.cachefunc import FileCache
    1130             sage: dir = tmp_dir()
    1131             sage: FC = FileCache(dir, memory_cache = False)
    1132             sage: FC[((),())] = 1
    1133             sage: FC[((1,2),())] = 2
    1134             sage: FC[((1,),(('a',1),))] = 3
    1135             sage: I = FC.items()
    1136             sage: I.sort(); print I
    1137             [(((), ()), 1), (((1,), (('a', 1),)), 3), (((1, 2), ()), 2)]
    1138         """
    1139         return [(k,self[k]) for k in self]
    1140 
    1141     def values(self):
    1142         """
    1143         Returns a list of values that are stored in ``self``.
    1144 
    1145         EXAMPLES::
    1146 
    1147             sage: from sage.misc.cachefunc import FileCache
    1148             sage: dir = tmp_dir()
    1149             sage: FC = FileCache(dir, memory_cache = False)
    1150             sage: FC[((),())] = 1
    1151             sage: FC[((1,2),())] = 2
    1152             sage: FC[((1,),(('a',1),))] = 3
    1153             sage: FC[((),(('a',1),))] = 4
    1154             sage: v = FC.values()
    1155             sage: v.sort(); print v
    1156             [1, 2, 3, 4]
    1157         """
    1158         return [self[k] for k in self]
    1159 
    1160     def __iter__(self):
    1161         """
    1162         Returns a list of keys of ``self``.
    1163 
    1164         EXAMPLES::
    1165 
    1166             sage: from sage.misc.cachefunc import FileCache
    1167             sage: dir = tmp_dir()
    1168             sage: FC = FileCache(dir, memory_cache = False)
    1169             sage: FC[((),())] = 1
    1170             sage: FC[((1,2),())] = 2
    1171             sage: FC[((1,),(('a',1),))] = 3
    1172             sage: for k in sorted(FC): print k
    1173             ((), ())
    1174             ((1,), (('a', 1),))
    1175             ((1, 2), ())
    1176         """
    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)
    1182 
    1183     def keys(self):
    1184         """
    1185         Returns a list of keys ``k`` where ``self[k]`` is defined.
    1186 
    1187         EXAMPLES::
    1188 
    1189             sage: from sage.misc.cachefunc import FileCache
    1190             sage: dir = tmp_dir()
    1191             sage: FC = FileCache(dir, memory_cache = False)
    1192             sage: FC[((),())] = 1
    1193             sage: FC[((1,2),())] = 2
    1194             sage: FC[((1,),(('a',1),))] = 3
    1195             sage: K = FC.keys()
    1196             sage: K.sort(); print K
    1197             [((), ()), ((1,), (('a', 1),)), ((1, 2), ())]
    1198         """
    1199         return [k for k in self]
    1200 
    1201     def _filename(self, key):
    1202         """
    1203         Computes the filename associated with a certain key.
    1204 
    1205         EXAMPLES::
    1206 
    1207             sage: from sage.misc.cachefunc import FileCache
    1208             sage: dir = tmp_dir() + '/'
    1209             sage: FC = FileCache(dir, memory_cache = False, prefix='foo')
    1210             sage: N = FC._filename(((1,2), (('a',1),('b',2))))
    1211             sage: print N[len(dir):]
    1212             foo-a-1_b-2.1_2
    1213             sage: N = FC._filename(((), (('a',1),('b',2))))
    1214             sage: print N[len(dir):]
    1215             foo-a-1_b-2
    1216             sage: N = FC._filename(((1,2), ()))
    1217             sage: print N[len(dir):]
    1218             foo-1_2
    1219         """
    1220         a,k = key
    1221         kwdstr = '_'.join('%s-%s'%x for x in k)
    1222         argstr = '_'.join('%s'%x for x in a)
    1223         if kwdstr and argstr:
    1224             keystr = kwdstr + '.' + argstr
    1225         else:
    1226             keystr = kwdstr + argstr
    1227         return self._dir + self._prefix + keystr
    1228 
    1229     def has_key(self, key):
    1230         """
    1231         Returns ``True`` if ``self[key]`` is defined and False otherwise.
    1232 
    1233         EXAMPLES::
    1234 
    1235             sage: from sage.misc.cachefunc import FileCache
    1236             sage: dir = tmp_dir() + '/'
    1237             sage: FC = FileCache(dir, memory_cache = False, prefix='foo')
    1238             sage: k = ((),(('a',1),))
    1239             sage: FC[k] = True
    1240             sage: FC.has_key(k)
    1241             True
    1242             sage: FC.has_key(((),()))
    1243             False
    1244         """
    1245         return os.path.exists(self._filename(key) + '.key.sobj')
    1246 
    1247     def __getitem__(self, key):
    1248         """
    1249         Returns the value set by ``self[key] = val``, in this session
    1250         or a previous one.
    1251 
    1252         EXAMPLES::
    1253 
    1254             sage: from sage.misc.cachefunc import FileCache
    1255             sage: dir = tmp_dir() + '/'
    1256             sage: FC1 = FileCache(dir, memory_cache = False, prefix='foo')
    1257             sage: FC2 = FileCache(dir, memory_cache = False, prefix='foo')
    1258             sage: k = ((),(('a',1),))
    1259             sage: t = randint(0, 1000)
    1260             sage: FC1[k] = t
    1261             sage: FC2[k] == FC1[k] == t
    1262             True
    1263             sage: FC1[(1,2),(('a',4),('b',2))]
    1264             Traceback (most recent call last):
    1265             ...
    1266             KeyError: ((1, 2), (('a', 4), ('b', 2)))
    1267 
    1268         """
    1269         from sage.structure.sage_object import load
    1270 
    1271         cache = self._cache
    1272         if cache is not None:
    1273             if cache.has_key(key):
    1274                 return cache[key]
    1275 
    1276         f = self._filename(key) + '.sobj'
    1277         try:
    1278             k,v = load(f)
    1279         except IOError:
    1280             raise KeyError, key
    1281         if k != key:
    1282             raise RuntimeError, "cache corrupted"
    1283 
    1284         if cache is not None:
    1285             cache[key] = v
    1286         return v
    1287 
    1288     def __setitem__(self, key, value):
    1289         """
    1290         Sets ``self[key] = value`` and stores both key and value on
    1291         disk.
    1292 
    1293         EXAMPLES::
    1294 
    1295             sage: from sage.misc.cachefunc import FileCache
    1296             sage: dir = tmp_dir() + '/'
    1297             sage: FC1 = FileCache(dir, memory_cache = False, prefix='foo')
    1298             sage: FC2 = FileCache(dir, memory_cache = False, prefix='foo')
    1299             sage: k = ((),(('a',1),))
    1300             sage: t = randint(0, 1000)
    1301             sage: FC1[k] = t
    1302             sage: FC2[k] == t
    1303             True
    1304             sage: FC1[k] = 2000
    1305             sage: FC2[k]!= t
    1306             True
    1307         """
    1308         from sage.structure.sage_object import save
    1309 
    1310         f = self._filename(key)
    1311 
    1312         save(key, f+'.key.sobj')
    1313         save((key,value), f + '.sobj')
    1314         if self._cache is not None:
    1315             self._cache[key] = value
    1316 
    1317     def __delitem__(self, key):
    1318         """
    1319         Delete the key,value pair from self and unlink the associated
    1320         files from the file cache.
    1321 
    1322         EXAMPLES::
    1323 
    1324             sage: from sage.misc.cachefunc import FileCache
    1325             sage: dir = tmp_dir() + '/'
    1326             sage: FC1 = FileCache(dir, memory_cache = False, prefix='foo')
    1327             sage: FC2 = FileCache(dir, memory_cache = False, prefix='foo')
    1328             sage: k = ((),(('a',1),))
    1329             sage: t = randint(0, 1000)
    1330             sage: FC1[k] = t
    1331             sage: del FC2[k]
    1332             sage: FC1.has_key(k)
    1333             False
    1334        """
    1335         f = self._filename(key)
    1336         cache = self._cache
    1337         if cache is not None and cache.has_key(key):
    1338             del self._cache[key]
    1339         if os.path.exists(f + '.sobj'):
    1340             os.remove(f + '.sobj')
    1341         if  os.path.exists(f + '.key.sobj'):
    1342            os.remove(f + '.key.sobj')
    1343 
    1344 
    1345 class DiskCachedFunction(CachedFunction):
    1346     """
    1347     Works similar to CachedFunction, but instead, we keep the
    1348     cache on disk (optionally, we keep it in memory too).
    1349 
    1350     EXAMPLES::
    1351 
    1352         sage: from sage.misc.cachefunc import DiskCachedFunction
    1353         sage: dir = tmp_dir()
    1354         sage: factor = DiskCachedFunction(factor, dir, memory_cache=True)
    1355         sage: f = factor(2775); f
    1356         3 * 5^2 * 37
    1357         sage: f is factor(2775)
    1358         True
    1359     """
    1360     def __init__(self, f, dir, memory_cache=False):
    1361         """
    1362         EXAMPLES::
    1363 
    1364             sage: from sage.misc.cachefunc import DiskCachedFunction
    1365             sage: def foo(x): sleep(x)
    1366             sage: dir = tmp_dir()
    1367             sage: bar = DiskCachedFunction(foo, dir, memory_cache = False)
    1368             sage: w = walltime()
    1369             sage: for i in range(10): bar(1)
    1370             sage: walltime(w) < 2
    1371             True
    1372         """
    1373         CachedFunction.__init__(self, f)
    1374         prefix = f.__name__
    1375         self.cache = FileCache(dir, prefix=prefix, memory_cache = memory_cache)
    1376 
    1377 
    1378 class disk_cached_function:
    1379     """
    1380     Decorator for :class:`DiskCachedFunction`.
    1381 
    1382     EXAMPLES::
    1383 
    1384         sage: dir = tmp_dir()
    1385         sage: @disk_cached_function(dir)
    1386         ... def foo(x): return next_prime(2^x)%x
    1387         sage: x = foo(200);x
    1388         11
    1389         sage: @disk_cached_function(dir)
    1390         ... def foo(x): return 1/x
    1391         sage: foo(200)
    1392         11
    1393         sage: foo.clear_cache()
    1394         sage: foo(200)
    1395         1/200
    1396     """
    1397     def __init__(self, dir, memory_cache = False):
    1398         """
    1399         EXAMPLES::
    1400 
    1401             sage: dir = tmp_dir()
    1402             sage: @disk_cached_function(dir, memory_cache=True)
    1403             ... def foo(x): return next_prime(2^x)
    1404             sage: x = foo(200)
    1405             sage: x is foo(200)
    1406             True
    1407             sage: @disk_cached_function(dir, memory_cache=False)
    1408             ... def foo(x): return next_prime(2^x)
    1409             sage: x is foo(200)
    1410             False
    1411         """
    1412         self._dir = dir
    1413         self._memory_cache = memory_cache
    1414 
    1415     def __call__(self, f):
    1416         """
    1417         EXAMPLES::
    1418 
    1419             sage: dir = tmp_dir()
    1420             sage: @disk_cached_function(dir)
    1421             ... def foo(x): return ModularSymbols(x)
    1422             sage: foo(389)
    1423             Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field
    1424         """
    1425         return DiskCachedFunction(f, self._dir, memory_cache = self._memory_cache)
    1426 
    1427 class ClearCacheOnPickle(object):
    1428     """
    1429     This class implements an appropriate __getstate__ method that
    1430     clears the cache of the methods (see @cached_method) before
    1431     passing them on to the caller, typically the pickle and copy modules.
    1432 
    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.
    1437 
    1438     """
    1439     def __getstate__(self):
    1440         """
    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__') )
  • new file sage/misc/cachefunc.pyx

    diff --git a/sage/misc/cachefunc.pyx b/sage/misc/cachefunc.pyx
    new file mode 100644
    - +  
     1r"""
     2Cached Functions and Methods
     3
     4AUTHORS:
     5
     6- William Stein (inspired by conversation with Justin Walker).
     7- Mike Hansen (added doctests and made it work with class methods).
     8- Willem Jan Palenstijn (add CachedMethodCaller for binding cached
     9  methods to instances).
     10- Tom Boothby (added DiskCachedFunction).
     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
     100To make cacheing work on the elements, we need to provide it with
     101a public attribute ``__cached_methods``, as in the second class below::
     102
     103    sage: cython_code = ["from sage.structure.element cimport Element",
     104    ... "cdef class MyBrokenElement(Element):",
     105    ... "    cdef public object x",
     106    ... "    def __init__(self,P,x):",
     107    ... "        self.x=x",
     108    ... "        Element.__init__(self,P)",
     109    ... "    def __neg__(self):",
     110    ... "        return MyElement(self.parent(),-self.x)",
     111    ... "    def _repr_(self):",
     112    ... "        return '<%s>'%self.x",
     113    ... "    def __hash__(self):",
     114    ... "        return hash(self.x)",
     115    ... "    def __cmp__(self,other):",
     116    ... "        if isinstance(other, MyBrokenElement):",
     117    ... "            return cmp(self.x,other.x)",
     118    ... "        return -1",
     119    ... "    def raw_test(self):",
     120    ... "        return -self",
     121    ... "cdef class MyElement(MyBrokenElement):",
     122    ... "    cdef public dict __cached_methods",
     123    ... "from sage.structure.parent cimport Parent",
     124    ... "cdef class MyParent(Parent):",
     125    ... "    Element = MyElement"]
     126    sage: cython('\n'.join(cython_code))
     127    sage: P = MyParent(category=C)
     128    sage: ebroken = MyBrokenElement(P,5)
     129    sage: e = MyElement(P,5)
     130
     131The cached methods inherited by the parent works::
     132
     133    sage: P.one()
     134    <1>
     135    sage: P.one() is P.one()
     136    True
     137    sage: P.invert(e)
     138    <-5>
     139    sage: P.invert(e) is P.invert(e)
     140    True
     141
     142The cached methods inherited by the element with ``__cached_method`` works::
     143
     144    sage: e.element_cache_test()
     145    <-5>
     146    sage: e.element_cache_test() is e.element_cache_test()
     147    True
     148    sage: e.element_via_parent_test()
     149    <-5>
     150    sage: e.element_via_parent_test() is e.element_via_parent_test()
     151    True
     152
     153The other element class can only inherit a `cached_in_parent_method`, since
     154the cache is stored in the parent. In fact, equal elements share the cache,
     155even if they are of different types::
     156
     157    sage: e == ebroken
     158    True
     159    sage: type(e) == type(ebroken)
     160    False
     161    sage: ebroken.element_via_parent_test() is e.element_via_parent_test()
     162    True
     163
     164However, the cache of the other inherited method breaks, although the method
     165as such works::
     166
     167    sage: ebroken.element_cache_test()
     168    <-5>
     169    sage: ebroken.element_cache_test() is ebroken.element_cache_test()
     170    False
     171
     172The cache can be emptied::
     173
     174    sage: a = test_pfunc(5)
     175    sage: test_pfunc.clear_cache()
     176    sage: a is test_pfunc(5)
     177    False
     178    sage: a = P.one()
     179    sage: P.one.clear_cache()
     180    sage: a is P.one()
     181    False   
     182
     183Since ``e`` and ``ebroken`` share the cache, when we empty it for one element
     184it is empty for the other as well::
     185
     186    sage: b = ebroken.element_via_parent_test()
     187    sage: e.element_via_parent_test.clear_cache()
     188    sage: b is ebroken.element_via_parent_test()
     189    False
     190
     191Introspection works::
     192
     193    sage: from sage.misc.edit_module import file_and_line
     194    sage: from sage.misc.sageinspect import sage_getdoc, sage_getfile, sage_getsource
     195    sage: print sage_getdoc(test_pfunc)
     196       Some documentation
     197    sage: print sage_getdoc(O.wrapped_method)
     198    File: ...
     199    (starting at line ...) some doc for a wrapped cython method
     200    sage: print sage_getsource(O.wrapped_method)
     201    cpdef test_meth(self,x):
     202        "some doc for a wrapped cython method"
     203        return -x
     204
     205It is a very common special case to cache a method that has no
     206arguments. In that special case, the time needed to access the cache
     207can be drastically reduced by using a special implmentation. The
     208cached method decorator automatically determines which implementation
     209ought to be chosen. A typical example is
     210:meth:`sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal.gens`
     211(no arguments) versus
     212:meth:`sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal.groebner_basis`
     213(several arguments)::
     214
     215    sage: P.<a,b,c,d> = QQ[]
     216    sage: I = P*[a,b]
     217    sage: I.gens()
     218    [a, b]
     219    sage: I.gens() is I.gens()
     220    True
     221    sage: I.groebner_basis()
     222    [a, b]
     223    sage: I.groebner_basis() is I.groebner_basis()
     224    True
     225    sage: type(I.gens)
     226    <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     227    sage: type(I.groebner_basis)
     228    <type 'sage.misc.cachefunc.CachedMethodCaller'>
     229
     230"""
     231########################################################################
     232#       Copyright (C) 2008 William Stein <wstein@gmail.com>
     233#                          Mike Hansen <mhansen@gmail.com>
     234#
     235#  Distributed under the terms of the GNU General Public License (GPL)
     236#
     237#                  http://www.gnu.org/licenses/
     238########################################################################
     239from function_mangling import ArgumentFixer
     240import os
     241from sage.misc.sageinspect import sage_getfile, sage_getsourcelines
     242
     243cdef class CachedFunction(object):
     244    """
     245    Create a cached version of a function, which only recomputes
     246    values it hasn't already computed. Synonyme: ``cached_function``
     247
     248    INPUT:
     249
     250    - ``f`` -- a function
     251    - ``name`` (optional string) -- name that the cached version
     252      of ``f`` should be provided with.
     253
     254    If ``f`` is a function, do either ``g = CachedFunction(f)``
     255    or ``g = cached_function(f)`` to make a cached version of ``f``,
     256    or put ``@cached_function`` right before the definition of ``f``
     257    (i.e., use Python decorators)::
     258
     259        @cached_function
     260        def f(...):
     261            ....
     262
     263    The inputs to the function must be hashable.
     264
     265    EXAMPLES::
     266
     267        sage: @cached_function
     268        ... def mul(x, y=2):
     269        ...     return x*y
     270        ...
     271        sage: mul(3)
     272        6
     273
     274    We demonstrate that the result is cached, and that, moreover,
     275    the cache takes into account the various ways of providing
     276    default arguments::
     277
     278        sage: mul(3) is mul(3,2)
     279        True
     280        sage: mul(3,y=2) is mul(3,2)
     281        True
     282
     283    The user can clear the cache::
     284
     285        sage: a = mul(4)
     286        sage: mul.clear_cache()
     287        sage: a is mul(4)
     288        False
     289
     290    It is also possible to explicitly override the cache with
     291    a different value::
     292
     293        sage: mul.set_cache('foo',5)
     294        sage: mul(5,2)
     295        'foo'
     296
     297    """
     298    def __init__(self, f, classmethod=False, name=None):
     299        """
     300        Create a cached version of a function, which only recomputes
     301        values it hasn't already computed. A custom name can be
     302        provided by an optional argument "name".
     303
     304        If f is a function, do either g = CachedFunction(f) to make
     305        a cached version of f, or put @CachedFunction right before
     306        the definition of f (i.e., use Python decorators, but then
     307        the optional argument ``name`` can not be used)::
     308
     309            @CachedFunction
     310            def f(...):
     311                ....
     312
     313        The inputs to the function must be hashable.
     314
     315        TESTS::
     316
     317            sage: g = CachedFunction(number_of_partitions)
     318            sage: g.__name__
     319            'number_of_partitions'
     320            sage: 'partitions' in sage.misc.sageinspect.sage_getdoc(g)
     321            True
     322            sage: g(5)
     323            7
     324            sage: g.cache
     325            {((5, None, 'default'), ()): 7}
     326            sage: def f(t=1): print(t)
     327            sage: h = CachedFunction(f)
     328            sage: w = walltime()
     329            sage: h(); h(1); h(t=1)
     330            1
     331            sage: walltime(w) < 2
     332            True
     333
     334        """
     335        self._common_init(f, ArgumentFixer(f,classmethod=classmethod), name=name)
     336        self.cache = {}
     337
     338    def _common_init(self, f, argument_fixer, name=None):
     339        """
     340        Perform initialization common to CachedFunction and CachedMethodCaller.
     341
     342        TESTS::
     343
     344            sage: @cached_function
     345            ... def test_cache(x):
     346            ...     return -x
     347            sage: test_cache._fix_to_pos is not None  # indirect doctest
     348            True
     349
     350        """
     351        self.f = f
     352        if name is not None:
     353            self.__name__ = name
     354        elif hasattr(f, "func_name"):
     355            self.__name__ = f.func_name
     356        else:
     357            self.__name__ = f.__name__
     358        self.__module__ = f.__module__
     359        if argument_fixer is not None: # it is None for CachedMethodCallerNoArgs
     360            self._argument_fixer = argument_fixer
     361            self._fix_to_pos = argument_fixer.fix_to_pos
     362
     363    #########
     364    ## Introspection
     365    ##
     366    ## We provide some methods explicitly, and
     367    ## forward other questions to the cached function.
     368
     369    def _sage_doc_(self):
     370        """
     371        Provide documentation for the cached function.
     372
     373        A cached function shall inherit the documentation
     374        from the function that is wrapped, not from the
     375        documentation of the wrapper.
     376
     377        TEST::
     378
     379            sage: P.<x,y> = QQ[]
     380            sage: I = P*[x,y]
     381            sage: from sage.misc.sageinspect import sage_getdoc
     382            sage: print sage_getdoc(I.groebner_basis) # indirect doctest
     383            File: sage/rings/polynomial/multi_polynomial_ideal.py (starting at
     384            line ...)
     385            ...
     386               ALGORITHM: Uses Singular, Magma (if available), Macaulay2 (if
     387               available), or a toy implementation.
     388
     389        """
     390        f = self.f
     391        if hasattr(f, "func_doc"):
     392            try:
     393                sourcelines = sage_getsourcelines(f)
     394            except IOError:
     395                sourcelines = None
     396            if sourcelines is not None:
     397                import os
     398                SAGE_ROOT = os.environ['SAGE_ROOT']
     399                filename = sage_getfile(f)
     400                # The following is a heuristics to get
     401                # the file name of the cached function
     402                # or method
     403                if filename.startswith(SAGE_ROOT+'/devel/sage/'):
     404                    filename = filename[len(SAGE_ROOT+'/devel/sage/'):]
     405                elif 'site-packages/' in filename:
     406                    filename = filename.split('site-packages/',1)[1]
     407                file_info = "File: %s (starting at line %d)"%(filename,sourcelines[1])
     408                doc = file_info+(f.func_doc or '')
     409            else:
     410                doc = f.func_doc
     411        else:
     412            doc = f.__doc__
     413        return doc
     414
     415    def _sage_src_(self):
     416        """
     417        Returns the source code for the wrapped function.
     418
     419        TESTS::
     420
     421            sage: from sage.misc.sageinspect import sage_getsource
     422            sage: g = CachedFunction(number_of_partitions)
     423            sage: 'bober' in sage_getsource(g)  # indirect doctest
     424            True
     425
     426        """
     427        from sage.misc.sageinspect import sage_getsource
     428        return sage_getsource(self.f)
     429
     430    def _sage_src_lines_(self):
     431        r"""
     432        Returns the list of source lines and the first line number
     433        of the wrapped function.
     434
     435        TEST::
     436
     437            sage: P.<x,y> = QQ[]
     438            sage: I = P*[x,y]
     439            sage: from sage.misc.sageinspect import sage_getsourcelines
     440            sage: l = "        elif algorithm == 'macaulay2:gb':\n"
     441            sage: l in sage_getsourcelines(I.groebner_basis)[0] # indirect doctest
     442            True
     443
     444        """
     445        from sage.misc.sageinspect import sage_getsourcelines
     446        return sage_getsourcelines(self.f)
     447
     448    def _sage_argspec_(self):
     449        """
     450        Return the argspec of the wrapped function or method.
     451
     452        This was implemented in trac ticket #11115.
     453
     454        EXAMPLE::
     455
     456            sage: P.<x,y> = QQ[]
     457            sage: I = P*[x,y]
     458            sage: from sage.misc.sageinspect import sage_getargspec
     459            sage: sage_getargspec(I.groebner_basis)   # indirect doctest
     460            ArgSpec(args=['self', 'algorithm', 'deg_bound', 'mult_bound', 'prot'],
     461            varargs='args', keywords='kwds', defaults=('', None, None,
     462            False))
     463
     464        """
     465        from sage.misc.sageinspect import sage_getargspec
     466        return sage_getargspec(self.f)
     467
     468    def __call__(self, *args, **kwds):
     469        """
     470        Return value from cache or call the wrapped function,
     471        caching the output.
     472
     473        TESTS::
     474
     475            sage: g = CachedFunction(number_of_partitions)
     476            sage: a = g(5)
     477            sage: g.get_cache()
     478            {((5, None, 'default'), ()): 7}
     479            sage: a = g(10^5)   # indirect doctest
     480            sage: a == number_of_partitions(10^5)
     481            True
     482            sage: a is g(10^5)
     483            True
     484            sage: a is number_of_partitions(10^5)
     485            False
     486
     487        """
     488        # We shortcut a common case of no arguments
     489        if args or kwds:
     490            k = self._fix_to_pos(*args, **kwds)
     491        else:
     492            if self._default_key is not None:
     493                k = self._default_key
     494            else:
     495                k = self._default_key = self._fix_to_pos()
     496
     497        try:
     498            return (<dict>self.cache)[k]
     499        except KeyError:
     500            w = self.f(*args, **kwds)
     501            self.cache[k] = w
     502            return w
     503
     504    cpdef get_cache(self):
     505        """
     506        Returns the cache dictionary.
     507
     508        EXAMPLES::
     509
     510            sage: g = CachedFunction(number_of_partitions)
     511            sage: a = g(5)
     512            sage: g.get_cache()
     513            {((5, None, 'default'), ()): 7}
     514
     515        """
     516        return self.cache
     517
     518    def is_in_cache(self, *args, **kwds):
     519        """
     520        Checks if the argument list is in the cache.
     521
     522        EXAMPLES::
     523
     524            sage: class Foo:
     525            ...       def __init__(self, x):
     526            ...           self._x = x
     527            ...       @cached_method
     528            ...       def f(self, z, y=0):
     529            ...           return self._x*z+y
     530            ...
     531            sage: a = Foo(2)
     532            sage: a.f.is_in_cache(3)
     533            False
     534            sage: a.f(3)
     535            6
     536            sage: a.f.is_in_cache(3,y=0)
     537            True
     538        """
     539        return self._fix_to_pos(*args, **kwds) in (<dict>self.cache)
     540
     541    def set_cache(self, value, *args, **kwds):
     542        """
     543        Set the value for those args and keyword args
     544        Mind the unintuitive syntax (value first).
     545        Any idea on how to improve that welcome!
     546
     547        EXAMPLES::
     548
     549            sage: g = CachedFunction(number_of_partitions)
     550            sage: a = g(5)
     551            sage: g.get_cache()
     552            {((5, None, 'default'), ()): 7}
     553            sage: g.set_cache(17, 5)
     554            sage: g.get_cache()
     555            {((5, None, 'default'), ()): 17}
     556            sage: g(5)
     557            17
     558
     559        DEVELOPER NOTE:
     560
     561        Is there a way to use the following intuitive syntax?
     562
     563        ::
     564
     565            sage: g(5) = 19    # todo: not implemented
     566            sage: g(5)         # todo: not implemented
     567            19
     568        """
     569        (<dict>self.cache)[self._fix_to_pos(*args, **kwds)] = value
     570
     571    def get_key(self, *args, **kwds):
     572        """
     573        Returns the key in the cache to be used when args
     574        and kwds are passed in as parameters.
     575
     576        EXAMPLES::
     577
     578            sage: @cached_function
     579            ... def foo(x):
     580            ...    return x^2
     581            ...
     582            sage: foo(2)
     583            4
     584            sage: foo.get_key(2)
     585            ((2,), ())
     586            sage: foo.get_key(x=3)
     587            ((3,), ())
     588        """
     589        return self._fix_to_pos(*args, **kwds)
     590
     591    def __repr__(self):
     592        """
     593        EXAMPLES::
     594
     595            sage: g = CachedFunction(number_of_partitions)
     596            sage: g     # indirect doctest
     597            Cached version of <function number_of_partitions at 0x...>
     598        """
     599        try:
     600            return "Cached version of %s"%self.f
     601        except AttributeError:
     602            return "Cached version of a method (pending reassignment)"
     603
     604    cpdef clear_cache(self):
     605        """
     606        Clear the cache dictionary.
     607
     608        EXAMPLES::
     609
     610            sage: g = CachedFunction(number_of_partitions)
     611            sage: a = g(5)
     612            sage: g.get_cache()
     613            {((5, None, 'default'), ()): 7}
     614            sage: g.clear_cache()
     615            sage: g.get_cache()
     616            {}
     617        """
     618        cdef object cache = self.cache
     619        for key in cache.keys():
     620            del cache[key]
     621
     622    def precompute(self, arglist, num_processes=1):
     623        """
     624        Cache values for a number of inputs.  Do the computation
     625        in parallel, and only bother to compute values that we
     626        haven't already cached.
     627
     628        EXAMPLES::
     629
     630            sage: @cached_function
     631            ... def oddprime_factors(n):
     632            ...     l = [p for p,e in factor(n) if p != 2]
     633            ...     return len(l)
     634            sage: oddprime_factors.precompute(range(1,100), 4)
     635            sage: oddprime_factors.cache[(25,),()]
     636            1
     637        """
     638        from sage.parallel.decorate import parallel, normalize_input
     639        P = parallel(num_processes)(self.f)
     640        has_key = self.cache.has_key
     641        get_key = self._fix_to_pos
     642        new = lambda x: not has_key(get_key(*x[0],**x[1]))
     643        arglist = filter(new, map(normalize_input, arglist))
     644        for ((args,kwargs), val) in P(arglist):
     645            self.set_cache(val, *args, **kwargs)
     646
     647
     648cached_function = CachedFunction
     649
     650class CachedMethodPickle(object):
     651    """
     652    This class helps to unpickle cached methods.
     653
     654    NOTE:
     655
     656    Since trac ticket #8611, a cached method is an attribute
     657    of the instance (provided that it has a ``__dict__``).
     658    Hence, when pickling the instance, it would be attempted
     659    to pickle that attribute as well, but this is a problem,
     660    since functions can not be pickled, currently. Therefore,
     661    we replace the actual cached method by a place holder,
     662    that kills itself as soon as any attribute is requested.
     663    Then, the original cached attribute is reinstated. But the
     664    cached values are in fact saved.
     665
     666    EXAMPLE::
     667
     668        sage: R.<x, y, z> = PolynomialRing(QQ, 3)
     669        sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
     670        sage: I.groebner_basis()
     671        [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]
     672        sage: I.groebner_basis
     673        Cached version of <function groebner_basis at 0x...>
     674
     675    We now pickle and unpickle the ideal. The cached method
     676    ``groebner_basis`` is replaced by a placeholder::
     677
     678        sage: J = loads(dumps(I))
     679        sage: J.groebner_basis
     680        Pickle of the cached method "groebner_basis"
     681
     682    But as soon as any other attribute is requested from the
     683    placeholder, it replaces itself by the cached method, and
     684    the entries of the cache are actually preserved::
     685
     686        sage: J.groebner_basis.is_in_cache()
     687        True
     688        sage: J.groebner_basis
     689        Cached version of <function groebner_basis at 0x...>
     690        sage: J.groebner_basis() == I.groebner_basis()
     691        True
     692
     693    TESTS:
     694
     695    Since Trac Ticket #11115, there is a special implementation for
     696    cached methods that don't take arguments::
     697
     698        sage: P.<a,b,c,d> = QQ[]
     699        sage: I = P*[a,b]
     700        sage: type(I.gens)
     701        <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     702        sage: type(I.groebner_basis)
     703        <type 'sage.misc.cachefunc.CachedMethodCaller'>
     704
     705    We demonstrate that both implementations can be pickled and
     706    preserve the cache. For that purpose, we assign nonsense to the
     707    cache. Of course, it is a very bad idea to override the cache in
     708    that way.  So, please don't try this at home::
     709
     710        sage: I.groebner_basis.set_cache('foo',algorithm='singular')
     711        sage: I.groebner_basis(algorithm='singular')
     712        'foo'
     713        sage: I.gens.set_cache('bar')
     714        sage: I.gens()
     715        'bar'
     716        sage: J = loads(dumps(I))
     717        sage: J.gens()
     718        'bar'
     719        sage: J.groebner_basis(algorithm='singular')
     720        'foo'
     721
     722    Anyway, the cache will be automatically reconstructed after
     723    clearing it::
     724
     725        sage: J.gens.clear_cache()
     726        sage: J.gens()
     727        [a, b]
     728        sage: J.groebner_basis.clear_cache()
     729        sage: J.groebner_basis(algorithm='singular')
     730        [a, b]
     731
     732    AUTHOR:
     733
     734    - Simon King (2011-01)
     735    """
     736    def __init__(self, inst, name, cache=None):
     737        """
     738        INPUT:
     739
     740        - ``inst`` - some instance.
     741        - ``name`` (string) - usually the name of an attribute
     742          of ``inst`` to which ``self`` is assigned.
     743
     744        TEST::
     745
     746            sage: from sage.misc.cachefunc import CachedMethodPickle
     747            sage: P = CachedMethodPickle(1, 'foo')
     748            sage: P
     749            Pickle of the cached method "foo"
     750
     751        """
     752        self._instance = inst
     753        self._name = name
     754        self._cache = cache
     755    def __repr__(self):
     756        """
     757        TEST::
     758
     759            sage: R.<x, y, z> = PolynomialRing(QQ, 3)
     760            sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
     761            sage: G = I.groebner_basis()
     762            sage: J = loads(dumps(I))
     763            sage: J.groebner_basis  #indirect doctest
     764            Pickle of the cached method "groebner_basis"
     765        """
     766        return 'Pickle of the cached method "%s"'%self._name
     767    def __reduce__(self):
     768        """
     769        This class is a pickle. However, sometimes, pickles
     770        need to be pickled another time.
     771
     772        TEST::
     773
     774            sage: PF = WeylGroup(['A',3]).pieri_factors()
     775            sage: a = PF.an_element()
     776            sage: a.bruhat_lower_covers()
     777            [[0 1 0 0]
     778            [0 0 1 0]
     779            [1 0 0 0]
     780            [0 0 0 1], [0 1 0 0]
     781            [1 0 0 0]
     782            [0 0 0 1]
     783            [0 0 1 0], [1 0 0 0]
     784            [0 0 1 0]
     785            [0 0 0 1]
     786            [0 1 0 0]]
     787            sage: b = loads(dumps(a))
     788            sage: b.bruhat_lower_covers
     789            Pickle of the cached method "bruhat_lower_covers"
     790
     791        When we now pickle ``b``, the pickle of the cached method
     792        needs to be taken care of::
     793
     794            sage: c = loads(dumps(b))  # indirect doctest
     795            sage: c.bruhat_lower_covers
     796            Pickle of the cached method "bruhat_lower_covers"
     797            sage: c.bruhat_lower_covers()
     798            [[0 1 0 0]
     799            [0 0 1 0]
     800            [1 0 0 0]
     801            [0 0 0 1], [0 1 0 0]
     802            [1 0 0 0]
     803            [0 0 0 1]
     804            [0 0 1 0], [1 0 0 0]
     805            [0 0 1 0]
     806            [0 0 0 1]
     807            [0 1 0 0]]
     808
     809        """
     810        return CachedMethodPickle,(self._instance,self._name,self._cache)
     811    def __call__(self,*args,**kwds):
     812        """
     813        The purpose of this call method is to kill ``self`` and to
     814        replace it by an actual :class:`CachedMethodCaller`. The last
     815        thing that ``self`` does before disappearing is to call the
     816        :class:`CachedMethodCaller` and return the result.
     817
     818        EXAMPLE::
     819
     820            sage: P.<a,b,c,d> = QQ[]
     821            sage: I = P*[a,b]
     822            sage: I.gens
     823            Cached version of <function gens at 0x...>
     824            sage: J = loads(dumps(I))
     825            sage: J.gens
     826            Pickle of the cached method "gens"
     827            sage: J.gens()   # indirect doctest
     828            [a, b]
     829            sage: J.gens
     830            Cached version of <function gens at 0x...>
     831
     832        """
     833        self._instance.__dict__.__delitem__(self._name)
     834        CM = getattr(self._instance,self._name)
     835        if self._cache is not None:
     836            if isinstance(CM, CachedMethodCallerNoArgs):
     837                CM.cache = self._cache
     838            else:
     839                for k,v in self._cache:
     840                    CM.cache[k] = v
     841        return CM(*args,**kwds)
     842       
     843    def __getattr__(self,s):
     844        """
     845        TEST::
     846
     847            sage: R.<x, y, z> = PolynomialRing(QQ, 3)
     848            sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
     849            sage: G = I.groebner_basis()
     850            sage: J = loads(dumps(I))
     851            sage: J.groebner_basis
     852            Pickle of the cached method "groebner_basis"
     853
     854        If an attribute of name ``s`` is requested (say,
     855        ``is_in_cache``), the attribute ``self._name`` of
     856        ``self._instance`` is deleted. Then, the attribute
     857        of name ``s`` of the attribute ``self._name`` of
     858        ``self._instance`` is requested. Since ``self._name``
     859        is a cached method defined for the class of
     860        ``self._instance``, retrieving the just-deleted
     861        attribute ``self._name`` succeeds.
     862
     863        In that way, the unpickling of the cached method is
     864        finally accomplished::
     865
     866            sage: J.groebner_basis.is_in_cache()  #indirect doctest
     867            True
     868            sage: J.groebner_basis
     869            Cached version of <function groebner_basis at 0x...>
     870
     871        """
     872        self._instance.__dict__.__delitem__(self._name)
     873        CM = getattr(self._instance,self._name)
     874        if self._cache is not None:
     875            if isinstance(CM, CachedMethodCallerNoArgs):
     876                CM.cache = self._cache
     877            else:
     878                for k,v in self._cache:
     879                    CM.cache[k] = v
     880        return getattr(CM,s)
     881
     882cdef class CachedMethodCaller(CachedFunction):
     883    """
     884    Utility class that is used by :class:`CachedMethod` to bind a
     885    cached method to an instance.
     886
     887    NOTE:
     888
     889    Since Trac Ticket #11115, there is a special implementation
     890    :class:`CachedMethodCallerNoArgs` for methods that do not take
     891    arguments.
     892
     893    EXAMPLE::
     894
     895        sage: class A:
     896        ...    @cached_method
     897        ...    def bar(self,x):
     898        ...        return x^2
     899        sage: a = A()
     900        sage: a.bar
     901        Cached version of <function bar at 0x...>
     902        sage: type(a.bar)
     903        <type 'sage.misc.cachefunc.CachedMethodCaller'>
     904        sage: a.bar(2) is a.bar(x=2)
     905        True
     906
     907    """
     908    def __init__(self, CachedMethod cachedmethod, inst, cache=None, inst_in_key=False, name=None):
     909        """
     910        EXAMPLES::
     911
     912            sage: class Foo:
     913            ...       def __init__(self, x):
     914            ...           self._x = x
     915            ...       @cached_method
     916            ...       def f(self,*args):
     917            ...           return self._x^2
     918            ...
     919            sage: a = Foo(2)
     920            sage: a.f.get_cache()
     921            {}
     922            sage: a.f()
     923            4
     924            sage: a.f.get_cache()
     925            {((), ()): 4}
     926        """
     927        # initialize CachedFunction, but re-use the ArgumentFixer
     928        self._common_init(cachedmethod._cachedfunc.f, cachedmethod._cachedfunc._argument_fixer, name=name)
     929        self.cache = {} if cache is None else cache
     930        self._instance = inst
     931        self._inst_in_key = inst_in_key
     932        self._cachedmethod = cachedmethod
     933
     934    def __reduce__(self):
     935        """
     936        The pickle of a :class:`CachedMethodCaller` unpickles
     937        to a :class:`CachedMethodPickle`, that is able to replace
     938        itself by a copy of the original :class:`CachedMethodCaller`.
     939
     940        TEST::
     941
     942            sage: R.<x, y, z> = PolynomialRing(QQ, 3)
     943            sage: I = R*(x^3 + y^3 + z^3,x^4-y^4)
     944            sage: G = I.groebner_basis()
     945            sage: J = loads(dumps(I))  #indirect doctest
     946            sage: J.groebner_basis
     947            Pickle of the cached method "groebner_basis"
     948            sage: J.groebner_basis.is_in_cache()
     949            True
     950            sage: J.groebner_basis
     951            Cached version of <function groebner_basis at 0x...>
     952
     953        """
     954#        if hasattr(self._instance,self._cachedmethod._cache_name):
     955#            return CachedMethodPickle,(self._instance,self.__name__)
     956        if isinstance(self._cachedmethod, CachedInParentMethod) or hasattr(self._instance,self._cachedmethod._cache_name):
     957            return CachedMethodPickle,(self._instance,self.__name__)
     958        return CachedMethodPickle,(self._instance,self.__name__,self.cache.items())
     959
     960    def _instance_call(self, *args, **kwds):
     961        """
     962        Call the cached method without using the cache.
     963
     964        EXAMPLE::
     965
     966            sage: P.<a,b,c,d> = QQ[]
     967            sage: I = P*[a,b]
     968            sage: I.groebner_basis()
     969            [a, b]
     970            sage: I.groebner_basis._instance_call() is I.groebner_basis()
     971            False
     972            sage: I.groebner_basis._instance_call() == I.groebner_basis()
     973            True
     974
     975        """
     976        return self._cachedmethod._instance_call(self._instance, *args, **kwds)
     977
     978    def __call__(self, *args, **kwds):
     979        """
     980        Call the cached method.
     981
     982        TESTS::
     983
     984            sage: class Foo:
     985            ...       @cached_method
     986            ...       def f(self, x,y=1):
     987            ...           return x+y
     988            ...
     989            sage: a = Foo()
     990            sage: a.f(1)  #indirect doctest
     991            2
     992
     993        The result is cached, taking into account
     994        the three ways of providing (named) arguments::
     995
     996            sage: a.f(5) is a.f(5,1)
     997            True
     998            sage: a.f(5) is a.f(5,y=1)
     999            True
     1000            sage: a.f(5) is a.f(y=1,x=5)
     1001            True
     1002
     1003        We test that #5843 is fixed::
     1004
     1005            sage: class Foo:
     1006            ...       def __init__(self, x):
     1007            ...           self._x = x
     1008            ...       @cached_method
     1009            ...       def f(self, y):
     1010            ...           return self._x
     1011            ...
     1012            sage: a = Foo(2)
     1013            sage: b = Foo(3)
     1014            sage: a.f(b.f)
     1015            2
     1016        """
     1017        # We shortcut a common case of no arguments
     1018        # and we avoid calling another python function,
     1019        # although that means to duplicate code.
     1020        cdef int lenargs
     1021        cdef int nargs
     1022        cdef tuple k
     1023        cdef dict cache = self.cache
     1024        if kwds:
     1025            if self._inst_in_key:
     1026                k = (self._instance,self._fix_to_pos(*args, **kwds))
     1027            else:
     1028                k = self._fix_to_pos(*args, **kwds)
     1029        else:
     1030            if args:
     1031                lenargs = len(args)
     1032                nargs = self._argument_fixer._nargs
     1033                if self._inst_in_key:
     1034                    if lenargs>=nargs:
     1035                        k = (self._instance,(args,()))
     1036                    else:
     1037                        k = (self._instance,(<tuple>args+(<tuple>self._argument_fixer._default_tuple)[-nargs+lenargs:],()))
     1038                else:
     1039                    if lenargs>=nargs:
     1040                        k = (args,())
     1041                    else:
     1042                        k = (<tuple>args+(<tuple>self._argument_fixer._default_tuple)[-nargs+lenargs:],())
     1043            elif self._default_key is not None:
     1044                k = self._default_key
     1045            else:
     1046                if self._inst_in_key:
     1047                    k = self._default_key = (self._instance,self._fix_to_pos())
     1048                else:
     1049                    k = self._default_key = self._fix_to_pos()
     1050        try:
     1051            return cache[k]
     1052        except KeyError:
     1053            w = self._cachedmethod._instance_call(self._instance, *args, **kwds)
     1054            cache[k] = w
     1055            return w
     1056
     1057    def get_key(self, *args, **kwds):
     1058        """
     1059        Convert arguments to the key for this instance's cache.
     1060
     1061        EXAMPLES::
     1062
     1063            sage: class Foo:
     1064            ...       def __init__(self, x):
     1065            ...           self._x = x
     1066            ...       @cached_method
     1067            ...       def f(self, y, z=0):
     1068            ...           return self._x * y + z
     1069            ...
     1070            sage: a = Foo(2)
     1071            sage: z = a.f(37)
     1072            sage: k = a.f.get_key(37); k
     1073            ((37, 0), ())
     1074            sage: a.f.get_cache()[k] is z
     1075            True
     1076
     1077        Note that the method does not test whether there are
     1078        too many arguments, or wrong argument names::
     1079
     1080            sage: a.f.get_key(1,2,3,x=4,y=5,z=6)
     1081            ((1, 2, 3), (('x', 4), ('y', 5), ('z', 6)))
     1082
     1083        It does, however, take into account the different
     1084        ways of providing named arguments, possibly with a
     1085        default value::
     1086
     1087            sage: a.f.get_key(5)
     1088            ((5, 0), ())
     1089            sage: a.f.get_key(y=5)
     1090            ((5, 0), ())
     1091            sage: a.f.get_key(5,0)
     1092            ((5, 0), ())
     1093            sage: a.f.get_key(5,z=0)
     1094            ((5, 0), ())
     1095            sage: a.f.get_key(y=5,z=0)
     1096            ((5, 0), ())
     1097
     1098        """
     1099        if self._inst_in_key:
     1100            return (self._instance,self._fix_to_pos(*args,**kwds))
     1101        return self._fix_to_pos(*args,**kwds)
     1102
     1103    def __get__(self, inst, cls): #cls=None):
     1104        r"""
     1105        Get a :class:`CachedMethodCaller` bound to a specific
     1106        instance of the class of the cached method.
     1107
     1108        NOTE:
     1109
     1110        :class:`CachedMethodCaller` has a separate ``__get__``
     1111        since the categories framework creates and caches the
     1112        return value of ``CachedMethod.__get__`` with
     1113        ``inst==None``.
     1114
     1115        This getter attempts to assign a bound method as an
     1116        attribute to the given instance. If this is not
     1117        possible (for example, for some extension classes),
     1118        it is attempted to find an attribute ``__cached_methods``,
     1119        and store/retrieve the bound method there. In that
     1120        way, cached methods can be implemented for extension
     1121        classes deriving from :class:`~sage.structure.parent.Parent`
     1122        and :class:`~sage.structure.element.Element`.
     1123
     1124        TESTS:
     1125
     1126        Due to the separate ``__get__`` method, it is possible
     1127        to define a cached method in one class and use it as
     1128        an attribute of another class.
     1129
     1130            sage: class Foo:
     1131            ...       @cached_method
     1132            ...       def f(self, y):
     1133            ...           return y - 1
     1134            sage: class Bar:
     1135            ...       f = Foo.f
     1136            sage: b1 = Bar()
     1137            sage: b2 = Bar()
     1138
     1139        The :class:`CachedMethod` is replaced by an instance
     1140        of :class:`CachedMethodCaller` that (by trac ticket
     1141        #8611) is set as an attribute. Hence, we have::
     1142
     1143            sage: b1.f is b1.f
     1144            True
     1145
     1146        Any instance of ``Bar`` gets its own instance of
     1147        :class:`CachedMethodCaller``::
     1148
     1149            sage: b1.f is b2.f
     1150            False
     1151 
     1152        The method caller knows the instance that it belongs
     1153        to::
     1154
     1155            sage: Foo.f._instance is None
     1156            True
     1157            sage: b1.f._instance is b1
     1158            True
     1159            sage: b2.f._instance is b2
     1160            True
     1161
     1162        An extension class can inherit a cached method from the
     1163        parent or element class of a category (trac ticket #11115).
     1164        See :class:`CachedMethodCaller` for examples.
     1165
     1166        """
     1167        # This is for Parents or Elements that do not allow attribute assignment
     1168        try:
     1169            return (<dict>inst.__cached_methods).__getitem__(self._cachedmethod._cachedfunc.__name__)
     1170        except (AttributeError,TypeError,KeyError):
     1171            pass
     1172        Caller = CachedMethodCaller(self._cachedmethod, inst, cache=self._cachedmethod._get_instance_cache(inst), inst_in_key=self._inst_in_key, name=self._cachedmethod._cachedfunc.__name__)
     1173        try:
     1174            setattr(inst,self._cachedmethod._cachedfunc.__name__, Caller)
     1175            return Caller
     1176        except AttributeError,msg:
     1177            pass
     1178        try:
     1179            if inst.__cached_methods is None:
     1180                inst.__cached_methods = {self._cachedmethod._cachedfunc.__name__ : Caller}
     1181            else:
     1182                (<dict>inst.__cached_methods).__setitem__(self._cachedmethod._cachedfunc.__name__, Caller)
     1183        except AttributeError,msg:
     1184            pass
     1185        return Caller
     1186
     1187cdef class CachedMethodCallerNoArgs(CachedFunction):
     1188    """
     1189    Utility class that is used by :class:`CachedMethod` to bind a
     1190    cached method to an instance, in the case of a method that does
     1191    not accept any arguments except ``self``.
     1192
     1193    NOTE:
     1194
     1195    The return value ``None`` would not be cached. So, if you have
     1196    a method that does not accept arguments and may return ``None``
     1197    after a lengthy computation, then ``@cached_method`` should not
     1198    be used.
     1199
     1200    EXAMPLE::
     1201
     1202        sage: P.<a,b,c,d> = QQ[]
     1203        sage: I = P*[a,b]
     1204        sage: I.gens
     1205        Cached version of <function gens at 0x...>
     1206        sage: type(I.gens)
     1207        <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1208        sage: I.gens is I.gens
     1209        True
     1210        sage: I.gens() is I.gens()
     1211        True
     1212
     1213    AUTHOR:
     1214
     1215    - Simon King (2011-04)
     1216    """
     1217    def __init__(self, inst, f, cache=None, name=None):
     1218        """
     1219        EXAMPLES::
     1220
     1221            sage: class Foo:
     1222            ...       def __init__(self, x):
     1223            ...           self._x = x
     1224            ...       @cached_method
     1225            ...       def f(self):
     1226            ...           return self._x^2
     1227            ...
     1228            sage: a = Foo(2)
     1229            sage: print a.f.get_cache()
     1230            None
     1231            sage: a.f()
     1232            4
     1233            sage: a.f.get_cache()
     1234            4
     1235
     1236        """
     1237        # initialize CachedFunction
     1238        if isinstance(f,basestring):
     1239            try:
     1240                F = getattr(inst.__class__,f)
     1241            except AttributeError:
     1242                 F = getattr(inst,f)
     1243            if isinstance(F,CachedFunction):
     1244                f = F.f
     1245            else:
     1246                f = F
     1247        self._common_init(f, None, name=name)
     1248        # This is for unpickling a CachedMethodCallerNoArgs out
     1249        # of an old CachedMethodCaller:
     1250        cachename = '_cache__' + self.__name__
     1251        if hasattr(inst, cachename):
     1252            # This is for data that are pickled in an old format
     1253            CACHE = getattr(inst, cachename)
     1254            if len(CACHE)>1:
     1255                raise TypeError, "Apparently you are opening a pickle in which '%s' was a method accepting arguments"%name
     1256            if len(CACHE)==1:
     1257                self.cache = CACHE.values()[0]
     1258            else:
     1259                self.cache = cache
     1260            delattr(inst, cachename)
     1261        else:
     1262            self.cache = cache  # None means: the underlying method will be called
     1263        self._instance = inst
     1264
     1265    def __reduce__(self):
     1266        """
     1267        Since functions can not be pickled, the cached method caller
     1268        is pickled by a :class:`CachedMethodPickle`, that replaces
     1269        itself by an actual :class:`CachedMethodCallerNoArgs` as soon
     1270        as it is asked to do anything.
     1271
     1272        TEST::
     1273
     1274            sage: P.<a,b,c,d> = QQ[]
     1275            sage: I = P*[a,b]
     1276            sage: I.gens()
     1277            [a, b]
     1278            sage: I.gens
     1279            Cached version of <function gens at 0x...>
     1280            sage: J = loads(dumps(I))
     1281            sage: J.gens
     1282            Pickle of the cached method "gens"
     1283            sage: J.gens.cache
     1284            [a, b]
     1285            sage: J.gens
     1286            Cached version of <function gens at 0x...>
     1287
     1288        """
     1289        return CachedMethodPickle,(self._instance,self.__name__,self.cache)
     1290
     1291    def _instance_call(self):
     1292        """
     1293        Call the cached method without using the cache.
     1294
     1295        EXAMPLE::
     1296
     1297            sage: P.<a,b,c,d> = QQ[]
     1298            sage: I = P*[a,b]
     1299            sage: I.gens()
     1300            [a, b]
     1301            sage: I.gens._instance_call() is I.gens()
     1302            False
     1303            sage: I.gens._instance_call() == I.gens()
     1304            True
     1305
     1306        """
     1307        return self.f(self._instance)
     1308
     1309    def __call__(self):
     1310        """
     1311        Call the cached method.
     1312
     1313        EXAMPLE::
     1314
     1315            sage: P.<a,b,c,d> = QQ[]
     1316            sage: I = P*[a,b]
     1317            sage: I.gens()    # indirect doctest
     1318            [a, b]
     1319            sage: I.gens() is I.gens()
     1320            True
     1321
     1322        """
     1323        if self.cache is None:
     1324            f = self.f
     1325            self.cache = f(self._instance)
     1326        return self.cache
     1327
     1328    def set_cache(self, value):
     1329        """
     1330        Override the cache with a specific value.
     1331
     1332        NOTE:
     1333
     1334        ``None`` is not suitable for a cached value. It would be
     1335        interpreted as an empty cache, forcing a new computation.
     1336
     1337        EXAMPLES::
     1338
     1339            sage: P.<a,b,c,d> = QQ[]
     1340            sage: I = P*[a,b]
     1341            sage: I.gens()
     1342            [a, b]
     1343            sage: I.gens.set_cache('bar')
     1344            sage: I.gens()
     1345            'bar'
     1346
     1347        The cache can be emptied and thus the original value will
     1348        be reconstructed::
     1349
     1350            sage: I.gens.clear_cache()
     1351            sage: I.gens()
     1352            [a, b]
     1353
     1354        The attempt to assign ``None`` to the cache fails::
     1355
     1356            sage: I.gens.set_cache(None)
     1357            sage: I.gens()
     1358            [a, b]
     1359
     1360        """
     1361        self.cache = value
     1362
     1363    cpdef clear_cache(self):
     1364        r"""
     1365        Clear the cache dictionary.
     1366
     1367        EXAMPLES::
     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.set_cache('bar')
     1374            sage: I.gens()
     1375            'bar'
     1376
     1377        The cache can be emptied and thus the original value will
     1378        be reconstructed::
     1379
     1380            sage: I.gens.clear_cache()
     1381            sage: I.gens()
     1382            [a, b]
     1383
     1384        """
     1385        self.cache = None
     1386
     1387    def is_in_cache(self):
     1388        """
     1389        Answers whether the return value is already in the cache.
     1390
     1391        NOTE:
     1392
     1393        Recall that a cached method without arguments can not cache
     1394        the return value ``None``.
     1395
     1396        EXAMPLE::
     1397
     1398            sage: P.<x,y> = QQ[]
     1399            sage: I = P*[x,y]
     1400            sage: I.gens.is_in_cache()
     1401            False
     1402            sage: I.gens()
     1403            [x, y]
     1404            sage: I.gens.is_in_cache()
     1405            True
     1406
     1407        """
     1408        return self.cache is not None
     1409
     1410    def __get__(self, inst, cls): #cls=None):
     1411        """
     1412        Get a :class:`CachedMethodCallerNoArgs` bound to a specific
     1413        instance of the class of the cached method.
     1414
     1415        NOTE:
     1416
     1417        :class:`CachedMethodCallerNoArgs` has a separate ``__get__``
     1418        since the categories framework creates and caches the
     1419        return value of ``CachedMethod.__get__`` with
     1420        ``inst==None``.
     1421
     1422        This getter attempts to assign a bound method as an
     1423        attribute to the given instance. If this is not
     1424        possible (for example, for some extension classes),
     1425        it is attempted to find an attribute ``__cached_methods``,
     1426        and store/retrieve the bound method there. In that
     1427        way, cached methods can be implemented for extension
     1428        classes deriving from :class:`~sage.structure.parent.Parent`
     1429        and :class:`~sage.structure.element.Element`.
     1430
     1431        TESTS:
     1432
     1433        Due to the separate ``__get__`` method, it is possible
     1434        to define a cached method in one class and use it as
     1435        an attribute of another class.
     1436
     1437            sage: class Foo:
     1438            ...       def __init__(self, n):
     1439            ...           self.__n = n
     1440            ...       @cached_method
     1441            ...       def f(self):
     1442            ...           return self.__n^2
     1443            ...
     1444            sage: class Bar:
     1445            ...       f = Foo.f
     1446            ...
     1447            sage: b1 = Bar()
     1448            sage: b2 = Bar()
     1449
     1450        The :class:`CachedMethod` is replaced by an instance of
     1451        :class:`CachedMethodCallerNoArgs` that is set as an
     1452        attribute. Hence, we have::
     1453
     1454            sage: b1.f is b1.f
     1455            True
     1456            sage: type(b1.f)
     1457            <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1458
     1459        Any instance of ``Bar`` gets its own instance of
     1460        :class:`CachedMethodCaller``::
     1461
     1462            sage: b1.f is b2.f
     1463            False
     1464 
     1465        The method caller knows the instance that it belongs
     1466        to::
     1467
     1468            sage: Foo.f._instance is None
     1469            True
     1470            sage: b1.f._instance is b1
     1471            True
     1472            sage: b2.f._instance is b2
     1473            True
     1474
     1475        """
     1476        # This is for Parents or Elements that do not allow attribute assignment
     1477        try:
     1478            return (<dict>inst.__cached_methods).__getitem__(self.__name__)
     1479        except (AttributeError,TypeError,KeyError),msg:
     1480            pass
     1481        Caller = CachedMethodCallerNoArgs(inst, self.f, name=self.__name__)
     1482        try:
     1483            setattr(inst,self.__name__, Caller)
     1484            return Caller
     1485        except AttributeError:
     1486            pass
     1487        try:
     1488            if inst.__cached_methods is None:
     1489                inst.__cached_methods = {self.__name__ : Caller}
     1490            else:
     1491                (<dict>inst.__cached_methods).__setitem__(self.__name__, Caller)
     1492        except AttributeError,msg:
     1493            pass
     1494        return Caller
     1495
     1496cdef class CachedMethod(object):
     1497    """
     1498    A decorator that creates a cached version of an instance
     1499    method of a class.
     1500
     1501    NOTE:
     1502
     1503    For proper behavior, the method must be a pure function
     1504    (no side effects). Arguments to the method must be hashable.
     1505
     1506    EXAMPLES::
     1507
     1508        sage: class Foo(object):
     1509        ...       @cached_method
     1510        ...       def f(self, t, x=2):
     1511        ...           print 'computing'
     1512        ...           return t**x
     1513        sage: a = Foo()
     1514
     1515    The example shows that the actual computation
     1516    takes place only once, and that the result is
     1517    identic for equivalent input::
     1518   
     1519        sage: res = a.f(3, 2); res
     1520        computing
     1521        9
     1522        sage: a.f(t = 3, x = 2) is res
     1523        True
     1524        sage: a.f(3) is res
     1525        True
     1526
     1527    Note, however, that the :class:`CachedMethod` is replaced by a
     1528    :class:`CachedMethodCaller` or :class:`CachedMethodCallerNoArgs`
     1529    as soon as it is bound to an instance or class::
     1530
     1531        sage: P.<a,b,c,d> = QQ[]
     1532        sage: I = P*[a,b]
     1533        sage: type(I.__class__.gens)
     1534        <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1535
     1536    So, you would hardly ever see an instance of this class alive.
     1537    """
     1538    def __init__(self, f, name=None):
     1539        """
     1540        EXAMPLES::
     1541
     1542            sage: class Foo:
     1543            ...       def __init__(self, x):
     1544            ...           self._x = x
     1545            ...       @cached_method
     1546            ...       def f(self,n):
     1547            ...           return self._x^n
     1548            ...       @cached_method
     1549            ...       def f0(self):
     1550            ...           return self._x^2
     1551            ...
     1552            sage: a = Foo(2)
     1553            sage: a.f(2)
     1554            4
     1555            sage: a.f0()
     1556            4
     1557
     1558        The computations in method ``f`` are tried to store in a
     1559        dictionary assigned to the instance ``a``::
     1560
     1561            sage: hasattr(a, '_cache__f')
     1562            True
     1563            sage: a._cache__f
     1564            {((2,), ()): 4}
     1565
     1566        As a shortcut, useful to speed up internal computations,
     1567        the same dictionary is also available as an attribute
     1568        of the ``CachedMethodCaller``::
     1569
     1570            sage: type(a.f)
     1571            <type 'sage.misc.cachefunc.CachedMethodCaller'>
     1572            sage: a.f.cache is a._cache__f
     1573            True
     1574
     1575        Note that if the instance ``a`` would not accept attribute
     1576        assignment, the computations would still be cached in
     1577        ``a.f.cache``, and they would in fact be preserved when
     1578        pickling.
     1579
     1580        The cached method ``f0`` accepts no arguments, which allows
     1581        for an improved way of caching: By an attribute of the cached
     1582        method itsel. This cache is *only* available in that way, i.e.,
     1583        it is not additionally stored as an attribute of ``a``::
     1584
     1585            sage: type(a.f0)
     1586            <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1587            sage: a.f0.cache
     1588            4
     1589            sage: sorted(dir(a))
     1590            ['__doc__', '__init__', '__module__', '_cache__f', '_x', 'f', 'f0']
     1591
     1592        """
     1593        self._cache_name = '_cache__' + (name or f.__name__)
     1594        self._cachedfunc = CachedFunction(f, classmethod=True, name=name)
     1595
     1596    def _instance_call(self, inst, *args, **kwds):
     1597        """
     1598        Call the cached method *without* using the cache.
     1599
     1600        INPUT:
     1601
     1602        - ``inst`` - an instance at which the method is to be called
     1603        - Further positional or named arguments.
     1604
     1605        EXAMPLES::
     1606
     1607            sage: class Foo(object):
     1608            ...       def __init__(self, x):
     1609            ...           self._x = x
     1610            ...       @cached_method
     1611            ...       def f(self,n=2):
     1612            ...           return self._x^n
     1613            ...
     1614            sage: a = Foo(2)
     1615            sage: a.f()
     1616            4
     1617
     1618        Usually, a cached method is indeed cached::
     1619
     1620            sage: a.f() is a.f()
     1621            True
     1622
     1623        However, when it becomes necessary, one can call it without
     1624        using the cache. Note that ``a.f`` is an instance of
     1625        :class:`CachedMethodCaller`.  But its
     1626        :meth:`CachedMethodCaller._instance_call` relies on this
     1627        method, so, we have an indirect doctest::
     1628
     1629            sage: a.f._instance_call() is a.f() # indirect doctest
     1630            False
     1631            sage: a.f._instance_call() == a.f()
     1632            True
     1633
     1634        """
     1635        return self._cachedfunc.f(inst, *args, **kwds)
     1636
     1637    cpdef dict _get_instance_cache(self, inst):
     1638        """
     1639        Returns the cache dictionary.
     1640
     1641        TESTS::
     1642
     1643            sage: class Foo:
     1644            ...       def __init__(self, x):
     1645            ...           self._x = x
     1646            ...       @cached_method
     1647            ...       def f(self,n=2):
     1648            ...           return self._x^n
     1649            ...
     1650            sage: a = Foo(2)
     1651            sage: a.f()
     1652            4
     1653
     1654        Note that we can not provide a direct test, since ``a.f`` is
     1655        an instance of :class:`CachedMethodCaller`.  But during its
     1656        initialisation, this method was called in order to provide the
     1657        cached method caller with its cache, and, if possible, assign
     1658        it to an attribute of ``a``.  So, the following is an indirect
     1659        doctest::
     1660
     1661            sage: a.f.get_cache()    # indirect doctest
     1662            {((2,), ()): 4}
     1663            sage: a._cache__f
     1664            {((2,), ()): 4}
     1665
     1666        """
     1667        try:
     1668            return inst.__dict__.setdefault(self._cache_name, {})
     1669        except AttributeError:
     1670            return {}
     1671
     1672    def __get__(self, inst, cls): #cls=None):
     1673        """
     1674        Get a CachedMethodCaller bound to this specific instance of
     1675        the class of the cached method.
     1676
     1677        TESTS::
     1678
     1679            sage: class Foo:
     1680            ...       @cached_method
     1681            ...       def f(self):
     1682            ...           return 1
     1683            ...       @cached_method
     1684            ...       def g(self, x,n=3):
     1685            ...           return x^n
     1686            ...
     1687            sage: a = Foo()
     1688            sage: type(a.f)
     1689            <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'>
     1690            sage: type(a.g)
     1691            <type 'sage.misc.cachefunc.CachedMethodCaller'>
     1692
     1693        By trac ticket #8611, it is attempted to set the
     1694        CachedMethodCaller as an attribute of the instance ``a``,
     1695        replacing the original cached attribute. Therefore, the
     1696        ``__get__`` method will be used only once, which saves much
     1697        time. Hence, we have::
     1698 
     1699            sage: a.f is a.f
     1700            True
     1701            sage: a.g is a.g
     1702            True
     1703
     1704        """
     1705        # This is for Parents or Elements that do not allow attribute assignment:
     1706        try:
     1707            name = self._cachedfunc.__name__
     1708        except AttributeError:
     1709            name = self.__name__
     1710        try:
     1711            return (<dict>inst.__cached_methods).__getitem__(name)
     1712        except (AttributeError,TypeError,KeyError),msg:
     1713            pass
     1714        # Apparently we need to construct the caller.
     1715        # Since we have an optimized version for functions that do not accept arguments,
     1716        # we need to analyse the argspec
     1717        f = (<CachedFunction>self._cachedfunc).f
     1718        from sage.misc.sageinspect import sage_getargspec
     1719        args, varargs, keywords, defaults = sage_getargspec(f)
     1720        if varargs is None and keywords is None and len(args)<=1:
     1721            Caller = CachedMethodCallerNoArgs(inst, f, name=name)
     1722        else:
     1723            Caller = CachedMethodCaller(self, inst,
     1724            cache=self._get_instance_cache(inst), name=name)
     1725        try:
     1726            setattr(inst,name, Caller)
     1727            return Caller
     1728        except AttributeError:
     1729            pass
     1730        try:
     1731            if inst.__cached_methods is None:
     1732                inst.__cached_methods = {name : Caller}
     1733            else:
     1734                (<dict>inst.__cached_methods).__setitem__(name, Caller)
     1735        except AttributeError:
     1736            pass
     1737        return Caller
     1738
     1739        # Note: a simpler approach to this would be
     1740        # def caller(*args, **kwds):
     1741        #     return self._instance_call(inst, *args, **kwds)
     1742        # return caller
     1743        # The disadvantage to this is that it does not provide
     1744        # is_in_cache(), set_cache(), clear_cache(), ... methods.
     1745
     1746
     1747cached_method = CachedMethod
     1748
     1749cdef class CachedInParentMethod(CachedMethod):
     1750    r"""
     1751    A decorator that creates a cached version of an instance
     1752    method of a class.
     1753
     1754    In contrast to :class:`CachedMethod`,
     1755    the cache dictionary is an attribute of the parent of
     1756    the instance to which the method belongs.
     1757
     1758    ASSUMPTION:
     1759
     1760    This way of caching works only if
     1761
     1762    - the instances *have* a parent, and
     1763    - the instances are hashable (they are part of the cache key).
     1764
     1765    NOTE:
     1766
     1767    For proper behavior, the method must be a pure function (no side
     1768    effects). If this decorator is used on a method, it will have
     1769    identical output on equal elements. This is since the element is
     1770    part of the hash key. Arguments to the method and the instance
     1771    it is assigned to must be hashable.
     1772
     1773    Examples can be found at :mod:`~sage.misc.cachefunc`.
     1774
     1775    """
     1776
     1777    def __init__(self, f, name=None):
     1778        """
     1779        Constructs a new method with cache stored in the parent of the instance.
     1780
     1781        See also ``cached_method`` and ``cached_function``.
     1782
     1783        EXAMPLES::
     1784
     1785            sage: class MyParent(Parent):
     1786            ...       pass
     1787            sage: class Foo:
     1788            ...       def __init__(self, x):
     1789            ...           self._x = x
     1790            ...       _parent = MyParent()
     1791            ...       def parent(self):
     1792            ...           return self._parent
     1793            ...       @cached_in_parent_method  #indirect doctest
     1794            ...       def f(self):
     1795            ...           return self._x^2
     1796            ...
     1797            sage: a = Foo(2)
     1798            sage: a.f()
     1799            4
     1800            sage: hasattr(a.parent(), '_cache__element_f')
     1801            True
     1802
     1803        For speeding up internal computations, this dictionary
     1804        is also accessible as an attribute of the CachedMethodCaller
     1805        (by trac ticket #8611)::
     1806
     1807            sage: a.parent()._cache__element_f is a.f.cache
     1808            True
     1809        """
     1810        self._cache_name = '_cache__' + 'element_' + (name or f.__name__)
     1811        self._cachedfunc = CachedFunction(f, classmethod=True, name=name)
     1812
     1813    cpdef dict _get_instance_cache(self, inst):
     1814        """
     1815        Returns the cache dictionary, which is stored in the parent.
     1816
     1817        EXAMPLES::
     1818
     1819            sage: class MyParent(Parent):
     1820            ...       pass
     1821            ...
     1822            sage: class Foo:
     1823            ...       def __init__(self, x):
     1824            ...           self._x = x
     1825            ...       _parent = MyParent()
     1826            ...       def parent(self):
     1827            ...           return self._parent
     1828            ...       def __eq__(self, other):
     1829            ...           return self._x^2 == other._x^2
     1830            ...       def __hash__(self):
     1831            ...           return hash(self._x^2)
     1832            ...       def __repr__(self):
     1833            ...           return 'My %s'%self._x
     1834            ...       @cached_in_parent_method
     1835            ...       def f(self):
     1836            ...           return self._x^3
     1837            ...
     1838            sage: a = Foo(2)
     1839            sage: a.f()
     1840            8
     1841            sage: a.f.get_cache()   #indirect doctest
     1842            {(My 2, ((), ())): 8}
     1843
     1844        Since the key for the cache depends on equality of
     1845        the instances, we obtain *identical* result for
     1846        *equal* instance - even though in this particular
     1847        example the result is wrong::
     1848
     1849            sage: b = Foo(-2)
     1850            sage: a is not b
     1851            True
     1852            sage: a == b
     1853            True
     1854            sage: b.f() is a.f()
     1855            True
     1856
     1857        Non-equal instances do not share the result of
     1858        the cached method, but they do share the cache::
     1859
     1860            sage: c = Foo(3)
     1861            sage: c.f()
     1862            27
     1863            sage: c.f.get_cache() is a.f.get_cache() #indirect doctest
     1864            True
     1865
     1866        Note that the cache is also available as an
     1867        attribute of the cached method, which speeds
     1868        up internal computations::
     1869
     1870            sage: a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c)
     1871            True
     1872
     1873        """
     1874        if inst is None:
     1875            return {}
     1876        try:
     1877            P = inst.parent()
     1878            return P.__dict__.setdefault(self._cache_name, {})
     1879        except AttributeError:
     1880            pass
     1881        if not hasattr(P,'__cached_methods'):
     1882            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."
     1883        if P.__cached_methods is None:
     1884            P.__cached_methods = {}
     1885        return (<dict>P.__cached_methods).setdefault(self._cache_name, {})
     1886
     1887    def __get__(self, inst, cls): #cls=None):
     1888        """
     1889        Get a CachedMethodCaller bound to this specific instance of
     1890        the class of the cached-in-parent method.
     1891        """
     1892        Caller = CachedMethodCaller(self, inst, cache=self._get_instance_cache(inst), inst_in_key=True)
     1893        try:
     1894            setattr(inst,self._cachedfunc.__name__, Caller)
     1895        except AttributeError:
     1896            pass
     1897        return Caller
     1898
     1899cached_in_parent_method = CachedInParentMethod
     1900
     1901class FileCache:
     1902    """
     1903    FileCache is a dictionary-like class which stores keys and
     1904    values on disk.  The keys take the form of a tuple (A,K)
     1905
     1906    - A is a tuple of objects t where each t is an exact
     1907      object which is uniquely identified by a short string.
     1908
     1909    - K is a tuple of tuples (s,v) where s is a valid
     1910      variable name and v is an exact object which is uniquely
     1911      identified by a short string with letters [a-zA-Z0-9-._]
     1912
     1913    The primary use case is the DiskCachedFunction.  If
     1914    ``memory_cache == True``, we maintain a cache of objects seen
     1915    during this session in memory -- but we don't load them from
     1916    disk until necessary.  The keys and values are stored in a
     1917    pair of files:
     1918
     1919    - ``prefix-argstring.key.sobj`` contains the ``key`` only,
     1920    - ``prefix-argstring.sobj`` contains the tuple ``(key,val)``
     1921
     1922    where ``self[key] == val``.
     1923
     1924    NOTE:
     1925
     1926    We assume that each FileCache lives in its own directory.
     1927    Use **extreme** caution if you wish to break that assumption.
     1928    """
     1929    def __init__(self, dir, prefix = '', memory_cache = False):
     1930        """
     1931        EXAMPLES::
     1932
     1933            sage: from sage.misc.cachefunc import FileCache
     1934            sage: dir = tmp_dir()
     1935            sage: FC = FileCache(dir, memory_cache = True)
     1936            sage: FC[((),())] = 1
     1937            sage: FC[((1,2),())] = 2
     1938            sage: FC[((),())]
     1939            1
     1940        """
     1941        if len(dir) == 0 or dir[-1] != '/':
     1942            dir += '/'
     1943        self._dir = dir
     1944        if not os.path.exists(dir):
     1945            os.mkdir(dir)
     1946
     1947        self._prefix = prefix + '-'
     1948
     1949        if memory_cache:
     1950            self._cache = {}
     1951        else:
     1952            self._cache = None
     1953
     1954    def file_list(self):
     1955        """
     1956        Returns the list of files corresponding to self.
     1957
     1958        EXAMPLES::
     1959
     1960            sage: from sage.misc.cachefunc import FileCache
     1961            sage: dir = tmp_dir()
     1962            sage: FC = FileCache(dir, memory_cache = True, prefix='t')
     1963            sage: FC[((),())] = 1
     1964            sage: FC[((1,2),())] = 2
     1965            sage: FC[((1,),(('a',1),))] = 3
     1966            sage: for f in sorted(FC.file_list()): print f[len(dir):]
     1967            /t-.key.sobj
     1968            /t-.sobj
     1969            /t-1_2.key.sobj
     1970            /t-1_2.sobj
     1971            /t-a-1.1.key.sobj
     1972            /t-a-1.1.sobj
     1973        """
     1974        files = []
     1975        prefix = self._prefix
     1976        dir = self._dir
     1977        l = len(prefix)
     1978        for f in os.listdir(dir):
     1979            if f[:l] == prefix:
     1980                files.append( dir + f )
     1981        return files
     1982
     1983    def items(self):
     1984        """
     1985        Returns a list of tuples ``(k,v)`` where ``self[k] = v``.
     1986
     1987        EXAMPLES::
     1988
     1989            sage: from sage.misc.cachefunc import FileCache
     1990            sage: dir = tmp_dir()
     1991            sage: FC = FileCache(dir, memory_cache = False)
     1992            sage: FC[((),())] = 1
     1993            sage: FC[((1,2),())] = 2
     1994            sage: FC[((1,),(('a',1),))] = 3
     1995            sage: I = FC.items()
     1996            sage: I.sort(); print I
     1997            [(((), ()), 1), (((1,), (('a', 1),)), 3), (((1, 2), ()), 2)]
     1998        """
     1999        return [(k,self[k]) for k in self]
     2000
     2001    def values(self):
     2002        """
     2003        Returns a list of values that are stored in ``self``.
     2004
     2005        EXAMPLES::
     2006
     2007            sage: from sage.misc.cachefunc import FileCache
     2008            sage: dir = tmp_dir()
     2009            sage: FC = FileCache(dir, memory_cache = False)
     2010            sage: FC[((),())] = 1
     2011            sage: FC[((1,2),())] = 2
     2012            sage: FC[((1,),(('a',1),))] = 3
     2013            sage: FC[((),(('a',1),))] = 4
     2014            sage: v = FC.values()
     2015            sage: v.sort(); print v
     2016            [1, 2, 3, 4]
     2017        """
     2018        return [self[k] for k in self]
     2019
     2020    def __iter__(self):
     2021        """
     2022        Returns a list of keys of ``self``.
     2023
     2024        EXAMPLES::
     2025
     2026            sage: from sage.misc.cachefunc import FileCache
     2027            sage: dir = tmp_dir()
     2028            sage: FC = FileCache(dir, memory_cache = False)
     2029            sage: FC[((),())] = 1
     2030            sage: FC[((1,2),())] = 2
     2031            sage: FC[((1,),(('a',1),))] = 3
     2032            sage: for k in sorted(FC): print k
     2033            ((), ())
     2034            ((1,), (('a', 1),))
     2035            ((1, 2), ())
     2036        """
     2037        return self.keys().__iter__()
     2038
     2039    def keys(self):
     2040        """
     2041        Returns a list of keys ``k`` where ``self[k]`` is defined.
     2042
     2043        EXAMPLES::
     2044
     2045            sage: from sage.misc.cachefunc import FileCache
     2046            sage: dir = tmp_dir()
     2047            sage: FC = FileCache(dir, memory_cache = False)
     2048            sage: FC[((),())] = 1
     2049            sage: FC[((1,2),())] = 2
     2050            sage: FC[((1,),(('a',1),))] = 3
     2051            sage: K = FC.keys()
     2052            sage: K.sort(); print K
     2053            [((), ()), ((1,), (('a', 1),)), ((1, 2), ())]
     2054        """
     2055        cdef list K = []
     2056        from sage.structure.sage_object import load
     2057        for f in self.file_list():
     2058            if f[-9:] == '.key.sobj':
     2059                K.append(load(f))
     2060        return K
     2061
     2062    def _filename(self, key):
     2063        """
     2064        Computes the filename associated with a certain key.
     2065
     2066        EXAMPLES::
     2067
     2068            sage: from sage.misc.cachefunc import FileCache
     2069            sage: dir = tmp_dir() + '/'
     2070            sage: FC = FileCache(dir, memory_cache = False, prefix='foo')
     2071            sage: N = FC._filename(((1,2), (('a',1),('b',2))))
     2072            sage: print N[len(dir):]
     2073            foo-a-1_b-2.1_2
     2074            sage: N = FC._filename(((), (('a',1),('b',2))))
     2075            sage: print N[len(dir):]
     2076            foo-a-1_b-2
     2077            sage: N = FC._filename(((1,2), ()))
     2078            sage: print N[len(dir):]
     2079            foo-1_2
     2080        """
     2081        a,k = key
     2082        kwdstr = '_'.join(['%s-%s'%x for x in k])
     2083        argstr = '_'.join(['%s'%x for x in a])
     2084        if kwdstr and argstr:
     2085            keystr = kwdstr + '.' + argstr
     2086        else:
     2087            keystr = kwdstr + argstr
     2088        return self._dir + self._prefix + keystr
     2089
     2090    def has_key(self, key):
     2091        """
     2092        Returns ``True`` if ``self[key]`` is defined and False otherwise.
     2093
     2094        EXAMPLES::
     2095
     2096            sage: from sage.misc.cachefunc import FileCache
     2097            sage: dir = tmp_dir() + '/'
     2098            sage: FC = FileCache(dir, memory_cache = False, prefix='foo')
     2099            sage: k = ((),(('a',1),))
     2100            sage: FC[k] = True
     2101            sage: FC.has_key(k)
     2102            True
     2103            sage: FC.has_key(((),()))
     2104            False
     2105        """
     2106        return os.path.exists(self._filename(key) + '.key.sobj')
     2107
     2108    def __getitem__(self, key):
     2109        """
     2110        Returns the value set by ``self[key] = val``, in this session
     2111        or a previous one.
     2112
     2113        EXAMPLES::
     2114
     2115            sage: from sage.misc.cachefunc import FileCache
     2116            sage: dir = tmp_dir() + '/'
     2117            sage: FC1 = FileCache(dir, memory_cache = False, prefix='foo')
     2118            sage: FC2 = FileCache(dir, memory_cache = False, prefix='foo')
     2119            sage: k = ((),(('a',1),))
     2120            sage: t = randint(0, 1000)
     2121            sage: FC1[k] = t
     2122            sage: FC2[k] == FC1[k] == t
     2123            True
     2124            sage: FC1[(1,2),(('a',4),('b',2))]
     2125            Traceback (most recent call last):
     2126            ...
     2127            KeyError: ((1, 2), (('a', 4), ('b', 2)))
     2128
     2129        """
     2130        from sage.structure.sage_object import load
     2131
     2132        cache = self._cache
     2133        if cache is not None:
     2134            if cache.has_key(key):
     2135                return cache[key]
     2136
     2137        f = self._filename(key) + '.sobj'
     2138        try:
     2139            k,v = load(f)
     2140        except IOError:
     2141            raise KeyError, key
     2142        if k != key:
     2143            raise RuntimeError, "cache corrupted"
     2144
     2145        if cache is not None:
     2146            cache[key] = v
     2147        return v
     2148
     2149    def __setitem__(self, key, value):
     2150        """
     2151        Sets ``self[key] = value`` and stores both key and value on
     2152        disk.
     2153
     2154        EXAMPLES::
     2155
     2156            sage: from sage.misc.cachefunc import FileCache
     2157            sage: dir = tmp_dir() + '/'
     2158            sage: FC1 = FileCache(dir, memory_cache = False, prefix='foo')
     2159            sage: FC2 = FileCache(dir, memory_cache = False, prefix='foo')
     2160            sage: k = ((),(('a',1),))
     2161            sage: t = randint(0, 1000)
     2162            sage: FC1[k] = t
     2163            sage: FC2[k] == t
     2164            True
     2165            sage: FC1[k] = 2000
     2166            sage: FC2[k]!= t
     2167            True
     2168        """
     2169        from sage.structure.sage_object import save
     2170
     2171        f = self._filename(key)
     2172
     2173        save(key, f+'.key.sobj')
     2174        save((key,value), f + '.sobj')
     2175        if self._cache is not None:
     2176            self._cache[key] = value
     2177
     2178    def __delitem__(self, key):
     2179        """
     2180        Delete the key,value pair from self and unlink the associated
     2181        files from the file cache.
     2182
     2183        EXAMPLES::
     2184
     2185            sage: from sage.misc.cachefunc import FileCache
     2186            sage: dir = tmp_dir() + '/'
     2187            sage: FC1 = FileCache(dir, memory_cache = False, prefix='foo')
     2188            sage: FC2 = FileCache(dir, memory_cache = False, prefix='foo')
     2189            sage: k = ((),(('a',1),))
     2190            sage: t = randint(0, 1000)
     2191            sage: FC1[k] = t
     2192            sage: del FC2[k]
     2193            sage: FC1.has_key(k)
     2194            False
     2195       """
     2196        f = self._filename(key)
     2197        cache = self._cache
     2198        if cache is not None and cache.has_key(key):
     2199            del self._cache[key]
     2200        if os.path.exists(f + '.sobj'):
     2201            os.remove(f + '.sobj')
     2202        if  os.path.exists(f + '.key.sobj'):
     2203           os.remove(f + '.key.sobj')
     2204
     2205
     2206class DiskCachedFunction(CachedFunction):
     2207    """
     2208    Works similar to CachedFunction, but instead, we keep the
     2209    cache on disk (optionally, we keep it in memory too).
     2210
     2211    EXAMPLES::
     2212
     2213        sage: from sage.misc.cachefunc import DiskCachedFunction
     2214        sage: dir = tmp_dir()
     2215        sage: factor = DiskCachedFunction(factor, dir, memory_cache=True)
     2216        sage: f = factor(2775); f
     2217        3 * 5^2 * 37
     2218        sage: f is factor(2775)
     2219        True
     2220    """
     2221    def __init__(self, f, dir, memory_cache=False):
     2222        """
     2223        EXAMPLES::
     2224
     2225            sage: from sage.misc.cachefunc import DiskCachedFunction
     2226            sage: def foo(x): sleep(x)
     2227            sage: dir = tmp_dir()
     2228            sage: bar = DiskCachedFunction(foo, dir, memory_cache = False)
     2229            sage: w = walltime()
     2230            sage: for i in range(10): bar(1)
     2231            sage: walltime(w) < 2
     2232            True
     2233        """
     2234        CachedFunction.__init__(self, f)
     2235        prefix = f.__name__
     2236        self.cache = FileCache(dir, prefix=prefix, memory_cache = memory_cache)
     2237
     2238
     2239class disk_cached_function:
     2240    """
     2241    Decorator for :class:`DiskCachedFunction`.
     2242
     2243    EXAMPLES::
     2244
     2245        sage: dir = tmp_dir()
     2246        sage: @disk_cached_function(dir)
     2247        ... def foo(x): return next_prime(2^x)%x
     2248        sage: x = foo(200);x
     2249        11
     2250        sage: @disk_cached_function(dir)
     2251        ... def foo(x): return 1/x
     2252        sage: foo(200)
     2253        11
     2254        sage: foo.clear_cache()
     2255        sage: foo(200)
     2256        1/200
     2257    """
     2258    def __init__(self, dir, memory_cache = False):
     2259        """
     2260        EXAMPLES::
     2261
     2262            sage: dir = tmp_dir()
     2263            sage: @disk_cached_function(dir, memory_cache=True)
     2264            ... def foo(x): return next_prime(2^x)
     2265            sage: x = foo(200)
     2266            sage: x is foo(200)
     2267            True
     2268            sage: @disk_cached_function(dir, memory_cache=False)
     2269            ... def foo(x): return next_prime(2^x)
     2270            sage: x is foo(200)
     2271            False
     2272        """
     2273        self._dir = dir
     2274        self._memory_cache = memory_cache
     2275
     2276    def __call__(self, f):
     2277        """
     2278        EXAMPLES::
     2279
     2280            sage: dir = tmp_dir()
     2281            sage: @disk_cached_function(dir)
     2282            ... def foo(x): return ModularSymbols(x)
     2283            sage: foo(389)
     2284            Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field
     2285        """
     2286        return DiskCachedFunction(f, self._dir, memory_cache = self._memory_cache)
     2287
     2288class ClearCacheOnPickle(object):
     2289    r"""
     2290    This class implements an appropriate ``__getstate__`` method that
     2291    clears the cache of the methods (see @cached_method) before
     2292    passing them on to the caller, typically the pickle and copy modules.
     2293
     2294    The implemented ``__getstate__`` method calls the ``__getstate__``
     2295    methods of classes later in the method resolution
     2296    order. Therefore, classes which want this behaviour should inherit
     2297    first from this one.
     2298
     2299    EXAMPLE:
     2300
     2301    In the following example, we create a Python class that inherits
     2302    from multivariate polynomial ideals, but does not pickle cached
     2303    values.  We provide the definition in Cython, however, since
     2304    interactive Cython definitions provide introspection by trac
     2305    ticket #9976, whereas Python definitions don't.
     2306    ::
     2307
     2308        sage: P.<a,b,c,d> = QQ[]
     2309        sage: I = P*[a,b]
     2310        sage: classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle',
     2311        ...    'from sage.all import QQ',
     2312        ...    'P = QQ["a","b","c","d"]; I = P*[P.gen(0),P.gen(1)]',
     2313        ...    'class MyClass(ClearCacheOnPickle,I.__class__):',
     2314        ...    '    def __init__(self,ring,gens):',
     2315        ...    '        I.__class__.__init__(self,ring,gens)',
     2316        ...    '    def __getnewargs__(self):',
     2317        ...    '        return (self._Ideal_generic__ring,self._Ideal_generic__gens)']
     2318        sage: cython('\n'.join(classdef))
     2319
     2320    We destroy the cache of two methods of ``I`` on purpose
     2321    (demonstrating that the two different implementations of cached
     2322    methods are correctly dealt with).  Pickling ``I`` preserves the
     2323    cache::
     2324
     2325        sage: I.gens.set_cache('bar')
     2326        sage: I.groebner_basis.set_cache('foo',algorithm='singular')
     2327        sage: J = loads(dumps(I))
     2328        sage: J.gens()
     2329        'bar'
     2330        sage: J.groebner_basis(algorithm='singular')
     2331        'foo'
     2332
     2333    However, if we have an ideal that additionally descends from
     2334    :class:`ClearCacheOnPickle`, the carefully corrupted cache is not
     2335    pickled::
     2336
     2337        sage: A = MyClass(P,[a,b])
     2338        sage: A
     2339        Ideal (a, b) of Multivariate Polynomial Ring in a, b, c, d over Rational Field
     2340        sage: A.gens.set_cache('foo')
     2341        sage: A.groebner_basis.set_cache('bar',algorithm='singular')
     2342        sage: A.gens()
     2343        'foo'
     2344        sage: A.groebner_basis(algorithm='singular')
     2345        'bar'
     2346        sage: B = loads(dumps(A))
     2347        sage: B.gens()
     2348        [a, b]
     2349        sage: B.groebner_basis(algorithm='singular')
     2350        [a, b]
     2351        sage: A.gens()
     2352        'foo'
     2353
     2354    """
     2355    def __getstate__(self):
     2356        r"""
     2357        The idea is to remove that might provide a cache to some cached method
     2358        from the return value of the ``__getstate__`` method.
     2359
     2360        EXAMPLE:
     2361
     2362        In the following example, we create a Python class that
     2363        inherits from multivariate polynomial ideals, but clears the
     2364        cache as well.
     2365
     2366            sage: P.<a,b,c,d> = QQ[]
     2367            sage: I = P*[a,b]
     2368
     2369        We destroy the cache of two methods if ``I`` on purpose
     2370        (demonstrating that the two different implementations of cached
     2371        methods are correctly dealt with).  Pickling ``I`` preserves the
     2372        cache::
     2373
     2374            sage: I.gens.set_cache('bar')
     2375            sage: I.groebner_basis.set_cache('foo',algorithm='singular')
     2376            sage: J = loads(dumps(I))
     2377            sage: J.gens()
     2378            'bar'
     2379            sage: J.groebner_basis(algorithm='singular')
     2380            'foo'
     2381
     2382        However, if we do the same with a class that additionally
     2383        descends from :class:`ClearCacheOnPickle`, the cache is not
     2384        pickled. We provide the definition in Cython, however, since
     2385        interactive Cython definitions provide introspection by trac
     2386        ticket #9976, whereas Python definitions don't.
     2387        ::
     2388
     2389            sage: classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle',
     2390            ...    'from sage.all import QQ',
     2391            ...    'from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal',
     2392            ...    'class MyClass(ClearCacheOnPickle,MPolynomialIdeal):',
     2393            ...    '    def __init__(self,ring,gens):',
     2394            ...    '        MPolynomialIdeal.__init__(self,ring,gens)',
     2395            ...    '    def __getnewargs__(self):',
     2396            ...    '        return (self._Ideal_generic__ring,self._Ideal_generic__gens)']
     2397            sage: cython('\n'.join(classdef))
     2398            sage: A = MyClass(P,[a,b])
     2399            sage: A
     2400            Ideal (a, b) of Multivariate Polynomial Ring in a, b, c, d over Rational Field
     2401            sage: A.gens.set_cache('foo')
     2402            sage: A.groebner_basis.set_cache('bar',algorithm='singular')
     2403            sage: A.gens()
     2404            'foo'
     2405            sage: A.groebner_basis(algorithm='singular')
     2406            'bar'
     2407            sage: B = loads(dumps(A))
     2408            sage: B.gens()
     2409            [a, b]
     2410            sage: B.groebner_basis(algorithm='singular')
     2411            [a, b]
     2412            sage: A.gens()
     2413            'foo'
     2414           
     2415        And here is why the example works::
     2416
     2417            sage: ST = I.__getstate__(); ST[0],sorted(ST[1].items())
     2418            (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...>)])
     2419            sage: ST = A.__getstate__(); ST[0],sorted(ST[1].items())
     2420            (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)])
     2421
     2422        """
     2423        OrigState = super(ClearCacheOnPickle, self).__getstate__()
     2424        def clear_list(T):
     2425            L = []
     2426            for x in T:
     2427                if isinstance(x,list):
     2428                    L.append(clear_list(x))
     2429                elif isinstance(x,tuple):
     2430                    L.append(clear_tuple(x))
     2431                elif isinstance(x,dict):
     2432                    L.append(clear_dict(x))
     2433                elif not isinstance(x,CachedFunction):
     2434                    L.append(x)
     2435            return L
     2436        def clear_tuple(T):
     2437            return tuple(clear_list(T))
     2438        def clear_dict(T):
     2439            D = {}
     2440            for key,value in T.iteritems():
     2441                if not ((type(key) == str and key[0:8] == '_cache__') or
     2442                            isinstance(value,CachedFunction)):
     2443                    if isinstance(value,list):
     2444                        D[key] = clear_list(value)
     2445                    elif isinstance(value,tuple):
     2446                        D[key] = clear_tuple(value)
     2447                    elif isinstance(value,dict):
     2448                        D[key] = clear_dict(value)
     2449                    else:
     2450                        D[key] = value
     2451            return D
     2452        if isinstance(OrigState,tuple):
     2453            return clear_tuple(OrigState)
     2454        if isinstance(OrigState,list):
     2455            return clear_list(OrigState)
     2456        if isinstance(OrigState,dict):
     2457            return clear_dict(OrigState)
     2458        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        if hasattr(a.__class__, '__cached_methods'):
     522            CM = getattr(a, '__cached_methods')
     523            if CM is None:
     524                CM = a.__cached_methods = {}
     525        else:
     526            CM = None
     527        if CM is not None:
     528            try:
     529                return CM[self.f.__name__]
     530            except KeyError:
     531                pass
    508532        result = self.f(a)
    509533        if result is NotImplemented:
    510534            # Workaround: we make sure that cls is the class
     
    515539                if self.f.__name__ in supercls.__dict__ and self is supercls.__dict__[self.f.__name__]:
    516540                    cls = supercls
    517541            return getattr(super(cls, a),self.f.__name__)
    518         setattr(a, self.f.__name__, result)
     542        try:
     543            setattr(a, self.f.__name__, result)
     544        except AttributeError:
     545            if CM is not None:
     546                CM[self.f.__name__] = result
     547                return result
     548            raise
    519549        return result
    520550
    521 
    522551class lazy_class_attribute(lazy_attribute):
    523552    """
    524553    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()
     581#        A=self._Cartier_matrix_cached.get_cache()
     582#        if len(A) !=0:
     583#            if A.items()[-1][-1][-1]==self:
     584#                M,Coeffs,g, Fq, p,E = A.items()[-1][1];
     585#            else:
     586#                A.clear()
     587#                M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
     588#        else:
     589#            A.clear()
     590#            M, Coeffs,g, Fq, p, E = self._Cartier_matrix_cached()
    580591        return M
    581592           
    582593    #This where Hasse_Witt is actually computed. This is either called by E.Hasse_Witt or p_rank
     
    643654        #is already computed it is stored in list A. If it was not cached (i.e. A is empty), we simply
    644655        #compute it. If it is cached then we need to make sure that we have the correct one. So check
    645656        #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        #the last entry in A. If it does not match, clear A and compute Cartier.
     658        #
     659        #Since Trac Ticket #11115, there is a different cache for methods
     660        #that don't  accept arguments. Anyway, the easiest is to call
     661        #the cached method and simply see whether the data belong to self.
     662        M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
     663        if E!=self:
     664            self._Cartier_matrix_cached.clear_cache()
     665            M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
     666
     667#        A=self._Cartier_matrix_cached.get_cache()
     668#        if len(A) !=0:
     669#            if A.items()[-1][-1][-1]==self:
     670#                M,Coeffs,g, Fq, p,E = A.items()[-1][1];
     671#            else:
     672#                A.clear()
     673#                M, Coeffs,g, Fq, p, E= self._Cartier_matrix_cached()
     674#        else:
     675#            A.clear()
     676#            M, Coeffs,g, Fq, p, E = self._Cartier_matrix_cached()
    657677       
    658678        #This compute the action of p^kth Frobenius  on list of coefficients       
    659679        def frob_mat(Coeffs, k):
     
    727747
    728748       
    729749        """
    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()
     750        # Since Trac Ticket #11115, there is a special
     751        # type of cached for those methods that don't
     752        # accept arguments. We want to get Hasse-Witt
     753        # from the cache - but apparently it could be
     754        # that the cached value does not belong to self.
     755        # So, the easiest is:
     756        N, E= self._Hasse_Witt_cached()
     757        if E!=self:
     758            self._Hasse_Witt_cached.clear_cache()
    739759            N, E= self._Hasse_Witt_cached()
    740760        return N
     761#        A=self._Hasse_Witt_cached.get_cache()
     762#        if len(A) !=0:
     763#            if A.items()[-1][-1][-1]==self:
     764#                N, E = A.items()[-1][1];
     765#            else:
     766#                A.clear()
     767#                N, E= self._Hasse_Witt_cached()
     768#        else:
     769#            A.clear()
     770#            N, E= self._Hasse_Witt_cached()
     771#        return N
    741772
    742773    def a_number(self):
    743774        r"""
     
    775806        #compute it. If it is cached then we need to make sure that we have the correct one. So check
    776807        #which curve does the matrix correspond to. Since caching stores a lot of stuff, we only check
    777808        #the last entry in A. If it does not match, clear A and compute Cartier.     
     809        # Since Trac Ticket #11115, there is a special cache for methods
     810        # that don't accept arguments. The easiest is: Call the cached
     811        # method, and test whether the last entry is self.
    778812
    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()
     813#        A=self._Cartier_matrix_cached.get_cache()
     814#        if len(A) !=0:
     815#            if A.items()[-1][-1][-1]==self:
     816#                M,Coeffs,g, Fq, p,E = A.items()[-1][1];
     817#            else:
     818#                A.clear()
     819#                M,Coeffs,g, Fq, p,E= self._Cartier_matrix_cached()
     820#        else:
     821#            A.clear()
     822#            M,Coeffs,g, Fq, p,E= self._Cartier_matrix_cached()
     823        M,Coeffs,g, Fq, p,E= self._Cartier_matrix_cached()
     824        if E != self:
     825            self._Cartier_matrix_cached.clear_cache()
    788826            M,Coeffs,g, Fq, p,E= self._Cartier_matrix_cached()
    789 
    790827        a=g-rank(M);
    791828        return a;
     829
    792830    def p_rank(self):
    793831        r"""
    794832        INPUT:
     
    825863        #is already computed it is stored in list A. If it was not cached (i.e. A is empty), we simply
    826864        #compute it. If it is cached then we need to make sure that we have the correct one. So check
    827865        #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()
     866        #the last entry in A. If it does not match, clear A and compute Hasse Witt.
     867        # However, it seems a waste of time to manually analyse the cache
     868        # -- See Trac Ticket #11115
     869
     870        N,E= self._Hasse_Witt_cached()
     871        if E!=self:
     872            self._Hasse_Witt_cached.clear_cache()
    839873            N,E= self._Hasse_Witt_cached()
    840 
    841 
    842        
     874#        A=self._Hasse_Witt_cached.get_cache()
     875#        if len(A) !=0:
     876#            if A.items()[-1][-1][-1]==self:
     877#                N,E = A.items()[-1][1];
     878#            else:
     879#                A.clear()
     880#                N,E= self._Hasse_Witt_cached()
     881#        else:
     882#            A.clear()
     883#            N,E= self._Hasse_Witt_cached()
    843884        pr=rank(N);
    844885        return pr
    845886       
  • 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            AttributeError: 'sage.structure.parent.Parent' object has no attribute '__foo'
    811814
    812815        """
     816        try:
     817            return self.__cached_methods[name]
     818        except (KeyError,TypeError):
     819            pass
    813820        if (name.startswith('__') and not name.endswith('_')) or self._category is None:
    814821            raise AttributeError, AttributeErrorMessage(self, name)
    815         return getattr_from_other_class(self, self._category.parent_class, name)
     822        if self.__cached_methods is None:
     823            self.__cached_methods  = {}
     824        attr = getattr_from_other_class(self, self._category.parent_class, name)
     825        self.__cached_methods[name] = attr
     826        return attr
    816827
    817828    def __dir__(self):
    818829        """
  • 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'