Python 3.x class decorator bug

This commit is contained in:
rocky
2016-06-20 00:32:00 -04:00
parent efb4012087
commit 078f15013e
5 changed files with 31 additions and 9 deletions

Binary file not shown.

View File

@@ -0,0 +1,6 @@
# From 3.4 tracemalloc.py
from functools import total_ordering
@total_ordering
class Frame:
pass

View File

@@ -193,7 +193,7 @@ class Python3Parser(PythonParser):
classdefdeco ::= classdefdeco1 designator classdefdeco ::= classdefdeco1 designator
classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1 classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
classdefdeco1 ::= expr classdefdeco2 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 assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1
assert2 ::= assert_expr jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1 assert2 ::= assert_expr jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1

View File

@@ -730,15 +730,20 @@ class FragmentsWalker(pysource.SourceWalker, object):
cclass = self.currentclass cclass = self.currentclass
if self.version > 3.0: if self.version > 3.0:
currentclass = node[1][0].pattr if node == 'classdefdeco2':
buildclass = node[0] currentclass = node[1][2].pattr
buildclass = node
else:
currentclass = node[1][0].pattr
buildclass = node[0]
if buildclass[0] == 'LOAD_BUILD_CLASS': if buildclass[0] == 'LOAD_BUILD_CLASS':
start = len(self.f.getvalue()) start = len(self.f.getvalue())
self.set_pos_info(buildclass[0], start, start + len('class')+2) self.set_pos_info(buildclass[0], start, start + len('class')+2)
if buildclass[1][0] == 'kwargs': if buildclass[1][0] == 'kwargs':
subclass = buildclass[1][1].attr subclass = buildclass[1][1].attr
subclass_info = node[0] subclass_info = node if node == 'classdefdeco2' else node[0]
elif buildclass[1][0] == 'load_closure': elif buildclass[1][0] == 'load_closure':
# Python 3 with closures not functions # Python 3 with closures not functions
load_closure = buildclass[1] load_closure = buildclass[1]
@@ -762,7 +767,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
subclass = buildclass[1][0].attr subclass = buildclass[1][0].attr
subclass_info = node[0] subclass_info = node[0]
else: else:
buildclass = node[0] buildclass = node if (node == 'classdefdeco2') else node[0]
build_list = buildclass[1][0] build_list = buildclass[1][0]
if hasattr(buildclass[-3][0], 'attr'): if hasattr(buildclass[-3][0], 'attr'):
subclass = buildclass[-3][0].attr subclass = buildclass[-3][0].attr
@@ -773,7 +778,11 @@ class FragmentsWalker(pysource.SourceWalker, object):
else: else:
raise 'Internal Error n_classdef: cannot find class name' 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) self.currentclass = str(currentclass)
start = len(self.f.getvalue()) start = len(self.f.getvalue())
self.write(self.indent, 'class ', self.currentclass) self.write(self.indent, 'class ', self.currentclass)
@@ -798,6 +807,8 @@ class FragmentsWalker(pysource.SourceWalker, object):
self.prune() self.prune()
n_classdefdeco2 = n_classdef
def gen_source(self, ast, name, customize, isLambda=False, returnNone=False): def gen_source(self, ast, name, customize, isLambda=False, returnNone=False):
"""convert AST to Python source code""" """convert AST to Python source code"""

View File

@@ -1187,11 +1187,16 @@ class SourceWalker(GenericASTTraversal, object):
cclass = self.currentclass cclass = self.currentclass
if self.version > 3.0: if self.version > 3.0:
currentclass = node[1][0].pattr if node == 'classdefdeco2':
buildclass = node[0] currentclass = node[1][2].pattr
buildclass = node
else:
currentclass = node[1][0].pattr
buildclass = node[0]
if buildclass[1][0] == 'kwargs': if buildclass[1][0] == 'kwargs':
subclass = buildclass[1][1].attr subclass = buildclass[1][1].attr
subclass_info = node[0] subclass_info = node if node == 'classdefdeco2' else node[0]
elif buildclass[1][0] == 'load_closure': elif buildclass[1][0] == 'load_closure':
# Python 3 with closures not functions # Python 3 with closures not functions
load_closure = buildclass[1] load_closure = buildclass[1]