[Python-checkins] r51978 - python/branches/theller_modulefinder/Lib/modulefinder.py

thomas.heller python-checkins at python.org
Fri Sep 22 13:40:52 CEST 2006


Author: thomas.heller
Date: Fri Sep 22 13:40:52 2006
New Revision: 51978

Modified:
   python/branches/theller_modulefinder/Lib/modulefinder.py
Log:
Rename the yield_opcodes method into scan_opcodes, and implement a
scan_opcodes_15 method that will be used in Python 2.5 and later with
the two-arguments IMPORT_NAME opcode.

The latter yields additional results: 'absolute_import' and
'relative_import', which are not yet supported in scan_code, but raise
a runtime error instead of interpreting the bytecode as 'normal' import.


Modified: python/branches/theller_modulefinder/Lib/modulefinder.py
==============================================================================
--- python/branches/theller_modulefinder/Lib/modulefinder.py	(original)
+++ python/branches/theller_modulefinder/Lib/modulefinder.py	Fri Sep 22 13:40:52 2006
@@ -319,8 +319,8 @@
                         fullname = name + "." + sub
                         self._add_badmodule(fullname, caller)
 
-    def yield_opcodes(self, co,
-                      unpack = struct.unpack):
+    def scan_opcodes(self, co,
+                     unpack = struct.unpack):
         # Scan the code, and yield 'interesting' opcode combinations
         code = co.co_code
         names = co.co_names
@@ -343,9 +343,43 @@
             else:
                 code = code[1:]
 
+    def scan_opcodes_25(self, co,
+                     unpack = struct.unpack):
+        # Scan the code, and yield 'interesting' opcode combinations
+        code = co.co_code
+        names = co.co_names
+        consts = co.co_consts
+        LOAD_LOAD_AND_IMPORT = LOAD_CONST + LOAD_CONST + IMPORT_NAME
+        while code:
+            c = code[0]
+            if c in STORE_OPS:
+                oparg, = unpack('<H', code[1:3])
+                yield "store", (names[oparg],)
+                code = code[3:]
+                continue
+            if code[:9:3] == LOAD_LOAD_AND_IMPORT:
+                oparg_1, oparg_2, oparg_3 = unpack('<xHxHxH', code[:9])
+                level = consts[oparg_1]
+                if level == -1: # normal import
+                    yield "import", (consts[oparg_2], names[oparg_3])
+                elif level == 0: # absolute import
+                    yield "absolute_import", (consts[oparg_2], names[oparg_3])
+                else: # relative import
+                    yield "relative_import", (level, consts[oparg_2], names[oparg_3])
+                code = code[9:]
+                continue
+            if c >= HAVE_ARGUMENT:
+                code = code[3:]
+            else:
+                code = code[1:]
+
     def scan_code(self, co, m):
         code = co.co_code
-        for what, args in self.yield_opcodes(co):
+        if sys.version_info >= (2, 5):
+            scanner = self.scan_opcodes_25
+        else:
+            scanner = self.scan_opcodes
+        for what, args in scanner(co):
             if what == "store":
                 name, = args
                 m.globalnames[name] = 1
@@ -376,6 +410,10 @@
                             m.starimports[name] = 1
                     else:
                         m.starimports[name] = 1
+            elif what == "absolute_import":
+                raise RuntimeError("absolute import not yet implemented")
+            elif what == "relative_import":
+                raise RuntimeError("relative import not yet implemented")
             else:
                 # We don't expect anything else from the generator.
                 raise RuntimeError(what)


More information about the Python-checkins mailing list