From 15ba4dae5a2b0bd2f06dff586cb469e7b5325209 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 1 Apr 2009 18:03:59 +0000 Subject: _warnings was importing itself to get an attribute. That's bad if warnings gets called in a thread that was spawned by an import itself. Last part to close #1665206. --- Lib/test/test_warnings.py | 35 +++++++++++++++++++++++++++++++++++ Misc/NEWS | 2 ++ Python/_warnings.c | 46 ++++++++++++++++++++++++++++++---------------- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py index e90a2c2..bc177ad 100644 --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -413,6 +413,41 @@ class _WarningsTests(BaseTest): finally: self.module.onceregistry = original_registry + def test_default_action(self): + # Replacing or removing defaultaction should be okay. + message = UserWarning("defaultaction test") + original = self.module.defaultaction + try: + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + self.module.resetwarnings() + registry = {} + self.module.warn_explicit(message, UserWarning, "", 42, + registry=registry) + self.assertEqual(w[-1].message, message) + self.assertEqual(len(w), 1) + self.assertEqual(len(registry), 1) + del w[:] + # Test removal. + del self.module.defaultaction + __warningregistry__ = {} + registry = {} + self.module.warn_explicit(message, UserWarning, "", 43, + registry=registry) + self.assertEqual(w[-1].message, message) + self.assertEqual(len(w), 1) + self.assertEqual(len(registry), 1) + del w[:] + # Test setting. + self.module.defaultaction = "ignore" + __warningregistry__ = {} + registry = {} + self.module.warn_explicit(message, UserWarning, "", 44, + registry=registry) + self.assertEqual(len(w), 0) + finally: + self.module.defaultaction = original + def test_showwarning_missing(self): # Test that showwarning() missing is okay. text = 'del showwarning test' diff --git a/Misc/NEWS b/Misc/NEWS index 3d2b492..f5e280c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,8 @@ What's New in Python 2.7 alpha 1 Core and Builtins ----------------- +- Issue #1665206: Remove the last eager import in _warnings.c and make it lazy. + - Issue #4865: On MacOSX /Library/Python/2.7/site-packages is added to the end sys.path, for compatibility with the system install of Python. diff --git a/Python/_warnings.c b/Python/_warnings.c index 8ddfc88..1a7c2d5 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -2,7 +2,6 @@ #include "frameobject.h" #define MODULE_NAME "_warnings" -#define DEFAULT_ACTION_NAME "default_action" PyDoc_STRVAR(warnings__doc__, MODULE_NAME " provides basic warning filtering support.\n" @@ -12,6 +11,7 @@ MODULE_NAME " provides basic warning filtering support.\n" get_warnings_attr() will reset these variables accordingly. */ static PyObject *_filters; /* List */ static PyObject *_once_registry; /* Dict */ +static PyObject *_default_action; /* String */ static int @@ -78,12 +78,31 @@ get_once_registry(void) } +static PyObject * +get_default_action(void) +{ + PyObject *default_action; + + default_action = get_warnings_attr("defaultaction"); + if (default_action == NULL) { + if (PyErr_Occurred()) { + return NULL; + } + return _default_action; + } + + Py_DECREF(_default_action); + _default_action = default_action; + return default_action; +} + + /* The item is a borrowed reference. */ static const char * get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, PyObject *module, PyObject **item) { - PyObject *action, *m, *d; + PyObject *action; Py_ssize_t i; PyObject *warnings_filters; @@ -135,22 +154,17 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, return PyString_AsString(action); } - m = PyImport_ImportModule(MODULE_NAME); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); - Py_DECREF(m); - if (d == NULL) - return NULL; - action = PyDict_GetItemString(d, DEFAULT_ACTION_NAME); - if (action != NULL) + action = get_default_action(); + if (action != NULL) { return PyString_AsString(action); + } PyErr_SetString(PyExc_ValueError, - MODULE_NAME "." DEFAULT_ACTION_NAME " not found"); + MODULE_NAME ".defaultaction not found"); return NULL; } + static int already_warned(PyObject *registry, PyObject *key, int should_set) { @@ -854,7 +868,7 @@ init_filters(void) PyMODINIT_FUNC _PyWarnings_Init(void) { - PyObject *m, *default_action; + PyObject *m; m = Py_InitModule3(MODULE_NAME, warnings_functions, warnings__doc__); if (m == NULL) @@ -874,9 +888,9 @@ _PyWarnings_Init(void) if (PyModule_AddObject(m, "once_registry", _once_registry) < 0) return; - default_action = PyString_InternFromString("default"); - if (default_action == NULL) + _default_action = PyString_FromString("default"); + if (_default_action == NULL) return; - if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0) + if (PyModule_AddObject(m, "default_action", _default_action) < 0) return; } -- cgit v0.12