X Tutup
Skip to content

Commit fe9c8d5

Browse files
committed
Python3 try/except handling improvements. Add Walker exception and use
that: fixes erroneous uncompyle success message on parse error.
1 parent 0409cee commit fe9c8d5

File tree

7 files changed

+74
-35
lines changed

7 files changed

+74
-35
lines changed
394 Bytes
Binary file not shown.

test/simple_source/exception/01_try_except.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,28 @@
55

66
try:
77
x = 1
8-
except RuntimeError as e:
9-
y = 2
8+
except:
9+
pass
1010

11-
# # Tests:
12-
# # trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
13-
# # try_middle COME_FROM
14-
# # except_stmt ::= except_cond1 except_suite
15-
# # except_suite ::= ...
11+
# Tests:
12+
# trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
13+
# try_middle COME_FROM
14+
# except_stmt ::= except_cond1 except_suite
15+
# except_suite ::= ...
1616

17-
# try:
18-
# x = 1
19-
# except ImportError:
20-
# pass
17+
try:
18+
x = 1
19+
except ImportError:
20+
pass
2121

22-
# try:
23-
# x = 2
24-
# except ImportError:
25-
# x = 3
26-
# finally:
27-
# x = 4
22+
try:
23+
x = 2
24+
except ImportError:
25+
x = 3
26+
finally:
27+
x = 4
28+
29+
try:
30+
x = 1
31+
except ImportError as e:
32+
x = 2
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
def handle(module):
2+
try:
3+
module = 1
4+
except ImportError as exc:
5+
module = exc
6+
return module
7+
18
try:
29
pass
310
except ImportError as exc:
411
pass
512
finally:
6-
del exc
13+
y = 1

