diff --git a/test/bytecode_3.4/10_class_deco.pyc b/test/bytecode_3.4/10_class_deco.pyc new file mode 100644 index 00000000..93a5f67d Binary files /dev/null and b/test/bytecode_3.4/10_class_deco.pyc differ diff --git a/test/simple_source/def/10_class_deco.py b/test/simple_source/def/10_class_deco.py new file mode 100644 index 00000000..76f9377d --- /dev/null +++ b/test/simple_source/def/10_class_deco.py @@ -0,0 +1,6 @@ +# From 3.4 tracemalloc.py +from functools import total_ordering + +@total_ordering +class Frame: + pass diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 6303f910..8d8fc324 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -193,7 +193,7 @@ class Python3Parser(PythonParser): classdefdeco ::= classdefdeco1 designator classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1 classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1 - classdefdeco2 ::= LOAD_CONST expr mkfunc CALL_FUNCTION_0 BUILD_CLASS + classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc LOAD_CONST CALL_FUNCTION_2 assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 assert2 ::= assert_expr jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1 diff --git a/uncompyle6/semantics/fragments.py b/uncompyle6/semantics/fragments.py index 794d17ac..5b23c908 100644 --- a/uncompyle6/semantics/fragments.py +++ b/uncompyle6/semantics/fragments.py @@ -730,15 +730,20 @@ class FragmentsWalker(pysource.SourceWalker, object): cclass = self.currentclass if self.version > 3.0: - currentclass = node[1][0].pattr - buildclass = node[0] + if node == 'classdefdeco2': + currentclass = node[1][2].pattr + buildclass = node + else: + currentclass = node[1][0].pattr + buildclass = node[0] + if buildclass[0] == 'LOAD_BUILD_CLASS': start = len(self.f.getvalue()) self.set_pos_info(buildclass[0], start, start + len('class')+2) if buildclass[1][0] == 'kwargs': subclass = buildclass[1][1].attr - subclass_info = node[0] + subclass_info = node if node == 'classdefdeco2' else node[0] elif buildclass[1][0] == 'load_closure': # Python 3 with closures not functions load_closure = buildclass[1] @@ -762,7 +767,7 @@ class FragmentsWalker(pysource.SourceWalker, object): subclass = buildclass[1][0].attr subclass_info = node[0] else: - buildclass = node[0] + buildclass = node if (node == 'classdefdeco2') else node[0] build_list = buildclass[1][0] if hasattr(buildclass[-3][0], 'attr'): subclass = buildclass[-3][0].attr @@ -773,7 +778,11 @@ class FragmentsWalker(pysource.SourceWalker, object): else: raise 'Internal Error n_classdef: cannot find class name' - self.write('\n\n') + if (node == 'classdefdeco2'): + self.write('\n') + else: + self.write('\n\n') + self.currentclass = str(currentclass) start = len(self.f.getvalue()) self.write(self.indent, 'class ', self.currentclass) @@ -798,6 +807,8 @@ class FragmentsWalker(pysource.SourceWalker, object): self.prune() + n_classdefdeco2 = n_classdef + def gen_source(self, ast, name, customize, isLambda=False, returnNone=False): """convert AST to Python source code""" diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 09170b4f..028168a5 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1187,11 +1187,16 @@ class SourceWalker(GenericASTTraversal, object): cclass = self.currentclass if self.version > 3.0: - currentclass = node[1][0].pattr - buildclass = node[0] + if node == 'classdefdeco2': + currentclass = node[1][2].pattr + buildclass = node + else: + currentclass = node[1][0].pattr + buildclass = node[0] + if buildclass[1][0] == 'kwargs': subclass = buildclass[1][1].attr - subclass_info = node[0] + subclass_info = node if node == 'classdefdeco2' else node[0] elif buildclass[1][0] == 'load_closure': # Python 3 with closures not functions load_closure = buildclass[1]