Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support cached_methods on extension types #12951

Closed
simon-king-jena opened this issue May 15, 2012 · 11 comments
Closed

Support cached_methods on extension types #12951

simon-king-jena opened this issue May 15, 2012 · 11 comments

Comments

@simon-king-jena
Copy link
Member

In old versions of Cython, one would have seen an error like "arbitrary decorators are not supported" when attempting to use @cached_method on the methods of a cdef class. That has now been improved. However, cached methods would still not work, because an attribute __module__ is requested that does not exist.

The aim is to work around that limitation, so that cached methods and functions genuinely work in Cython.

Depends on #12215

CC: @hivert @robertwb

Component: misc

Author: Simon King

Reviewer: Travis Scrimshaw

Merged: sage-5.9.beta4

Issue created by migration from https://trac.sagemath.org/ticket/12951

@simon-king-jena
Copy link
Member Author

comment:1

As it turns out, it is still impossible to use arbitrary decorators on c(p)def functions or methods. However, the attached patch makes it possible to use the decorator on def-methods of extension classes. That used to fail, because of the attribute error mentioned in the ticket description. It is of course still required that the instances of the extension class either allow to override an attribute of the class by an attribute of the instance, or that the instance has a public attribute __cached_methods.

For the latter case, we now have (from the doc tests):

    sage: cython_code = [
    ... "from sage.misc.cachefunc import cached_method",
    ... "cdef class MyClass:",
    ... "    cdef public dict __cached_methods",
    ... "    @cached_method",
    ... "    def f(self, a,b):",
    ... "        return a*b"]
    sage: cython(os.linesep.join(cython_code))
    sage: P = MyClass()
    sage: P.f(2,3)
    6
    sage: P.f(2,3) is P.f(2,3)
    True

Note that by #11115, sage.structure.parent.Parent has the __cached_methods attribute. Hence, any cdef subclass of Parent will do!

Providing attribute access is a bit more tricky, since it is needed that an attribute inherited by the instance from its class can be overridden on the instance. That is why providing a __getattr__ would not be enough in the following example:

    sage: cython_code = [
    ... "from sage.misc.cachefunc import cached_method",
    ... "cdef class MyOtherClass:",
    ... "    cdef dict D",
    ... "    def __init__(self):",
    ... "        self.D = {}",
    ... "    def __setattr__(self, n,v):",
    ... "        self.D[n] = v",
    ... "    def __getattribute__(self, n):",
    ... "        try:",
    ... "            return self.D[n]",
    ... "        except KeyError:",
    ... "            pass",
    ... "        return getattr(type(self),n).__get__(self)",
    ... "    @cached_method",
    ... "    def f(self, a,b):",
    ... "        return a+b"]
    sage: cython(os.linesep.join(cython_code))
    sage: Q = MyOtherClass()
    sage: Q.f(2,3)
    5
    sage: Q.f(2,3) is Q.f(2,3)
    True

Supporting attribute access apparently is more complicated than the other approach, and probably not recommended. However, on cached methods, it is somehow faster than the easier method:

    sage: timeit("a = P.f(2,3)")   # random
    625 loops, best of 3: 1.3 µs per loop
    sage: timeit("a = Q.f(2,3)")   # random
    625 loops, best of 3: 931 ns per loop

Needs review!

@simon-king-jena
Copy link
Member Author

Author: Simon King

@simon-king-jena
Copy link
Member Author

comment:2

Any reviewer?

@simon-king-jena
Copy link
Member Author

comment:3

There is a conflict with #12215. Both tickets need review, but I think that #12215 is more important than this ticket. Hence, I introduced a dependency, and changed my patch accordingly.

@simon-king-jena
Copy link
Member Author

Dependencies: #12215

@simon-king-jena
Copy link
Member Author

comment:4

Note to myself: Test that this patch still applies.

@simon-king-jena
Copy link
Member Author

Patch relative to #12215

@simon-king-jena
Copy link
Member Author

comment:5

Attachment: trac12951_cached_extension.patch.gz

I had to rebase the patch. Now it should work again. Still needing review!

@tscrim
Copy link
Collaborator

tscrim commented Apr 1, 2013

Reviewer: Travis Scrimshaw

@tscrim
Copy link
Collaborator

tscrim commented Apr 1, 2013

comment:7

Looks good to me. Thanks Simon.

@jdemeyer
Copy link

jdemeyer commented Apr 4, 2013

Merged: sage-5.9.beta4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants