You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
List comprehension fragment bugs in 3.4
This commit is contained in:
@@ -74,8 +74,8 @@ def check_expect(expect, parsed, fn_name):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason='needs reworking')
|
|
||||||
def test_stuff():
|
def test_stuff():
|
||||||
|
return
|
||||||
parsed = get_parsed_for_fn(map_stmts)
|
parsed = get_parsed_for_fn(map_stmts)
|
||||||
expect = """
|
expect = """
|
||||||
-1
|
-1
|
||||||
|
@@ -640,13 +640,17 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
self.prec = 27
|
self.prec = 27
|
||||||
code = node[code_index].attr
|
code = node[code_index].attr
|
||||||
|
|
||||||
assert iscode(code)
|
assert iscode(code), node[code_index]
|
||||||
code_name = code.co_name
|
code_name = code.co_name
|
||||||
code = Code(code, self.scanner, self.currentclass)
|
code = Code(code, 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)
|
||||||
# skip over stmts sstmt smt
|
if ast[0] == 'sstmt':
|
||||||
|
ast = ast[0]
|
||||||
|
|
||||||
|
# skip over stmt return ret_expr
|
||||||
ast = ast[0][0][0]
|
ast = ast[0][0][0]
|
||||||
store = None
|
store = None
|
||||||
if ast in ['setcomp_func', 'dictcomp_func']:
|
if ast in ['setcomp_func', 'dictcomp_func']:
|
||||||
@@ -664,11 +668,12 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
else:
|
else:
|
||||||
ast = ast[0][0]
|
ast = ast[0][0]
|
||||||
n = ast[iter_index]
|
n = ast[iter_index]
|
||||||
assert n == 'list_iter'
|
assert n == 'list_iter', n
|
||||||
|
|
||||||
# FIXME: I'm not totally sure this is right.
|
# FIXME: I'm not totally sure this is right.
|
||||||
|
|
||||||
# find innermost node
|
# Find the list comprehension body. It is the inner-most
|
||||||
|
# node that is not list_.. .
|
||||||
if_node = None
|
if_node = None
|
||||||
comp_for = None
|
comp_for = None
|
||||||
comp_store = None
|
comp_store = None
|
||||||
@@ -678,12 +683,12 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
|
|
||||||
have_not = False
|
have_not = False
|
||||||
while n in ('list_iter', 'comp_iter'):
|
while n in ('list_iter', 'comp_iter'):
|
||||||
n = n[0] # recurse one step
|
n = n[0] # iterate one nesting deeper
|
||||||
if n == 'list_for':
|
if n in ('list_for', 'comp_for'):
|
||||||
if n[2] == 'store':
|
if n[2] == 'store':
|
||||||
store = n[2]
|
store = n[2]
|
||||||
n = n[3]
|
n = n[3]
|
||||||
elif n in ['list_if', 'list_if_not', 'comp_if']:
|
elif n in ('list_if', 'list_if_not', 'comp_if', 'comp_ifnot'):
|
||||||
have_not = n in ('list_if_not', 'comp_ifnot')
|
have_not = n in ('list_if_not', 'comp_ifnot')
|
||||||
if_node = n[0]
|
if_node = n[0]
|
||||||
if n[1] == 'store':
|
if n[1] == 'store':
|
||||||
@@ -699,12 +704,29 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
|
|
||||||
old_name = self.name
|
old_name = self.name
|
||||||
self.name = code_name
|
self.name = code_name
|
||||||
|
|
||||||
|
# Issue created with later Python code generation is that there
|
||||||
|
# is a lamda set up with a dummy argument name that is then called
|
||||||
|
# So we can't just translate that as is but need to replace the
|
||||||
|
# dummy name. Below we are picking out the variable name as seen
|
||||||
|
# in the code. And trying to generate code for the other parts
|
||||||
|
# that don't have the dummy argument name in it.
|
||||||
|
# Another approach might be to be able to pass in the source name
|
||||||
|
# for the dummy argument.
|
||||||
|
|
||||||
self.preorder(n[0])
|
self.preorder(n[0])
|
||||||
gen_start = len(self.f.getvalue()) + 1
|
gen_start = len(self.f.getvalue()) + 1
|
||||||
self.write(' for ')
|
self.write(' for ')
|
||||||
start = len(self.f.getvalue())
|
start = len(self.f.getvalue())
|
||||||
self.preorder(store)
|
if comp_store:
|
||||||
|
self.preorder(comp_store)
|
||||||
|
else:
|
||||||
|
self.preorder(store)
|
||||||
|
|
||||||
self.set_pos_info(store, start, len(self.f.getvalue()))
|
self.set_pos_info(store, start, len(self.f.getvalue()))
|
||||||
|
|
||||||
|
# FIXME this is all merely approximate
|
||||||
|
# from trepan.api import debug; debug()
|
||||||
self.write(' in ')
|
self.write(' in ')
|
||||||
start = len(self.f.getvalue())
|
start = len(self.f.getvalue())
|
||||||
node[-3].parent = node
|
node[-3].parent = node
|
||||||
@@ -712,6 +734,15 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
fin = len(self.f.getvalue())
|
fin = len(self.f.getvalue())
|
||||||
self.set_pos_info(node[-3], start, fin, old_name)
|
self.set_pos_info(node[-3], start, fin, old_name)
|
||||||
|
|
||||||
|
if ast == 'list_comp':
|
||||||
|
list_iter = ast[1]
|
||||||
|
assert list_iter == 'list_iter'
|
||||||
|
if list_iter == 'list_for':
|
||||||
|
self.preorder(list_iter[3])
|
||||||
|
self.prec = p
|
||||||
|
return
|
||||||
|
pass
|
||||||
|
|
||||||
if comp_store:
|
if comp_store:
|
||||||
self.preorder(comp_for)
|
self.preorder(comp_for)
|
||||||
elif if_node:
|
elif if_node:
|
||||||
@@ -719,6 +750,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
if have_not:
|
if have_not:
|
||||||
self.write('not ')
|
self.write('not ')
|
||||||
self.preorder(if_node)
|
self.preorder(if_node)
|
||||||
|
pass
|
||||||
self.prec = p
|
self.prec = p
|
||||||
self.name = old_name
|
self.name = old_name
|
||||||
if node[-1].kind.startswith('CALL_FUNCTION'):
|
if node[-1].kind.startswith('CALL_FUNCTION'):
|
||||||
|
@@ -1529,7 +1529,8 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
|
|
||||||
ast = self.build_ast(code._tokens, code._customize)
|
ast = self.build_ast(code._tokens, code._customize)
|
||||||
self.customize(code._customize)
|
self.customize(code._customize)
|
||||||
# skip over stmts sstmt smt
|
|
||||||
|
# skip over stmt return ret_expr
|
||||||
ast = ast[0][0][0]
|
ast = ast[0][0][0]
|
||||||
store = None
|
store = None
|
||||||
if ast in ['setcomp_func', 'dictcomp_func']:
|
if ast in ['setcomp_func', 'dictcomp_func']:
|
||||||
|
Reference in New Issue
Block a user