Skip to content

Commit

Permalink
Backport PR #2169: ipdb: pdef, pdoc, pinfo magics all broken
Browse files Browse the repository at this point in the history
```
In[1]: dg.meshes.square.qmesh(2)
...
IndexError: index (48) out of range (0<=index<47) in dimension 0

In [2]: debug
...
ipdb> pinfo jx
...
/usr/lib/python2.7/dist-packages/IPython/core/debugger.pyc in do_pinfo(self, arg)
    490         namespaces = [('Locals', self.curframe.f_locals),
    491                       ('Globals', self.curframe.f_globals)]
--> 492         self.shell.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
    493
    494     def checkline(self, filename, lineno):

AttributeError: 'TerminalInteractiveShell' object has no attribute 'magic_pinfo'
```
  • Loading branch information
minrk committed Jul 27, 2012
1 parent 01e35e5 commit 07ce325
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 4 deletions.
7 changes: 4 additions & 3 deletions IPython/core/debugger.py
Expand Up @@ -477,19 +477,20 @@ def do_pdef(self, arg):
"""The debugger interface to magic_pdef"""
namespaces = [('Locals', self.curframe.f_locals),
('Globals', self.curframe.f_globals)]
self.shell.magic_pdef(arg, namespaces=namespaces)
self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)

def do_pdoc(self, arg):
"""The debugger interface to magic_pdoc"""
namespaces = [('Locals', self.curframe.f_locals),
('Globals', self.curframe.f_globals)]
self.shell.magic_pdoc(arg, namespaces=namespaces)
self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)

def do_pinfo(self, arg):
"""The debugger equivalant of ?obj"""
namespaces = [('Locals', self.curframe.f_locals),
('Globals', self.curframe.f_globals)]
self.shell.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
self.shell.find_line_magic('pinfo')("pinfo %s" % arg,
namespaces=namespaces)

def checkline(self, filename, lineno):
"""Check whether specified line seems to be executable.
Expand Down
2 changes: 1 addition & 1 deletion IPython/core/interactiveshell.py
Expand Up @@ -1478,7 +1478,7 @@ def _inspect(self, meth, oname, namespaces=None, **kw):
"""Generic interface to the inspector system.
This function is meant to be called by pdef, pdoc & friends."""
info = self._object_find(oname)
info = self._object_find(oname, namespaces)
if info.found:
pmethod = getattr(self.inspector, meth)
formatter = format_screen if info.ismagic else None
Expand Down
88 changes: 88 additions & 0 deletions IPython/core/tests/test_debugger.py
Expand Up @@ -12,12 +12,46 @@
# Imports
#-----------------------------------------------------------------------------

import sys

# third-party
import nose.tools as nt

# Our own
from IPython.core import debugger

#-----------------------------------------------------------------------------
# Helper classes, from CPython's Pdb test suite
#-----------------------------------------------------------------------------

class _FakeInput(object):
"""
A fake input stream for pdb's interactive debugger. Whenever a
line is read, print it (to simulate the user typing it), and then
return it. The set of lines to return is specified in the
constructor; they should not have trailing newlines.
"""
def __init__(self, lines):
self.lines = iter(lines)

def readline(self):
line = next(self.lines)
print line
return line+'\n'

class PdbTestInput(object):
"""Context manager that makes testing Pdb in doctests easier."""

def __init__(self, input):
self.input = input

def __enter__(self):
self.real_stdin = sys.stdin
sys.stdin = _FakeInput(self.input)

def __exit__(self, *exc):
sys.stdin = self.real_stdin

#-----------------------------------------------------------------------------
# Tests
#-----------------------------------------------------------------------------
Expand All @@ -33,3 +67,57 @@ def test_longer_repr():
# in-place, since that global is used directly by the stdlib's pdb module.
t = debugger.Tracer()
nt.assert_equals(trepr(a), ar)

def test_ipdb_magics():
'''Test calling some IPython magics from ipdb.
First, set up some test functions and classes which we can inspect.
>>> class ExampleClass(object):
... """Docstring for ExampleClass."""
... def __init__(self):
... """Docstring for ExampleClass.__init__"""
... pass
... def __str__(self):
... return "ExampleClass()"
>>> def example_function(x, y, z="hello"):
... """Docstring for example_function."""
... pass
Create a function which triggers ipdb.
>>> def trigger_ipdb():
... a = ExampleClass()
... debugger.Pdb().set_trace()
>>> with PdbTestInput([
... 'pdef example_function',
... 'pdoc ExampleClass',
... 'pinfo a',
... 'continue',
... ]):
... trigger_ipdb()
--Return--
None
> <doctest ...>(3)trigger_ipdb()
1 def trigger_ipdb():
2 a = ExampleClass()
----> 3 debugger.Pdb().set_trace()
<BLANKLINE>
ipdb> pdef example_function
example_function(x, y, z='hello')
ipdb> pdoc ExampleClass
Class Docstring:
Docstring for ExampleClass.
Constructor Docstring:
Docstring for ExampleClass.__init__
ipdb> pinfo a
Type: ExampleClass
String Form:ExampleClass()
Namespace: Locals
File: ...
Docstring: Docstring for ExampleClass.
Constructor Docstring:Docstring for ExampleClass.__init__
ipdb> continue
'''

0 comments on commit 07ce325

Please sign in to comment.