Ticket #11115: trac11115cached_in_parent_with_category.patch
File trac11115cached_in_parent_with_category.patch, 4.8 KB (added by SimonKing, 4 years ago) 


sage/misc/cachefunc.pyx
# HG changeset patch # User Simon King <simon.king@unijena.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 """1 r""" 2 2 Cached Functions and Methods 3 3 4 4 AUTHORS: … … 338 338 return sage_getsource(self.f) 339 339 340 340 def _sage_src_lines_(self): 341 """341 r""" 342 342 Returns the list of source lines and the first line number 343 343 of the wrapped function. 344 344 … … 1013 1013 return self._fix_to_pos(*args,**kwds) 1014 1014 1015 1015 def __get__(self, inst, cls): #cls=None): 1016 """1016 r""" 1017 1017 Get a :class:`CachedMethodCaller` bound to a specific 1018 1018 instance of the class of the cached method. 1019 1019 … … 1288 1288 self.cache = value 1289 1289 1290 1290 cpdef clear_cache(self): 1291 """1291 r""" 1292 1292 Clear the cache dictionary. 1293 1293 1294 1294 EXAMPLES:: … … 1672 1672 cached_method = CachedMethod 1673 1673 1674 1674 cdef class CachedInParentMethod(CachedMethod): 1675 """1675 r""" 1676 1676 A decorator that creates a cached version of an instance 1677 1677 method of a class. 1678 1678 … … 1684 1684 1685 1685 This way of caching works only if 1686 1686 1687  the instances *have* a parent, 1688  the parent allows assignment of attributes, and 1687  the instances *have* a parent, and 1689 1688  the instances are hashable (they are part of the cache key). 1690 1689 1691 1690 NOTE: … … 1751 1750 1752 1751 sage: a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c) 1753 1752 True 1753 1754 TEST: 1755 1756 By trac ticket #11115, cachedinparent 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 1754 1818 """ 1755 1819 1756 1820 def __init__(self, f, name=None): … … 1850 1914 True 1851 1915 1852 1916 """ 1853 P = inst.parent() 1917 try: 1918 P = inst.parent() 1919 except AttributeError: 1920 return {} 1854 1921 try: 1855 1922 return P.__dict__.setdefault(self._cache_name, {}) 1856 1923 except AttributeError: … … 2280 2347 We provide the definition in Cython, however, since interactive 2281 2348 Cython definitions provide introspection by trac ticket #9976, whereas 2282 2349 Python definitions don't. 2350 :: 2283 2351 2284 2352 sage: P.<a,b,c,d> = QQ[] 2285 2353 sage: I = P*[a,b] … … 2329 2397 2330 2398 """ 2331 2399 def __getstate__(self): 2332 """2400 r""" 2333 2401 The idea is to remove that might provide a cache to some cached method 2334 2402 from the return value of the ``__getstate__`` method. 2335 2403