Ticket #11115: trac11115-cached_in_parent_with_category.patch

File trac11115-cached_in_parent_with_category.patch, 4.8 KB (added by SimonKing, 3 years ago)

Allow the use of cached_in_parent methods in the category framework

  • sage/misc/cachefunc.pyx

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1303982811 -7200
    # Node ID a3255b872cd4d9e4733acb665fd0279ed6c256ba
    # Parent  96ba4e37581e095fd0c29e9071e72b9c856c4f9c
    #11115: Make cached_in_parent methods work for the element class of categories.
    
    diff --git a/sage/misc/cachefunc.pyx b/sage/misc/cachefunc.pyx
    a b  
    1 """ 
     1r""" 
    22Cached Functions and Methods 
    33 
    44AUTHORS: 
     
    338338        return sage_getsource(self.f) 
    339339 
    340340    def _sage_src_lines_(self): 
    341         """ 
     341        r""" 
    342342        Returns the list of source lines and the first line number 
    343343        of the wrapped function. 
    344344 
     
    10131013        return self._fix_to_pos(*args,**kwds) 
    10141014 
    10151015    def __get__(self, inst, cls): #cls=None): 
    1016         """ 
     1016        r""" 
    10171017        Get a :class:`CachedMethodCaller` bound to a specific 
    10181018        instance of the class of the cached method. 
    10191019 
     
    12881288        self.cache = value 
    12891289 
    12901290    cpdef clear_cache(self): 
    1291         """ 
     1291        r""" 
    12921292        Clear the cache dictionary. 
    12931293 
    12941294        EXAMPLES:: 
     
    16721672cached_method = CachedMethod 
    16731673 
    16741674cdef class CachedInParentMethod(CachedMethod): 
    1675     """ 
     1675    r""" 
    16761676    A decorator that creates a cached version of an instance 
    16771677    method of a class. 
    16781678 
     
    16841684 
    16851685    This way of caching works only if 
    16861686 
    1687     - the instances *have* a parent, 
    1688     - the parent allows assignment of attributes, and 
     1687    - the instances *have* a parent, and 
    16891688    - the instances are hashable (they are part of the cache key). 
    16901689 
    16911690    NOTE: 
     
    17511750 
    17521751        sage: a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c) 
    17531752        True 
     1753 
     1754    TEST: 
     1755 
     1756    By trac ticket #11115, cached-in-parent methods can be inherited 
     1757    from the element class of a category. That even holds if neither 
     1758    the element nor the parent allow attribute assignment:: 
     1759 
     1760        sage: cython_code = ["from sage.structure.parent cimport Parent", 
     1761        ... "from sage.structure.element cimport Element", 
     1762        ... "from sage.all import Category, cached_in_parent_method", 
     1763        ... "cdef class MyElement(Element):", 
     1764        ... "    cdef object x", 
     1765        ... "    def __init__(self,P,x):", 
     1766        ... "        self.x=x", 
     1767        ... "        Element.__init__(self,P)", 
     1768        ... "    def _repr_(self):", 
     1769        ... "        return '<%s>'%self.x", 
     1770        ... "    def __neg__(self):", 
     1771        ... "        return MyElement(self.parent(),-self.x)", 
     1772        ... "    def __hash__(self):", 
     1773        ... "        return hash(self.x)", 
     1774        ... "    def __cmp__(self, other):", 
     1775        ... "        return cmp(self.x, (<MyElement>other).x)", 
     1776        ... "cdef class MyParent(Parent): pass", 
     1777        ... "class MyCategory(Category):", 
     1778        ... "    def super_categories(self):", 
     1779        ... "        return [Objects()]", 
     1780        ... "    class ElementMethods:", 
     1781        ... "        @cached_in_parent_method", 
     1782        ... "        def test_cache(self):", 
     1783        ... "            return -self"] 
     1784        sage: cython('\n'.join(cython_code)) 
     1785        sage: C = MyCategory() 
     1786        sage: P = MyParent(category=C) 
     1787        sage: e1 = MyElement(P,5) 
     1788        sage: e2 = MyElement(P,5) 
     1789        sage: e3 = MyElement(P,6) 
     1790     
     1791    We verify that attribute assignment does not work:: 
     1792 
     1793        sage: e1.bla = 1 
     1794        Traceback (most recent call last): 
     1795        ... 
     1796        AttributeError: '...MyElement' object has no attribute 'bla' 
     1797        sage: P.bla = 1 
     1798        Traceback (most recent call last): 
     1799        ... 
     1800        AttributeError: '...MyParent' object has no attribute 'bla' 
     1801 
     1802    Nevertheless, the cached method works, and it returns identical 
     1803    output for equal elements, as expected:: 
     1804 
     1805        sage: e1.test_cache() 
     1806        <-5> 
     1807        sage: e1 is e2 
     1808        False 
     1809        sage: e1 == e2 
     1810        True 
     1811        sage: e2.test_cache() is e1.test_cache() 
     1812        True 
     1813        sage: e1 == e3 
     1814        False 
     1815        sage: e2.test_cache() == e3.test_cache() 
     1816        False 
     1817 
    17541818    """ 
    17551819 
    17561820    def __init__(self, f, name=None): 
     
    18501914            True 
    18511915 
    18521916        """ 
    1853         P = inst.parent() 
     1917        try: 
     1918            P = inst.parent() 
     1919        except AttributeError: 
     1920            return {} 
    18541921        try: 
    18551922            return P.__dict__.setdefault(self._cache_name, {}) 
    18561923        except AttributeError: 
     
    22802347    We provide the definition in Cython, however, since interactive 
    22812348    Cython definitions provide introspection by trac ticket #9976, whereas 
    22822349    Python definitions don't. 
     2350    :: 
    22832351 
    22842352        sage: P.<a,b,c,d> = QQ[] 
    22852353        sage: I = P*[a,b] 
     
    23292397 
    23302398    """ 
    23312399    def __getstate__(self): 
    2332         """ 
     2400        r""" 
    23332401        The idea is to remove that might provide a cache to some cached method 
    23342402        from the return value of the ``__getstate__`` method. 
    23352403