mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-02-17 03:38:13 +00:00
2.7 and 3.x bug in dict comprehensions
This commit is contained in:
parent
520290898b
commit
5c268ee2a6
BIN
test/bytecode_2.7/03_map.pyc
Normal file
BIN
test/bytecode_2.7/03_map.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.7/05_set_comprehension.pyc
Normal file
BIN
test/bytecode_2.7/05_set_comprehension.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.4/03_map.pyc
Normal file
BIN
test/bytecode_3.4/03_map.pyc
Normal file
Binary file not shown.
Binary file not shown.
@ -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)}
|
||||
|
||||
# Bug in python 3.4 (base64.py) in handling dict comprehension
|
||||
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
|
||||
|
@ -24,6 +24,10 @@ class Python2Parser(PythonParser):
|
||||
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
|
||||
self.customized = {}
|
||||
|
||||
# FIXME: redo with parse3's add_unique_rule.
|
||||
self.seen32 = False
|
||||
self.seen1024 = False
|
||||
|
||||
def p_list_comprehension2(self, args):
|
||||
"""
|
||||
list_for ::= expr _for designator list_iter JUMP_BACK
|
||||
@ -331,8 +335,23 @@ class Python2Parser(PythonParser):
|
||||
|
||||
op = k[:k.rfind('_')]
|
||||
if op in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET'):
|
||||
rule = ('build_list ::= ' + 'expr1024 '*(v//1024) +
|
||||
'expr32 '*((v//32)%32) + 'expr '*(v%32) + k)
|
||||
thousands = (v//1024)
|
||||
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'):
|
||||
rule = 'unpack ::= ' + k + ' designator'*v
|
||||
elif op == 'UNPACK_LIST':
|
||||
|
@ -336,11 +336,13 @@ class Python3Parser(PythonParser):
|
||||
# Is there something general going on here?
|
||||
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
|
||||
dictcomp ::= load_closure LOAD_DICTCOMP LOAD_CONST MAKE_CLOSURE_0 expr GET_ITER CALL_FUNCTION_1
|
||||
'''
|
||||
|
||||
def p_expr3(self, args):
|
||||
'''
|
||||
expr ::= LOAD_CLASSNAME
|
||||
expr ::= LOAD_ASSERT
|
||||
# Python3 drops slice0..slice3
|
||||
|
||||
# Python 3.3+ adds yield from
|
||||
@ -502,7 +504,6 @@ class Python3Parser(PythonParser):
|
||||
if opname_base == 'BUILD_TUPLE':
|
||||
rule = ('load_closure ::= %s%s' % (('LOAD_CLOSURE ' * v), opname))
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
|
||||
elif opname_base == 'BUILD_MAP':
|
||||
kvlist_n = "kvlist_%s" % token.attr
|
||||
if self.version >= 3.5:
|
||||
|
@ -55,7 +55,7 @@ class Scanner27(Scanner2):
|
||||
self.opc.CALL_FUNCTION_KW, self.opc.CALL_FUNCTION_VAR_KW,
|
||||
self.opc.DUP_TOPX, self.opc.RAISE_VARARGS,
|
||||
# New in Python 2.7
|
||||
self.opc.BUILD_SET])
|
||||
self.opc.BUILD_SET, self.opc.BUILD_MAP])
|
||||
|
||||
# "setup" opcodes
|
||||
self.setup_ops = frozenset([
|
||||
|
@ -1140,7 +1140,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
||||
pass
|
||||
else:
|
||||
# Python 2 style kvlist
|
||||
assert node[-1] == 'kvlist'
|
||||
assert node[-1].type.startswith('kvlist')
|
||||
kv_node = node[-1] # goto kvlist
|
||||
|
||||
for kv in kv_node:
|
||||
|
@ -1006,21 +1006,25 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
def comprehension_walk(self, node, iter_index, code_index=-5):
|
||||
p = self.prec
|
||||
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
|
||||
code = node[code_index].attr
|
||||
cn = node[code_index]
|
||||
else:
|
||||
if len(node[1]) > 1 and hasattr(node[1][1], 'attr'):
|
||||
# Python 3.3+ does this
|
||||
code = node[1][1].attr
|
||||
cn = node[1][1]
|
||||
elif hasattr(node[1][0], 'attr'):
|
||||
# Python 3.2 does this
|
||||
code = node[1][0].attr
|
||||
cn = node[1][0]
|
||||
else:
|
||||
assert False, "Can't find code for comprehension"
|
||||
|
||||
assert iscode(code)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
assert iscode(cn.attr)
|
||||
code = Code(cn.attr, self.scanner, self.currentclass)
|
||||
ast = self.build_ast(code._tokens, code._customize)
|
||||
self.customize(code._customize)
|
||||
ast = ast[0][0][0]
|
||||
@ -1308,7 +1312,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
sep = INDENT_PER_LEVEL[:-1]
|
||||
self.write('{')
|
||||
|
||||
if self.version > 3.0:
|
||||
if self.version >= 3.0:
|
||||
if node[0].type.startswith('kvlist'):
|
||||
# Python 3.5+ style key/value list in mapexpr
|
||||
kv_node = node[0]
|
||||
@ -1342,7 +1346,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
pass
|
||||
else:
|
||||
# Python 2 style kvlist
|
||||
assert node[-1] == 'kvlist'
|
||||
assert node[-1].type.startswith('kvlist')
|
||||
kv_node = node[-1] # goto kvlist
|
||||
|
||||
for kv in kv_node:
|
||||
|
Loading…
x
Reference in New Issue
Block a user