diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2006-09-08 10:01:23 +0000 |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2006-09-08 10:01:23 +0000 |
commit | 62f19e4281a12a9460c8f04dc205c3a99271e8c9 (patch) | |
tree | 59a6cd2b7b4c141b35d1aab357f4b5a972be1932 | |
parent | 8de403a56a824947c95511d61b226019c1c813da (diff) | |
download | cpython-git-62f19e4281a12a9460c8f04dc205c3a99271e8c9.tar.gz |
Backport inspect.py fix from rev 51803
-rw-r--r-- | Lib/inspect.py | 19 | ||||
-rw-r--r-- | Lib/test/test_inspect.py | 11 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
3 files changed, 31 insertions, 2 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index 0b498b5c87..ba2021ab94 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -403,6 +403,7 @@ def getabsfile(object, _filename=None): return os.path.normcase(os.path.abspath(_filename)) modulesbyfile = {} +_filesbymodname = {} def getmodule(object, _filename=None): """Return the module an object was defined in, or None if not found.""" @@ -410,19 +411,32 @@ def getmodule(object, _filename=None): return object if hasattr(object, '__module__'): return sys.modules.get(object.__module__) + # Try the filename to modulename cache + if _filename is not None and _filename in modulesbyfile: + return sys.modules.get(modulesbyfile[_filename]) + # Try the cache again with the absolute file name try: file = getabsfile(object, _filename) except TypeError: return None if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) - for module in sys.modules.values(): + # Update the filename to module name cache and check yet again + # Copy sys.modules in order to cope with changes while iterating + for modname, module in sys.modules.items(): if ismodule(module) and hasattr(module, '__file__'): + f = module.__file__ + if f == _filesbymodname.get(modname, None): + # Have already mapped this module, so skip it + continue + _filesbymodname[modname] = f f = getabsfile(module) + # Always map to the name the module knows itself by modulesbyfile[f] = modulesbyfile[ os.path.realpath(f)] = module.__name__ if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) + # Check the main module main = sys.modules['__main__'] if not hasattr(object, '__name__'): return None @@ -430,6 +444,7 @@ def getmodule(object, _filename=None): mainobject = getattr(main, object.__name__) if mainobject is object: return main + # Check builtins builtin = sys.modules['__builtin__'] if hasattr(builtin, object.__name__): builtinobject = getattr(builtin, object.__name__) @@ -444,7 +459,7 @@ def findsource(object): in the file and the line number indexes a line in that list. An IOError is raised if the source code cannot be retrieved.""" file = getsourcefile(object) or getfile(object) - module = getmodule(object) + module = getmodule(object, file) if module: lines = linecache.getlines(file, module.__dict__) else: diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index fa4bd4003f..d880e87dcd 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -178,7 +178,18 @@ class TestRetrievingSourceCode(GetSourceBase): self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n') def test_getmodule(self): + # Check actual module + self.assertEqual(inspect.getmodule(mod), mod) + # Check class (uses __module__ attribute) self.assertEqual(inspect.getmodule(mod.StupidGit), mod) + # Check a method (no __module__ attribute, falls back to filename) + self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod) + # Do it again (check the caching isn't broken) + self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod) + # Check a builtin + self.assertEqual(inspect.getmodule(str), sys.modules["__builtin__"]) + # Check filename override + self.assertEqual(inspect.getmodule(None, modfile), mod) def test_getsource(self): self.assertSourceEqual(git.abuse, 29, 39) @@ -46,6 +46,9 @@ Core and builtins Library ------- +- Patch #1553314: Fix the inspect.py slowdown that was hurting IPython & SAGE + by adding smarter caching in inspect.getmodule() + - Fix missing import of the types module in logging.config. - Patch #1550886: Fix decimal module context management implementation |