mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
Issue #26881: The modulefinder module now supports extended opcode arguments.
This commit is contained in:
parent
c7cc9850d4
commit
02d9f5e5b2
4 changed files with 63 additions and 58 deletions
|
@ -13,13 +13,12 @@ with warnings.catch_warnings():
|
|||
warnings.simplefilter('ignore', PendingDeprecationWarning)
|
||||
import imp
|
||||
|
||||
# XXX Clean up once str8's cstor matches bytes.
|
||||
LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')])
|
||||
IMPORT_NAME = bytes([dis.opname.index('IMPORT_NAME')])
|
||||
STORE_NAME = bytes([dis.opname.index('STORE_NAME')])
|
||||
STORE_GLOBAL = bytes([dis.opname.index('STORE_GLOBAL')])
|
||||
STORE_OPS = [STORE_NAME, STORE_GLOBAL]
|
||||
HAVE_ARGUMENT = bytes([dis.HAVE_ARGUMENT])
|
||||
LOAD_CONST = dis.opmap['LOAD_CONST']
|
||||
IMPORT_NAME = dis.opmap['IMPORT_NAME']
|
||||
STORE_NAME = dis.opmap['STORE_NAME']
|
||||
STORE_GLOBAL = dis.opmap['STORE_GLOBAL']
|
||||
STORE_OPS = STORE_NAME, STORE_GLOBAL
|
||||
EXTENDED_ARG = dis.EXTENDED_ARG
|
||||
|
||||
# Modulefinder does a good job at simulating Python's, but it can not
|
||||
# handle __path__ modifications packages make at runtime. Therefore there
|
||||
|
@ -337,38 +336,30 @@ class ModuleFinder:
|
|||
fullname = name + "." + sub
|
||||
self._add_badmodule(fullname, caller)
|
||||
|
||||
def scan_opcodes_25(self, co,
|
||||
unpack = struct.unpack):
|
||||
def scan_opcodes(self, co):
|
||||
# Scan the code, and yield 'interesting' opcode combinations
|
||||
# Python 2.5 version (has absolute and relative imports)
|
||||
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 = bytes([code[0]])
|
||||
if c in STORE_OPS:
|
||||
oparg, = unpack('<H', code[1:3])
|
||||
opargs = [(op, arg) for _, op, arg in dis._unpack_opargs(code)
|
||||
if op != EXTENDED_ARG]
|
||||
for i, (op, oparg) in enumerate(opargs):
|
||||
if op in STORE_OPS:
|
||||
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 (op == IMPORT_NAME and i >= 2
|
||||
and opargs[i-1][0] == opargs[i-2][0] == LOAD_CONST):
|
||||
level = consts[opargs[i-2][1]]
|
||||
fromlist = consts[opargs[i-1][1]]
|
||||
if level == 0: # absolute import
|
||||
yield "absolute_import", (consts[oparg_2], names[oparg_3])
|
||||
yield "absolute_import", (fromlist, names[oparg])
|
||||
else: # relative import
|
||||
yield "relative_import", (level, consts[oparg_2], names[oparg_3])
|
||||
code = code[9:]
|
||||
yield "relative_import", (level, fromlist, names[oparg])
|
||||
continue
|
||||
if c >= HAVE_ARGUMENT:
|
||||
code = code[3:]
|
||||
else:
|
||||
code = code[1:]
|
||||
|
||||
def scan_code(self, co, m):
|
||||
code = co.co_code
|
||||
scanner = self.scan_opcodes_25
|
||||
scanner = self.scan_opcodes
|
||||
for what, args in scanner(co):
|
||||
if what == "store":
|
||||
name, = args
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue