You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
3.7 "imports" and "or"
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.7_run/01_conditional.pyc
Normal file
BIN
test/bytecode_3.7_run/01_conditional.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.8_run/01_conditional.pyc
Normal file
BIN
test/bytecode_3.8_run/01_conditional.pyc
Normal file
Binary file not shown.
Binary file not shown.
@@ -5,12 +5,15 @@
|
|||||||
|
|
||||||
# RUNNABLE!
|
# RUNNABLE!
|
||||||
import os.path as osp
|
import os.path as osp
|
||||||
from sys import path
|
from sys import platform
|
||||||
from os import sep, name
|
from os import sep, name
|
||||||
import collections.abc
|
import collections.abc
|
||||||
|
|
||||||
assert osp.basename("a") == "a"
|
assert osp.basename("a") == "a"
|
||||||
assert path
|
|
||||||
|
assert isinstance(platform, str)
|
||||||
assert sep
|
assert sep
|
||||||
assert name
|
assert name
|
||||||
assert collections.abc
|
assert collections.abc
|
||||||
|
import os.path as path
|
||||||
|
assert path
|
||||||
|
@@ -8,3 +8,14 @@ def foo(n):
|
|||||||
assert foo(95)
|
assert foo(95)
|
||||||
assert not foo(94)
|
assert not foo(94)
|
||||||
assert not foo(96)
|
assert not foo(96)
|
||||||
|
|
||||||
|
# from test_buffer.py
|
||||||
|
# Bug was handling "or" inside a conditional
|
||||||
|
def rslice(a, b):
|
||||||
|
minlen = 0 if a or b else 1
|
||||||
|
return minlen
|
||||||
|
|
||||||
|
assert rslice(False, False) == 1
|
||||||
|
assert rslice(False, True) == 0
|
||||||
|
assert rslice(True, False) == 0
|
||||||
|
assert rslice(True, True) == 0
|
||||||
|
@@ -454,7 +454,6 @@ case $PYVERSION in
|
|||||||
[test_compare.py]=1 # test assert fail - investigate
|
[test_compare.py]=1 # test assert fail - investigate
|
||||||
[test_compile.py]=1
|
[test_compile.py]=1
|
||||||
[test_configparser.py]=1
|
[test_configparser.py]=1
|
||||||
[test_contextlib_async.py]=1 # Investigate
|
|
||||||
[test_context.py]=1
|
[test_context.py]=1
|
||||||
[test_coroutines.py]=1 # Parse error
|
[test_coroutines.py]=1 # Parse error
|
||||||
[test_crypt.py]=1 # Parse error
|
[test_crypt.py]=1 # Parse error
|
||||||
|
@@ -913,6 +913,7 @@ class Python37Parser(Python37BaseParser):
|
|||||||
or ::= and jitop_come_from expr COME_FROM
|
or ::= and jitop_come_from expr COME_FROM
|
||||||
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
||||||
or ::= expr JUMP_IF_TRUE expr COME_FROM
|
or ::= expr JUMP_IF_TRUE expr COME_FROM
|
||||||
|
or ::= expr POP_JUMP_IF_TRUE expr POP_JUMP_IF_FALSE COME_FROM
|
||||||
|
|
||||||
testfalse_not_or ::= expr jmp_false expr jmp_false COME_FROM
|
testfalse_not_or ::= expr jmp_false expr jmp_false COME_FROM
|
||||||
testfalse_not_and ::= and jmp_true come_froms
|
testfalse_not_and ::= and jmp_true come_froms
|
||||||
|
@@ -3,10 +3,7 @@
|
|||||||
|
|
||||||
def or_check(self, lhs, n, rule, ast, tokens, first, last):
|
def or_check(self, lhs, n, rule, ast, tokens, first, last):
|
||||||
if rule == ("or", ("expr", "jmp_true", "expr")):
|
if rule == ("or", ("expr", "jmp_true", "expr")):
|
||||||
if tokens[last] in (
|
if tokens[last] in ("LOAD_ASSERT", "RAISE_VARARGS_1",):
|
||||||
"LOAD_ASSERT",
|
|
||||||
"RAISE_VARARGS_1",
|
|
||||||
):
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# The following test is be the most accurate. It prevents "or" from being
|
# The following test is be the most accurate. It prevents "or" from being
|
||||||
@@ -16,7 +13,7 @@ def or_check(self, lhs, n, rule, ast, tokens, first, last):
|
|||||||
# The below then is useful until we get better control-flow analysis.
|
# The below then is useful until we get better control-flow analysis.
|
||||||
# Note it is too hard in the scanner right nowto turn the LOAD_GLOBAL into
|
# Note it is too hard in the scanner right nowto turn the LOAD_GLOBAL into
|
||||||
# int LOAD_ASSERT, however in 3.9ish code generation does this by default.
|
# int LOAD_ASSERT, however in 3.9ish code generation does this by default.
|
||||||
load_global = tokens[last-1]
|
load_global = tokens[last - 1]
|
||||||
if load_global == "LOAD_GLOBAL" and load_global.attr == "AssertionError":
|
if load_global == "LOAD_GLOBAL" and load_global.attr == "AssertionError":
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -24,11 +21,14 @@ def or_check(self, lhs, n, rule, ast, tokens, first, last):
|
|||||||
jmp_false = tokens[last]
|
jmp_false = tokens[last]
|
||||||
# If the jmp is backwards
|
# If the jmp is backwards
|
||||||
if jmp_false == "POP_JUMP_IF_FALSE":
|
if jmp_false == "POP_JUMP_IF_FALSE":
|
||||||
if jmp_false.attr < jmp_false.off2int():
|
jmp_false_offset = jmp_false.off2int()
|
||||||
|
if jmp_false.attr < jmp_false_offset:
|
||||||
# For a backwards loop, well compare to the instruction *after*
|
# For a backwards loop, well compare to the instruction *after*
|
||||||
# then POP_JUMP...
|
# then POP_JUMP...
|
||||||
jmp_false = tokens[last+1]
|
jmp_false = tokens[last + 1]
|
||||||
return not (jmp_true_target == jmp_false.off2int() or
|
return not (
|
||||||
jmp_true_target < tokens[first].off2int())
|
(jmp_false_offset <= jmp_true_target <= jmp_false_offset + 2)
|
||||||
|
or jmp_true_target < tokens[first].off2int()
|
||||||
|
)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@@ -287,6 +287,32 @@ class TreeTransform(GenericASTTraversal, object):
|
|||||||
|
|
||||||
n_ifelsestmtc = n_ifelsestmtl = n_ifelsestmt
|
n_ifelsestmtc = n_ifelsestmtl = n_ifelsestmt
|
||||||
|
|
||||||
|
def n_import_from37(self, node):
|
||||||
|
importlist37 = node[3]
|
||||||
|
assert importlist37 == "importlist37"
|
||||||
|
if len(importlist37) == 1:
|
||||||
|
alias37 = importlist37[0]
|
||||||
|
store = alias37[1]
|
||||||
|
assert store == "store"
|
||||||
|
alias_name = store[0].attr
|
||||||
|
import_name_attr = node[2]
|
||||||
|
assert import_name_attr == "IMPORT_NAME_ATTR"
|
||||||
|
dotted_names = import_name_attr.attr.split(".")
|
||||||
|
if len(dotted_names) > 1:
|
||||||
|
# Simulate:
|
||||||
|
# Instead of
|
||||||
|
# import_from37 ::= LOAD_CONST LOAD_CONST IMPORT_NAME_ATTR importlist37 POP_TOP
|
||||||
|
# import_as37 ::= LOAD_CONST LOAD_CONST importlist37 store POP_TOP
|
||||||
|
# 'import_as37': ( '%|import %c as %c\n', 2, -2),
|
||||||
|
assert dotted_names[-1] == alias_name
|
||||||
|
node = SyntaxTree("import_as37",
|
||||||
|
[node[0], node[1], import_name_attr, store, node[-1]])
|
||||||
|
node.transformed_by="n_import_from37"
|
||||||
|
pass
|
||||||
|
pass
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
def n_list_for(self, list_for_node):
|
def n_list_for(self, list_for_node):
|
||||||
expr = list_for_node[0]
|
expr = list_for_node[0]
|
||||||
if expr == "expr" and expr[0] == "get_iter":
|
if expr == "expr" and expr[0] == "get_iter":
|
||||||
|
Reference in New Issue
Block a user