From 37f38e45e1030e0cb4b9596a0616e7b2d23e1c1f Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 9 Nov 2024 11:57:11 -0500 Subject: [PATCH 1/5] Don't update global tables... Work off of copies of them instead. Issue #503 --- uncompyle6/semantics/customize.py | 32 ++++++++++++---------- uncompyle6/semantics/customize14.py | 11 +++----- uncompyle6/semantics/customize26_27.py | 37 +++++++++++++++---------- uncompyle6/semantics/customize3.py | 11 ++++---- uncompyle6/semantics/customize35.py | 19 +++++++------ uncompyle6/semantics/customize36.py | 7 +++-- uncompyle6/semantics/customize37.py | 8 ++++-- uncompyle6/semantics/customize38.py | 7 +++-- uncompyle6/semantics/fragments.py | 22 +++++++++++---- uncompyle6/semantics/pysource.py | 38 +++++++++++++++++--------- 10 files changed, 114 insertions(+), 78 deletions(-) diff --git a/uncompyle6/semantics/customize.py b/uncompyle6/semantics/customize.py index 93855726..843c0fc7 100644 --- a/uncompyle6/semantics/customize.py +++ b/uncompyle6/semantics/customize.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018-2019, 2021-2022 by Rocky Bernstein +# Copyright (c) 2018-2019, 2021-2022 2024 by Rocky Bernstein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,24 +17,25 @@ """ from uncompyle6.parsers.treenode import SyntaxTree +from uncompyle6.scanners.tok import Token from uncompyle6.semantics.consts import ( INDENT_PER_LEVEL, NO_PARENTHESIS_EVER, PRECEDENCE, - TABLE_R, TABLE_DIRECT, + TABLE_R, ) from uncompyle6.semantics.helper import flatten_list -from uncompyle6.scanners.tok import Token def customize_for_version(self, is_pypy, version): + self.TABLE_DIRECT = TABLE_DIRECT.copy() if is_pypy: ######################## # PyPy changes ####################### # fmt: off - TABLE_DIRECT.update({ + self.TABLE_DIRECT.update({ "assert": ("%|assert %c\n", 0), # This can happen as a result of an if transformation @@ -114,7 +115,7 @@ def customize_for_version(self, is_pypy, version): ######################## # Without PyPy ####################### - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { # "assert" and "assert_expr" are added via transform rules. "assert": ("%|assert %c\n", 0), @@ -133,23 +134,23 @@ def customize_for_version(self, is_pypy, version): ) if version >= (3, 0): if version >= (3, 2): - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( {"del_deref_stmt": ("%|del %c\n", 0), "DELETE_DEREF": ("%{pattr}", 0)} ) from uncompyle6.semantics.customize3 import customize_for_version3 customize_for_version3(self, version) else: # < 3.0 - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( {"except_cond3": ("%|except %c, %c:\n", (1, "expr"), (-2, "store"))} ) if version <= (2, 6): - TABLE_DIRECT["testtrue_then"] = TABLE_DIRECT["testtrue"] + self.TABLE_DIRECT["testtrue_then"] = self.TABLE_DIRECT["testtrue"] if (2, 4) <= version <= (2, 6): - TABLE_DIRECT.update({"comp_for": (" for %c in %c", 3, 1)}) + self.TABLE_DIRECT.update({"comp_for": (" for %c in %c", 3, 1)}) else: - TABLE_DIRECT.update({"comp_for": (" for %c in %c%c", 2, 0, 3)}) + self.TABLE_DIRECT.update({"comp_for": (" for %c in %c%c", 2, 0, 3)}) if version >= (2, 5): from uncompyle6.semantics.customize25 import customize_for_version25 @@ -197,7 +198,7 @@ def customize_for_version(self, is_pypy, version): ) ], ) - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { "importmultiple": ("%|import %c%c\n", 2, 3), "import_cont": (", %c", 2), @@ -247,9 +248,9 @@ def customize_for_version(self, is_pypy, version): self.n_call = n_call else: # 1.0 <= version <= 2.3: - TABLE_DIRECT.update({"if1_stmt": ("%|if 1\n%+%c%-", 5)}) + self.TABLE_DIRECT.update({"if1_stmt": ("%|if 1\n%+%c%-", 5)}) if version <= (2, 1): - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { "importmultiple": ("%c", 2), # FIXME: not quite right. We have indiividual imports @@ -263,7 +264,8 @@ def customize_for_version(self, is_pypy, version): # < 3.0 continues - TABLE_R.update( + self.TABLE_R = TABLE_R.copy() + self.TABLE_R.update( { "STORE_SLICE+0": ("%c[:]", 0), "STORE_SLICE+1": ("%c[%p:]", 0, (1, -1)), @@ -275,7 +277,7 @@ def customize_for_version(self, is_pypy, version): "DELETE_SLICE+3": ("%|del %c[%c:%c]\n", 0, 1, 2), } ) - TABLE_DIRECT.update({"raise_stmt2": ("%|raise %c, %c\n", 0, 1)}) + self.TABLE_DIRECT.update({"raise_stmt2": ("%|raise %c, %c\n", 0, 1)}) # exec as a built-in statement is only in Python 2.x def n_exec_stmt(node): diff --git a/uncompyle6/semantics/customize14.py b/uncompyle6/semantics/customize14.py index 3ba53f52..566a6ec1 100644 --- a/uncompyle6/semantics/customize14.py +++ b/uncompyle6/semantics/customize14.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 by Rocky Bernstein +# Copyright (c) 2022, 2024 by Rocky Bernstein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -15,16 +15,13 @@ """Isolate Python 1.4- version-specific semantic actions here. """ -from uncompyle6.semantics.consts import TABLE_DIRECT ####################### # Python 1.4- Changes # ####################### -def customize_for_version14(self, version): - TABLE_DIRECT.update( +def customize_for_version14(self, version: tuple): + self.TABLE_DIRECT.update( { - "print_expr_stmt": ( - ("%|print %c\n", 0) - ), + "print_expr_stmt": (("%|print %c\n", 0)), } ) diff --git a/uncompyle6/semantics/customize26_27.py b/uncompyle6/semantics/customize26_27.py index 19196614..4f835239 100644 --- a/uncompyle6/semantics/customize26_27.py +++ b/uncompyle6/semantics/customize26_27.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 2021 by Rocky Bernstein +# Copyright (c) 2019 2021, 2024 by Rocky Bernstein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,8 +17,9 @@ from uncompyle6.semantics.consts import TABLE_DIRECT -def customize_for_version26_27(self, version): +def customize_for_version26_27(self, version: tuple): + self.TABLE_DIRECT = TABLE_DIRECT.copy() ######################################## # Python 2.6+ # except as @@ -29,16 +30,20 @@ def customize_for_version26_27(self, version): # matches how we parse this in bytecode ######################################## if version > (2, 6): - TABLE_DIRECT.update({ - "except_cond2": ( "%|except %c as %c:\n", 1, 5 ), - # When a generator is a single parameter of a function, - # it doesn't need the surrounding parenethesis. - "call_generator": ('%c%P', 0, (1, -1, ', ', 100)), - }) + self.TABLE_DIRECT.update( + { + "except_cond2": ("%|except %c as %c:\n", 1, 5), + # When a generator is a single parameter of a function, + # it doesn't need the surrounding parenethesis. + "call_generator": ("%c%P", 0, (1, -1, ", ", 100)), + } + ) else: - TABLE_DIRECT.update({ - 'testtrue_then': ( 'not %p', (0, 22) ), - }) + self.TABLE_DIRECT.update( + { + "testtrue_then": ("not %p", (0, 22)), + } + ) # FIXME: this should be a transformation def n_call(node): @@ -47,22 +52,24 @@ def customize_for_version26_27(self, version): for i in mapping[1:]: key = key[i] pass - if key.kind == 'CALL_FUNCTION_1': + if key.kind == "CALL_FUNCTION_1": # A function with one argument. If this is a generator, # no parenthesis is needed. args_node = node[-2] - if args_node == 'expr': + if args_node == "expr": n = args_node[0] - if n == 'generator_exp': - node.kind = 'call_generator' + if n == "generator_exp": + node.kind = "call_generator" pass pass self.default(node) + self.n_call = n_call def n_import_from(node): if node[0].pattr > 0: node[2].pattr = ("." * node[0].pattr) + node[2].pattr self.default(node) + self.n_import_from = n_import_from diff --git a/uncompyle6/semantics/customize3.py b/uncompyle6/semantics/customize3.py index 80309c37..194b8d49 100644 --- a/uncompyle6/semantics/customize3.py +++ b/uncompyle6/semantics/customize3.py @@ -29,8 +29,9 @@ from uncompyle6.semantics.make_function3 import make_function3_annotate from uncompyle6.util import get_code_name -def customize_for_version3(self, version): - TABLE_DIRECT.update( +def customize_for_version3(self, version: tuple): + self.TABLE_DIRECT = TABLE_DIRECT.copy() + self.TABLE_DIRECT.update( { "comp_for": (" for %c in %c", (2, "store"), (0, "expr")), "if_exp_not": ( @@ -183,7 +184,7 @@ def customize_for_version3(self, version): # the iteration variable. These rules we can ignore # since we pick up the iteration variable some other way and # we definitely don't include in the source _[dd]. - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { "ifstmt30": ( "%|if %c:\n%+%c%-", @@ -335,7 +336,7 @@ def customize_for_version3(self, version): self.n_mkfunc_annotate = n_mkfunc_annotate - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { "tryelsestmtl3": ( "%|try:\n%+%c%-%c%|else:\n%+%c%-", @@ -350,7 +351,7 @@ def customize_for_version3(self, version): ####################### # Python 3.4+ Changes # ####################### - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { "LOAD_CLASSDEREF": ("%{pattr}",), "yield_from": ("yield from %c", (0, "expr")), diff --git a/uncompyle6/semantics/customize35.py b/uncompyle6/semantics/customize35.py index 946c3e68..13bd5f10 100644 --- a/uncompyle6/semantics/customize35.py +++ b/uncompyle6/semantics/customize35.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2020, 2022 by Rocky Bernstein +# Copyright (c) 2019-2020, 2022, 2024 by Rocky Bernstein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,21 +16,18 @@ """ from xdis import co_flags_is_async, iscode -from uncompyle6.semantics.consts import ( - INDENT_PER_LEVEL, - PRECEDENCE, - TABLE_DIRECT, -) +from uncompyle6.semantics.consts import INDENT_PER_LEVEL, PRECEDENCE, TABLE_DIRECT from uncompyle6.semantics.helper import flatten_list, gen_function_parens_adjust ####################### # Python 3.5+ Changes # ####################### -def customize_for_version35(self, version): +def customize_for_version35(self, version: tuple): # fmt: off - TABLE_DIRECT.update( + self.TABLE_DIRECT = TABLE_DIRECT.copy() + self.TABLE_DIRECT.update( { # nested await expressions like: # return await (await bar()) @@ -197,7 +194,11 @@ def customize_for_version35(self, version): self.template_engine(template, args_node) else: if len(node) - nargs > 3: - template = ("*%c, %P)", nargs + 1, (nargs + kwargs + 1, -1, ", ", 100)) + template = ( + "*%c, %P)", + nargs + 1, + (nargs + kwargs + 1, -1, ", ", 100), + ) else: template = ("*%c)", nargs + 1) self.template_engine(template, node) diff --git a/uncompyle6/semantics/customize36.py b/uncompyle6/semantics/customize36.py index 3bc2f574..99c4905d 100644 --- a/uncompyle6/semantics/customize36.py +++ b/uncompyle6/semantics/customize36.py @@ -38,7 +38,7 @@ def escape_format(s): ####################### -def customize_for_version36(self, version): +def customize_for_version36(self, version: tuple): # fmt: off PRECEDENCE["call_kw"] = 0 PRECEDENCE["call_kw36"] = 1 @@ -50,7 +50,7 @@ def customize_for_version36(self, version): PRECEDENCE["dict_pack"] = 0 # **{ ... } PRECEDENCE["formatted_value1"] = 100 - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { "ann_assign_init_value": ( "%|%c = %p\n", @@ -96,7 +96,8 @@ def customize_for_version36(self, version): } ) - TABLE_R.update( + self.TABLE_R = TABLE_R.copy() + self.TABLE_R.update( { "CALL_FUNCTION_EX": ("%c(*%P)", 0, (1, 2, ", ", 100)), # Not quite right diff --git a/uncompyle6/semantics/customize37.py b/uncompyle6/semantics/customize37.py index 6102d818..91b4de8d 100644 --- a/uncompyle6/semantics/customize37.py +++ b/uncompyle6/semantics/customize37.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2023 by Rocky Bernstein +# Copyright (c) 2019-2024 by Rocky Bernstein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -25,11 +25,13 @@ FSTRING_CONVERSION_MAP = {1: "!s", 2: "!r", 3: "!a", "X": ":X"} ####################### -def customize_for_version37(self, version): +def customize_for_version37(self, version: tuple): ######################## # Python 3.7+ changes ####################### + self.TABLE_DIRECT = TABLE_DIRECT.copy() + # fmt: off PRECEDENCE["attribute37"] = 2 PRECEDENCE["call_ex"] = 1 @@ -47,7 +49,7 @@ def customize_for_version37(self, version): PRECEDENCE["dict_unpack"] = 0 # **{...} # fmt: on - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { "and_not": ("%c and not %c", (0, "expr"), (2, "expr")), "ann_assign": ( diff --git a/uncompyle6/semantics/customize38.py b/uncompyle6/semantics/customize38.py index df08c36f..c3e4cf78 100644 --- a/uncompyle6/semantics/customize38.py +++ b/uncompyle6/semantics/customize38.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2020, 2022 by Rocky Bernstein +# Copyright (c) 2019-2020, 2022, 2024 by Rocky Bernstein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -24,13 +24,14 @@ from uncompyle6.semantics.customize37 import FSTRING_CONVERSION_MAP from uncompyle6.semantics.helper import escape_string, strip_quotes -def customize_for_version38(self, version): +def customize_for_version38(self, version: tuple): # FIXME: pytest doesn't add proper keys in testing. Reinstate after we have fixed pytest. # for lhs in 'for forelsestmt forelselaststmt ' # 'forelselaststmtc tryfinally38'.split(): # del TABLE_DIRECT[lhs] - TABLE_DIRECT.update( + self.TABLE_DIRECT = TABLE_DIRECT.copy() + self.TABLE_DIRECT.update( { "async_for_stmt38": ( "%|async for %c in %c:\n%+%c%-%-\n\n", diff --git a/uncompyle6/semantics/fragments.py b/uncompyle6/semantics/fragments.py index 6dfa4ac7..330b97bf 100644 --- a/uncompyle6/semantics/fragments.py +++ b/uncompyle6/semantics/fragments.py @@ -85,6 +85,7 @@ from uncompyle6.semantics.consts import ( PASS, PRECEDENCE, TABLE_DIRECT, + TABLE_R, escape, ) from uncompyle6.semantics.pysource import ( @@ -189,8 +190,7 @@ class FragmentsWalker(pysource.SourceWalker, object): self.is_pypy = is_pypy # FIXME: is there a better way? - global MAP_DIRECT_FRAGMENT - MAP_DIRECT_FRAGMENT = (dict(TABLE_DIRECT, **TABLE_DIRECT_FRAGMENT),) + self.MAP_DIRECT_FRAGMENT = (dict(TABLE_DIRECT, **TABLE_DIRECT_FRAGMENT),) return f = property( @@ -655,6 +655,19 @@ class FragmentsWalker(pysource.SourceWalker, object): code = Code(cn.attr, self.scanner, self.currentclass) ast = self.build_ast(code._tokens, code._customize, code) + + self.TABLE_DIRECT = TABLE_DIRECT.copy() + self.TABLE_R = TABLE_R.copy() + self.MAP_DIRECT = (self.TABLE_DIRECT,) + self.MAP_R = (self.TABLE_R, -1) + + self.MAP = { + "stmt": self.MAP_R, + "call": self.MAP_R, + "delete": self.MAP_R, + "store": self.MAP_R, + } + self.customize(code._customize) # Remove single reductions as in ("stmts", "sstmt"): @@ -2003,8 +2016,7 @@ class FragmentsWalker(pysource.SourceWalker, object): self.set_pos_info(last_node, startnode_start, self.last_finish) return - @classmethod - def _get_mapping(cls, node): + def _get_mapping(self, node): if ( hasattr(node, "data") and len(node) > 0 @@ -2012,7 +2024,7 @@ class FragmentsWalker(pysource.SourceWalker, object): and not hasattr(node[-1], "parent") ): node[-1].parent = node - return MAP.get(node, MAP_DIRECT_FRAGMENT) + return self.MAP.get(node, self.MAP_DIRECT_FRAGMENT) pass diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index c351337e..00138023 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -146,8 +146,6 @@ from uncompyle6.semantics.consts import ( ASSIGN_TUPLE_PARAM, INDENT_PER_LEVEL, LINE_LENGTH, - MAP, - MAP_DIRECT, NAME_MODULE, NO_PARENTHESIS_EVER, NONE, @@ -156,6 +154,7 @@ from uncompyle6.semantics.consts import ( RETURN_LOCALS, RETURN_NONE, TAB, + TABLE_DIRECT, TABLE_R, escape, ) @@ -316,7 +315,21 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin): # An example is: # __module__ = __name__ self.hide_internal = True + + self.TABLE_DIRECT = TABLE_DIRECT.copy() + self.TABLE_R = TABLE_R.copy() + self.MAP_DIRECT = (self.TABLE_DIRECT,) + self.MAP_R = (self.TABLE_R, -1) + + self.MAP = { + "stmt": self.MAP_R, + "call": self.MAP_R, + "delete": self.MAP_R, + "store": self.MAP_R, + } + customize_for_version(self, is_pypy, version) + return def maybe_show_tree(self, tree, phase): @@ -902,17 +915,17 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin): of arguments -- we add a new entry for each in TABLE_R. """ for k, v in list(customize.items()): - if k in TABLE_R: + if k in self.TABLE_R: continue op = k[: k.rfind("_")] if k.startswith("CALL_METHOD"): # This happens in PyPy and Python 3.7+ - TABLE_R[k] = ("%c(%P)", (0, "expr"), (1, -1, ", ", 100)) + self.TABLE_R[k] = ("%c(%P)", (0, "expr"), (1, -1, ", ", 100)) elif self.version >= (3, 6) and k.startswith("CALL_FUNCTION_KW"): - TABLE_R[k] = ("%c(%P)", (0, "expr"), (1, -1, ", ", 100)) + self.TABLE_R[k] = ("%c(%P)", (0, "expr"), (1, -1, ", ", 100)) elif op == "CALL_FUNCTION": - TABLE_R[k] = ( + self.TABLE_R[k] = ( "%c(%P)", (0, "expr"), (1, -1, ", ", PRECEDENCE["yield"] - 1), @@ -971,13 +984,13 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin): else: assert False, "Unhandled CALL_FUNCTION %s" % op - TABLE_R[k] = entry + self.TABLE_R[k] = entry pass # handled by n_dict: - # if op == 'BUILD_SLICE': TABLE_R[k] = ('%C' , (0,-1,':')) + # if op == 'BUILD_SLICE': self.TABLE_R[k] = ('%C' , (0,-1,':')) # handled by n_list: - # if op == 'BUILD_LIST': TABLE_R[k] = ('[%C]' , (0,-1,', ')) - # elif op == 'BUILD_TUPLE': TABLE_R[k] = ('(%C%,)', (0,-1,', ')) + # if op == 'BUILD_LIST': self.TABLE_R[k] = ('[%C]' , (0,-1,', ')) + # elif op == 'BUILD_TUPLE': self.TABLE_R[k] = ('(%C%,)', (0,-1,', ')) pass return @@ -1272,9 +1285,8 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin): del ast # Save memory return transform_tree - @classmethod - def _get_mapping(cls, node): - return MAP.get(node, MAP_DIRECT) + def _get_mapping(self, node): + return self.MAP.get(node, self.MAP_DIRECT) def code_deparse( From cf34014766e9672c1f7d50c60a1aa91c72216ef3 Mon Sep 17 00:00:00 2001 From: gdesmar <75089569+gdesmar@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:42:17 +0000 Subject: [PATCH 2/5] Use a single TABLE copy --- uncompyle6/semantics/customize.py | 2 -- uncompyle6/semantics/customize25.py | 2 +- uncompyle6/semantics/customize26_27.py | 1 - uncompyle6/semantics/customize3.py | 1 - uncompyle6/semantics/customize35.py | 1 - uncompyle6/semantics/customize36.py | 1 - uncompyle6/semantics/customize37.py | 2 -- uncompyle6/semantics/customize38.py | 2 -- uncompyle6/semantics/fragments.py | 2 -- 9 files changed, 1 insertion(+), 13 deletions(-) diff --git a/uncompyle6/semantics/customize.py b/uncompyle6/semantics/customize.py index 843c0fc7..cb475827 100644 --- a/uncompyle6/semantics/customize.py +++ b/uncompyle6/semantics/customize.py @@ -29,7 +29,6 @@ from uncompyle6.semantics.helper import flatten_list def customize_for_version(self, is_pypy, version): - self.TABLE_DIRECT = TABLE_DIRECT.copy() if is_pypy: ######################## # PyPy changes @@ -264,7 +263,6 @@ def customize_for_version(self, is_pypy, version): # < 3.0 continues - self.TABLE_R = TABLE_R.copy() self.TABLE_R.update( { "STORE_SLICE+0": ("%c[:]", 0), diff --git a/uncompyle6/semantics/customize25.py b/uncompyle6/semantics/customize25.py index d3df25d2..d635e9f1 100644 --- a/uncompyle6/semantics/customize25.py +++ b/uncompyle6/semantics/customize25.py @@ -25,7 +25,7 @@ def customize_for_version25(self, version): ######################## # Import style for 2.5+ ######################## - TABLE_DIRECT.update( + self.TABLE_DIRECT.update( { "importmultiple": ("%|import %c%c\n", 2, 3), "import_cont": (", %c", 2), diff --git a/uncompyle6/semantics/customize26_27.py b/uncompyle6/semantics/customize26_27.py index 4f835239..d70e43f2 100644 --- a/uncompyle6/semantics/customize26_27.py +++ b/uncompyle6/semantics/customize26_27.py @@ -19,7 +19,6 @@ from uncompyle6.semantics.consts import TABLE_DIRECT def customize_for_version26_27(self, version: tuple): - self.TABLE_DIRECT = TABLE_DIRECT.copy() ######################################## # Python 2.6+ # except as diff --git a/uncompyle6/semantics/customize3.py b/uncompyle6/semantics/customize3.py index 194b8d49..45564d25 100644 --- a/uncompyle6/semantics/customize3.py +++ b/uncompyle6/semantics/customize3.py @@ -30,7 +30,6 @@ from uncompyle6.util import get_code_name def customize_for_version3(self, version: tuple): - self.TABLE_DIRECT = TABLE_DIRECT.copy() self.TABLE_DIRECT.update( { "comp_for": (" for %c in %c", (2, "store"), (0, "expr")), diff --git a/uncompyle6/semantics/customize35.py b/uncompyle6/semantics/customize35.py index 13bd5f10..df371415 100644 --- a/uncompyle6/semantics/customize35.py +++ b/uncompyle6/semantics/customize35.py @@ -26,7 +26,6 @@ from uncompyle6.semantics.helper import flatten_list, gen_function_parens_adjust ####################### def customize_for_version35(self, version: tuple): # fmt: off - self.TABLE_DIRECT = TABLE_DIRECT.copy() self.TABLE_DIRECT.update( { # nested await expressions like: diff --git a/uncompyle6/semantics/customize36.py b/uncompyle6/semantics/customize36.py index 99c4905d..bb5efd84 100644 --- a/uncompyle6/semantics/customize36.py +++ b/uncompyle6/semantics/customize36.py @@ -96,7 +96,6 @@ def customize_for_version36(self, version: tuple): } ) - self.TABLE_R = TABLE_R.copy() self.TABLE_R.update( { "CALL_FUNCTION_EX": ("%c(*%P)", 0, (1, 2, ", ", 100)), diff --git a/uncompyle6/semantics/customize37.py b/uncompyle6/semantics/customize37.py index 91b4de8d..41e375ab 100644 --- a/uncompyle6/semantics/customize37.py +++ b/uncompyle6/semantics/customize37.py @@ -30,8 +30,6 @@ def customize_for_version37(self, version: tuple): # Python 3.7+ changes ####################### - self.TABLE_DIRECT = TABLE_DIRECT.copy() - # fmt: off PRECEDENCE["attribute37"] = 2 PRECEDENCE["call_ex"] = 1 diff --git a/uncompyle6/semantics/customize38.py b/uncompyle6/semantics/customize38.py index c3e4cf78..5b3684bb 100644 --- a/uncompyle6/semantics/customize38.py +++ b/uncompyle6/semantics/customize38.py @@ -29,8 +29,6 @@ def customize_for_version38(self, version: tuple): # for lhs in 'for forelsestmt forelselaststmt ' # 'forelselaststmtc tryfinally38'.split(): # del TABLE_DIRECT[lhs] - - self.TABLE_DIRECT = TABLE_DIRECT.copy() self.TABLE_DIRECT.update( { "async_for_stmt38": ( diff --git a/uncompyle6/semantics/fragments.py b/uncompyle6/semantics/fragments.py index 330b97bf..537ca7f5 100644 --- a/uncompyle6/semantics/fragments.py +++ b/uncompyle6/semantics/fragments.py @@ -656,8 +656,6 @@ class FragmentsWalker(pysource.SourceWalker, object): code = Code(cn.attr, self.scanner, self.currentclass) ast = self.build_ast(code._tokens, code._customize, code) - self.TABLE_DIRECT = TABLE_DIRECT.copy() - self.TABLE_R = TABLE_R.copy() self.MAP_DIRECT = (self.TABLE_DIRECT,) self.MAP_R = (self.TABLE_R, -1) From 5c391f9101b193d8d2491dd7071f335d183d8378 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 12 Nov 2024 16:33:23 -0500 Subject: [PATCH 3/5] Update CircleCI --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 84edb951..b7649f12 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -64,7 +64,7 @@ jobs: # Test # This would typically be a build job when using workflows, possibly combined with build # This is based on your 1.0 configuration file or project settings - - run: sudo python ./setup.py develop && make check-3.6 + - run: sudo pip install -e . && make check-3.6 - run: cd ./test/stdlib && bash ./runtests.sh 'test_[p-z]*.py' # Teardown # If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each From 9f915384ce926360a8bbdf6798ef9587d971893b Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 15 Nov 2024 19:45:29 -0500 Subject: [PATCH 4/5] Bump spark_parser version allowed --- __pkginfo__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__pkginfo__.py b/__pkginfo__.py index 0e9eaee4..d11c0f54 100644 --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -79,7 +79,7 @@ entry_points = { ] } ftp_url = None -install_requires = ["click", "spark-parser >= 1.8.9, < 1.9.1", "xdis >= 6.1.1, < 6.2.0"] +install_requires = ["click", "spark-parser >= 1.8.9, < 1.9.2", "xdis >= 6.1.1, < 6.2.0"] license = "GPL3" mailing_list = "python-debugger@googlegroups.com" From f9d32f19d445de1ec692322aa89ff55898040a0d Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 19 Nov 2024 15:27:50 -0500 Subject: [PATCH 5/5] Add BlackHat Asia 2024 and update CircleCI link --- README.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 124b486f..b3c8c7b1 100644 --- a/README.rst +++ b/README.rst @@ -282,6 +282,7 @@ to spend. See Also -------- +* https://rocky.github.io/blackhat-asia-2024-additional/all-notes-print.html : How to Read and Write a High-Level Bytecode Decompiler: ``uncompyle6`` ``decompyle3`` -- BlackHat 2024 Asia (`video `_. A big thanks to the Organizers and Reviewers for letting me speak. This kind of thing encourages me to work on projects like this. * https://github.com/rocky/python-decompile3 : Much smaller and more modern code, focusing on 3.7 and 3.8. Changes in that will get migrated back here. * https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique than what is used here. Currently unmaintained. * https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Includes some fixes like supporting function annotations. Currently unmaintained. @@ -306,8 +307,8 @@ See Also .. _uncompyle2: https://github.com/wibiti/uncompyle2 .. _unpyc37: https://github.com/andrew-tavera/unpyc37 .. _this: https://github.com/rocky/python-uncompyle6/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting -.. |buildstatus| image:: https://travis-ci.org/rocky/python-uncompyle6.svg - :target: https://travis-ci.org/rocky/python-uncompyle6 +.. |buildstatus| image:: https://circleci.com/gh/rocky/python-uncompyle6.svg?style=svg + :target: https://app.circleci.com/pipelines/github/rocky/python-uncompyle6 .. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:uncompyle6.svg :target: https://repology.org/project/python:uncompyle6/versions .. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84