|
1 from __future__ import with_statement |
|
2 |
|
3 import sys |
|
4 |
|
5 __all__ = ['nested', 'catch_warnings', 'examine_warnings'] |
|
6 |
|
7 |
|
8 try: |
|
9 from contextlib import nested |
|
10 except ImportError: |
|
11 from contextlib import contextmanager |
|
12 @contextmanager |
|
13 def nested(*managers): |
|
14 exits = [] |
|
15 vars = [] |
|
16 exc = (None, None, None) |
|
17 try: |
|
18 for mgr in managers: |
|
19 exit = mgr.__exit__ |
|
20 enter = mgr.__enter__ |
|
21 vars.append(enter()) |
|
22 exits.append(exit) |
|
23 yield vars |
|
24 except: |
|
25 exc = sys.exc_info() |
|
26 finally: |
|
27 while exits: |
|
28 exit = exits.pop() |
|
29 try: |
|
30 if exit(*exc): |
|
31 exc = (None, None, None) |
|
32 except: |
|
33 exc = sys.exc_info() |
|
34 if exc != (None, None, None): |
|
35 raise exc[1] |
|
36 |
|
37 # copied from Python 2.6 |
|
38 try: |
|
39 from warnings import catch_warnings |
|
40 except ImportError: |
|
41 class catch_warnings(object): |
|
42 def __init__(self, record=False, module=None): |
|
43 self._record = record |
|
44 self._module = sys.modules['warnings'] |
|
45 self._entered = False |
|
46 |
|
47 def __repr__(self): |
|
48 args = [] |
|
49 if self._record: |
|
50 args.append("record=True") |
|
51 name = type(self).__name__ |
|
52 return "%s(%s)" % (name, ", ".join(args)) |
|
53 |
|
54 def __enter__(self): |
|
55 if self._entered: |
|
56 raise RuntimeError("Cannot enter %r twice" % self) |
|
57 self._entered = True |
|
58 self._filters = self._module.filters |
|
59 self._module.filters = self._filters[:] |
|
60 self._showwarning = self._module.showwarning |
|
61 if self._record: |
|
62 log = [] |
|
63 def showwarning(*args, **kwargs): |
|
64 log.append(WarningMessage(*args, **kwargs)) |
|
65 self._module.showwarning = showwarning |
|
66 return log |
|
67 else: |
|
68 return None |
|
69 |
|
70 def __exit__(self, *exc_info): |
|
71 if not self._entered: |
|
72 raise RuntimeError("Cannot exit %r without entering first" % self) |
|
73 self._module.filters = self._filters |
|
74 self._module.showwarning = self._showwarning |
|
75 |
|
76 class WarningMessage(object): |
|
77 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", |
|
78 "line") |
|
79 def __init__(self, message, category, filename, lineno, file=None, |
|
80 line=None): |
|
81 local_values = locals() |
|
82 for attr in self._WARNING_DETAILS: |
|
83 setattr(self, attr, local_values[attr]) |
|
84 self._category_name = None |
|
85 if category.__name__: |
|
86 self._category_name = category.__name__ |
|
87 |
|
88 |
|
89 def examine_warnings(func): |
|
90 def wrapper(): |
|
91 with catch_warnings(record=True) as ws: |
|
92 func(ws) |
|
93 return wrapper |