Ticket #11115: trac11115-cached_in_parent_with_category.patch

File trac11115-cached_in_parent_with_category.patch, 4.8 KB (added by SimonKing, 5 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