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
Make calling a cached method independent of source code inspection #17814
Comments
This comment has been minimized.
This comment has been minimized.
comment:3
Here one can see how introspection enters:
So: cached_method tries to determine the number of arguments. This is because there is a special implementation for functions with no argument (except In other words, the wrong behaviour could be fixed by finding a way to get the number of arguments (or better the argspec) of a cython function without looking at its source code. I'll see if that's possible. So, the fix will likely be in |
comment:4
Fixing sageinspect won't be easy. I currently have absolutely no clue how to read off the number of arguments (or even the names of the arguments) of a function that is defined in a Cython file. Those functions don't seem to have any attributes holding useful information. Has someone else an idea? If not, then I don't see what we can do. We do want a special cached method implementation for methods without arguments, and thus we need to determine the number of arguments of the to-be-wrapped method. If that doesn't work without reading the sources, what could we possibly do? |
comment:5
Replying to @simon-king-jena:
Do you really require the number and names of arguments or do you only want to know whether a function takes any Technically, Python always uses |
comment:6
The question is also: if there is a method
do we require that |
comment:7
Replying to @jdemeyer:
Yes, we do require that. Equivalent inputs should result in identical output. The problem occurs when the cached method is bound to an instance. At that point, we want to know if the method accepts any argument in addition to |
comment:8
The two statements below seem like a contraction: using the example above, if you want to ensure that Replying to @simon-king-jena:
|
comment:9
Replying to @simon-king-jena:
That's possible using the Python API function |
comment:10
Replying to @jdemeyer:
For calling the function, you of course need it (so, I admit that the title of this ticket is misleading). However, for determining whether it ought to be a And thank you for the link to |
comment:11
Replying to @simon-king-jena:
Sure, but that doesn't solve the problem really (unless you want to fix the issue of this ticket only for methods taking no arguments). You still need to call the function eventually. |
comment:12
Replying to @simon-king-jena:
Is that really so important? Does it happen a lot in practice that people or the Sage library call a function in different but equivalent ways? |
comment:13
Replying to @jdemeyer:
I believe it is important, and I think it is specified somewhere in the docs of sage.misc.cachefunc. There are places where it is used for Hence, if we changed that, we would break uniqueness of |
comment:14
I see. This is important where the semantics of I always had in mind only the application of speeding up the function by not computing the same thing multiple times. For the latter application, you need to consider also the overhead of parsing |
comment:15
Proposal: have 2 different implementations of
|
comment:16
This proposal would solve the issue on the ticket. Specializing for Cython, it might also be possible to speed-up things more. |
comment:17
Replying to @simon-king-jena:
It is puzzling. When I call |
comment:18
Replying to @simon-king-jena:
It's hard to tell without seeing the code. Are you sure the Anyway, I'm still very curious what you think about [comment:11] and [comment:15] |
comment:19
The proposal from comment:15 would of course solve the problem of the introspection that is needed to wrap a cython function in a cached method. However, it would mean that the specification of uniqueness would be violated for those cython functions for which the argument spectrum is not available. I'll try to show you a diff file shortly, so that you can see how calling |
comment:20
Replying to @simon-king-jena:
True, but I think the uniqueness is only important for certain very specific functions. In any case, if we want to solve this ticket, I think it's the only way to go. |
comment:21
Try this: diff --git a/src/sage/misc/cachefunc.pyx b/src/sage/misc/cachefunc.pyx
index a4276b9..515c74a 100644
--- a/src/sage/misc/cachefunc.pyx
+++ b/src/sage/misc/cachefunc.pyx
@@ -481,6 +481,12 @@ import sage.misc.weak_dict
from sage.misc.weak_dict import WeakValueDictionary
from sage.misc.decorators import decorator_keywords
+from cpython cimport PyObject
+
+cdef extern from "methodobject.h":
+ cdef int PyCFunction_GetFlags(PyObject *op)
+
+
cdef frozenset special_method_names = frozenset(['__abs__', '__add__',
'__and__', '__call__', '__cmp__', '__coerce__', '__complex__', '__contains__', '__del__',
'__delattr__', '__delete__', '__delitem__', '__delslice__', '__dir__', '__div__',
@@ -2672,6 +2678,7 @@ cdef class CachedMethod(object):
# we need to analyse the argspec
f = (<CachedFunction>self._cachedfunc).f
if self.nargs==0:
+ bla = PyCFunction_GetFlags(<PyObject *>f)
args, varargs, keywords, defaults = sage_getargspec(f)
if varargs is None and keywords is None and len(args)<=1:
self.nargs = 1 According to the crash report that I get, the error occurs in the line |
comment:22
Replace
by
|
comment:23
With the correct
|
comment:24
Replying to @jdemeyer:
OK, we then have an error whose traceback points to calling the function. |
comment:25
Apparently |
comment:26
Replying to @simon-king-jena:
It is the right tool for bound Cython methods. |
comment:27
I am currently testing something else, but for example
This |
comment:60
Replying to @simon-king-jena:
This is a one-off hitch. It just means that when we enable
We can.
but it's easy to reformulate those cases. |
comment:61
Let me mention that #17847 is now in Sage, which makes this ticket feasible. |
comment:62
Would it be ok to rebase this branch on top of the current develop branch (and then force-push)? Or would it be ok if I merged this branch into the current develop and start with it? Or merge the current develop into this branch? I still don't get what is considered best praxis. |
comment:64
I am now using the embedded signatures (due to #17847) for introspection. I preserved the previous commits by merging the previous ticket branch into the current develop to get the new ticket branch; hopefully the correct procedure. In order to demonstrate what is happening, I added a dummy method to a nested test class provided in sage.misc.nested_class. As it turns out, there has been a bug in the previous
Actually the default is not None but is a tuple, which is correctly determined by the new version of
Moreover, the above does not involve reading the source code. I wrote a new function that determines the argspec from the embedded signature, and strips the signature at the same time:
The tests in sage.misc pass. |
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:66
On 6.7-beta2 I got
|
comment:67
sorry already in comment:27... could you update the description then? |
comment:68
Replying to @videlec:
You mean, you got it after removing |
comment:69
Replying to @videlec:
I don't understand what info you need. |
comment:70
Replying to @simon-king-jena:
Nope. Just starting from a fresh sage-6.7.beta2. |
comment:71
Replying to @videlec:
My mistake... I read too fast!! |
comment:72
I still don't see what info was requested. Hence, I change it back to "needs review". |
Reviewer: Volker Braun |
Changed branch from u/SimonKing/make_calling_a_cached_method_independent_of_source_code_inspection to |
If a pyx file in the sage library uses cached methods and then the source file is removed after compiling Sage, then accessing the cached methods in this file becomes impossible. Example: Move the file
src/sage/rings/finite_rings/finite_field_base.pyx
away. Then:The same does work in attached pyx files, even after removing the temporary copy of the pyx file. Conjecture: The cached method's
__get__
method relies on source code inspection. That should of course not be the case. Source code inspection should only come in play if the user wants to see the source code or at least the doc string.I chose the component "distribution", since it was reported on sage-devel as something that happened on certain sage distributions that do not provide sage sources.
Component: distribution
Author: Simon King
Branch/Commit:
0e8ef00
Reviewer: Volker Braun
Issue created by migration from https://trac.sagemath.org/ticket/17814
The text was updated successfully, but these errors were encountered: