]> granicus.if.org Git - python/commitdiff
Merged revisions 70965 via svnmerge from
authorBrett Cannon <bcannon@gmail.com>
Wed, 1 Apr 2009 18:13:07 +0000 (18:13 +0000)
committerBrett Cannon <bcannon@gmail.com>
Wed, 1 Apr 2009 18:13:07 +0000 (18:13 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r70965 | brett.cannon | 2009-04-01 11:03:59 -0700 (Wed, 01 Apr 2009) | 5 lines

  _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
Misc/NEWS
Python/_warnings.c

index 4b6feb37cb9102c6e86baa5de8be555a75a8c67e..49f3d3a7b776c1f15c8b158c9c9f566ba268ae6b 100644 (file)
@@ -423,6 +423,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, "<test>", 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, "<test>", 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, "<test>", 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'
index 524a79c8c7b0d15d848569effed9186535a1134f..2ecd85b0dead8351ea1b6571a530ecc51071d255 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@ What's New in Python 3.1 alpha 2?
 Core and Builtins
 -----------------
 
+- Issue #1665206: Remove the last eager import in _warnings.c and make it lazy.
+
 - Fix a segfault when running test_exceptions with coverage, caused by
   insufficient checks in accessors of Exception.__context__.
 
index 43e6b802bffdaaa371b32923ee102f4494351a80..da52e357c3eeee649c0239c105e5cbbf9ec377e2 100644 (file)
@@ -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 _PyUnicode_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 _PyUnicode_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)
 {
@@ -874,7 +888,7 @@ static struct PyModuleDef warningsmodule = {
 PyMODINIT_FUNC
 _PyWarnings_Init(void)
 {
-    PyObject *m, *default_action;
+    PyObject *m;
 
     m = PyModule_Create(&warningsmodule);
     if (m == NULL)
@@ -894,10 +908,10 @@ _PyWarnings_Init(void)
     if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
         return NULL;
 
-    default_action = PyUnicode_InternFromString("default");
-    if (default_action == NULL)
+    _default_action = PyUnicode_FromString("default");
+    if (_default_action == NULL)
         return NULL;
-    if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0)
+    if (PyModule_AddObject(m, "default_action", _default_action) < 0)
         return NULL;
     return m;
 }