Skip to content

Commit e974689

Browse files
committed
Re-implement the 'warnings' module in C. This allows for usage of the
'warnings' code in places where it was previously not possible (e.g., the parser). It could also potentially lead to a speed-up in interpreter start-up if the C version of the code (_warnings) is imported over the use of the Python version in key places. Closes issue #1631171.
1 parent e6c0303 commit e974689

File tree

18 files changed

+1459
-379
lines changed

18 files changed

+1459
-379
lines changed

Doc/library/warnings.rst

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,20 +211,28 @@ Available Functions
211211
is using :exc:`DeprecationWarning` as default warning class.
212212

213213

214-
.. function:: showwarning(message, category, filename, lineno[, file])
214+
.. function:: showwarning(message, category, filename, lineno[, file[, line]])
215215

216216
Write a warning to a file. The default implementation calls
217-
``formatwarning(message, category, filename, lineno)`` and writes the resulting
218-
string to *file*, which defaults to ``sys.stderr``. You may replace this
219-
function with an alternative implementation by assigning to
217+
``formatwarning(message, category, filename, lineno, line)`` and writes the
218+
resulting string to *file*, which defaults to ``sys.stderr``. You may replace
219+
this function with an alternative implementation by assigning to
220220
``warnings.showwarning``.
221221

222+
..versionchanged:: 2.6
223+
Added the `line` argument.
222224

223-
.. function:: formatwarning(message, category, filename, lineno)
225+
226+
227+
228+
.. function:: formatwarning(message, category, filename, lineno[, line])
224229

225230
Format a warning the standard way. This returns a string which may contain
226231
embedded newlines and ends in a newline.
227232

233+
..versionchanged:: 2.6
234+
Added the `line` argument.
235+
228236

229237
.. function:: filterwarnings(action[, message[, category[, module[, lineno[, append]]]]])
230238

Include/Python.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
#include "iterobject.h"
111111
#include "genobject.h"
112112
#include "descrobject.h"
113+
#include "warnings.h"
113114
#include "weakrefobject.h"
114115

115116
#include "codecs.h"

Include/pyerrors.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -227,16 +227,6 @@ PyAPI_FUNC(PyObject *) PyErr_NewException(char *name, PyObject *base,
227227
PyObject *dict);
228228
PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *);
229229

230-
/* Issue a warning or exception */
231-
PyAPI_FUNC(int) PyErr_WarnEx(PyObject *category, const char *msg,
232-
Py_ssize_t stack_level);
233-
PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *,
234-
const char *, int,
235-
const char *, PyObject *);
236-
/* PyErr_Warn is only for backwards compatability and will be removed.
237-
Use PyErr_WarnEx instead. */
238-
#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1)
239-
240230
/* In sigcheck.c or signalmodule.c */
241231
PyAPI_FUNC(int) PyErr_CheckSignals(void);
242232
PyAPI_FUNC(void) PyErr_SetInterrupt(void);

Include/sysmodule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ PyAPI_DATA(int) _PySys_CheckInterval;
2323

2424
PyAPI_FUNC(void) PySys_ResetWarnOptions(void);
2525
PyAPI_FUNC(void) PySys_AddWarnOption(char *);
26+
PyAPI_FUNC(int) PySys_HasWarnOptions(void);
2627

2728
#ifdef __cplusplus
2829
}

Include/traceback.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef struct _traceback {
1919

2020
PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *);
2121
PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *);
22+
PyAPI_FUNC(int) Py_DisplaySourceLine(PyObject *, const char *, int);
2223

2324
/* Reveal traceback type so we can typecheck traceback objects */
2425
PyAPI_DATA(PyTypeObject) PyTraceBack_Type;

Include/warnings.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef Py_WARNINGS_H
2+
#define Py_WARNINGS_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
PyAPI_FUNC(void) _PyWarnings_Init(void);
8+
9+
PyAPI_FUNC(int) PyErr_WarnEx(PyObject *, const char *, Py_ssize_t);
10+
PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *, const char *, int,
11+
const char *, PyObject *);
12+
13+
/* DEPRECATED: Use PyErr_WarnEx() instead. */
14+
#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1)
15+
16+
#ifdef __cplusplus
17+
}
18+
#endif
19+
#endif /* !Py_WARNINGS_H */

Lib/test/test_support.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -363,14 +363,26 @@ def __init__(self):
363363
self.filename = None
364364
self.lineno = None
365365

366-
def _showwarning(self, message, category, filename, lineno, file=None):
366+
def _showwarning(self, message, category, filename, lineno, file=None,
367+
line=None):
367368
self.message = message
368369
self.category = category
369370
self.filename = filename
370371
self.lineno = lineno
372+
self.line = line
373+
374+
def reset(self):
375+
self._showwarning(*((None,)*6))
376+
377+
def __str__(self):
378+
return ("{message : %r, category : %r, filename : %r, lineno : %s, "
379+
"line : %r}" % (self.message,
380+
self.category.__name__ if self.category else None,
381+
self.filename, self.lineno, self.line))
382+
371383

372384
@contextlib.contextmanager
373-
def catch_warning():
385+
def catch_warning(module=warnings):
374386
"""
375387
Guard the warnings filter from being permanently changed and record the
376388
data of the last warning that has been issued.
@@ -381,15 +393,15 @@ def catch_warning():
381393
warnings.warn("foo")
382394
assert str(w.message) == "foo"
383395
"""
384-
warning = WarningMessage()
385-
original_filters = warnings.filters[:]
386-
original_showwarning = warnings.showwarning
387-
warnings.showwarning = warning._showwarning
396+
warning_obj = WarningMessage()
397+
original_filters = module.filters[:]
398+
original_showwarning = module.showwarning
399+
module.showwarning = warning_obj._showwarning
388400
try:
389-
yield warning
401+
yield warning_obj
390402
finally:
391-
warnings.showwarning = original_showwarning
392-
warnings.filters = original_filters
403+
module.showwarning = original_showwarning
404+
module.filters = original_filters
393405

394406
class EnvironmentVarGuard(object):
395407

0 commit comments

Comments
 (0)