From 81e4169dea5056f668bb2f5defb14bcfc4fcdff2 Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 16 Apr 2022 00:14:40 -0400 Subject: [PATCH] Python 2.4 tolerance --- pytest/validate.py | 8 ++++- test/dis-compare.py | 12 ++++---- uncompyle6/scanner.py | 46 +++++++++++------------------ uncompyle6/scanners/scanner37.py | 2 +- uncompyle6/semantics/customize37.py | 5 +++- uncompyle6/semantics/fragments.py | 6 +++- uncompyle6/semantics/pysource.py | 8 +++-- 7 files changed, 46 insertions(+), 41 deletions(-) diff --git a/pytest/validate.py b/pytest/validate.py index f1dd0193..567a2e74 100644 --- a/pytest/validate.py +++ b/pytest/validate.py @@ -17,6 +17,12 @@ from xdis import Bytecode, get_opcode opc = get_opcode(PYTHON_VERSION_TRIPLE, IS_PYPY) Bytecode = functools.partial(Bytecode, opc=opc) + +if PYTHON_VERSION_TRIPLE < (2, 5): + from cStringIO import StringIO +else: + from StringIO import StringIO + import six def _dis_to_text(co): @@ -122,7 +128,7 @@ def validate_uncompyle(text, mode="exec"): original_text = text deparsed = code_deparse( - original_code, out=six.StringIO(), version=PYTHON_VERSION_TRIPLE, compile_mode=mode + original_code, out=StringIO(), version=PYTHON_VERSION_TRIPLE, compile_mode=mode ) uncompyled_text = deparsed.text uncompyled_code = compile(uncompyled_text, "", "exec") diff --git a/test/dis-compare.py b/test/dis-compare.py index 7c853b7d..ac07ebe5 100755 --- a/test/dis-compare.py +++ b/test/dis-compare.py @@ -1,16 +1,16 @@ #!/usr/bin/env python # Mode: -*- python -*- # -# Copyright (c) 2015, 2017 by Rocky Bernstein +# Copyright (c) 2015, 2017, 2022 by Rocky Bernstein # - import dis, os.path +from xdis import PYTHON_VERSION_TRIPL< PYTHON_VERSION_STR -try: +if PYTHON_VERSION_TRIPLE < (2, 5): + from cStringIO import StringIO +else: from StringIO import StringIO -except ImportError: - from io import StringIO program = os.path.basename(__file__) @@ -22,7 +22,7 @@ Usage: %s [OPTIONS]... FILE usage_short = "Usage: %s [OPTIONS]... FILE" % program import uncompyle6 -from uncompyle6 import PYTHON_VERSION_STR, check_python_version +from uncompyle6 check_python_version from uncompyle6.disas import disco def inst_fmt(inst): diff --git a/uncompyle6/scanner.py b/uncompyle6/scanner.py index 1cf7557d..d5877aa2 100644 --- a/uncompyle6/scanner.py +++ b/uncompyle6/scanner.py @@ -542,36 +542,26 @@ def get_scanner(version, is_pypy=False, show_asm=None): # Pick up appropriate scanner if version[:2] in PYTHON_VERSIONS: v_str = version_tuple_to_str(version, start=0, end=2, delimiter="") - try: - import importlib - - if is_pypy: - scan = importlib.import_module("uncompyle6.scanners.pypy%s" % v_str) - else: - scan = importlib.import_module("uncompyle6.scanners.scanner%s" % v_str) - if False: - print(scan) # Avoid unused scan - except ImportError: - if is_pypy: - exec( - "import uncompyle6.scanners.pypy%s as scan" % v_str, - locals(), - globals(), - ) - else: - exec( - "import uncompyle6.scanners.scanner%s as scan" % v_str, - locals(), - globals(), - ) if is_pypy: - scanner = eval( - "scan.ScannerPyPy%s(show_asm=show_asm)" % v_str, locals(), globals() - ) + import_name = "pypy%s" % v_str else: - scanner = eval( - "scan.Scanner%s(show_asm=show_asm)" % v_str, locals(), globals() - ) + import_name = "scanner%s" % v_str + + scan_toplevel = __import__("uncompyle6.scanners.%s" % import_name) + if scan_toplevel is None: + raise RuntimeError( + "Import Python version, %s, for decompilation failed" + % version_tuple_to_str(version) + ) + + if is_pypy: + scanner_class_name = "ScannerPyPy%s" % v_str + else: + scanner_class_name = "Scanner%s" % v_str + scanners = scan_toplevel.scanners + specific_scanners_module = getattr(scanners, import_name) + scanner_class = getattr(specific_scanners_module, scanner_class_name) + scanner = scanner_class(show_asm=show_asm) else: raise RuntimeError( "Unsupported Python version, %s, for decompilation" diff --git a/uncompyle6/scanners/scanner37.py b/uncompyle6/scanners/scanner37.py index 8a1de663..c0b8e0e8 100644 --- a/uncompyle6/scanners/scanner37.py +++ b/uncompyle6/scanners/scanner37.py @@ -32,7 +32,7 @@ JUMP_OPs = opc.JUMP_OPS class Scanner37(Scanner37Base): - def __init__(self, show_asm=None, is_pypy: bool=False): + def __init__(self, show_asm=None, is_pypy=False): Scanner37Base.__init__(self, (3, 7), show_asm) self.is_pypy = is_pypy return diff --git a/uncompyle6/semantics/customize37.py b/uncompyle6/semantics/customize37.py index 38341785..dee85477 100644 --- a/uncompyle6/semantics/customize37.py +++ b/uncompyle6/semantics/customize37.py @@ -381,7 +381,10 @@ def customize_for_version37(self, version): and opname == "CALL_FUNCTION_1" or not re.match(r"\d", opname[-1]) ): - template = "(%c)(%p)" if node[0][0] == "lambda_body" else "%c(%p)" + if node[0][0] == "lambda_body": + template = "(%c)(%p)" + else: + template = "%c(%p)" self.template_engine( (template, (0, "expr"), (1, PRECEDENCE["yield"] - 1)), node ) diff --git a/uncompyle6/semantics/fragments.py b/uncompyle6/semantics/fragments.py index 5981546f..ffce9ef8 100644 --- a/uncompyle6/semantics/fragments.py +++ b/uncompyle6/semantics/fragments.py @@ -64,7 +64,6 @@ The node position 0 will be associated with "import". # FIXME: DRY code with pysource import re -from StringIO import StringIO from uncompyle6.semantics import pysource from uncompyle6 import parser @@ -80,6 +79,11 @@ from uncompyle6.semantics.pysource import ParserError from xdis import iscode from xdis.version_info import IS_PYPY, PYTHON_VERSION_TRIPLE +if PYTHON_VERSION_TRIPLE < (2, 5): + from cStringIO import StringIO +else: + from StringIO import StringIO + from uncompyle6.semantics.consts import ( INDENT_PER_LEVEL, NONE, diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 7ea698a5..9200d6e7 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -180,12 +180,14 @@ from uncompyle6.semantics.consts import ( from uncompyle6.show import maybe_show_tree from uncompyle6.util import better_repr -from StringIO import StringIO +if PYTHON_VERSION_TRIPLE < (2, 5): + from cStringIO import StringIO +else: + from StringIO import StringIO DEFAULT_DEBUG_OPTS = {"asm": False, "tree": False, "grammar": False} def unicode(x): return x -from StringIO import StringIO PARSER_DEFAULT_DEBUG = { "rules": False, @@ -2773,7 +2775,7 @@ def code_deparse( try: stmts = deparsed.ast first_stmt = stmts[0][0] - if version >= 3.6: + if (version >= (3, 6, 0)): if first_stmt[0] == "SETUP_ANNOTATIONS": del stmts[0] assert stmts[0] == "sstmt"