Skip to content

Commit

Permalink
bpo-17735: inspect.findsource now raises OSError when co_lineno is ou…
Browse files Browse the repository at this point in the history
…t of range (pythonGH-23633)

This can happen when a file was edited after it was imported.
  • Loading branch information
iritkatriel committed Dec 4, 2020
1 parent 8d4f57d commit 2e0760b
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
7 changes: 6 additions & 1 deletion Lib/inspect.py
Expand Up @@ -868,7 +868,12 @@ def findsource(object):
lnum = object.co_firstlineno - 1
pat = re.compile(r'^(\s*def\s)|(\s*async\s+def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
while lnum > 0:
if pat.match(lines[lnum]): break
try:
line = lines[lnum]
except IndexError:
raise OSError('lineno is out of bounds')
if pat.match(line):
break
lnum = lnum - 1
return lines, lnum
raise OSError('could not find code object')
Expand Down
11 changes: 11 additions & 0 deletions Lib/test/test_inspect.py
Expand Up @@ -712,6 +712,17 @@ def test_findsource_without_filename(self):
self.assertRaises(IOError, inspect.findsource, co)
self.assertRaises(IOError, inspect.getsource, co)

def test_findsource_with_out_of_bounds_lineno(self):
mod_len = len(inspect.getsource(mod))
src = '\n' * 2* mod_len + "def f(): pass"
co = compile(src, mod.__file__, "exec")
g, l = {}, {}
eval(co, g, l)
func = l['f']
self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len)
with self.assertRaisesRegex(IOError, "lineno is out of bounds"):
inspect.findsource(func)

def test_getsource_on_method(self):
self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)

Expand Down
@@ -0,0 +1,4 @@
:func:`inspect.findsource` now raises :exc:`OSError` instead of
:exc:`IndexError` when :attr:`co_lineno` of a code object is greater than the
file length. This can happen, for example, when a file is edited after it was
imported. PR by Irit Katriel.

0 comments on commit 2e0760b

Please sign in to comment.