diff --git a/test/simple_source/bug26/.gitignore b/test/simple_source/bug26/.gitignore new file mode 100644 index 00000000..183700bc --- /dev/null +++ b/test/simple_source/bug26/.gitignore @@ -0,0 +1 @@ +/.python-version diff --git a/test/stdlib/2.4-exclude.sh b/test/stdlib/2.4-exclude.sh index 664f6da5..3bb058ec 100644 --- a/test/stdlib/2.4-exclude.sh +++ b/test/stdlib/2.4-exclude.sh @@ -38,17 +38,14 @@ SKIP_TESTS=( [test_winreg.py]=1 # it fails on its own [test_winsound.py]=1 # it fails on its own [test_zlib.py]=1 # it fails on its own - - [test_decimal.py]=1 # + [test_decimal.py]=1 # fails on its own - no module named test_support [test_dis.py]=1 # We change line numbers - duh! - [test_generators.py]=1 # Investigate + [test_generators.py]=1 # fails on its own - no module named test_support # [test_grammar.py]=1 # fails on its own - no module tests.test_support [test_grp.py]=1 # Long test - might work Control flow? - [test_pep247.py]=1 # Long test - might work? Control flow? [test_socketserver.py]=1 # -- test takes too long to run: 40 seconds [test_threading.py]=1 # test takes too long to run: 11 seconds [test_thread.py]=1 # test takes too long to run: 36 seconds [test_trace.py]=1 # Long test - works - [test_zipfile64.py]=1 # Runs ok but takes 204 seconds ) # About 243 files, 0 in 19 minutes diff --git a/test/test_pyenvlib.py b/test/test_pyenvlib.py index 7b76e5ed..861b82ed 100755 --- a/test/test_pyenvlib.py +++ b/test/test_pyenvlib.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # emacs-mode: -*-python-*- """ -test_pyenvlib -- uncompyle and verify Python libraries +test_pyenvlib -- decompile and verify Python libraries Usage-Examples: @@ -22,12 +22,17 @@ Step 2: Run the test: from __future__ import print_function -import os, time, re, shutil, sys +import os +import re +import shutil +import sys +import time from fnmatch import fnmatch -from uncompyle6 import main import xdis.magics as magics +from uncompyle6 import main + # ----- configure this for your needs python_versions = [v for v in magics.python_versions if re.match("^[0-9.]+$", v)] @@ -82,6 +87,7 @@ for vers in TEST_VERSIONS: if vers == "native": short_vers = os.path.basename(sys.path[-1]) from xdis.version_info import PYTHON_VERSION_TRIPLE, version_tuple_to_str + if PYTHON_VERSION_TRIPLE > (3, 0): version = version_tuple_to_str(end=2) PYC = f"*.cpython-{version}.pyc" @@ -133,8 +139,17 @@ def do_tests( pass if len(files) > max_files: - files = [file for file in files if not "site-packages" in file and (file.endswith(".pyo") or file.endswith(".pyc"))] - files = [file for file in files if not "test" in file and (file.endswith(".pyo") or file.endswith(".pyc"))] + files = [ + file + for file in files + if not "site-packages" in file + and (file.endswith(".pyo") or file.endswith(".pyc")) + ] + files = [ + file + for file in files + if not "test" in file and (file.endswith(".pyo") or file.endswith(".pyc")) + ] if len(files) > max_files: # print("Number of files %d - truncating to last 200" % len(files)) print( @@ -151,7 +166,8 @@ def do_tests( if __name__ == "__main__": - import getopt, sys + import getopt + import sys do_coverage = do_verify = False test_dirs = [] diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index 53907904..71b3b877 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -493,51 +493,6 @@ class Python26Parser(Python2Parser): return tokens[last - 3].kind not in frozenset( ("JUMP_FORWARD", "RETURN_VALUE") ) or (tokens[last - 3] == "JUMP_FORWARD" and tokens[last - 3].attr != 2) - elif lhs == "tryelsestmt": - # We need to distinguish "try_except" from "tryelsestmt"; we do that - # by making sure that the jump before the except handler jumps to - # code somewhere before the end of the construct. - # This AST method is slower, but the token-only based approach - # didn't work as it failed with a "try" embedded inside a "try/else" - # since we can't detect COME_FROM boundaries. - - if ast[3] == "except_handler": - except_handler = ast[3] - if except_handler[0] == "JUMP_FORWARD": - else_start = int(except_handler[0].pattr) - if last == len(tokens): - last -= 1 - if tokens[last] == "COME_FROM" and isinstance: - last_offset = int(tokens[last].offset.split("_")[0]) - return else_start >= last_offset - - # The above test apparently isn't good enough, so we have additional - # checks distinguish "try_except" from "tryelsestmt". we do that - # by checking the jump before the "END_FINALLY". - # If we have: - # insn - # POP_TOP - # END_FINALLY - # COME_FROM - # then insn is neither a JUMP_FORWARD nor RETURN_VALUE, - # or if it is JUMP_FORWARD, then it can't be a JUMP_FORWARD to right after - # COME_FROM - if last == len(tokens): - last -= 1 - while tokens[last - 1] == "COME_FROM" and tokens[last - 2] == "COME_FROM": - last -= 1 - if tokens[last] == "COME_FROM" and tokens[last - 1] == "COME_FROM": - last -= 1 - if ( - tokens[last] == "COME_FROM" - and tokens[last - 1] == "END_FINALLY" - and tokens[last - 2] == "POP_TOP" - ): - # A jump of 2 is a jump around POP_TOP, END_FINALLY which - # would indicate try/else rather than try - return tokens[last - 3].kind in frozenset( - ("JUMP_FORWARD", "RETURN_VALUE") - ) and (tokens[last - 3] != "JUMP_FORWARD" or tokens[last - 3].attr == 2) return False diff --git a/uncompyle6/semantics/n_actions.py b/uncompyle6/semantics/n_actions.py index d48ea3fb..a5d5faf2 100644 --- a/uncompyle6/semantics/n_actions.py +++ b/uncompyle6/semantics/n_actions.py @@ -926,66 +926,18 @@ class NonterminalActions: n_set = n_build_set = n_tuple = n_list def n_list_comp(self, node): - """List comprehensions""" - p = self.prec - self.prec = 100 - if self.version >= (2, 7): - if self.is_pypy: - self.n_list_comp_pypy27(node) - return - n = node[-1] - elif node[-1] == "delete": - if node[-2] == "JUMP_BACK": - n = node[-3] - else: - n = node[-2] - - assert n == "list_iter" - - # Find the list comprehension body. It is the inner-most - # node that is not list_.. . - # FIXME: DRY with other use - while n == "list_iter": - n = n[0] # iterate one nesting deeper - if n == "list_for": - n = n[3] - elif n == "list_if": - n = n[2] - elif n == "list_if_not": - n = n[2] - assert n == "lc_body" - self.write("[ ") - - if self.version >= (2, 7): - expr = n[0] - list_iter = node[-1] + self.write("[") + if node[0].kind == "load_closure": + assert self.version >= (3, 0) + self.listcomp_closure3(node) else: - expr = n[1] - if node[-2] == "JUMP_BACK": - list_iter = node[-3] + if node == "listcomp_async": + list_iter_index = 5 else: - list_iter = node[-2] - - assert expr == "expr" - assert list_iter == "list_iter" - - # FIXME: use source line numbers for directing line breaks - - line_number = self.line_number - last_line = self.f.getvalue().split("\n")[-1] - l = len(last_line) - indent = " " * (l - 1) - - self.preorder(expr) - line_number = self.indent_if_source_nl(line_number, indent) - self.preorder(list_iter) - l2 = self.indent_if_source_nl(line_number, indent) - if l2 != line_number: - self.write(" " * (len(indent) - len(self.indent) - 1) + "]") - else: - self.write(" ]") - self.prec = p - self.prune() # stop recursing + list_iter_index = 1 + self.comprehension_walk_newer(node, list_iter_index, 0) + self.write("]") + self.prune() def n_list_comp_pypy27(self, node): """List comprehensions in PYPY.""" @@ -1036,20 +988,6 @@ class NonterminalActions: self.prec = p self.prune() # stop recursing - def n_list_comp(self, node): - self.write("[") - if node[0].kind == "load_closure": - assert self.version >= (3, 0) - self.listcomp_closure3(node) - else: - if node == "listcomp_async": - list_iter_index = 5 - else: - list_iter_index = 1 - self.comprehension_walk_newer(node, list_iter_index, 0) - self.write("]") - self.prune() - def n_mkfunc(self, node): code_node = find_code_node(node, -2) code = code_node.attr