Skip to content

Commit

Permalink
Trac #26906: Fix broken pinfo magic for interface functions
Browse files Browse the repository at this point in the history
For some interfaces, using the IPython `%pinfo`/`%pinfo2` magic or the
questionmark syntax for viewing the help and source code fails with an
`AttributeError` (see below).

The interfaces R and Macaulay2 are affected by this, possibly others as
well.

This bug occurs in the console as well as the Jupyter notebook. The
oldstyle notebook does not seem to be affected. Possibly related: #11913
and #10860.

I found the bug to be caused by `sage.misc.sageinspect.sage_getargspec`
returning `None` in this case, which apparently is not supported by
IPython.

Here is the stack trace:
{{{
sage: r.lm?
------------------------------------------------------------------------
---
AttributeError                            Traceback (most recent call
last)
<ipython-input-1-955de2536d9d> in <module>()
----> 1 get_ipython().magic(u'pinfo r.lm')

/Applications/SageMath/local/lib/python2.7/site-
packages/IPython/core/interactiveshell.pyc in magic(self, arg_s)
   2158         magic_name, _, magic_arg_s = arg_s.partition(' ')
   2159         magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
-> 2160         return self.run_line_magic(magic_name, magic_arg_s)
   2161
   2162     #-----------------------------------------------------------
--------------

/Applications/SageMath/local/lib/python2.7/site-
packages/IPython/core/interactiveshell.pyc in run_line_magic(self,
magic_name, line)
   2079                 kwargs['local_ns'] =
sys._getframe(stack_depth).f_locals
   2080             with self.builtin_trap:
-> 2081                 result = fn(*args,**kwargs)
   2082             return result
   2083

<decorator-gen-74> in pinfo(self, parameter_s, namespaces)

/Applications/SageMath/local/lib/python2.7/site-
packages/IPython/core/magic.pyc in <lambda>(f, *a, **k)
    186     # but it's overkill for just that one bit of state.
    187     def magic_deco(arg):
--> 188         call = lambda f, *a, **k: f(*a, **k)
    189
    190         if callable(arg):

/Applications/SageMath/local/lib/python2.7/site-
packages/IPython/core/magics/namespace.pyc in pinfo(self, parameter_s,
namespaces)
     59         else:
     60             self.shell._inspect('pinfo', oname,
detail_level=detail_level,
---> 61                                 namespaces=namespaces)
     62
     63     @line_magic

/Applications/SageMath/local/lib/python2.7/site-
packages/IPython/core/interactiveshell.pyc in _inspect(self, meth,
oname, namespaces, **kw)
   1534             elif meth == 'pinfo':
   1535                 pmethod(info.obj, oname, formatter, info,
-> 1536
enable_html_pager=self.enable_html_pager, **kw)
   1537             else:
   1538                 pmethod(info.obj, oname)

/Applications/SageMath/local/lib/python2.7/site-
packages/IPython/core/oinspect.pyc in pinfo(self, obj, oname, formatter,
info, detail_level, enable_html_pager)
    713         - detail_level: if set to 1, more information is given.
    714         """
--> 715         info = self._get_info(obj, oname, formatter, info,
detail_level)
    716         if not enable_html_pager:
    717             del info['text/html']

/Applications/SageMath/local/lib/python2.7/site-
packages/IPython/core/oinspect.pyc in _get_info(self, obj, oname,
formatter, info, detail_level)
    614         """Retrieve an info dict and format it."""
    615
--> 616         info = self._info(obj, oname=oname, info=info,
detail_level=detail_level)
    617
    618         _mime = {

/Applications/SageMath/local/lib/python2.7/site-
packages/IPython/core/oinspect.pyc in _info(self, obj, oname, info,
detail_level)
    944                 # named tuples' _asdict() method returns an
OrderedDict, but we
    945                 # we want a normal
--> 946                 out['argspec'] = argspec_dict =
dict(argspec._asdict())
    947                 # We called this varkw before argspec became a
named tuple.
    948                 # With getfullargspec it's also called varkw.

AttributeError: 'NoneType' object has no attribute '_asdict'
}}}

Tested using Sage 8.5.rc1 on OS X and Linux.

URL: https://trac.sagemath.org/26906
Reported by: gh-mwageringel
Ticket author(s): Markus Wageringel
Reviewer(s): Travis Scrimshaw, Dima Pasechnik
  • Loading branch information
Release Manager authored and vbraun committed Feb 8, 2019
2 parents f3b620f + b1c5aa7 commit 365c4a4
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
9 changes: 6 additions & 3 deletions src/sage/misc/sageinspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1507,9 +1507,11 @@ def foo(x, a='\')"', b={not (2+1==3):'bar'}): return
sage: sage.misc.sageinspect.sage_getargspec(foo)
ArgSpec(args=['x', 'a', 'b'], varargs=None, keywords=None, defaults=('\')"', {False: 'bar'}))
The following produced a syntax error before the patch at :trac:`11913`::
The following produced a syntax error before the patch at :trac:`11913`,
see also :trac:`26906`::
sage: sage.misc.sageinspect.sage_getargspec(r.lm)
ArgSpec(args=['self'], varargs='args', keywords='kwds', defaults=None)
The following was fixed in :trac:`16309`::
Expand Down Expand Up @@ -1598,8 +1600,9 @@ def foo(x, a='\')"', b={not (2+1==3):'bar'}): return
return _sage_getargspec_from_ast(proxy)
except SyntaxError:
# To fix trac #10860. See #11913 for more information.
return None
elif isinstance(obj,functools.partial):
# See also #26906.
pass
if isinstance(obj, functools.partial):
base_spec = sage_getargspec(obj.func)
return base_spec
return sage_getargspec(obj.__class__.__call__)
Expand Down
31 changes: 31 additions & 0 deletions src/sage/repl/ipython_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@
File: .../sage/tests/stl_vector.pyx
Type: type
Next, test the ``pinfo`` magic for ``R`` interface code, see :trac:`26906`::
sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell()
sage: shell.run_cell(u'%pinfo r.lm')
Signature: r.lm(self, *args, **kwds)
Call signature: r.lm(*args, **kwds)
Type: RFunction
String form: lm
File: .../sage/interfaces/r.py
Docstring:
title
*****
<BLANKLINE>
Fitting Linear Models
...
Next, test the pinfo2 magic for Python code. This is what IPython
calls when you ask for the double-questionmark help, like `foo??` ::
Expand Down Expand Up @@ -101,6 +118,20 @@ def __cinit__(self):
File: .../sage/tests/stl_vector.pyx
Type: type
Next, test the ``pinfo2`` magic for ``R`` interface code, see :trac:`26906`::
sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell()
sage: shell.run_cell(u'%pinfo2 r.lm')
Signature: r.lm(self, *args, **kwds)
Call signature: r.lm(*args, **kwds)
Type: RFunction
String form: lm
File: .../sage/interfaces/r.py
Source:
function (formula, data, subset, weights, na.action, method = "qr",
...
Test that there are no warnings being ignored internally::
sage: import warnings
Expand Down

0 comments on commit 365c4a4

Please sign in to comment.