blob: fa286122ced87a4c67253419ebb56851a1b9ccc6 [file] [log] [blame] [edit]
from __future__ import with_statement
import sys
__all__ = ['nested', 'catch_warnings', 'examine_warnings']
try:
from contextlib import nested
except ImportError:
from contextlib import contextmanager
@contextmanager
def nested(*managers):
exits = []
vars = []
exc = (None, None, None)
try:
for mgr in managers:
exit = mgr.__exit__
enter = mgr.__enter__
vars.append(enter())
exits.append(exit)
yield vars
except:
exc = sys.exc_info()
finally:
while exits:
exit = exits.pop()
try:
if exit(*exc):
exc = (None, None, None)
except:
exc = sys.exc_info()
if exc != (None, None, None):
raise exc[1]
# copied from Python 2.6
try:
from warnings import catch_warnings
except ImportError:
class catch_warnings(object):
def __init__(self, record=False, module=None):
self._record = record
self._module = sys.modules['warnings']
self._entered = False
def __repr__(self):
args = []
if self._record:
args.append("record=True")
name = type(self).__name__
return "%s(%s)" % (name, ", ".join(args))
def __enter__(self):
if self._entered:
raise RuntimeError("Cannot enter %r twice" % self)
self._entered = True
self._filters = self._module.filters
self._module.filters = self._filters[:]
self._showwarning = self._module.showwarning
if self._record:
log = []
def showwarning(*args, **kwargs):
log.append(WarningMessage(*args, **kwargs))
self._module.showwarning = showwarning
return log
else:
return None
def __exit__(self, *exc_info):
if not self._entered:
raise RuntimeError("Cannot exit %r without entering first" % self)
self._module.filters = self._filters
self._module.showwarning = self._showwarning
class WarningMessage(object):
_WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
"line")
def __init__(self, message, category, filename, lineno, file=None,
line=None):
local_values = locals()
for attr in self._WARNING_DETAILS:
setattr(self, attr, local_values[attr])
self._category_name = None
if category.__name__:
self._category_name = category.__name__
def examine_warnings(func):
def wrapper():
with catch_warnings(record=True) as ws:
func(ws)
return wrapper