You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Merge branch 'master' of github.com:rocky/python-uncompyle6
This commit is contained in:
7
Makefile
7
Makefile
@@ -27,8 +27,9 @@ check:
|
||||
check-short: pytest
|
||||
$(MAKE) -C test check-short
|
||||
|
||||
# Note for 2.6 use <=3.0.1 see requirements-dev.txt
|
||||
#: Tests for Python 2.7, 3.3 and 3.4
|
||||
check-2.7 check-3.3 check-3.4: pytest
|
||||
check-2.6 check-2.7 check-3.3 check-3.4: pytest
|
||||
$(MAKE) -C test $@
|
||||
|
||||
#: Tests for Python 3.2 and 3.5 - pytest doesn't work here
|
||||
@@ -38,10 +39,6 @@ check-3.0 check-3.1 check-3.2 check-3.5 check-3.6:
|
||||
|
||||
check-3.7: pytest
|
||||
|
||||
#:Tests for Python 2.6 (doesn't have pytest)
|
||||
check-2.6:
|
||||
$(MAKE) -C test $@
|
||||
|
||||
#:PyPy 2.6.1 PyPy 5.0.1, or PyPy 5.8.0-beta0
|
||||
# Skip for now
|
||||
2.6 5.0 5.3 5.6 5.8:
|
||||
|
@@ -23,12 +23,7 @@ def test_if_in_for():
|
||||
code = bug.__code__
|
||||
scan = get_scanner(PYTHON_VERSION)
|
||||
if 2.7 <= PYTHON_VERSION <= 3.0 and not IS_PYPY:
|
||||
bytecode = scan.build_instructions(code)
|
||||
scan.lines = scan.build_lines_data(code)
|
||||
scan.insts = list(bytecode)
|
||||
scan.offset2inst_index = {}
|
||||
for i, inst in enumerate(scan.insts):
|
||||
scan.offset2inst_index[inst.offset] = i
|
||||
scan.build_instructions(code)
|
||||
fjt = scan.find_jump_targets(False)
|
||||
|
||||
## FIXME: the data below is wrong.
|
||||
@@ -43,12 +38,7 @@ def test_if_in_for():
|
||||
# {'start': 62, 'end': 63, 'type': 'for-else'}]
|
||||
|
||||
code = bug_loop.__code__
|
||||
bytecode = scan.build_instructions(code)
|
||||
scan.lines = scan.build_lines_data(code)
|
||||
scan.insts = list(bytecode)
|
||||
scan.offset2inst_index = {}
|
||||
for i, inst in enumerate(scan.insts):
|
||||
scan.offset2inst_index[inst.offset] = i
|
||||
scan.build_instructions(code)
|
||||
fjt = scan.find_jump_targets(False)
|
||||
assert{64: [42], 67: [42, 42], 42: [16, 41], 19: [6]} == fjt
|
||||
assert scan.structs == [
|
||||
@@ -62,12 +52,7 @@ def test_if_in_for():
|
||||
{'start': 48, 'end': 67, 'type': 'while-loop'}]
|
||||
|
||||
elif 3.2 < PYTHON_VERSION <= 3.4:
|
||||
bytecode = scan.build_instructions(code)
|
||||
scan.lines = scan.build_lines_data(code)
|
||||
scan.insts = list(bytecode)
|
||||
scan.offset2inst_index = {}
|
||||
for i, inst in enumerate(scan.insts):
|
||||
scan.offset2inst_index[inst.offset] = i
|
||||
scan.build_instructions(code)
|
||||
fjt = scan.find_jump_targets(False)
|
||||
assert {69: [66], 63: [18]} == fjt
|
||||
assert scan.structs == \
|
||||
|
@@ -6,7 +6,7 @@ import pytest
|
||||
# uncompyle
|
||||
from validate import validate_uncompyle
|
||||
from test_fstring import expressions
|
||||
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
|
||||
alpha = st.sampled_from(string.ascii_lowercase)
|
||||
numbers = st.sampled_from(string.digits)
|
||||
@@ -81,10 +81,11 @@ def function_calls(draw,
|
||||
def test_function_no_args():
|
||||
validate_uncompyle("fn()")
|
||||
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
def isolated_function_calls(which):
|
||||
"""
|
||||
Returns a strategy for generating function calls, but isolated to
|
||||
Returns a strategy for generating function calls, but isolated to
|
||||
particular types of arguments, for example only positional arguments.
|
||||
|
||||
This can help reason about debugging errors in specific types of function
|
||||
@@ -108,21 +109,29 @@ def isolated_function_calls(which):
|
||||
|
||||
with settings(max_examples=25):
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
@given(isolated_function_calls('positional'))
|
||||
@example("fn(0)")
|
||||
def test_function_positional_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
@given(isolated_function_calls('keyword'))
|
||||
@example("fn(a=0)")
|
||||
def test_function_call_keyword_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
@given(isolated_function_calls('star'))
|
||||
@example("fn(*items)")
|
||||
def test_function_call_star_only(expr):
|
||||
validate_uncompyle(expr)
|
||||
|
||||
@pytest.mark.skipif(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
@given(isolated_function_calls('double_star'))
|
||||
@example("fn(**{})")
|
||||
def test_function_call_double_star_only(expr):
|
||||
|
@@ -20,13 +20,17 @@ def test_grammar():
|
||||
# We have custom rules that create the below
|
||||
expect_lhs = set(['pos_arg', 'get_iter', 'attribute'])
|
||||
|
||||
unused_rhs = set(['list', 'mkfunc', 'dict',
|
||||
unused_rhs = set(['list', 'mkfunc',
|
||||
'mklambda',
|
||||
'unpack',])
|
||||
expect_right_recursive = set([('designList',
|
||||
('store', 'DUP_TOP', 'designList'))])
|
||||
expect_lhs.add('kvlist')
|
||||
expect_lhs.add('kv3')
|
||||
|
||||
if PYTHON_VERSION > 2.6:
|
||||
expect_lhs.add('kvlist')
|
||||
expect_lhs.add('kv3')
|
||||
unused_rhs.add('dict')
|
||||
|
||||
if PYTHON3:
|
||||
expect_lhs.add('load_genexpr')
|
||||
|
||||
@@ -85,6 +89,8 @@ def test_grammar():
|
||||
""".split())
|
||||
if 2.6 <= PYTHON_VERSION <= 2.7:
|
||||
opcode_set = set(s.opc.opname).union(ignore_set)
|
||||
if PYTHON_VERSION == 2.6:
|
||||
opcode_set.add("THEN")
|
||||
check_tokens(tokens, opcode_set)
|
||||
elif PYTHON_VERSION == 3.4:
|
||||
ignore_set.add('LOAD_CLASSNAME')
|
||||
|
@@ -1,6 +1,8 @@
|
||||
import pytest
|
||||
from uncompyle6 import PYTHON_VERSION, PYTHON3, deparse_code
|
||||
from uncompyle6 import PYTHON_VERSION, deparse_code
|
||||
|
||||
@pytest.mark.skip(PYTHON_VERSION < 2.7,
|
||||
reason="need at least Python 2.7")
|
||||
def test_single_mode():
|
||||
single_expressions = (
|
||||
'i = 1',
|
||||
|
@@ -1,3 +1,3 @@
|
||||
pytest>=3.0.0
|
||||
pytest>=3.0.0,<=3.0.1
|
||||
flake8
|
||||
hypothesis<=3.8.3
|
||||
hypothesis<=3.0.0
|
||||
|
@@ -105,6 +105,11 @@ class Scanner(object):
|
||||
bytecode = Bytecode(co, self.opc)
|
||||
self.build_prev_op()
|
||||
self.insts = self.remove_extended_args(list(bytecode))
|
||||
self.lines = self.build_lines_data(co)
|
||||
self.offset2inst_index = {}
|
||||
for i, inst in enumerate(self.insts):
|
||||
self.offset2inst_index[inst.offset] = i
|
||||
|
||||
return bytecode
|
||||
|
||||
def build_lines_data(self, code_obj):
|
||||
@@ -117,10 +122,6 @@ class Scanner(object):
|
||||
linestarts = list(self.opc.findlinestarts(code_obj))
|
||||
self.linestarts = dict(linestarts)
|
||||
|
||||
# Plain set with offsets of first ops on line.
|
||||
# FIXME: we probably could do without
|
||||
self.linestart_offsets = set(a for (a, _) in linestarts)
|
||||
|
||||
# 'List-map' which shows line number of current op and offset of
|
||||
# first op on following line, given offset of op as index
|
||||
lines = []
|
||||
@@ -452,6 +453,9 @@ class Scanner(object):
|
||||
Go through passed offsets, filtering ifs
|
||||
located somewhere mid-line.
|
||||
"""
|
||||
|
||||
# FIXME: this doesn't work for Python 3.6+
|
||||
|
||||
filtered = []
|
||||
for i in ifs:
|
||||
# For each offset, if line number of current and next op
|
||||
|
@@ -171,11 +171,6 @@ class Scanner2(Scanner):
|
||||
customize['PyPy'] = 0
|
||||
|
||||
codelen = len(self.code)
|
||||
self.lines = self.build_lines_data(co)
|
||||
|
||||
self.offset2inst_index = {}
|
||||
for i, inst in enumerate(self.insts):
|
||||
self.offset2inst_index[inst.offset] = i
|
||||
|
||||
free, names, varnames = self.unmangle_code_names(co, classname)
|
||||
self.names = names
|
||||
@@ -186,8 +181,6 @@ class Scanner2(Scanner):
|
||||
self.load_asserts = set()
|
||||
for i in self.op_range(0, codelen):
|
||||
|
||||
self.offset2inst_index[inst.offset] = i
|
||||
|
||||
# We need to detect the difference between:
|
||||
# raise AssertionError
|
||||
# and
|
||||
@@ -358,7 +351,7 @@ class Scanner2(Scanner):
|
||||
if (offset in self.stmts and
|
||||
self.code[offset+3] not in (self.opc.END_FINALLY,
|
||||
self.opc.POP_BLOCK)):
|
||||
if ((offset in self.linestart_offsets and
|
||||
if ((offset in self.linestarts and
|
||||
self.code[self.prev[offset]] == self.opc.JUMP_ABSOLUTE)
|
||||
or self.code[target] == self.opc.FOR_ITER
|
||||
or offset not in self.not_continue):
|
||||
@@ -956,7 +949,7 @@ class Scanner2(Scanner):
|
||||
'end': pre_rtarget})
|
||||
|
||||
# FIXME: this is yet another case were we need dominators.
|
||||
if (pre_rtarget not in self.linestart_offsets
|
||||
if (pre_rtarget not in self.linestarts
|
||||
or self.version < 2.7):
|
||||
self.not_continue.add(pre_rtarget)
|
||||
|
||||
|
@@ -84,13 +84,6 @@ class Scanner26(scan.Scanner2):
|
||||
|
||||
codelen = len(self.code)
|
||||
|
||||
self.lines = self.build_lines_data(co)
|
||||
|
||||
self.insts = list(bytecode)
|
||||
self.offset2inst_index = {}
|
||||
for i, inst in enumerate(self.insts):
|
||||
self.offset2inst_index[inst.offset] = i
|
||||
|
||||
free, names, varnames = self.unmangle_code_names(co, classname)
|
||||
self.names = names
|
||||
|
||||
@@ -248,7 +241,7 @@ class Scanner26(scan.Scanner2):
|
||||
if (offset in self.stmts
|
||||
and self.code[offset+3] not in (self.opc.END_FINALLY,
|
||||
self.opc.POP_BLOCK)):
|
||||
if ((offset in self.linestart_offsets and
|
||||
if ((offset in self.linestarts and
|
||||
tokens[-1].kind == 'JUMP_BACK')
|
||||
or offset not in self.not_continue):
|
||||
op_name = 'CONTINUE'
|
||||
|
@@ -187,19 +187,14 @@ class Scanner3(Scanner):
|
||||
if self.is_pypy:
|
||||
customize['PyPy'] = 0
|
||||
|
||||
self.lines = self.build_lines_data(co)
|
||||
|
||||
# Scan for assertions. Later we will
|
||||
# turn 'LOAD_GLOBAL' to 'LOAD_ASSERT'.
|
||||
# 'LOAD_ASSERT' is used in assert statements.
|
||||
self.load_asserts = set()
|
||||
|
||||
self.offset2inst_index = {}
|
||||
n = len(self.insts)
|
||||
for i, inst in enumerate(self.insts):
|
||||
|
||||
self.offset2inst_index[inst.offset] = i
|
||||
|
||||
# We need to detect the difference between:
|
||||
# raise AssertionError
|
||||
# and
|
||||
|
Reference in New Issue
Block a user