##// END OF EJS Templates
Backport PR #4218: Fix display of SyntaxError when .py file is modified...
MinRK -
Show More
@@ -108,8 +108,33 b' class IndentationErrorTest(unittest.TestCase):'
108 with tt.AssertPrints("zoon()", suppress=False):
108 with tt.AssertPrints("zoon()", suppress=False):
109 ip.magic('run %s' % fname)
109 ip.magic('run %s' % fname)
110
110
111 se_file_1 = """1
112 2
113 7/
114 """
115
116 se_file_2 = """7/
117 """
118
111 class SyntaxErrorTest(unittest.TestCase):
119 class SyntaxErrorTest(unittest.TestCase):
112 def test_syntaxerror_without_lineno(self):
120 def test_syntaxerror_without_lineno(self):
113 with tt.AssertNotPrints("TypeError"):
121 with tt.AssertNotPrints("TypeError"):
114 with tt.AssertPrints("line unknown"):
122 with tt.AssertPrints("line unknown"):
115 ip.run_cell("raise SyntaxError()")
123 ip.run_cell("raise SyntaxError()")
124
125 def test_changing_py_file(self):
126 with TemporaryDirectory() as td:
127 fname = os.path.join(td, "foo.py")
128 with open(fname, 'w') as f:
129 f.write(se_file_1)
130
131 with tt.AssertPrints(["7/", "SyntaxError"]):
132 ip.magic("run " + fname)
133
134 # Modify the file
135 with open(fname, 'w') as f:
136 f.write(se_file_2)
137
138 # The SyntaxError should point to the correct line
139 with tt.AssertPrints(["7/", "SyntaxError"]):
140 ip.magic("run " + fname)
@@ -1193,6 +1193,20 b' class SyntaxTB(ListTB):'
1193 self.last_syntax_error = value
1193 self.last_syntax_error = value
1194 ListTB.__call__(self,etype,value,elist)
1194 ListTB.__call__(self,etype,value,elist)
1195
1195
1196 def structured_traceback(self, etype, value, elist, tb_offset=None,
1197 context=5):
1198 # If the source file has been edited, the line in the syntax error can
1199 # be wrong (retrieved from an outdated cache). This replaces it with
1200 # the current value.
1201 if isinstance(value.filename, py3compat.string_types) \
1202 and isinstance(value.lineno, int):
1203 linecache.checkcache(value.filename)
1204 newtext = ulinecache.getline(value.filename, value.lineno)
1205 if newtext:
1206 value.text = newtext
1207 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1208 tb_offset=tb_offset, context=context)
1209
1196 def clear_err_state(self):
1210 def clear_err_state(self):
1197 """Return the current error state and clear it"""
1211 """Return the current error state and clear it"""
1198 e = self.last_syntax_error
1212 e = self.last_syntax_error
@@ -18,7 +18,6 b' from __future__ import absolute_import'
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 import inspect
22 import os
21 import os
23 import re
22 import re
24 import sys
23 import sys
@@ -350,6 +349,8 b' class AssertPrints(object):'
350 """
349 """
351 def __init__(self, s, channel='stdout', suppress=True):
350 def __init__(self, s, channel='stdout', suppress=True):
352 self.s = s
351 self.s = s
352 if isinstance(self.s, py3compat.string_types):
353 self.s = [self.s]
353 self.channel = channel
354 self.channel = channel
354 self.suppress = suppress
355 self.suppress = suppress
355
356
@@ -363,7 +364,8 b' class AssertPrints(object):'
363 self.tee.flush()
364 self.tee.flush()
364 setattr(sys, self.channel, self.orig_stream)
365 setattr(sys, self.channel, self.orig_stream)
365 printed = self.buffer.getvalue()
366 printed = self.buffer.getvalue()
366 assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed)
367 for s in self.s:
368 assert s in printed, notprinted_msg.format(s, self.channel, printed)
367 return False
369 return False
368
370
369 printed_msg = """Found {0!r} in printed output (on {1}):
371 printed_msg = """Found {0!r} in printed output (on {1}):
@@ -380,7 +382,8 b' class AssertNotPrints(AssertPrints):'
380 self.tee.flush()
382 self.tee.flush()
381 setattr(sys, self.channel, self.orig_stream)
383 setattr(sys, self.channel, self.orig_stream)
382 printed = self.buffer.getvalue()
384 printed = self.buffer.getvalue()
383 assert self.s not in printed, printed_msg.format(self.s, self.channel, printed)
385 for s in self.s:
386 assert s not in printed, printed_msg.format(s, self.channel, printed)
384 return False
387 return False
385
388
386 @contextmanager
389 @contextmanager
General Comments 0
You need to be logged in to leave comments. Login now