diff --git a/test/bytecode_3.2/06_classbug.pyc b/test/bytecode_3.2/06_classbug.pyc new file mode 100644 index 00000000..b02eb7a3 Binary files /dev/null and b/test/bytecode_3.2/06_classbug.pyc differ diff --git a/uncompyle6/parsers/astnode.py b/uncompyle6/parsers/astnode.py index f2999480..30fac7f7 100644 --- a/uncompyle6/parsers/astnode.py +++ b/uncompyle6/parsers/astnode.py @@ -28,7 +28,8 @@ class AST(UserList): else: return self.type == o - def __hash__(self): return hash(self.type) + def __hash__(self): + return hash(self.type) def __repr__(self, indent=''): rv = str(self.type) diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 4a21200c..b41c003b 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -19,7 +19,7 @@ from __future__ import print_function from uncompyle6.parser import PythonParser, nop_func from uncompyle6.parsers.astnode import AST -from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG +from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG from uncompyle6 import PYTHON3 class Python3Parser(PythonParser): @@ -154,6 +154,9 @@ class Python3Parser(PythonParser): designList ::= designator designator designList ::= designator DUP_TOP designList + # FIXME: Store local is only used in Python 3.2 + designator ::= STORE_LOCALS + designator ::= STORE_FAST designator ::= STORE_NAME designator ::= STORE_GLOBAL diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 0bf18476..03b67e27 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -93,7 +93,6 @@ RETURN_LOCALS = AST('return_stmt', [ AST('ret_expr', [AST('expr', [ Token('LOAD_LOCALS') ])]), Token('RETURN_VALUE')]) - NONE = AST('expr', [ NoneToken ] ) RETURN_NONE = AST('stmt', @@ -1224,6 +1223,14 @@ class SourceWalker(GenericASTTraversal, object): n_unpack_w_parens = n_unpack + def n_assign(self, node): + # A horrible hack for Python 3.0 .. 3.2 + if 3.0 <= self.version <= 3.2 and len(node) == 2: + if (node[0][0] == 'LOAD_FAST' and node[0][0].pattr == '__locals__' and + node[1][0].type == 'STORE_LOCALS'): + self.prune() + self.default(node) + def n_assign2(self, node): for n in node[-2:]: if n[0] == 'unpack': @@ -1538,12 +1545,20 @@ class SourceWalker(GenericASTTraversal, object): pass # if docstring exists, dump it - if (code.co_consts and code.co_consts[0] is not None - and len(ast) > 0 and ast[0][0] == ASSIGN_DOC_STRING(code.co_consts[0])): - if self.hide_internal: + if (code.co_consts and code.co_consts[0] is not None and len(ast) > 0): + do_doc = False + if (ast[0][0] == ASSIGN_DOC_STRING(code.co_consts[0])): + i = 0 + do_doc = True + elif (len(ast) > 2 and 3.0 <= self.version <= 3.2 and + ast[2][0] == ASSIGN_DOC_STRING(code.co_consts[0])): + i = 2 + do_doc = True + if do_doc and self.hide_internal: self.print_docstring(indent, code.co_consts[0]) self.print_() - del ast[0] + del ast[i] + # the function defining a class normally returns locals(); we # don't want this to show up in the source, thus remove the node