Commit 1bd827ef authored by Preston Landers's avatar Preston Landers

Attempt to fix issue #866 by iterating over code with `dis.Bytecode` instead...

Attempt to fix issue #866 by iterating over code with `dis.Bytecode` instead of the internal `_iter_code`.

The `dis` module was already used in `_iter_code` so I figured it was safe to use `Bytecode` from it. Not sure how this assumption holds up across all supported Python releases. I can only assume `Bytecode` wasn't there before when `_iter_code` was originally written?

Note that `_iter_code` doesn't appear to be called anywhere in light of this change so I removed it.

I should also note that `get_module_constant` has never worked with `setuptools.__version__` (returns -1) because it's not a string literal; it gets that attribute from another module.  But this change does work in cases where a string literal is requested.

https://github.com/pypa/setuptools/issues/866
parent 6d69dd73
...@@ -4,7 +4,6 @@ import marshal ...@@ -4,7 +4,6 @@ import marshal
from distutils.version import StrictVersion from distutils.version import StrictVersion
from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN
from setuptools.extern import six
__all__ = [ __all__ = [
'Require', 'find_module', 'get_module_constant', 'extract_constant' 'Require', 'find_module', 'get_module_constant', 'extract_constant'
...@@ -78,39 +77,6 @@ class Require: ...@@ -78,39 +77,6 @@ class Require:
return self.version_ok(version) return self.version_ok(version)
def _iter_code(code):
"""Yield '(op,arg)' pair for each operation in code object 'code'"""
from array import array
from dis import HAVE_ARGUMENT, EXTENDED_ARG
bytes = array('b', code.co_code)
eof = len(code.co_code)
ptr = 0
extended_arg = 0
while ptr < eof:
op = bytes[ptr]
if op >= HAVE_ARGUMENT:
arg = bytes[ptr + 1] + bytes[ptr + 2] * 256 + extended_arg
ptr += 3
if op == EXTENDED_ARG:
long_type = six.integer_types[-1]
extended_arg = arg * long_type(65536)
continue
else:
arg = None
ptr += 1
yield op, arg
def find_module(module, paths=None): def find_module(module, paths=None):
"""Just like 'imp.find_module()', but with package support""" """Just like 'imp.find_module()', but with package support"""
...@@ -176,11 +142,12 @@ def extract_constant(code, symbol, default=-1): ...@@ -176,11 +142,12 @@ def extract_constant(code, symbol, default=-1):
only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol'
must be present in 'code.co_names'. must be present in 'code.co_names'.
""" """
if symbol not in code.co_names: if symbol not in code.co_names:
# name's not there, can't possibly be an assigment # name's not there, can't possibly be an assignment
return None return None
from dis import Bytecode
name_idx = list(code.co_names).index(symbol) name_idx = list(code.co_names).index(symbol)
STORE_NAME = 90 STORE_NAME = 90
...@@ -189,7 +156,9 @@ def extract_constant(code, symbol, default=-1): ...@@ -189,7 +156,9 @@ def extract_constant(code, symbol, default=-1):
const = default const = default
for op, arg in _iter_code(code): for byte_code in Bytecode(code):
op = byte_code.opcode
arg = byte_code.arg
if op == LOAD_CONST: if op == LOAD_CONST:
const = code.co_consts[arg] const = code.co_consts[arg]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment