]> granicus.if.org Git - python/commitdiff
#8720: fix inspect regression by teaching getsourcefile about linecache.
authorR. David Murray <rdmurray@bitdance.com>
Thu, 17 Jun 2010 01:36:52 +0000 (01:36 +0000)
committerR. David Murray <rdmurray@bitdance.com>
Thu, 17 Jun 2010 01:36:52 +0000 (01:36 +0000)
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
Lib/test/test_inspect.py
Misc/NEWS

index 5344893a43029fb33d224a9be814ce41c6df23f3..8f79bc34416709769b52081d582ed668f32b6986 100644 (file)
@@ -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.
index aaa15f881a866680932e8b325332047e97517436..08630a59f7ea19ea5cb6f41392235bd2f9ed8690 100644 (file)
@@ -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)]
index 152725aaa3e2cee9b003f2e40ea50fd27d6592b4..21bbc3dca5ef92bd0762fc52d90fc3e758cb9466 100644 (file)
--- 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.