summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/inspect.py7
-rw-r--r--Lib/test/test_inspect.py15
-rw-r--r--Misc/NEWS3
3 files changed, 24 insertions, 1 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py
index ea30466..d6ac4e0 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -437,7 +437,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 filename[-4:].lower() in ('.pyc', '.pyo'):
filename = filename[:-4] + '.py'
@@ -450,6 +452,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 b89f8075..b515c1f 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
import collections
from os.path import normcase
@@ -275,6 +276,11 @@ class TestRetrievingSourceCode(GetSourceBase):
def test_getsourcefile(self):
self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
+ fn = "_non_existing_filename_used_for_sourcefile_test.py"
+ co = compile("None", fn, "exec")
+ self.assertEqual(normcase(inspect.getsourcefile(co)), None)
+ linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
+ self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
def test_getfile(self):
self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
@@ -373,6 +379,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 7f8ccef..0de8581 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -437,6 +437,9 @@ C-API
Library
-------
+- Issue #8720: fix regression caused by fix for #4050 by making getsourcefile
+ smart enough to find source files in the linecache.
+
- Issue #5610: feedparser no longer eats extra characters at the end of
a body part if the body part ends with a \r\n.