diff options
-rw-r--r-- | Lib/inspect.py | 16 | ||||
-rw-r--r-- | Lib/test/test_inspect.py | 33 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
3 files changed, 46 insertions, 6 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index 83044b4..b789d66 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -653,11 +653,17 @@ def findsource(object): in the file and the line number indexes a line in that list. An OSError is raised if the source code cannot be retrieved.""" - file = getfile(object) - sourcefile = getsourcefile(object) - if not sourcefile and file[:1] + file[-1:] != '<>': - raise OSError('source code not available') - file = sourcefile if sourcefile else file + file = getsourcefile(object) + if file: + # Invalidate cache if needed. + linecache.checkcache(file) + else: + file = getfile(object) + # Allow filenames in form of "<something>" to pass through. + # `doctest` monkeypatches `linecache` module to enable + # inspection, so let `linecache.getlines` to be called. + if not (file.startswith('<') and file.endswith('>')): + raise OSError('source code not available') module = getmodule(object, file) if module: diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 9586041..bbc5385 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -14,6 +14,7 @@ import re import shutil import sys import types +import textwrap import unicodedata import unittest import unittest.mock @@ -29,6 +30,8 @@ from test.script_helper import assert_python_ok, assert_python_failure from test import inspect_fodder as mod from test import inspect_fodder2 as mod2 +from test.test_import import _ready_to_import + # Functions tested in this suite: # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode, @@ -3262,6 +3265,34 @@ class TestMain(unittest.TestCase): self.assertEqual(err, b'') +class TestReload(unittest.TestCase): + + src_before = textwrap.dedent("""\ +def foo(): + print("Bla") + """) + + src_after = textwrap.dedent("""\ +def foo(): + print("Oh no!") + """) + + def assertInspectEqual(self, path, source): + inspected_src = inspect.getsource(source) + with open(path) as src: + self.assertEqual( + src.read().splitlines(True), + inspected_src.splitlines(True) + ) + + def test_getsource_reload(self): + # see issue 1218234 + with _ready_to_import('reload_bug', self.src_before) as (name, path): + module = importlib.import_module(name) + self.assertInspectEqual(path, module) + with open(path, 'w') as src: + src.write(self.src_after) + self.assertInspectEqual(path, module) def test_main(): @@ -3272,7 +3303,7 @@ def test_main(): TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState, TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject, TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars, - TestUnwrap, TestMain + TestUnwrap, TestMain, TestReload ) if __name__ == "__main__": @@ -194,6 +194,9 @@ Core and Builtins Library ------- +- Issue #1218234: Fix inspect.getsource() to load updated source of + reloaded module. Initial patch by Berker Peksag. + - Issue #21740: Support wrapped callables in pydoc. Patch by Claudiu Popa. - Issue #23009: Make sure selectors.EpollSelecrtor.select() works when no |