Skip to content

Commit eb2b63c

Browse files
committed
Merge remote-tracking branch 'origin' into line-mappings
2 parents 79863ae + 805e179 commit eb2b63c

File tree

10 files changed

+158
-73
lines changed

10 files changed

+158
-73
lines changed

pytest/test_fjt.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ def bug(state, slotstate):
88
for key, value in slotstate.items():
99
setattr(state, key, 2)
1010

11+
# From 2.7 disassemble
12+
# Problem is not getting while, because
13+
# COME_FROM not added
14+
def bug_loop(disassemble, tb=None):
15+
if tb:
16+
try:
17+
tb = 5
18+
except AttributeError:
19+
raise RuntimeError
20+
while tb: tb = tb.tb_next
21+
disassemble(tb)
22+
1123
def test_if_in_for():
1224
code = bug.__code__
1325
scan = get_scanner(PYTHON_VERSION)
@@ -16,18 +28,35 @@ def test_if_in_for():
1628
n = scan.setup_code(code)
1729
scan.build_lines_data(code, n)
1830
scan.build_prev_op(n)
19-
fjt = scan.find_jump_targets()
31+
fjt = scan.find_jump_targets(False)
2032
assert {15: [3], 69: [66], 63: [18]} == fjt
2133
assert scan.structs == \
2234
[{'start': 0, 'end': 72, 'type': 'root'},
23-
{'start': 18, 'end': 66, 'type': 'if-then'},
35+
{'start': 15, 'end': 66, 'type': 'if-then'},
2436
{'start': 31, 'end': 59, 'type': 'for-loop'},
2537
{'start': 62, 'end': 63, 'type': 'for-else'}]
38+
39+
code = bug_loop.__code__
40+
n = scan.setup_code(code)
41+
scan.build_lines_data(code, n)
42+
scan.build_prev_op(n)
43+
fjt = scan.find_jump_targets(False)
44+
assert{64: [42], 67: [42, 42], 42: [16, 41], 19: [6]} == fjt
45+
assert scan.structs == [
46+
{'start': 0, 'end': 80, 'type': 'root'},
47+
{'start': 3, 'end': 64, 'type': 'if-then'},
48+
{'start': 6, 'end': 15, 'type': 'try'},
49+
{'start': 19, 'end': 38, 'type': 'except'},
50+
{'start': 45, 'end': 67, 'type': 'while-loop'},
51+
{'start': 70, 'end': 64, 'type': 'while-else'},
52+
# previous bug was not mistaking while-loop for if-then
53+
{'start': 48, 'end': 67, 'type': 'while-loop'}]
54+
2655
elif 3.2 < PYTHON_VERSION <= 3.4:
2756
scan.code = array('B', code.co_code)
2857
scan.build_lines_data(code)
2958
scan.build_prev_op()
30-
fjt = scan.find_jump_targets()
59+
fjt = scan.find_jump_targets(False)
3160
assert {69: [66], 63: [18]} == fjt
3261
assert scan.structs == \
3362
[{'end': 72, 'type': 'root', 'start': 0},

test/bytecode_2.7/00_docstring.pyc

571 Bytes
Binary file not shown.
-211 Bytes
Binary file not shown.
File renamed without changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# uncompyle2 bug was not escaping """ properly
2+
r'''func placeholder - with ("""\nstring\n""")'''
3+
def foo():
4+
r'''func placeholder - ' and with ("""\nstring\n""")'''
5+
6+
def bar():
7+
r"""func placeholder - ' and with ('''\nstring\n''') and \"\"\"\nstring\n\"\"\" """

uncompyle6/scanners/scanner2.py

Lines changed: 90 additions & 56 deletions
Large diffs are not rendered by default.

uncompyle6/scanners/scanner26.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def ingest(self, co, classname=None, code_objects={}, show_asm=None):
130130
if names[self.get_argument(i+4)] == 'AssertionError':
131131
self.load_asserts.add(i+4)
132132

133-
jump_targets = self.find_jump_targets()
133+
jump_targets = self.find_jump_targets(show_asm)
134134
# contains (code, [addrRefToCode])
135135

136136
last_stmt = self.next_stmt[0]

uncompyle6/scanners/scanner3.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def ingest(self, co, classname=None, code_objects={}, show_asm=None):
199199

200200
# Get jump targets
201201
# Format: {target offset: [jump offsets]}
202-
jump_targets = self.find_jump_targets()
202+
jump_targets = self.find_jump_targets(show_asm)
203203

204204
for inst in bytecode:
205205

@@ -401,7 +401,7 @@ def build_prev_op(self):
401401
for _ in range(self.op_size(op)):
402402
self.prev_op.append(offset)
403403

404-
def find_jump_targets(self):
404+
def find_jump_targets(self, debug):
405405
"""
406406
Detect all offsets in a byte code which are jump targets
407407
where we might insert a COME_FROM instruction.
@@ -428,6 +428,8 @@ def find_jump_targets(self):
428428
# Containers filled by detect_structure()
429429
self.not_continue = set()
430430
self.return_end_ifs = set()
431+
self.setup_loop_targets = {} # target given setup_loop offset
432+
self.setup_loops = {} # setup_loop offset given target
431433

432434
targets = {}
433435
for offset in self.op_range(0, n):
@@ -455,6 +457,13 @@ def find_jump_targets(self):
455457
elif op == self.opc.END_FINALLY and offset in self.fixed_jumps:
456458
label = self.fixed_jumps[offset]
457459
targets[label] = targets.get(label, []) + [offset]
460+
pass
461+
pass
462+
# DEBUG:
463+
if debug in ('both', 'after'):
464+
import pprint as pp
465+
pp.pprint(self.structs)
466+
458467
return targets
459468

460469
def build_statement_indices(self):
@@ -585,6 +594,8 @@ def detect_structure(self, offset, targets):
585594
start = offset+3
586595
target = self.get_target(offset)
587596
end = self.restrict_to_parent(target, parent)
597+
self.setup_loop_targets[offset] = target
598+
self.setup_loops[target] = offset
588599

589600
if target != end:
590601
self.fixed_jumps[offset] = end

uncompyle6/semantics/pysource.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,12 @@ def println(self, *data):
741741
self.pending_newlines = max(self.pending_newlines, 1)
742742

743743
def print_docstring(self, indent, docstring):
744-
quote = '"""'
744+
## FIXME: put this into a testable function.
745+
if docstring.find('"""') == -1:
746+
quote = '"""'
747+
else:
748+
quote = "'''"
749+
745750
self.write(indent)
746751
if not PYTHON3 and not isinstance(docstring, str):
747752
# Must be unicode in Python2
@@ -774,10 +779,11 @@ def print_docstring(self, indent, docstring):
774779
# ruin the ending triple quote
775780
if len(docstring) and docstring[-1] == '"':
776781
docstring = docstring[:-1] + '\\"'
777-
# Escape triple quote anywhere
778-
docstring = docstring.replace('"""', '\\"\\"\\"')
779782
# Restore escaped backslashes
780783
docstring = docstring.replace('\t', '\\\\')
784+
# Escape triple quote when needed
785+
if quote == '""""':
786+
docstring = docstring.replace('"""', '\\"\\"\\"')
781787
lines = docstring.split('\n')
782788
calculate_indent = maxint
783789
for line in lines[1:]:
@@ -1010,10 +1016,7 @@ def n_exec_stmt(self, node):
10101016
def n_ifelsestmt(self, node, preprocess=False):
10111017
else_suite = node[3]
10121018

1013-
try:
1014-
n = else_suite[0]
1015-
except:
1016-
from trepan.api import debug; debug()
1019+
n = else_suite[0]
10171020

10181021
if len(n) == 1 == len(n[0]) and n[0] == '_stmts':
10191022
n = n[0][0][0]
@@ -1202,6 +1205,8 @@ def n_list_compr(self, node):
12021205
assert expr == 'expr'
12031206
assert list_iter == 'list_iter'
12041207

1208+
# FIXME: use source line numbers for directing line breaks
1209+
12051210
self.preorder(expr)
12061211
self.preorder(list_iter)
12071212
self.write( ' ]')
@@ -1217,7 +1222,7 @@ def n_list_compr_pypy27(self, node):
12171222
n = node[-1]
12181223
elif self.is_pypy and node[-1] == 'JUMP_BACK':
12191224
n = node[-2]
1220-
list_expr = node[0]
1225+
list_expr = node[1]
12211226

12221227
if len(node) >= 3:
12231228
designator = node[3]
@@ -1242,10 +1247,9 @@ def n_list_compr_pypy27(self, node):
12421247
assert expr == 'expr'
12431248
assert list_iter == 'list_iter'
12441249

1250+
# FIXME: use source line numbers for directing line breaks
1251+
12451252
self.preorder(expr)
1246-
self.write( ' for ')
1247-
self.preorder(designator)
1248-
self.write( ' in ')
12491253
self.preorder(list_expr)
12501254
self.write( ' ]')
12511255
self.prec = p

0 commit comments

Comments
 (0)