Package: emacs;
Reported by: Steven De Herdt <steven.deherdt <at> gmail.com>
Date: Sun, 20 Dec 2020 23:21:01 UTC
Severity: normal
Found in version 27.1
View this message in rfc822 format
From: Tomas Nordin <tomasn <at> posteo.net> To: Steven De Herdt <steven.deherdt <at> gmail.com>, 45348 <at> debbugs.gnu.org Subject: bug#45348: 27.1; python-eldoc-setup-code uses obsolete python function Date: Thu, 24 Dec 2020 00:53:38 +0100
[Message part 1 (text/plain, inline)]
Steven De Herdt <steven.deherdt <at> gmail.com> writes: > Hello folks > > This report concerns eldoc for Python. I'm using Debian testing, with > Python 3.9, in my daily config I use ipython3 as > python-shell-interpreter. Every time I place point in the argument list > of a Python function without documentation, the minibuffer expands to > show a warning ("DeprecationWarning: `formatargspec` is deprecated since > Python 3.5. Use `signature` and the `Signature` object directly"), an > unrelated snippet of my code, as well as the intended function signature. > > This behaviour can be partly reproduced in a minimal setting with the > attached func.py: > * emacs -Q func.py > * C-u C-c C-p , choose "python3 -i" > * in buffer for func.py: C-c C-c > * place point at argument (13) of the call to func > The DeprecationWarning only shows the first time with python3. My > ipython3 shows it every time however, that's a bit annoying. I'm not > sure the repeated warning is an issue with ipython, but the eldoc setup > code would need to upgrade from deprecated functionality anyway. I can reproduce this with Python 3.7.3 on Debian stable. And yes, strange behaviour with Ipython, which is maybe not about the eldoc setup code. > Maybe I'll try to make python-eldoc-setup-code use inspect.signature if > it annoys me too much. :) Yes, did you figure out something safe and sound? Otherwise can you please try the attached patch. It fixes the problem here. The patch touch the string of python code `python-eldoc-setup-code' and do a little more than simply not call formatargspec with python 3, but does not change the intended effect. I think the patch improves readability somewhat. But also I identified a few bugs with the python code in the string. Those bugs doesn't surface due to the (needed) wrapping try block. Here are the observed bugs, - if obj is not a string, if isinstance(obj, str_type) fails and doc does not get defined. After this, doc is referred to in the next test, (if not doc and callable(obj):) which will then error. - if obj is a class instance and has an empty docstring and is not callable (often not), then (if not doc and callable(obj)) fails and doc.splitlines()[0] will Error. - again, if obj is a class instance, not callable but has no docstring, doc will be None and doc.splitlines() will error. - if obj is provided as the object itself, the function always fail because doc does not get defined. Those bugs are fixed with the patch, as well as using inspect.signature with python 3 as recommended by the deprecation warning. Besides the patch, I wonder what other users thinks about the resulting behaviour of this python function. Here is a a suitable docstring for `python-eldoc-setup-code', would it be provided: """Provide a docstring or signature on obj. Prefer a docstring, and fall back on the signature if no docstring is found.""" Meaning, if there is a docstring, we will not get the call signature, we get that only when there is no docstring. Personally I would prefer the call signature always, like in elisp. Then perhaps when doing C-c C-f (python-eldoc-at-point) show the (full) docstring. But that would be another bug-report I guess. Best regards -- Tomas
[pydoc-45348.patch (text/x-diff, inline)]
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index d58b32f3c3..6acfafdb68 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -4533,33 +4533,35 @@ python-eldoc-setup-code "def __PYDOC_get_help(obj): try: import inspect + from sys import version_info as version_info + try: - str_type = basestring - argspec_function = inspect.getargspec - except NameError: - str_type = str - argspec_function = inspect.getfullargspec - if isinstance(obj, str_type): obj = eval(obj, globals()) - doc = inspect.getdoc(obj) + doc = inspect.getdoc(obj) + except TypeError: + doc = inspect.getdoc(obj) + if not doc and callable(obj): - target = None if inspect.isclass(obj) and hasattr(obj, '__init__'): target = obj.__init__ objtype = 'class' else: target = obj objtype = 'def' - if target: - args = inspect.formatargspec(*argspec_function(target)) - name = obj.__name__ - doc = '{objtype} {name}{args}'.format( - objtype=objtype, name=name, args=args - ) - else: + if version_info.major == 3: + args = str(inspect.signature(target)) + else: + args = inspect.formatargspec(*inspect.getargspec(target)) + + name = obj.__name__ + doc = '{objtype} {name}{args}'.format( + objtype=objtype, name=name, args=args) + elif doc: doc = doc.splitlines()[0] + else: + doc = '' except: - doc = '' + return '' return doc" "Python code to setup documentation retrieval." :type 'string
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.