[Python-checkins] r51803 - in python/trunk/Lib: inspect.py test/test_inspect.py

nick.coghlan python-checkins at python.org
Thu Sep 7 12:50:35 CEST 2006


Author: nick.coghlan
Date: Thu Sep  7 12:50:34 2006
New Revision: 51803

Modified:
   python/trunk/Lib/inspect.py
   python/trunk/Lib/test/test_inspect.py
Log:
Fix the speed regression in inspect.py by adding another cache to speed up getmodule(). Patch #1553314

Modified: python/trunk/Lib/inspect.py
==============================================================================
--- python/trunk/Lib/inspect.py	(original)
+++ python/trunk/Lib/inspect.py	Thu Sep  7 12:50:34 2006
@@ -403,6 +403,7 @@
     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 @@
         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 @@
         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 @@
     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:

Modified: python/trunk/Lib/test/test_inspect.py
==============================================================================
--- python/trunk/Lib/test/test_inspect.py	(original)
+++ python/trunk/Lib/test/test_inspect.py	Thu Sep  7 12:50:34 2006
@@ -178,7 +178,18 @@
         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)


More information about the Python-checkins mailing list