summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2006-09-08 10:01:23 +0000
committerNick Coghlan <ncoghlan@gmail.com>2006-09-08 10:01:23 +0000
commit62f19e4281a12a9460c8f04dc205c3a99271e8c9 (patch)
tree59a6cd2b7b4c141b35d1aab357f4b5a972be1932
parent8de403a56a824947c95511d61b226019c1c813da (diff)
downloadcpython-git-62f19e4281a12a9460c8f04dc205c3a99271e8c9.tar.gz
Backport inspect.py fix from rev 51803
-rw-r--r--Lib/inspect.py19
-rw-r--r--Lib/test/test_inspect.py11
-rw-r--r--Misc/NEWS3
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)
diff --git a/Misc/NEWS b/Misc/NEWS
index f4dd226f4d..b72e758850 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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