Ticket #6520: trac_6520_weakref-cached-function-dr.patch

File trac_6520_weakref-cached-function-dr.patch, 7.1 KB (added by nthiery, 12 years ago)
  • sage/misc/all.py

    # HG changeset patch
    # User Nicolas M. Thiery <nthiery@users.sf.net>
    # Date 1247466839 -7200
    # Node ID 6aed85da2f82a9910efc7ae3cc861e2951cd6b01
    # Parent  c23dbd5c76172249af4ce90204117d91d364561a
    [mq]: trac_6520_weakref-cached-function-dr.patch
    
    diff --git a/sage/misc/all.py b/sage/misc/all.py
    a b from trace import trace 
    152152
    153153from constant_function import ConstantFunction
    154154
    155 from cachefunc import CachedFunction, cached_function, cached_method, cached_in_parent_method
     155from cachefunc import CachedFunction, cached_function, weakref_cached_function, cached_method, cached_in_parent_method
    156156
    157157from lazy_attribute import lazy_attribute
    158158
  • sage/misc/cachefunc.py

    diff --git a/sage/misc/cachefunc.py b/sage/misc/cachefunc.py
    a b AUTHOR: 
    1313#
    1414#                  http://www.gnu.org/licenses/
    1515########################################################################
     16
     17import weakref
     18
    1619class CachedFunction(object):
    1720    def __init__(self, f):
    1821        """
    class CachedFunction(object): 
    2932
    3033        The inputs to the function must be hashable.
    3134
    32         EXAMPELES:
     35        EXAMPLES::
     36
    3337            sage: g = CachedFunction(number_of_partitions)
    3438            sage: g.__name__
    3539            'number_of_partitions'
    class CachedFunction(object): 
    5357        """
    5458        Returns the source code for the wrapped function.
    5559
    56         EXAMPLES:
     60        EXAMPLES::
     61
    5762            sage: from sage.misc.sageinspect import sage_getsource
    5863            sage: g = CachedFunction(number_of_partitions)
    5964            sage: 'bober' in sage_getsource(g)
    class CachedFunction(object): 
    6671       
    6772    def __call__(self, *args, **kwds):
    6873        """
    69         EXAMPLES:
     74        EXAMPLES::
     75
    7076            sage: g = CachedFunction(number_of_partitions)
    7177            sage: a = g(5)
    7278            sage: g.get_cache()
    class CachedFunction(object): 
    8793        """
    8894        Returns the cache dictionary.
    8995
    90         EXAMPLES:
     96        EXAMPLES::
     97
    9198            sage: g = CachedFunction(number_of_partitions)
    9299            sage: a = g(5)
    93100            sage: g.get_cache()
    class CachedFunction(object): 
    98105
    99106    def is_in_cache(self, *args, **kwds):
    100107        """
    101         EXAMPLES:
     108        EXAMPLES::
     109
    102110            sage: class Foo:
    103111            ...       def __init__(self, x):
    104112            ...           self._x = x
    class CachedFunction(object): 
    123131        Mind the unintuitive syntax (value first)
    124132        Any idea on how to improve that welcome
    125133       
    126         EXAMPLES:
     134        EXAMPLES::
     135
    127136            sage: g = CachedFunction(number_of_partitions)
    128137            sage: a = g(5)
    129138            sage: g.get_cache()
    class CachedFunction(object): 
    148157        Returns the key in the cache to be used when args
    149158        and kwds are passed in as parameters.
    150159
    151         EXAMPLES:
     160        EXAMPLES::
     161
    152162            sage: class Foo:
    153163            ...       def __init__(self, x):
    154164            ...           self._x = x
    class CachedFunction(object): 
    164174
    165175    def __repr__(self):
    166176        """
    167         EXAMPLES:
     177        EXAMPLES::
     178
    168179            sage: g = CachedFunction(number_of_partitions)
    169180            sage: g
    170181            Cached version of <function number_of_partitions at 0x...>
    class CachedFunction(object): 
    175186        """
    176187        Clear the cache dictionary.
    177188
    178         EXAMPLES:
     189        EXAMPLES::
     190
    179191            sage: g = CachedFunction(number_of_partitions)
    180192            sage: a = g(5)
    181193            sage: g.get_cache()
    class CachedFunction(object): 
    188200        for key in cache.keys():
    189201            del cache[key]
    190202
     203cached_function = CachedFunction
    191204
    192 cached_function = CachedFunction
     205class WeakrefCachedFunction(CachedFunction):
     206    def __call__(self, *args, **kwds):
     207        """
     208        TODO: weakref_cached_function don't seem to work with integers
     209        (TypeError: cannot create weak reference to 'sage.rings.integer.Integer' object)
     210        Fix the implementation or the doctests accordingly.
     211
     212        EXAMPLES::
     213
     214            sage: g = weakref_cached_function(number_of_partitions)
     215            sage: a = g(5)
     216            sage: g.get_cache()
     217            {((5,), ()): 7}
     218            sage: a = g(10^5)
     219            sage: a == number_of_partitions(10^5)
     220            True
     221        """
     222        cache = self.get_cache()
     223        k = self.get_key(*args, **kwds)
     224        if cache.has_key(k):
     225            w = cache[k]()
     226            if w is not None:
     227                return w
     228        w = self.f(*args, **kwds)
     229        cache[k] = weakref.ref(w)
     230        return w
     231   
     232    def is_in_cache(self, *args, **kwds):
     233        """
     234        TODO: fix this doctest to use a weakref_cached_function
     235        (and similarly of is_in_cache of CachedFunction)
     236       
     237        EXAMPLES::
     238
     239            sage: class Foo:
     240            ...       def __init__(self, x):
     241            ...           self._x = x
     242            ...       @cached_method
     243            ...       def f(self, z):
     244            ...           return self._x*z
     245            ...
     246            sage: a = Foo(2)
     247            sage: a.f.is_in_cache(3)
     248            False
     249            sage: a.f(3)
     250            6
     251            sage: a.f.is_in_cache(3)
     252            True
     253        """
     254        cache = self.get_cache()
     255        k = self.get_key(*args, **kwds)
     256        return cache.has_key(k) and cache[k]() is not None
     257
     258    def set_cache(self, value, *args, **kwds):
     259        """
     260        Set the value for those args and keyword args
     261        Mind the unintuitive syntax (value first)
     262        Any idea on how to improve that welcome
     263       
     264        EXAMPLES:;
     265
     266            sage: g = weakref_cached_function(number_of_partitions)
     267            sage: a = g(5)
     268            sage: g.get_cache()
     269            {((5,), ()): 7}
     270            sage: g.set_cache(17, 5)
     271            sage: g.get_cache()
     272            {((5,), ()): 17}
     273            sage: g(5)
     274            17
     275
     276          Is there a way to use the following intuitive syntax?
     277            sage: g(5) = 19    # todo: not implemented
     278            sage: g(5)         # todo: not implemented
     279            19
     280        """
     281        cache = self.get_cache()
     282        cache[self.get_key(*args, **kwds)] = weakref.ref(value)   
     283
     284weakref_cached_function = WeakrefCachedFunction
    193285
    194286class CachedMethod(CachedFunction):
    195287    def __init__(self, f):
    196288        """
    197         EXAMPLES:
     289        EXAMPLES::
     290
    198291            sage: class Foo:
    199292            ...       def __init__(self, x):
    200293            ...           self._x = x
    class CachedMethod(CachedFunction): 
    210303
    211304    def __call__(self, *args, **kwds):
    212305        """
    213         EXAMPLES:
     306        EXAMPLES::
     307
    214308            sage: class Foo(object):
    215309            ...       def __init__(self, x):
    216310            ...           self._x = x
    class CachedMethod(CachedFunction): 
    246340        """
    247341        Returns the cache dictionary.
    248342
    249         EXAMPLES:
     343        EXAMPLES::
     344
    250345            sage: class Foo:
    251346            ...       def __init__(self, x):
    252347            ...           self._x = x