From df1cf301c2da740f9271b3ff164d7f0e5cb9082c Mon Sep 17 00:00:00 2001 From: "R. David Murray" Date: Thu, 17 Jun 2010 01:36:52 +0000 Subject: [PATCH] #8720: fix inspect regression by teaching getsourcefile about linecache. The fix for issue 4050 caused a regression: before that fix, source lines in the linecache would eventually be found by inspect. After the fix inspect reports an error earlier, and the source isn't found. The fix for the fix is to have getsourcefile look in the linecache for the file and return the psuedo-filename if the source is there, just as it already returns it if there is a PEP 302 loader. --- Lib/inspect.py | 7 ++++++- Lib/test/test_inspect.py | 15 +++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index 5344893a43..8f79bc3441 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -440,7 +440,9 @@ def getmodulename(path): if info: return info[0] def getsourcefile(object): - """Return the Python source file an object was defined in, if it exists.""" + """Return the filename that can be used to locate an object's source. + Return None if no way can be identified to get the source. + """ filename = getfile(object) if string.lower(filename[-4:]) in ('.pyc', '.pyo'): filename = filename[:-4] + '.py' @@ -453,6 +455,9 @@ def getsourcefile(object): # only return a non-existent filename if the module has a PEP 302 loader if hasattr(getmodule(object, filename), '__loader__'): return filename + # or it is in the linecache + if filename in linecache.cache: + return filename def getabsfile(object, _filename=None): """Return an absolute path to the source or compiled file for an object. diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index aaa15f881a..08630a59f7 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -3,6 +3,7 @@ import sys import types import unittest import inspect +import linecache import datetime from UserList import UserList from UserDict import UserDict @@ -274,6 +275,11 @@ class TestRetrievingSourceCode(GetSourceBase): def test_getsourcefile(self): self.assertEqual(inspect.getsourcefile(mod.spam), modfile) self.assertEqual(inspect.getsourcefile(git.abuse), modfile) + fn = "_non_existing_filename_used_for_sourcefile_test.py" + co = compile("None", fn, "exec") + self.assertEqual(inspect.getsourcefile(co), None) + linecache.cache[co.co_filename] = (1, None, "None", co.co_filename) + self.assertEqual(inspect.getsourcefile(co), fn) def test_getfile(self): self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__) @@ -372,6 +378,15 @@ class TestBuggyCases(GetSourceBase): self.assertRaises(IOError, inspect.getsource, unicodedata) self.assertRaises(IOError, inspect.findsource, unicodedata) + def test_findsource_code_in_linecache(self): + lines = ["x=1"] + co = compile(lines[0], "_dynamically_created_file", "exec") + self.assertRaises(IOError, inspect.findsource, co) + self.assertRaises(IOError, inspect.getsource, co) + linecache.cache[co.co_filename] = (1, None, lines, co.co_filename) + self.assertEquals(inspect.findsource(co), (lines,0)) + self.assertEquals(inspect.getsource(co), lines[0]) + # Helper for testing classify_class_attrs. def attrs_wo_objs(cls): return [t[:3] for t in inspect.classify_class_attrs(cls)] diff --git a/Misc/NEWS b/Misc/NEWS index 152725aaa3..21bbc3dca5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,9 @@ Core and Builtins Library ------- +- Issue #8720: fix regression caused by fix for #4050 by making getsourcefile + smart enough to find source files in the linecache. + - Issue #8986: math.erfc was incorrectly raising OverflowError for values between -27.3 and -30.0 on some platforms. -- 2.40.0