[Python-checkins] r51826 - in python/branches/release25-maint: Lib/inspect.py Lib/test/test_inspect.py Misc/NEWS

nick.coghlan python-checkins at python.org
Fri Sep 8 12:01:24 CEST 2006


Author: nick.coghlan
Date: Fri Sep  8 12:01:23 2006
New Revision: 51826

Modified:
   python/branches/release25-maint/Lib/inspect.py
   python/branches/release25-maint/Lib/test/test_inspect.py
   python/branches/release25-maint/Misc/NEWS
Log:
Backport inspect.py fix from rev 51803

Modified: python/branches/release25-maint/Lib/inspect.py
==============================================================================
--- python/branches/release25-maint/Lib/inspect.py	(original)
+++ python/branches/release25-maint/Lib/inspect.py	Fri Sep  8 12:01:23 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/branches/release25-maint/Lib/test/test_inspect.py
==============================================================================
--- python/branches/release25-maint/Lib/test/test_inspect.py	(original)
+++ python/branches/release25-maint/Lib/test/test_inspect.py	Fri Sep  8 12:01:23 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)

Modified: python/branches/release25-maint/Misc/NEWS
==============================================================================
--- python/branches/release25-maint/Misc/NEWS	(original)
+++ python/branches/release25-maint/Misc/NEWS	Fri Sep  8 12:01:23 2006
@@ -46,6 +46,9 @@
 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


More information about the Python-checkins mailing list