uncompyle6/main.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ def uncompyle(version, co, out=None, showasm=False, showast=False,
2727

2828
try:
2929
pysource.deparse_code(version, co, out, showasm, showast, showgrammar)
30-
except pysource.ParserError as e : # parser failed, dump disassembly
31-
print(e, file=real_out)
30+
except pysource.WalkerError as e:
31+
# deparsing failed
32+
if real_out != out:
33+
print(e, file=real_out)
3234
raise
3335

3436
def uncompyle_file(filename, outstream=None, showasm=False, showast=False,

uncompyle6/opcodes/opcode_34.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,10 @@ def updateGlobal():
8181
def_op('INPLACE_FLOOR_DIVIDE', 28)
8282
def_op('INPLACE_TRUE_DIVIDE', 29)
8383

84-
# Gone from Python 3 are
85-
# Python 2's SLICE+0 .. SLICE+3
84+
# Gone from Python 3 are Python2's
85+
# SLICE+0 .. SLICE+3
86+
# STORE_SLICE+0 .. STORE_SLICE+3
87+
# DELETE_SLICE+0 .. DELETE_SLICE+3
8688

8789
def_op('STORE_MAP', 54)
8890
def_op('INPLACE_ADD', 55)

uncompyle6/parsers/parse3.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ def p_grammar(self, args):
449449
450450
except_stmt ::= except_cond1 except_suite
451451
except_stmt ::= except_cond2 except_suite
452+
except_stmt ::= except_cond2 except_suite_finalize
452453
except_stmt ::= except
453454
454455
# Python3 introduced POP_EXCEPT
@@ -457,10 +458,11 @@ def p_grammar(self, args):
457458
458459
# This is used in Python 3 in
459460
# "except ... as e" to remove 'e' after the c_stmts_opt finishes
460-
except_suite ::= SETUP_FINALLY c_stmts_opt
461-
POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM LOAD_CONST
462-
STORE_NAME DELETE_NAME END_FINALLY
463-
JUMP_FORWARD
461+
except_suite_finalize ::= SETUP_FINALLY c_stmts_opt except_var_finalize
462+
END_FINALLY JUMP_FORWARD
463+
464+
except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM LOAD_CONST
465+
designator del_stmt
464466
465467
except_suite ::= return_stmts
466468

uncompyle6/semantics/pysource.py

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@
6363

6464
import inspect, sys, re
6565

66-
6766
from uncompyle6 import PYTHON3
6867
from uncompyle6.parser import get_python_parser
6968
from uncompyle6.parsers.astnode import AST
@@ -124,9 +123,14 @@
124123
INDENT_PER_LEVEL = ' ' # additional intent per pretty-print level
125124

126125
TABLE_R = {
127-
'POP_TOP': ( '%|%c\n', 0 ),
128126
'STORE_ATTR': ( '%c.%[1]{pattr}', 0),
129127
# 'STORE_SUBSCR': ( '%c[%c]', 0, 1 ),
128+
'DELETE_ATTR': ( '%|del %c.%[-1]{pattr}\n', 0 ),
129+
# 'EXEC_STMT': ( '%|exec %c in %[1]C\n', 0, (0,maxint,', ') ),
130+
}
131+
132+
if not PYTHON3:
133+
TABLE_R.update({
130134
'STORE_SLICE+0': ( '%c[:]', 0 ),
131135
'STORE_SLICE+1': ( '%c[%p:]', 0, (1, 100) ),
132136
'STORE_SLICE+2': ( '%c[:%p]', 0, (1, 100) ),
@@ -135,9 +139,8 @@
135139
'DELETE_SLICE+1': ( '%|del %c[%c:]\n', 0, 1 ),
136140
'DELETE_SLICE+2': ( '%|del %c[:%c]\n', 0, 1 ),
137141
'DELETE_SLICE+3': ( '%|del %c[%c:%c]\n', 0, 1, 2 ),
138-
'DELETE_ATTR': ( '%|del %c.%[-1]{pattr}\n', 0 ),
139-
# 'EXEC_STMT': ( '%|exec %c in %[1]C\n', 0, (0,maxint,', ') ),
140-
}
142+
})
143+
141144
TABLE_R0 = {
142145
# 'BUILD_LIST': ( '[%C]', (0,-1,', ') ),
143146
# 'BUILD_TUPLE': ( '(%C)', (0,-1,', ') ),
@@ -317,6 +320,7 @@
317320
'except_cond1': ( '%|except %c:\n', 1 ),
318321
'except_cond2': ( '%|except %c as %c:\n', 1, 5 ),
319322
'except_suite': ( '%+%c%-%C', 0, (1, maxint, '') ),
323+
'except_suite_finalize': ( '%+%c%-%C', 1, (3, maxint, '') ),
320324
'tryfinallystmt': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 5 ),
321325
'withstmt': ( '%|with %c:\n%+%c%-', 0, 3),
322326
'withasstmt': ( '%|with %c as %c:\n%+%c%-', 0, 2, 3),
@@ -438,7 +442,6 @@ def __str__(self):
438442
lines.extend( ['', str(self.error)] )
439443
return '\n'.join(lines)
440444

441-
442445
def find_globals(node, globs):
443446
"""Find globals in this statement."""
444447
for n in node:
@@ -467,6 +470,13 @@ def find_none(node):
467470
return True
468471
return False
469472

473+
class WalkerError(Exception):
474+
def __init__(self, errmsg):
475+
self.errmsg = errmsg
476+
477+
def __str__(self):
478+
return self.errmsg
479+
470480
class Walker(GenericASTTraversal, object):
471481
stacked_params = ('f', 'indent', 'isLambda', '_globals')
472482

@@ -1233,8 +1243,6 @@ def engine(self, entry, startnode):
12331243
# self.print_("-----")
12341244
# self.print(startnode)
12351245

1236-
# from trepan.api import debug
1237-
# debug(start_opts={'startup-profile': True})
12381246

12391247
fmt = entry[0]
12401248
arg = 1
@@ -1262,7 +1270,18 @@ def engine(self, entry, startnode):
12621270
elif typ == ',':
12631271
pass
12641272
elif typ == 'c':
1265-
self.preorder(node[entry[arg]])
1273+
# FIXME: In Python3 sometimes like from
1274+
# importfrom
1275+
# importlist2
1276+
# import_as
1277+
# designator
1278+
# STORE_NAME 'load_entry_point'
1279+
# POP_TOP '' (2, (0, 1))
1280+
# we get that weird POP_TOP tuple, e.g (2, (0,1)).
1281+
# Why? and
1282+
# Is there some sort of invalid bounds access going on?
1283+
if isinstance(entry[arg], int):
1284+
self.preorder(node[entry[arg]])
12661285
arg += 1
12671286
elif typ == 'p':
12681287
p = self.prec
@@ -1637,6 +1656,8 @@ def deparse_code(version, co, out=sys.stdout, showasm=False, showast=False,
16371656
for g in deparsed.mod_globs:
16381657
deparsed.write('# global %s ## Warning: Unused global' % g)
16391658

1659+
if deparsed.ERROR:
1660+
raise WalkerError("Deparsing stopped due to parse error")
16401661
return deparsed
16411662

16421663
if __name__ == '__main__':

0 commit comments

Comments
 (0)
X Tutup