Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
69f163fb
Commit
69f163fb
authored
Jan 26, 2013
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
make except-as delete the target after the except clause
parent
48c6bb4c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
90 additions
and
7 deletions
+90
-7
Cython/Compiler/FlowControl.py
Cython/Compiler/FlowControl.py
+2
-0
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+17
-2
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+5
-2
tests/run/moduletryexcept.pyx
tests/run/moduletryexcept.pyx
+25
-3
tests/run/tryexcept.pyx
tests/run/tryexcept.pyx
+41
-0
No files found.
Cython/Compiler/FlowControl.py
View file @
69f163fb
...
...
@@ -1098,6 +1098,8 @@ class ControlFlowAnalysis(CythonTransform):
if
clause
.
target
:
self
.
mark_assignment
(
clause
.
target
)
self
.
visit
(
clause
.
body
)
if
clause
.
is_except_as
:
self
.
flow
.
mark_deletion
(
clause
.
target
,
clause
.
target
.
entry
)
if
self
.
flow
.
block
:
self
.
flow
.
block
.
add_child
(
next_block
)
...
...
Cython/Compiler/Nodes.py
View file @
69f163fb
...
...
@@ -6033,6 +6033,7 @@ class ExceptClauseNode(Node):
# exc_value ExcValueNode used internally
# function_name string qualified name of enclosing function
# exc_vars (string * 3) local exception variables
# is_except_as bool Py3-style "except ... as xyz"
# excinfo_target is never set by the parser, but can be set by a transform
# in order to extract more extensive information about the exception as a
...
...
@@ -6042,6 +6043,7 @@ class ExceptClauseNode(Node):
exc_value
=
None
excinfo_target
=
None
is_except_as
=
False
def
analyse_declarations
(
self
,
env
):
if
self
.
target
:
...
...
@@ -6089,11 +6091,16 @@ class ExceptClauseNode(Node):
else
:
code
.
putln
(
"/*except:*/ {"
)
if
not
getattr
(
self
.
body
,
'stats'
,
True
)
and
\
self
.
excinfo_target
is
None
and
self
.
target
is
None
:
if
(
not
getattr
(
self
.
body
,
'stats'
,
True
)
and
self
.
excinfo_target
is
None
and
(
self
.
target
is
None
or
self
.
is_except_as
)):
# most simple case: no exception variable, empty body (pass)
# => reset the exception state, done
code
.
putln
(
"PyErr_Restore(0,0,0);"
)
if
self
.
is_except_as
and
self
.
target
:
# "except ... as x" deletes x after use
# target is known to be a NameNode
self
.
target
.
generate_deletion_code
(
code
)
code
.
put_goto
(
end_label
)
code
.
putln
(
"}"
)
return
...
...
@@ -6133,6 +6140,10 @@ class ExceptClauseNode(Node):
self
.
excinfo_tuple
.
generate_disposal_code
(
code
)
for
var
in
exc_vars
:
code
.
put_decref_clear
(
var
,
py_object_type
)
if
self
.
is_except_as
and
self
.
target
:
# "except ... as x" deletes x after use
# target is known to be a NameNode
self
.
target
.
generate_deletion_code
(
code
)
code
.
put_goto
(
end_label
)
if
code
.
label_used
(
code
.
break_label
):
...
...
@@ -6141,6 +6152,8 @@ class ExceptClauseNode(Node):
self
.
excinfo_tuple
.
generate_disposal_code
(
code
)
for
var
in
exc_vars
:
code
.
put_decref_clear
(
var
,
py_object_type
)
if
self
.
is_except_as
and
self
.
target
:
self
.
target
.
generate_deletion_code
(
code
)
code
.
put_goto
(
old_break_label
)
code
.
break_label
=
old_break_label
...
...
@@ -6150,6 +6163,8 @@ class ExceptClauseNode(Node):
self
.
excinfo_tuple
.
generate_disposal_code
(
code
)
for
var
in
exc_vars
:
code
.
put_decref_clear
(
var
,
py_object_type
)
if
self
.
is_except_as
and
self
.
target
:
self
.
target
.
generate_deletion_code
(
code
)
code
.
put_goto
(
old_continue_label
)
code
.
continue_label
=
old_continue_label
...
...
Cython/Compiler/Parsing.py
View file @
69f163fb
...
...
@@ -1565,6 +1565,7 @@ def p_except_clause(s):
s
.
next
()
exc_type
=
None
exc_value
=
None
is_except_as
=
False
if
s
.
sy
!=
':'
:
exc_type
=
p_test
(
s
)
# normalise into list of single exception tests
...
...
@@ -1572,7 +1573,7 @@ def p_except_clause(s):
exc_type
=
exc_type
.
args
else
:
exc_type
=
[
exc_type
]
if
s
.
sy
==
','
or
(
s
.
sy
==
'IDENT'
and
s
.
systring
==
'as'
)
:
if
s
.
sy
==
','
:
s
.
next
()
exc_value
=
p_test
(
s
)
elif
s
.
sy
==
'IDENT'
and
s
.
systring
==
'as'
:
...
...
@@ -1581,9 +1582,11 @@ def p_except_clause(s):
pos2
=
s
.
position
()
name
=
p_ident
(
s
)
exc_value
=
ExprNodes
.
NameNode
(
pos2
,
name
=
name
)
is_except_as
=
True
body
=
p_suite
(
s
)
return
Nodes
.
ExceptClauseNode
(
pos
,
pattern
=
exc_type
,
target
=
exc_value
,
body
=
body
)
pattern
=
exc_type
,
target
=
exc_value
,
body
=
body
,
is_except_as
=
is_except_as
)
def
p_include_statement
(
s
,
ctx
):
pos
=
s
.
position
()
...
...
tests/run/moduletryexcept.pyx
View file @
69f163fb
...
...
@@ -13,6 +13,11 @@ __doc__ = u"""
'ValueError'
>>> exc[3] is val
True
>>> except_as_deletes
True
>>> no_match_does_not_delete
True
"""
a
=
0
...
...
@@ -48,8 +53,9 @@ except KeyError as e:
except
IndexError
as
e
:
exc
[
0
]
=
e
except
:
exc
[
0
]
=
e
exc
[
0
]
=
'SOMETHING ELSE'
e
=
None
try
:
raise
KeyError
except
AttributeError
as
e
:
...
...
@@ -59,7 +65,23 @@ except KeyError as e:
except
IndexError
as
e
:
exc
[
1
]
=
e
except
:
exc
[
1
]
=
e
exc
[
1
]
=
'SOMETHING ELSE'
try
:
e
except
NameError
:
except_as_deletes
=
True
else
:
except_as_deletes
=
False
e
=
123
try
:
raise
TypeError
except
NameError
as
e
:
pass
except
TypeError
:
pass
no_match_does_not_delete
=
(
e
==
123
)
try
:
raise
IndexError
...
...
@@ -70,7 +92,7 @@ except KeyError as e:
except
IndexError
as
e
:
exc
[
2
]
=
e
except
:
exc
[
2
]
=
e
exc
[
2
]
=
'SOMETHING ELSE'
val
=
None
try
:
...
...
tests/run/tryexcept.pyx
View file @
69f163fb
...
...
@@ -343,6 +343,47 @@ def except_as_raise(x, a):
assert
isinstance
(
b
,
a
)
return
i
def
except_as_no_raise_does_not_touch_target
(
a
):
"""
>>> i,b = except_as_no_raise_does_not_touch_target(TypeError)
>>> i
1
>>> b
1
"""
b
=
1
try
:
i
=
1
except
a
as
b
:
i
=
2
return
i
,
b
def
except_as_raise_deletes_target
(
x
,
a
):
"""
>>> except_as_raise_deletes_target(None, TypeError)
1
1
>>> except_as_raise_deletes_target(TypeError('test'), TypeError)
Traceback (most recent call last):
UnboundLocalError: local variable 'b' referenced before assignment
>>> except_as_raise_deletes_target(ValueError('test'), TypeError)
Traceback (most recent call last):
ValueError: test
>>> except_as_raise_deletes_target(None, TypeError)
1
1
"""
b
=
1
try
:
i
=
1
if
x
:
raise
x
except
a
as
b
:
i
=
2
assert
isinstance
(
b
,
a
)
print
(
b
)
# raises NameError if except clause was executed
return
i
def
complete_except_as_no_raise
(
a
,
b
):
"""
>>> complete_except_as_no_raise(TypeError, ValueError)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment