| Index: Lib/warnings.py |
| =================================================================== |
| --- Lib/warnings.py (revision 65979) |
| +++ Lib/warnings.py (working copy) |
| @@ -272,7 +272,8 @@ |
| fxn_code = showwarning.__func__.func_code |
| if fxn_code: |
| args = fxn_code.co_varnames[:fxn_code.co_argcount] |
| - if 'line' not in args: |
| + CO_VARARGS = 0x4 |
| + if 'line' not in args and not fxn_code.co_flags & CO_VARARGS: |
| showwarning_msg = ("functions overriding warnings.showwarning() " |
| "must support the 'line' argument") |
| if message == showwarning_msg: |
| @@ -283,6 +284,82 @@ |
| showwarning(message, category, filename, lineno) |
| +class WarningMessage(object): |
|
Benjamin
2008/08/23 01:46:36
What happened to the idea of making this a namedtu
brett.cannon
2008/08/23 02:19:54
On 2008/08/23 01:46:36, Benjamin wrote:
> What hap
|
| + |
| + """Holds the result of a single showwarning() call.""" |
| + |
| + _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 = category.__name__ if category else None |
| + |
| + def __str__(self): |
| + return ("{message : %r, category : %r, filename : %r, lineno : %s, " |
| + "line : %r}" % (self.message, self._category_name, |
| + self.filename, self.lineno, self.line)) |
| + |
| + |
| +class WarningsRecorder(list): |
| + |
| + """Record the result of various showwarning() calls.""" |
| + |
| + # Explicitly stated arguments so as to not trigger DeprecationWarning |
| + # about adding 'line'. |
| + def showwarning(self, *args, **kwargs): |
| + self.append(WarningMessage(*args, **kwargs)) |
| + |
| + def __getattr__(self, attr): |
| + return getattr(self[-1], attr) |
| + |
| + def reset(self): |
| + while True: |
|
Benjamin
2008/08/23 01:46:36
Can't this be "del self[:]"?
brett.cannon
2008/08/23 02:19:54
On 2008/08/23 01:46:36, Benjamin wrote:
> Can't th
|
| + try: |
| + self.pop() |
| + except IndexError: |
| + break |
| + |
| + |
| +class catch_warnings(object): |
|
Benjamin
2008/08/23 01:46:36
Shouldn't this be called "catchwarnings"?
Benjamin
2008/08/23 01:46:36
Can't this be a simple generator contextmanager?
brett.cannon
2008/08/23 02:19:54
On 2008/08/23 01:46:36, Benjamin wrote:
> Shouldn'
brett.cannon
2008/08/23 02:19:54
On 2008/08/23 01:46:36, Benjamin wrote:
> Can't th
|
| + |
| + """Guard the warnings filter from being permanently changed and optionally |
| + record the details of any warnings that are issued. |
| + |
| + Context manager returns an instance of warnings.WarningRecorder which is a |
| + list of WarningMessage instances. Attributes on WarningRecorder are |
| + redirected to the last created WarningMessage instance. |
| + |
| + """ |
| + |
| + def __init__(self, record=False, module=None): |
| + """Specify whether to record warnings and if an alternative module |
| + should be used other than sys.modules['warnings']. |
| + |
| + For compatibility with Python 3.0, please consider all arguments to be |
| + keyword-only. |
| + |
| + """ |
| + self._recorder = WarningsRecorder() if record else None |
| + self._module = sys.modules['warnings'] if module is None else module |
| + |
| + def __enter__(self): |
| + self._filters = self._module.filters |
| + self._module.filters = self._filters[:] |
| + self._showwarning = self._module.showwarning |
| + if self._recorder is not None: |
| + self._recorder.reset() # In case the instance is being reused. |
| + self._module.showwarning = self._recorder.showwarning |
| + return self._recorder |
| + |
| + def __exit__(self, *exc_info): |
| + self._module.filters = self._filters |
| + self._module.showwarning = self._showwarning |
| + |
| + |
| # filters contains a sequence of filter 5-tuples |
| # The components of the 5-tuple are: |
| # - an action: error, ignore, always, default, module, or once |