2.7 and 3.x bug in dict comprehensions

This commit is contained in:
rocky
2016-06-19 13:41:49 -04:00
parent 520290898b
commit 5c268ee2a6
10 changed files with 43 additions and 14 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,10 @@
# Bug in python 3.x handling set comprehensions # Bug from python 3.x handling set comprehensions
{y for y in range(3)} {y for y in range(3)}
# Bug in python 3.4 (base64.py) in handling dict comprehension # Bug in python 3.4 (base64.py) in handling dict comprehension
b = {v: k for k, v in enumerate(b3)} b = {v: k for k, v in enumerate(b3)}
# Bug from Python 3.4 enum
def __new__(classdict):
members = {k: classdict[k] for k in classdict._member_names}
return members

View File

@@ -24,6 +24,10 @@ class Python2Parser(PythonParser):
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser) super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
self.customized = {} self.customized = {}
# FIXME: redo with parse3's add_unique_rule.
self.seen32 = False
self.seen1024 = False
def p_list_comprehension2(self, args): def p_list_comprehension2(self, args):
""" """
list_for ::= expr _for designator list_iter JUMP_BACK list_for ::= expr _for designator list_iter JUMP_BACK
@@ -331,8 +335,23 @@ class Python2Parser(PythonParser):
op = k[:k.rfind('_')] op = k[:k.rfind('_')]
if op in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET'): if op in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET'):
rule = ('build_list ::= ' + 'expr1024 '*(v//1024) + thousands = (v//1024)
'expr32 '*((v//32)%32) + 'expr '*(v%32) + k) thirty32s = ((v//32)%32)
if thirty32s > 0 and not self.seen32:
rule = "expr32 ::=%s" % (' expr' * 32)
self.addRule(rule, nop_func)
self.seen32 = True
if thousands > 0 and not self.seen1025:
self.addRule("expr1024 ::=%s" % (' expr32' * 32), nop_func)
self.seen1024 = True
rule = ('build_list ::= ' + 'expr1024 '*thousands +
'expr32 '*thirty32s + 'expr '*(v%32) + k)
elif op == 'BUILD_MAP':
kvlist_n = "kvlist_%s" % v
rule = kvlist_n + ' ::= ' + ' kv3' * v
self.addRule(rule, nop_func)
rule = "mapexpr ::= %s %s" % (k, kvlist_n)
self.addRule(rule, nop_func)
elif op in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): elif op in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
rule = 'unpack ::= ' + k + ' designator'*v rule = 'unpack ::= ' + k + ' designator'*v
elif op == 'UNPACK_LIST': elif op == 'UNPACK_LIST':

View File

@@ -336,11 +336,13 @@ class Python3Parser(PythonParser):
# Is there something general going on here? # Is there something general going on here?
genexpr ::= LOAD_GENEXPR LOAD_CONST MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1 genexpr ::= LOAD_GENEXPR LOAD_CONST MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
genexpr ::= load_closure LOAD_GENEXPR LOAD_CONST MAKE_CLOSURE_0 expr GET_ITER CALL_FUNCTION_1 genexpr ::= load_closure LOAD_GENEXPR LOAD_CONST MAKE_CLOSURE_0 expr GET_ITER CALL_FUNCTION_1
dictcomp ::= load_closure LOAD_DICTCOMP LOAD_CONST MAKE_CLOSURE_0 expr GET_ITER CALL_FUNCTION_1
''' '''
def p_expr3(self, args): def p_expr3(self, args):
''' '''
expr ::= LOAD_CLASSNAME expr ::= LOAD_CLASSNAME
expr ::= LOAD_ASSERT
# Python3 drops slice0..slice3 # Python3 drops slice0..slice3
# Python 3.3+ adds yield from # Python 3.3+ adds yield from
@@ -502,7 +504,6 @@ class Python3Parser(PythonParser):
if opname_base == 'BUILD_TUPLE': if opname_base == 'BUILD_TUPLE':
rule = ('load_closure ::= %s%s' % (('LOAD_CLOSURE ' * v), opname)) rule = ('load_closure ::= %s%s' % (('LOAD_CLOSURE ' * v), opname))
self.add_unique_rule(rule, opname, token.attr, customize) self.add_unique_rule(rule, opname, token.attr, customize)
elif opname_base == 'BUILD_MAP': elif opname_base == 'BUILD_MAP':
kvlist_n = "kvlist_%s" % token.attr kvlist_n = "kvlist_%s" % token.attr
if self.version >= 3.5: if self.version >= 3.5:

View File

@@ -55,7 +55,7 @@ class Scanner27(Scanner2):
self.opc.CALL_FUNCTION_KW, self.opc.CALL_FUNCTION_VAR_KW, self.opc.CALL_FUNCTION_KW, self.opc.CALL_FUNCTION_VAR_KW,
self.opc.DUP_TOPX, self.opc.RAISE_VARARGS, self.opc.DUP_TOPX, self.opc.RAISE_VARARGS,
# New in Python 2.7 # New in Python 2.7
self.opc.BUILD_SET]) self.opc.BUILD_SET, self.opc.BUILD_MAP])
# "setup" opcodes # "setup" opcodes
self.setup_ops = frozenset([ self.setup_ops = frozenset([

View File

@@ -1140,7 +1140,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
pass pass
else: else:
# Python 2 style kvlist # Python 2 style kvlist
assert node[-1] == 'kvlist' assert node[-1].type.startswith('kvlist')
kv_node = node[-1] # goto kvlist kv_node = node[-1] # goto kvlist
for kv in kv_node: for kv in kv_node:

View File

@@ -1006,21 +1006,25 @@ class SourceWalker(GenericASTTraversal, object):
def comprehension_walk(self, node, iter_index, code_index=-5): def comprehension_walk(self, node, iter_index, code_index=-5):
p = self.prec p = self.prec
self.prec = 27 self.prec = 27
if hasattr(node[code_index], 'attr'):
# FIXME: clean this up
if self.version > 3.0 and node == 'dictcomp':
cn = node[1]
elif hasattr(node[code_index], 'attr'):
# Python 2.5+ (and earlier?) does this # Python 2.5+ (and earlier?) does this
code = node[code_index].attr cn = node[code_index]
else: else:
if len(node[1]) > 1 and hasattr(node[1][1], 'attr'): if len(node[1]) > 1 and hasattr(node[1][1], 'attr'):
# Python 3.3+ does this # Python 3.3+ does this
code = node[1][1].attr cn = node[1][1]
elif hasattr(node[1][0], 'attr'): elif hasattr(node[1][0], 'attr'):
# Python 3.2 does this # Python 3.2 does this
code = node[1][0].attr cn = node[1][0]
else: else:
assert False, "Can't find code for comprehension" assert False, "Can't find code for comprehension"
assert iscode(code) assert iscode(cn.attr)
code = Code(code, self.scanner, self.currentclass) code = Code(cn.attr, self.scanner, self.currentclass)
ast = self.build_ast(code._tokens, code._customize) ast = self.build_ast(code._tokens, code._customize)
self.customize(code._customize) self.customize(code._customize)
ast = ast[0][0][0] ast = ast[0][0][0]
@@ -1308,7 +1312,7 @@ class SourceWalker(GenericASTTraversal, object):
sep = INDENT_PER_LEVEL[:-1] sep = INDENT_PER_LEVEL[:-1]
self.write('{') self.write('{')
if self.version > 3.0: if self.version >= 3.0:
if node[0].type.startswith('kvlist'): if node[0].type.startswith('kvlist'):
# Python 3.5+ style key/value list in mapexpr # Python 3.5+ style key/value list in mapexpr
kv_node = node[0] kv_node = node[0]
@@ -1342,7 +1346,7 @@ class SourceWalker(GenericASTTraversal, object):
pass pass
else: else:
# Python 2 style kvlist # Python 2 style kvlist
assert node[-1] == 'kvlist' assert node[-1].type.startswith('kvlist')
kv_node = node[-1] # goto kvlist kv_node = node[-1] # goto kvlist
for kv in kv_node: for kv in kv_node: