Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
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
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
77452fc1
Commit
77452fc1
authored
Jun 01, 2012
by
Nick Coghlan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
parent
c4b78a3e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
33 additions
and
14 deletions
+33
-14
Lib/contextlib.py
Lib/contextlib.py
+13
-3
Lib/test/test_contextlib.py
Lib/test/test_contextlib.py
+18
-11
Misc/NEWS
Misc/NEWS
+2
-0
No files found.
Lib/contextlib.py
View file @
77452fc1
...
@@ -225,6 +225,17 @@ class ExitStack(object):
...
@@ -225,6 +225,17 @@ class ExitStack(object):
return
self
return
self
def
__exit__
(
self
,
*
exc_details
):
def
__exit__
(
self
,
*
exc_details
):
# We manipulate the exception state so it behaves as though
# we were actually nesting multiple with statements
frame_exc
=
sys
.
exc_info
()[
1
]
def
_fix_exception_context
(
new_exc
,
old_exc
):
while
1
:
exc_context
=
new_exc
.
__context__
if
exc_context
in
(
None
,
frame_exc
):
break
new_exc
=
exc_context
new_exc
.
__context__
=
old_exc
# Callbacks are invoked in LIFO order to match the behaviour of
# Callbacks are invoked in LIFO order to match the behaviour of
# nested context managers
# nested context managers
suppressed_exc
=
False
suppressed_exc
=
False
...
@@ -236,9 +247,8 @@ class ExitStack(object):
...
@@ -236,9 +247,8 @@ class ExitStack(object):
exc_details
=
(
None
,
None
,
None
)
exc_details
=
(
None
,
None
,
None
)
except
:
except
:
new_exc_details
=
sys
.
exc_info
()
new_exc_details
=
sys
.
exc_info
()
if
exc_details
!=
(
None
,
None
,
None
):
# simulate the stack of exceptions by setting the context
# simulate the stack of exceptions by setting the context
_fix_exception_context
(
new_exc_details
[
1
],
exc_details
[
1
])
new_exc_details
[
1
].
__context__
=
exc_details
[
1
]
if
not
self
.
_exit_callbacks
:
if
not
self
.
_exit_callbacks
:
raise
raise
exc_details
=
new_exc_details
exc_details
=
new_exc_details
...
...
Lib/test/test_contextlib.py
View file @
77452fc1
...
@@ -505,6 +505,18 @@ class TestExitStack(unittest.TestCase):
...
@@ -505,6 +505,18 @@ class TestExitStack(unittest.TestCase):
def
__exit__
(
self
,
*
exc_details
):
def
__exit__
(
self
,
*
exc_details
):
raise
self
.
exc
raise
self
.
exc
class
RaiseExcWithContext
:
def
__init__
(
self
,
outer
,
inner
):
self
.
outer
=
outer
self
.
inner
=
inner
def
__enter__
(
self
):
return
self
def
__exit__
(
self
,
*
exc_details
):
try
:
raise
self
.
inner
except
:
raise
self
.
outer
class
SuppressExc
:
class
SuppressExc
:
def
__enter__
(
self
):
def
__enter__
(
self
):
return
self
return
self
...
@@ -514,11 +526,10 @@ class TestExitStack(unittest.TestCase):
...
@@ -514,11 +526,10 @@ class TestExitStack(unittest.TestCase):
try
:
try
:
with
RaiseExc
(
IndexError
):
with
RaiseExc
(
IndexError
):
with
RaiseExc
(
KeyError
):
with
RaiseExcWithContext
(
KeyError
,
AttributeError
):
with
RaiseExc
(
AttributeError
):
with
SuppressExc
():
with
SuppressExc
():
with
RaiseExc
(
ValueError
):
with
RaiseExc
(
ValueError
):
1
/
0
1
/
0
except
IndexError
as
exc
:
except
IndexError
as
exc
:
self
.
assertIsInstance
(
exc
.
__context__
,
KeyError
)
self
.
assertIsInstance
(
exc
.
__context__
,
KeyError
)
self
.
assertIsInstance
(
exc
.
__context__
.
__context__
,
AttributeError
)
self
.
assertIsInstance
(
exc
.
__context__
.
__context__
,
AttributeError
)
...
@@ -553,12 +564,8 @@ class TestExitStack(unittest.TestCase):
...
@@ -553,12 +564,8 @@ class TestExitStack(unittest.TestCase):
except
IndexError
as
exc
:
except
IndexError
as
exc
:
self
.
assertIsInstance
(
exc
.
__context__
,
KeyError
)
self
.
assertIsInstance
(
exc
.
__context__
,
KeyError
)
self
.
assertIsInstance
(
exc
.
__context__
.
__context__
,
AttributeError
)
self
.
assertIsInstance
(
exc
.
__context__
.
__context__
,
AttributeError
)
# Inner exceptions were suppressed, but the with statement
# Inner exceptions were suppressed
# cleanup code adds the one from the body back in as the
self
.
assertIsNone
(
exc
.
__context__
.
__context__
.
__context__
)
# context of the exception raised by the outer callbacks
# See http://bugs.python.org/issue14969
suite_exc
=
exc
.
__context__
.
__context__
.
__context__
self
.
assertIsInstance
(
suite_exc
,
ZeroDivisionError
)
else
:
else
:
self
.
fail
(
"Expected IndexError, but no exception was raised"
)
self
.
fail
(
"Expected IndexError, but no exception was raised"
)
# Check the inner exceptions
# Check the inner exceptions
...
...
Misc/NEWS
View file @
77452fc1
...
@@ -10,6 +10,8 @@ What's New in Python 3.3.0 Beta 1?
...
@@ -10,6 +10,8 @@ What's New in Python 3.3.0 Beta 1?
Library
Library
-------
-------
- Issue #14969: Better handling of exception chaining in contextlib.ExitStack
- Issue #14962: Update text coloring in IDLE shell window after changing
- Issue #14962: Update text coloring in IDLE shell window after changing
options. Patch by Roger Serwy.
options. Patch by Roger Serwy.
...
...
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