Skip to content

Commit

Permalink
Merge pull request ipython#2232 from takluyver/i1456
Browse files Browse the repository at this point in the history
Reapply monkeypatch to inspect.findsource()
  • Loading branch information
Carreau committed Aug 2, 2012
2 parents 6ae0c65 + 27221c2 commit 03af7c7
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 16 deletions.
51 changes: 51 additions & 0 deletions IPython/core/tests/test_ultratb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Tests for IPython.core.ultratb
"""

import os.path
import unittest

from IPython.testing import tools as tt
from IPython.utils.syspathcontext import prepended_to_syspath
from IPython.utils.tempdir import TemporaryDirectory

ip = get_ipython()

file_1 = """1
2
3
def f():
1/0
"""

file_2 = """def f():
1/0
"""

class ChangedPyFileTest(unittest.TestCase):
def test_changing_py_file(self):
"""Traceback produced if the line where the error occurred is missing?
https://github.com/ipython/ipython/issues/1456
"""
with TemporaryDirectory() as td:
fname = os.path.join(td, "foo.py")
with open(fname, "w") as f:
f.write(file_1)

with prepended_to_syspath(td):
ip.run_cell("import foo")

with tt.AssertPrints("ZeroDivisionError"):
ip.run_cell("foo.f()")

# Make the file shorter, so the line of the error is missing.
with open(fname, "w") as f:
f.write(file_2)

# For some reason, this was failing on the *second* call after
# changing the file, so we call f() twice.
with tt.AssertNotPrints("Internal Python error", channel='stderr'):
with tt.AssertPrints("ZeroDivisionError"):
ip.run_cell("foo.f()")
with tt.AssertPrints("ZeroDivisionError"):
ip.run_cell("foo.f()")
19 changes: 6 additions & 13 deletions IPython/core/ultratb.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,10 @@ def inspect_error():
error('Internal Python error in the inspect module.\n'
'Below is the traceback from this internal error.\n')


# N.B. This function is a monkeypatch we are currently not applying.
# It was written some time ago, to fix an apparent Python bug with
# codeobj.co_firstlineno . Unfortunately, we don't know under what conditions
# the bug occurred, so we can't tell if it has been fixed. If it reappears, we
# will apply the monkeypatch again. Also, note that findsource() is not called
# by our code at this time - we don't know if it was when the monkeypatch was
# written, or if the monkeypatch is needed for some other code (like a debugger).
# For the discussion about not applying it, see gh-1229. TK, Jan 2011.
# This function is a monkeypatch we apply to the Python inspect module. We have
# now found when it's needed (see discussion on issue gh-1456), and we have a
# test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
# the monkeypatch is not applied. TK, Aug 2012.
def findsource(object):
"""Return the entire source file and starting line number for an object.
Expand Down Expand Up @@ -210,10 +205,8 @@ def findsource(object):
return lines, lnum
raise IOError('could not find code object')

# Not applying the monkeypatch - see above the function for details. TK, Jan 2012
# Monkeypatch inspect to apply our bugfix. This code only works with py25
#if sys.version_info[:2] >= (2,5):
# inspect.findsource = findsource
# Monkeypatch inspect to apply our bugfix. This code only works with Python >= 2.5
inspect.findsource = findsource

def fix_frame_records_filenames(records):
"""Try to fix the filenames in each record from inspect.getinnerframes().
Expand Down
15 changes: 12 additions & 3 deletions IPython/testing/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,10 @@ def write(self, s):
super(MyStringIO, self).write(s)

notprinted_msg = """Did not find {0!r} in printed output (on {1}):
{2!r}"""
-------
{2!s}
-------
"""

class AssertPrints(object):
"""Context manager for testing that code prints certain text.
Expand Down Expand Up @@ -337,7 +340,13 @@ def __exit__(self, etype, value, traceback):
printed = self.buffer.getvalue()
assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed)
return False


printed_msg = """Found {0!r} in printed output (on {1}):
-------
{2!s}
-------
"""

class AssertNotPrints(AssertPrints):
"""Context manager for checking that certain output *isn't* produced.
Expand All @@ -346,7 +355,7 @@ def __exit__(self, etype, value, traceback):
self.tee.flush()
setattr(sys, self.channel, self.orig_stream)
printed = self.buffer.getvalue()
assert self.s not in printed, notprinted_msg.format(self.s, self.channel, printed)
assert self.s not in printed, printed_msg.format(self.s, self.channel, printed)
return False

@contextmanager
Expand Down

0 comments on commit 03af7c7

Please sign in to comment.