| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 1 | #include "Python.h" | 
 | 2 | #include "frameobject.h" | 
 | 3 |  | 
 | 4 | #define MODULE_NAME "_warnings" | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 5 |  | 
 | 6 | PyDoc_STRVAR(warnings__doc__, | 
 | 7 | MODULE_NAME " provides basic warning filtering support.\n" | 
 | 8 | "It is a helper module to speed up interpreter start-up."); | 
 | 9 |  | 
 | 10 | /* Both 'filters' and 'onceregistry' can be set in warnings.py; | 
 | 11 |    get_warnings_attr() will reset these variables accordingly. */ | 
 | 12 | static PyObject *_filters;  /* List */ | 
 | 13 | static PyObject *_once_registry;  /* Dict */ | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 14 | static PyObject *_default_action; /* String */ | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 15 |  | 
 | 16 |  | 
 | 17 | static int | 
 | 18 | check_matched(PyObject *obj, PyObject *arg) | 
 | 19 | { | 
 | 20 |     PyObject *result; | 
| Martin v. Löwis | afe55bb | 2011-10-09 10:38:36 +0200 | [diff] [blame] | 21 |     _Py_identifier(match); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 22 |     int rc; | 
 | 23 |  | 
 | 24 |     if (obj == Py_None) | 
 | 25 |         return 1; | 
| Martin v. Löwis | afe55bb | 2011-10-09 10:38:36 +0200 | [diff] [blame] | 26 |     result = _PyObject_CallMethodId(obj, &PyId_match, "O", arg); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 27 |     if (result == NULL) | 
 | 28 |         return -1; | 
 | 29 |  | 
 | 30 |     rc = PyObject_IsTrue(result); | 
 | 31 |     Py_DECREF(result); | 
 | 32 |     return rc; | 
 | 33 | } | 
 | 34 |  | 
 | 35 | /* | 
 | 36 |    Returns a new reference. | 
 | 37 |    A NULL return value can mean false or an error. | 
 | 38 | */ | 
 | 39 | static PyObject * | 
 | 40 | get_warnings_attr(const char *attr) | 
 | 41 | { | 
 | 42 |     static PyObject *warnings_str = NULL; | 
 | 43 |     PyObject *all_modules; | 
 | 44 |     PyObject *warnings_module; | 
 | 45 |     int result; | 
 | 46 |  | 
 | 47 |     if (warnings_str == NULL) { | 
 | 48 |         warnings_str = PyUnicode_InternFromString("warnings"); | 
 | 49 |         if (warnings_str == NULL) | 
 | 50 |             return NULL; | 
 | 51 |     } | 
 | 52 |  | 
 | 53 |     all_modules = PyImport_GetModuleDict(); | 
 | 54 |     result = PyDict_Contains(all_modules, warnings_str); | 
 | 55 |     if (result == -1 || result == 0) | 
 | 56 |         return NULL; | 
 | 57 |  | 
 | 58 |     warnings_module = PyDict_GetItem(all_modules, warnings_str); | 
 | 59 |     if (!PyObject_HasAttrString(warnings_module, attr)) | 
 | 60 |             return NULL; | 
 | 61 |     return PyObject_GetAttrString(warnings_module, attr); | 
 | 62 | } | 
 | 63 |  | 
 | 64 |  | 
| Neal Norwitz | 32dde22 | 2008-04-15 06:43:13 +0000 | [diff] [blame] | 65 | static PyObject * | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 66 | get_once_registry(void) | 
 | 67 | { | 
 | 68 |     PyObject *registry; | 
 | 69 |  | 
 | 70 |     registry = get_warnings_attr("onceregistry"); | 
 | 71 |     if (registry == NULL) { | 
 | 72 |         if (PyErr_Occurred()) | 
 | 73 |             return NULL; | 
 | 74 |         return _once_registry; | 
 | 75 |     } | 
 | 76 |     Py_DECREF(_once_registry); | 
 | 77 |     _once_registry = registry; | 
 | 78 |     return registry; | 
 | 79 | } | 
 | 80 |  | 
 | 81 |  | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 82 | static PyObject * | 
 | 83 | get_default_action(void) | 
 | 84 | { | 
 | 85 |     PyObject *default_action; | 
 | 86 |  | 
 | 87 |     default_action = get_warnings_attr("defaultaction"); | 
 | 88 |     if (default_action == NULL) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 89 |         if (PyErr_Occurred()) { | 
 | 90 |             return NULL; | 
 | 91 |         } | 
 | 92 |         return _default_action; | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 93 |     } | 
 | 94 |  | 
 | 95 |     Py_DECREF(_default_action); | 
 | 96 |     _default_action = default_action; | 
 | 97 |     return default_action; | 
 | 98 | } | 
 | 99 |  | 
 | 100 |  | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 101 | /* The item is a borrowed reference. */ | 
 | 102 | static const char * | 
 | 103 | get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, | 
 | 104 |            PyObject *module, PyObject **item) | 
 | 105 | { | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 106 |     PyObject *action; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 107 |     Py_ssize_t i; | 
 | 108 |     PyObject *warnings_filters; | 
 | 109 |  | 
 | 110 |     warnings_filters = get_warnings_attr("filters"); | 
 | 111 |     if (warnings_filters == NULL) { | 
 | 112 |         if (PyErr_Occurred()) | 
 | 113 |             return NULL; | 
 | 114 |     } | 
 | 115 |     else { | 
 | 116 |         Py_DECREF(_filters); | 
 | 117 |         _filters = warnings_filters; | 
 | 118 |     } | 
 | 119 |  | 
| Victor Stinner | 7d79b8b | 2010-05-19 20:40:50 +0000 | [diff] [blame] | 120 |     if (_filters == NULL || !PyList_Check(_filters)) { | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 121 |         PyErr_SetString(PyExc_ValueError, | 
 | 122 |                         MODULE_NAME ".filters must be a list"); | 
 | 123 |         return NULL; | 
 | 124 |     } | 
 | 125 |  | 
 | 126 |     /* _filters could change while we are iterating over it. */ | 
 | 127 |     for (i = 0; i < PyList_GET_SIZE(_filters); i++) { | 
 | 128 |         PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj; | 
 | 129 |         Py_ssize_t ln; | 
 | 130 |         int is_subclass, good_msg, good_mod; | 
 | 131 |  | 
 | 132 |         tmp_item = *item = PyList_GET_ITEM(_filters, i); | 
 | 133 |         if (PyTuple_Size(tmp_item) != 5) { | 
 | 134 |             PyErr_Format(PyExc_ValueError, | 
 | 135 |                          MODULE_NAME ".filters item %zd isn't a 5-tuple", i); | 
 | 136 |             return NULL; | 
 | 137 |         } | 
 | 138 |  | 
 | 139 |         /* Python code: action, msg, cat, mod, ln = item */ | 
 | 140 |         action = PyTuple_GET_ITEM(tmp_item, 0); | 
 | 141 |         msg = PyTuple_GET_ITEM(tmp_item, 1); | 
 | 142 |         cat = PyTuple_GET_ITEM(tmp_item, 2); | 
 | 143 |         mod = PyTuple_GET_ITEM(tmp_item, 3); | 
 | 144 |         ln_obj = PyTuple_GET_ITEM(tmp_item, 4); | 
 | 145 |  | 
 | 146 |         good_msg = check_matched(msg, text); | 
 | 147 |         good_mod = check_matched(mod, module); | 
 | 148 |         is_subclass = PyObject_IsSubclass(category, cat); | 
 | 149 |         ln = PyLong_AsSsize_t(ln_obj); | 
 | 150 |         if (good_msg == -1 || good_mod == -1 || is_subclass == -1 || | 
 | 151 |             (ln == -1 && PyErr_Occurred())) | 
 | 152 |             return NULL; | 
 | 153 |  | 
 | 154 |         if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) | 
| Marc-André Lemburg | 4cc0f24 | 2008-08-07 18:54:33 +0000 | [diff] [blame] | 155 |             return _PyUnicode_AsString(action); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 156 |     } | 
 | 157 |  | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 158 |     action = get_default_action(); | 
 | 159 |     if (action != NULL) { | 
| Marc-André Lemburg | 4cc0f24 | 2008-08-07 18:54:33 +0000 | [diff] [blame] | 160 |         return _PyUnicode_AsString(action); | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 161 |     } | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 162 |  | 
 | 163 |     PyErr_SetString(PyExc_ValueError, | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 164 |                     MODULE_NAME ".defaultaction not found"); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 165 |     return NULL; | 
 | 166 | } | 
 | 167 |  | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 168 |  | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 169 | static int | 
 | 170 | already_warned(PyObject *registry, PyObject *key, int should_set) | 
 | 171 | { | 
 | 172 |     PyObject *already_warned; | 
 | 173 |  | 
 | 174 |     if (key == NULL) | 
 | 175 |         return -1; | 
 | 176 |  | 
 | 177 |     already_warned = PyDict_GetItem(registry, key); | 
 | 178 |     if (already_warned != NULL) { | 
 | 179 |         int rc = PyObject_IsTrue(already_warned); | 
 | 180 |         if (rc != 0) | 
 | 181 |             return rc; | 
 | 182 |     } | 
 | 183 |  | 
 | 184 |     /* This warning wasn't found in the registry, set it. */ | 
 | 185 |     if (should_set) | 
 | 186 |         return PyDict_SetItem(registry, key, Py_True); | 
 | 187 |     return 0; | 
 | 188 | } | 
 | 189 |  | 
 | 190 | /* New reference. */ | 
 | 191 | static PyObject * | 
 | 192 | normalize_module(PyObject *filename) | 
 | 193 | { | 
 | 194 |     PyObject *module; | 
 | 195 |     const char *mod_str; | 
 | 196 |     Py_ssize_t len; | 
 | 197 |  | 
 | 198 |     int rc = PyObject_IsTrue(filename); | 
 | 199 |     if (rc == -1) | 
 | 200 |         return NULL; | 
 | 201 |     else if (rc == 0) | 
 | 202 |         return PyUnicode_FromString("<unknown>"); | 
 | 203 |  | 
| Marc-André Lemburg | 4cc0f24 | 2008-08-07 18:54:33 +0000 | [diff] [blame] | 204 |     mod_str = _PyUnicode_AsString(filename); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 205 |     if (mod_str == NULL) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 206 |             return NULL; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 207 |     len = PyUnicode_GetSize(filename); | 
 | 208 |     if (len < 0) | 
 | 209 |         return NULL; | 
 | 210 |     if (len >= 3 && | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 211 |         strncmp(mod_str + (len - 3), ".py", 3) == 0) { | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 212 |         module = PyUnicode_FromStringAndSize(mod_str, len-3); | 
 | 213 |     } | 
 | 214 |     else { | 
 | 215 |         module = filename; | 
 | 216 |         Py_INCREF(module); | 
 | 217 |     } | 
 | 218 |     return module; | 
 | 219 | } | 
 | 220 |  | 
 | 221 | static int | 
 | 222 | update_registry(PyObject *registry, PyObject *text, PyObject *category, | 
 | 223 |                 int add_zero) | 
 | 224 | { | 
 | 225 |     PyObject *altkey, *zero = NULL; | 
 | 226 |     int rc; | 
 | 227 |  | 
 | 228 |     if (add_zero) { | 
 | 229 |         zero = PyLong_FromLong(0); | 
 | 230 |         if (zero == NULL) | 
 | 231 |             return -1; | 
 | 232 |         altkey = PyTuple_Pack(3, text, category, zero); | 
 | 233 |     } | 
 | 234 |     else | 
 | 235 |         altkey = PyTuple_Pack(2, text, category); | 
 | 236 |  | 
 | 237 |     rc = already_warned(registry, altkey, 1); | 
 | 238 |     Py_XDECREF(zero); | 
 | 239 |     Py_XDECREF(altkey); | 
 | 240 |     return rc; | 
 | 241 | } | 
 | 242 |  | 
 | 243 | static void | 
 | 244 | show_warning(PyObject *filename, int lineno, PyObject *text, PyObject | 
 | 245 |                 *category, PyObject *sourceline) | 
 | 246 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 247 |     PyObject *f_stderr; | 
 | 248 |     PyObject *name; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 249 |     char lineno_str[128]; | 
| Martin v. Löwis | 1ee1b6f | 2011-10-10 18:11:30 +0200 | [diff] [blame^] | 250 |     _Py_identifier(__name__); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 251 |  | 
 | 252 |     PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno); | 
 | 253 |  | 
| Martin v. Löwis | 1ee1b6f | 2011-10-10 18:11:30 +0200 | [diff] [blame^] | 254 |     name = _PyObject_GetAttrId(category, &PyId___name__); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 255 |     if (name == NULL)  /* XXX Can an object lack a '__name__' attribute? */ | 
| Benjamin Peterson | 7ab4b8d | 2010-06-28 00:01:59 +0000 | [diff] [blame] | 256 |         return; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 257 |  | 
 | 258 |     f_stderr = PySys_GetObject("stderr"); | 
 | 259 |     if (f_stderr == NULL) { | 
 | 260 |         fprintf(stderr, "lost sys.stderr\n"); | 
 | 261 |         Py_DECREF(name); | 
 | 262 |         return; | 
 | 263 |     } | 
 | 264 |  | 
 | 265 |     /* Print "filename:lineno: category: text\n" */ | 
 | 266 |     PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW); | 
 | 267 |     PyFile_WriteString(lineno_str, f_stderr); | 
 | 268 |     PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW); | 
 | 269 |     PyFile_WriteString(": ", f_stderr); | 
 | 270 |     PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW); | 
 | 271 |     PyFile_WriteString("\n", f_stderr); | 
 | 272 |     Py_XDECREF(name); | 
 | 273 |  | 
 | 274 |     /* Print "  source_line\n" */ | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 275 |     if (sourceline) { | 
| Marc-André Lemburg | 4cc0f24 | 2008-08-07 18:54:33 +0000 | [diff] [blame] | 276 |         char *source_line_str = _PyUnicode_AsString(sourceline); | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 277 |         if (source_line_str == NULL) | 
 | 278 |                 return; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 279 |         while (*source_line_str == ' ' || *source_line_str == '\t' || | 
 | 280 |                 *source_line_str == '\014') | 
 | 281 |             source_line_str++; | 
 | 282 |  | 
 | 283 |         PyFile_WriteString(source_line_str, f_stderr); | 
 | 284 |         PyFile_WriteString("\n", f_stderr); | 
 | 285 |     } | 
 | 286 |     else | 
| Victor Stinner | 0fe25a4 | 2010-06-17 23:08:50 +0000 | [diff] [blame] | 287 |         if (_Py_DisplaySourceLine(f_stderr, filename, lineno, 2) < 0) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 288 |                 return; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 289 |     PyErr_Clear(); | 
 | 290 | } | 
 | 291 |  | 
 | 292 | static PyObject * | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 293 | warn_explicit(PyObject *category, PyObject *message, | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 294 |               PyObject *filename, int lineno, | 
 | 295 |               PyObject *module, PyObject *registry, PyObject *sourceline) | 
 | 296 | { | 
 | 297 |     PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL; | 
 | 298 |     PyObject *item = Py_None; | 
 | 299 |     const char *action; | 
 | 300 |     int rc; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 301 |  | 
| Brett Cannon | db73491 | 2008-06-27 00:52:15 +0000 | [diff] [blame] | 302 |     if (registry && !PyDict_Check(registry) && (registry != Py_None)) { | 
 | 303 |         PyErr_SetString(PyExc_TypeError, "'registry' must be a dict"); | 
 | 304 |         return NULL; | 
 | 305 |     } | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 306 |  | 
 | 307 |     /* Normalize module. */ | 
 | 308 |     if (module == NULL) { | 
 | 309 |         module = normalize_module(filename); | 
 | 310 |         if (module == NULL) | 
 | 311 |             return NULL; | 
 | 312 |     } | 
 | 313 |     else | 
 | 314 |         Py_INCREF(module); | 
 | 315 |  | 
 | 316 |     /* Normalize message. */ | 
 | 317 |     Py_INCREF(message);  /* DECREF'ed in cleanup. */ | 
 | 318 |     rc = PyObject_IsInstance(message, PyExc_Warning); | 
 | 319 |     if (rc == -1) { | 
 | 320 |         goto cleanup; | 
 | 321 |     } | 
 | 322 |     if (rc == 1) { | 
 | 323 |         text = PyObject_Str(message); | 
| Hirokazu Yamamoto | 1c0c003 | 2009-07-17 06:55:42 +0000 | [diff] [blame] | 324 |         if (text == NULL) | 
 | 325 |             goto cleanup; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 326 |         category = (PyObject*)message->ob_type; | 
 | 327 |     } | 
 | 328 |     else { | 
 | 329 |         text = message; | 
 | 330 |         message = PyObject_CallFunction(category, "O", message); | 
| Brett Cannon | db73491 | 2008-06-27 00:52:15 +0000 | [diff] [blame] | 331 |         if (message == NULL) | 
 | 332 |             goto cleanup; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 333 |     } | 
 | 334 |  | 
 | 335 |     lineno_obj = PyLong_FromLong(lineno); | 
 | 336 |     if (lineno_obj == NULL) | 
 | 337 |         goto cleanup; | 
 | 338 |  | 
 | 339 |     /* Create key. */ | 
 | 340 |     key = PyTuple_Pack(3, text, category, lineno_obj); | 
 | 341 |     if (key == NULL) | 
 | 342 |         goto cleanup; | 
 | 343 |  | 
| Brett Cannon | db73491 | 2008-06-27 00:52:15 +0000 | [diff] [blame] | 344 |     if ((registry != NULL) && (registry != Py_None)) { | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 345 |         rc = already_warned(registry, key, 0); | 
 | 346 |         if (rc == -1) | 
 | 347 |             goto cleanup; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 348 |         else if (rc == 1) | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 349 |             goto return_none; | 
 | 350 |         /* Else this warning hasn't been generated before. */ | 
 | 351 |     } | 
 | 352 |  | 
 | 353 |     action = get_filter(category, text, lineno, module, &item); | 
 | 354 |     if (action == NULL) | 
 | 355 |         goto cleanup; | 
 | 356 |  | 
 | 357 |     if (strcmp(action, "error") == 0) { | 
 | 358 |         PyErr_SetObject(category, message); | 
 | 359 |         goto cleanup; | 
 | 360 |     } | 
 | 361 |  | 
 | 362 |     /* Store in the registry that we've been here, *except* when the action | 
 | 363 |        is "always". */ | 
 | 364 |     rc = 0; | 
 | 365 |     if (strcmp(action, "always") != 0) { | 
| Brett Cannon | db73491 | 2008-06-27 00:52:15 +0000 | [diff] [blame] | 366 |         if (registry != NULL && registry != Py_None && | 
 | 367 |                 PyDict_SetItem(registry, key, Py_True) < 0) | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 368 |             goto cleanup; | 
 | 369 |         else if (strcmp(action, "ignore") == 0) | 
 | 370 |             goto return_none; | 
 | 371 |         else if (strcmp(action, "once") == 0) { | 
| Brett Cannon | db73491 | 2008-06-27 00:52:15 +0000 | [diff] [blame] | 372 |             if (registry == NULL || registry == Py_None) { | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 373 |                 registry = get_once_registry(); | 
 | 374 |                 if (registry == NULL) | 
 | 375 |                     goto cleanup; | 
 | 376 |             } | 
 | 377 |             /* _once_registry[(text, category)] = 1 */ | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 378 |             rc = update_registry(registry, text, category, 0); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 379 |         } | 
 | 380 |         else if (strcmp(action, "module") == 0) { | 
 | 381 |             /* registry[(text, category, 0)] = 1 */ | 
| Brett Cannon | db73491 | 2008-06-27 00:52:15 +0000 | [diff] [blame] | 382 |             if (registry != NULL && registry != Py_None) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 383 |                 rc = update_registry(registry, text, category, 0); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 384 |         } | 
 | 385 |         else if (strcmp(action, "default") != 0) { | 
 | 386 |             PyObject *to_str = PyObject_Str(item); | 
 | 387 |             const char *err_str = "???"; | 
 | 388 |  | 
| Brett Cannon | 54bd41d | 2008-09-02 04:01:42 +0000 | [diff] [blame] | 389 |             if (to_str != NULL) { | 
| Marc-André Lemburg | 4cc0f24 | 2008-08-07 18:54:33 +0000 | [diff] [blame] | 390 |                 err_str = _PyUnicode_AsString(to_str); | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 391 |                 if (err_str == NULL) | 
 | 392 |                         goto cleanup; | 
 | 393 |             } | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 394 |             PyErr_Format(PyExc_RuntimeError, | 
 | 395 |                         "Unrecognized action (%s) in warnings.filters:\n %s", | 
 | 396 |                         action, err_str); | 
 | 397 |             Py_XDECREF(to_str); | 
 | 398 |             goto cleanup; | 
 | 399 |         } | 
 | 400 |     } | 
 | 401 |  | 
| Christian Heimes | 1a8501c | 2008-10-02 19:56:01 +0000 | [diff] [blame] | 402 |     if (rc == 1)  /* Already warned for this module. */ | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 403 |         goto return_none; | 
 | 404 |     if (rc == 0) { | 
 | 405 |         PyObject *show_fxn = get_warnings_attr("showwarning"); | 
 | 406 |         if (show_fxn == NULL) { | 
 | 407 |             if (PyErr_Occurred()) | 
 | 408 |                 goto cleanup; | 
 | 409 |             show_warning(filename, lineno, text, category, sourceline); | 
 | 410 |         } | 
 | 411 |         else { | 
| Brett Cannon | ec92e18 | 2008-09-02 02:46:59 +0000 | [diff] [blame] | 412 |             PyObject *res; | 
| Christian Heimes | 8dc226f | 2008-05-06 23:45:46 +0000 | [diff] [blame] | 413 |  | 
| Brett Cannon | 52a7d98 | 2011-07-17 19:17:55 -0700 | [diff] [blame] | 414 |             if (!PyCallable_Check(show_fxn)) { | 
| Brett Cannon | ec92e18 | 2008-09-02 02:46:59 +0000 | [diff] [blame] | 415 |                 PyErr_SetString(PyExc_TypeError, | 
 | 416 |                                 "warnings.showwarning() must be set to a " | 
| Brett Cannon | 52a7d98 | 2011-07-17 19:17:55 -0700 | [diff] [blame] | 417 |                                 "callable"); | 
| Christian Heimes | 8dc226f | 2008-05-06 23:45:46 +0000 | [diff] [blame] | 418 |                 Py_DECREF(show_fxn); | 
| Brett Cannon | ec92e18 | 2008-09-02 02:46:59 +0000 | [diff] [blame] | 419 |                 goto cleanup; | 
| Christian Heimes | 8dc226f | 2008-05-06 23:45:46 +0000 | [diff] [blame] | 420 |             } | 
| Brett Cannon | ec92e18 | 2008-09-02 02:46:59 +0000 | [diff] [blame] | 421 |  | 
 | 422 |             res = PyObject_CallFunctionObjArgs(show_fxn, message, category, | 
 | 423 |                                                 filename, lineno_obj, | 
 | 424 |                                                 NULL); | 
 | 425 |             Py_DECREF(show_fxn); | 
 | 426 |             Py_XDECREF(res); | 
 | 427 |             if (res == NULL) | 
 | 428 |                 goto cleanup; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 429 |         } | 
 | 430 |     } | 
 | 431 |     else /* if (rc == -1) */ | 
 | 432 |         goto cleanup; | 
 | 433 |  | 
 | 434 |  return_none: | 
 | 435 |     result = Py_None; | 
 | 436 |     Py_INCREF(result); | 
 | 437 |  | 
 | 438 |  cleanup: | 
 | 439 |     Py_XDECREF(key); | 
 | 440 |     Py_XDECREF(text); | 
 | 441 |     Py_XDECREF(lineno_obj); | 
 | 442 |     Py_DECREF(module); | 
| Brett Cannon | db73491 | 2008-06-27 00:52:15 +0000 | [diff] [blame] | 443 |     Py_XDECREF(message); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 444 |     return result;  /* Py_None or NULL. */ | 
 | 445 | } | 
 | 446 |  | 
 | 447 | /* filename, module, and registry are new refs, globals is borrowed */ | 
 | 448 | /* Returns 0 on error (no new refs), 1 on success */ | 
 | 449 | static int | 
 | 450 | setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, | 
 | 451 |               PyObject **module, PyObject **registry) | 
 | 452 | { | 
 | 453 |     PyObject *globals; | 
 | 454 |  | 
 | 455 |     /* Setup globals and lineno. */ | 
 | 456 |     PyFrameObject *f = PyThreadState_GET()->frame; | 
| Christian Heimes | 5d8da20 | 2008-05-06 13:58:24 +0000 | [diff] [blame] | 457 |     while (--stack_level > 0 && f != NULL) | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 458 |         f = f->f_back; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 459 |  | 
 | 460 |     if (f == NULL) { | 
 | 461 |         globals = PyThreadState_Get()->interp->sysdict; | 
 | 462 |         *lineno = 1; | 
 | 463 |     } | 
 | 464 |     else { | 
 | 465 |         globals = f->f_globals; | 
| Alexandre Vassalotti | 7b82b40 | 2009-07-21 04:30:03 +0000 | [diff] [blame] | 466 |         *lineno = PyFrame_GetLineNumber(f); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 467 |     } | 
 | 468 |  | 
 | 469 |     *module = NULL; | 
 | 470 |  | 
 | 471 |     /* Setup registry. */ | 
 | 472 |     assert(globals != NULL); | 
 | 473 |     assert(PyDict_Check(globals)); | 
 | 474 |     *registry = PyDict_GetItemString(globals, "__warningregistry__"); | 
 | 475 |     if (*registry == NULL) { | 
 | 476 |         int rc; | 
 | 477 |  | 
 | 478 |         *registry = PyDict_New(); | 
 | 479 |         if (*registry == NULL) | 
 | 480 |             return 0; | 
 | 481 |  | 
 | 482 |          rc = PyDict_SetItemString(globals, "__warningregistry__", *registry); | 
 | 483 |          if (rc < 0) | 
 | 484 |             goto handle_error; | 
 | 485 |     } | 
 | 486 |     else | 
 | 487 |         Py_INCREF(*registry); | 
 | 488 |  | 
 | 489 |     /* Setup module. */ | 
 | 490 |     *module = PyDict_GetItemString(globals, "__name__"); | 
 | 491 |     if (*module == NULL) { | 
 | 492 |         *module = PyUnicode_FromString("<string>"); | 
 | 493 |         if (*module == NULL) | 
 | 494 |             goto handle_error; | 
 | 495 |     } | 
 | 496 |     else | 
 | 497 |         Py_INCREF(*module); | 
 | 498 |  | 
 | 499 |     /* Setup filename. */ | 
 | 500 |     *filename = PyDict_GetItemString(globals, "__file__"); | 
| Victor Stinner | 8b0508e | 2011-07-04 02:43:09 +0200 | [diff] [blame] | 501 |     if (*filename != NULL && PyUnicode_Check(*filename)) { | 
| Victor Stinner | b62a7b2 | 2011-10-06 02:34:51 +0200 | [diff] [blame] | 502 |         Py_ssize_t len; | 
 | 503 |         int kind; | 
 | 504 |         void *data; | 
 | 505 |  | 
 | 506 |         if (PyUnicode_READY(*filename)) | 
 | 507 |             goto handle_error; | 
 | 508 |  | 
 | 509 |         len = PyUnicode_GetSize(*filename); | 
 | 510 |         kind = PyUnicode_KIND(*filename); | 
 | 511 |         data = PyUnicode_DATA(*filename); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 512 |  | 
 | 513 |         /* if filename.lower().endswith((".pyc", ".pyo")): */ | 
 | 514 |         if (len >= 4 && | 
| Martin v. Löwis | d63a3b8 | 2011-09-28 07:41:54 +0200 | [diff] [blame] | 515 |             PyUnicode_READ(kind, data, len-4) == '.' && | 
 | 516 |             Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-3)) == 'p' && | 
 | 517 |             Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-2)) == 'y' && | 
 | 518 |             (Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-1)) == 'c' || | 
 | 519 |                 Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-1)) == 'o')) | 
| Christian Heimes | 81ee3ef | 2008-05-04 22:42:01 +0000 | [diff] [blame] | 520 |         { | 
| Martin v. Löwis | d63a3b8 | 2011-09-28 07:41:54 +0200 | [diff] [blame] | 521 |             *filename = PyUnicode_Substring(*filename, 0, | 
 | 522 |                                             PyUnicode_GET_LENGTH(*filename)-1); | 
| Victor Stinner | 2e5f117 | 2010-08-08 22:12:45 +0000 | [diff] [blame] | 523 |             if (*filename == NULL) | 
 | 524 |                 goto handle_error; | 
 | 525 |         } | 
 | 526 |         else | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 527 |             Py_INCREF(*filename); | 
 | 528 |     } | 
 | 529 |     else { | 
| Marc-André Lemburg | 4cc0f24 | 2008-08-07 18:54:33 +0000 | [diff] [blame] | 530 |         const char *module_str = _PyUnicode_AsString(*module); | 
| Benjamin Peterson | bb4a747 | 2011-07-04 22:27:16 -0500 | [diff] [blame] | 531 |         *filename = NULL; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 532 |         if (module_str == NULL) | 
 | 533 |                 goto handle_error; | 
| Brett Cannon | 54bd41d | 2008-09-02 04:01:42 +0000 | [diff] [blame] | 534 |         if (strcmp(module_str, "__main__") == 0) { | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 535 |             PyObject *argv = PySys_GetObject("argv"); | 
 | 536 |             if (argv != NULL && PyList_Size(argv) > 0) { | 
| Christian Heimes | 81ee3ef | 2008-05-04 22:42:01 +0000 | [diff] [blame] | 537 |                 int is_true; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 538 |                 *filename = PyList_GetItem(argv, 0); | 
 | 539 |                 Py_INCREF(*filename); | 
| Christian Heimes | 81ee3ef | 2008-05-04 22:42:01 +0000 | [diff] [blame] | 540 |                 /* If sys.argv[0] is false, then use '__main__'. */ | 
 | 541 |                 is_true = PyObject_IsTrue(*filename); | 
 | 542 |                 if (is_true < 0) { | 
 | 543 |                     Py_DECREF(*filename); | 
 | 544 |                     goto handle_error; | 
 | 545 |                 } | 
 | 546 |                 else if (!is_true) { | 
 | 547 |                     Py_DECREF(*filename); | 
| Benjamin Peterson | 9f4bf1d | 2008-05-04 23:22:13 +0000 | [diff] [blame] | 548 |                     *filename = PyUnicode_FromString("__main__"); | 
| Christian Heimes | 81ee3ef | 2008-05-04 22:42:01 +0000 | [diff] [blame] | 549 |                     if (*filename == NULL) | 
 | 550 |                         goto handle_error; | 
 | 551 |                 } | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 552 |             } | 
 | 553 |             else { | 
 | 554 |                 /* embedded interpreters don't have sys.argv, see bug #839151 */ | 
 | 555 |                 *filename = PyUnicode_FromString("__main__"); | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 556 |                     if (*filename == NULL) | 
 | 557 |                         goto handle_error; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 558 |             } | 
 | 559 |         } | 
 | 560 |         if (*filename == NULL) { | 
 | 561 |             *filename = *module; | 
 | 562 |             Py_INCREF(*filename); | 
 | 563 |         } | 
 | 564 |     } | 
 | 565 |  | 
 | 566 |     return 1; | 
 | 567 |  | 
 | 568 |  handle_error: | 
 | 569 |     /* filename not XDECREF'ed here as there is no way to jump here with a | 
 | 570 |        dangling reference. */ | 
 | 571 |     Py_XDECREF(*registry); | 
 | 572 |     Py_XDECREF(*module); | 
 | 573 |     return 0; | 
 | 574 | } | 
 | 575 |  | 
 | 576 | static PyObject * | 
 | 577 | get_category(PyObject *message, PyObject *category) | 
 | 578 | { | 
 | 579 |     int rc; | 
 | 580 |  | 
 | 581 |     /* Get category. */ | 
 | 582 |     rc = PyObject_IsInstance(message, PyExc_Warning); | 
 | 583 |     if (rc == -1) | 
 | 584 |         return NULL; | 
 | 585 |  | 
 | 586 |     if (rc == 1) | 
 | 587 |         category = (PyObject*)message->ob_type; | 
 | 588 |     else if (category == NULL) | 
 | 589 |         category = PyExc_UserWarning; | 
 | 590 |  | 
 | 591 |     /* Validate category. */ | 
 | 592 |     rc = PyObject_IsSubclass(category, PyExc_Warning); | 
 | 593 |     if (rc == -1) | 
 | 594 |         return NULL; | 
 | 595 |     if (rc == 0) { | 
 | 596 |         PyErr_SetString(PyExc_ValueError, | 
 | 597 |                         "category is not a subclass of Warning"); | 
 | 598 |         return NULL; | 
 | 599 |     } | 
 | 600 |  | 
 | 601 |     return category; | 
 | 602 | } | 
 | 603 |  | 
 | 604 | static PyObject * | 
 | 605 | do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level) | 
 | 606 | { | 
 | 607 |     PyObject *filename, *module, *registry, *res; | 
 | 608 |     int lineno; | 
 | 609 |  | 
 | 610 |     if (!setup_context(stack_level, &filename, &lineno, &module, ®istry)) | 
 | 611 |         return NULL; | 
 | 612 |  | 
 | 613 |     res = warn_explicit(category, message, filename, lineno, module, registry, | 
 | 614 |                         NULL); | 
 | 615 |     Py_DECREF(filename); | 
 | 616 |     Py_DECREF(registry); | 
 | 617 |     Py_DECREF(module); | 
 | 618 |     return res; | 
 | 619 | } | 
 | 620 |  | 
 | 621 | static PyObject * | 
 | 622 | warnings_warn(PyObject *self, PyObject *args, PyObject *kwds) | 
 | 623 | { | 
 | 624 |     static char *kw_list[] = { "message", "category", "stacklevel", 0 }; | 
 | 625 |     PyObject *message, *category = NULL; | 
 | 626 |     Py_ssize_t stack_level = 1; | 
 | 627 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 628 |     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list, | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 629 |                                      &message, &category, &stack_level)) | 
 | 630 |         return NULL; | 
 | 631 |  | 
 | 632 |     category = get_category(message, category); | 
 | 633 |     if (category == NULL) | 
 | 634 |         return NULL; | 
 | 635 |     return do_warn(message, category, stack_level); | 
 | 636 | } | 
 | 637 |  | 
 | 638 | static PyObject * | 
 | 639 | warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) | 
 | 640 | { | 
 | 641 |     static char *kwd_list[] = {"message", "category", "filename", "lineno", | 
 | 642 |                                 "module", "registry", "module_globals", 0}; | 
 | 643 |     PyObject *message; | 
 | 644 |     PyObject *category; | 
 | 645 |     PyObject *filename; | 
 | 646 |     int lineno; | 
 | 647 |     PyObject *module = NULL; | 
 | 648 |     PyObject *registry = NULL; | 
 | 649 |     PyObject *module_globals = NULL; | 
 | 650 |  | 
 | 651 |     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit", | 
 | 652 |                 kwd_list, &message, &category, &filename, &lineno, &module, | 
 | 653 |                 ®istry, &module_globals)) | 
 | 654 |         return NULL; | 
 | 655 |  | 
 | 656 |     if (module_globals) { | 
 | 657 |         static PyObject *get_source_name = NULL; | 
 | 658 |         static PyObject *splitlines_name = NULL; | 
 | 659 |         PyObject *loader; | 
 | 660 |         PyObject *module_name; | 
 | 661 |         PyObject *source; | 
 | 662 |         PyObject *source_list; | 
 | 663 |         PyObject *source_line; | 
 | 664 |         PyObject *returned; | 
 | 665 |  | 
 | 666 |         if (get_source_name == NULL) { | 
 | 667 |             get_source_name = PyUnicode_InternFromString("get_source"); | 
 | 668 |             if (!get_source_name) | 
 | 669 |                 return NULL; | 
 | 670 |         } | 
 | 671 |         if (splitlines_name == NULL) { | 
 | 672 |             splitlines_name = PyUnicode_InternFromString("splitlines"); | 
 | 673 |             if (!splitlines_name) | 
 | 674 |                 return NULL; | 
 | 675 |         } | 
 | 676 |  | 
 | 677 |         /* Check/get the requisite pieces needed for the loader. */ | 
 | 678 |         loader = PyDict_GetItemString(module_globals, "__loader__"); | 
 | 679 |         module_name = PyDict_GetItemString(module_globals, "__name__"); | 
 | 680 |  | 
 | 681 |         if (loader == NULL || module_name == NULL) | 
 | 682 |             goto standard_call; | 
 | 683 |  | 
 | 684 |         /* Make sure the loader implements the optional get_source() method. */ | 
 | 685 |         if (!PyObject_HasAttrString(loader, "get_source")) | 
 | 686 |                 goto standard_call; | 
 | 687 |         /* Call get_source() to get the source code. */ | 
 | 688 |         source = PyObject_CallMethodObjArgs(loader, get_source_name, | 
 | 689 |                                                 module_name, NULL); | 
 | 690 |         if (!source) | 
 | 691 |             return NULL; | 
 | 692 |         else if (source == Py_None) { | 
 | 693 |             Py_DECREF(Py_None); | 
 | 694 |             goto standard_call; | 
 | 695 |         } | 
 | 696 |  | 
 | 697 |         /* Split the source into lines. */ | 
 | 698 |         source_list = PyObject_CallMethodObjArgs(source, splitlines_name, | 
 | 699 |                                                     NULL); | 
 | 700 |         Py_DECREF(source); | 
 | 701 |         if (!source_list) | 
 | 702 |             return NULL; | 
 | 703 |  | 
 | 704 |         /* Get the source line. */ | 
 | 705 |         source_line = PyList_GetItem(source_list, lineno-1); | 
 | 706 |         if (!source_line) { | 
 | 707 |             Py_DECREF(source_list); | 
 | 708 |             return NULL; | 
 | 709 |         } | 
 | 710 |  | 
 | 711 |         /* Handle the warning. */ | 
 | 712 |         returned = warn_explicit(category, message, filename, lineno, module, | 
 | 713 |                             registry, source_line); | 
 | 714 |         Py_DECREF(source_list); | 
 | 715 |         return returned; | 
 | 716 |     } | 
 | 717 |  | 
 | 718 |  standard_call: | 
 | 719 |     return warn_explicit(category, message, filename, lineno, module, | 
 | 720 |                                 registry, NULL); | 
 | 721 | } | 
 | 722 |  | 
 | 723 |  | 
 | 724 | /* Function to issue a warning message; may raise an exception. */ | 
| Victor Stinner | 4a2b7a1 | 2010-08-13 14:03:48 +0000 | [diff] [blame] | 725 |  | 
 | 726 | static int | 
 | 727 | warn_unicode(PyObject *category, PyObject *message, | 
 | 728 |              Py_ssize_t stack_level) | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 729 | { | 
 | 730 |     PyObject *res; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 731 |  | 
 | 732 |     if (category == NULL) | 
 | 733 |         category = PyExc_RuntimeWarning; | 
 | 734 |  | 
 | 735 |     res = do_warn(message, category, stack_level); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 736 |     if (res == NULL) | 
 | 737 |         return -1; | 
 | 738 |     Py_DECREF(res); | 
 | 739 |  | 
 | 740 |     return 0; | 
 | 741 | } | 
 | 742 |  | 
| Victor Stinner | 4a2b7a1 | 2010-08-13 14:03:48 +0000 | [diff] [blame] | 743 | int | 
 | 744 | PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, | 
 | 745 |                  const char *format, ...) | 
 | 746 | { | 
 | 747 |     int ret; | 
 | 748 |     PyObject *message; | 
 | 749 |     va_list vargs; | 
 | 750 |  | 
 | 751 | #ifdef HAVE_STDARG_PROTOTYPES | 
 | 752 |     va_start(vargs, format); | 
 | 753 | #else | 
 | 754 |     va_start(vargs); | 
 | 755 | #endif | 
 | 756 |     message = PyUnicode_FromFormatV(format, vargs); | 
 | 757 |     if (message != NULL) { | 
 | 758 |         ret = warn_unicode(category, message, stack_level); | 
 | 759 |         Py_DECREF(message); | 
 | 760 |     } | 
 | 761 |     else | 
 | 762 |         ret = -1; | 
 | 763 |     va_end(vargs); | 
 | 764 |     return ret; | 
 | 765 | } | 
 | 766 |  | 
 | 767 | int | 
 | 768 | PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) | 
 | 769 | { | 
 | 770 |     int ret; | 
 | 771 |     PyObject *message = PyUnicode_FromString(text); | 
 | 772 |     if (message == NULL) | 
 | 773 |         return -1; | 
 | 774 |     ret = warn_unicode(category, message, stack_level); | 
 | 775 |     Py_DECREF(message); | 
 | 776 |     return ret; | 
 | 777 | } | 
 | 778 |  | 
| Ezio Melotti | 42da663 | 2011-03-15 05:18:48 +0200 | [diff] [blame] | 779 | /* PyErr_Warn is only for backwards compatibility and will be removed. | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 780 |    Use PyErr_WarnEx instead. */ | 
 | 781 |  | 
 | 782 | #undef PyErr_Warn | 
 | 783 |  | 
 | 784 | PyAPI_FUNC(int) | 
 | 785 | PyErr_Warn(PyObject *category, char *text) | 
 | 786 | { | 
 | 787 |     return PyErr_WarnEx(category, text, 1); | 
 | 788 | } | 
 | 789 |  | 
 | 790 | /* Warning with explicit origin */ | 
 | 791 | int | 
 | 792 | PyErr_WarnExplicit(PyObject *category, const char *text, | 
 | 793 |                    const char *filename_str, int lineno, | 
 | 794 |                    const char *module_str, PyObject *registry) | 
 | 795 | { | 
 | 796 |     PyObject *res; | 
 | 797 |     PyObject *message = PyUnicode_FromString(text); | 
| Victor Stinner | cb428f0 | 2010-12-27 20:10:36 +0000 | [diff] [blame] | 798 |     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 799 |     PyObject *module = NULL; | 
 | 800 |     int ret = -1; | 
 | 801 |  | 
 | 802 |     if (message == NULL || filename == NULL) | 
 | 803 |         goto exit; | 
 | 804 |     if (module_str != NULL) { | 
 | 805 |         module = PyUnicode_FromString(module_str); | 
 | 806 |             if (module == NULL) | 
 | 807 |                 goto exit; | 
 | 808 |     } | 
 | 809 |  | 
 | 810 |     if (category == NULL) | 
 | 811 |         category = PyExc_RuntimeWarning; | 
 | 812 |     res = warn_explicit(category, message, filename, lineno, module, registry, | 
 | 813 |                         NULL); | 
 | 814 |     if (res == NULL) | 
 | 815 |         goto exit; | 
 | 816 |     Py_DECREF(res); | 
 | 817 |     ret = 0; | 
 | 818 |  | 
 | 819 |  exit: | 
 | 820 |     Py_XDECREF(message); | 
 | 821 |     Py_XDECREF(module); | 
 | 822 |     Py_XDECREF(filename); | 
 | 823 |     return ret; | 
 | 824 | } | 
 | 825 |  | 
 | 826 |  | 
 | 827 | PyDoc_STRVAR(warn_doc, | 
 | 828 | "Issue a warning, or maybe ignore it or raise an exception."); | 
 | 829 |  | 
 | 830 | PyDoc_STRVAR(warn_explicit_doc, | 
 | 831 | "Low-level inferface to warnings functionality."); | 
 | 832 |  | 
 | 833 | static PyMethodDef warnings_functions[] = { | 
 | 834 |     {"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS, | 
 | 835 |         warn_doc}, | 
 | 836 |     {"warn_explicit", (PyCFunction)warnings_warn_explicit, | 
 | 837 |         METH_VARARGS | METH_KEYWORDS, warn_explicit_doc}, | 
| Christian Heimes | 1a8501c | 2008-10-02 19:56:01 +0000 | [diff] [blame] | 838 |     /* XXX(brett.cannon): add showwarning? */ | 
 | 839 |     /* XXX(brett.cannon): Reasonable to add formatwarning? */ | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 840 |     {NULL, NULL}                /* sentinel */ | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 841 | }; | 
 | 842 |  | 
 | 843 |  | 
 | 844 | static PyObject * | 
 | 845 | create_filter(PyObject *category, const char *action) | 
 | 846 | { | 
 | 847 |     static PyObject *ignore_str = NULL; | 
 | 848 |     static PyObject *error_str = NULL; | 
 | 849 |     static PyObject *default_str = NULL; | 
| Georg Brandl | 08be72d | 2010-10-24 15:11:22 +0000 | [diff] [blame] | 850 |     static PyObject *always_str = NULL; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 851 |     PyObject *action_obj = NULL; | 
 | 852 |     PyObject *lineno, *result; | 
 | 853 |  | 
 | 854 |     if (!strcmp(action, "ignore")) { | 
 | 855 |         if (ignore_str == NULL) { | 
 | 856 |             ignore_str = PyUnicode_InternFromString("ignore"); | 
 | 857 |             if (ignore_str == NULL) | 
 | 858 |                 return NULL; | 
 | 859 |         } | 
 | 860 |         action_obj = ignore_str; | 
 | 861 |     } | 
 | 862 |     else if (!strcmp(action, "error")) { | 
 | 863 |         if (error_str == NULL) { | 
 | 864 |             error_str = PyUnicode_InternFromString("error"); | 
 | 865 |             if (error_str == NULL) | 
 | 866 |                 return NULL; | 
 | 867 |         } | 
 | 868 |         action_obj = error_str; | 
 | 869 |     } | 
 | 870 |     else if (!strcmp(action, "default")) { | 
 | 871 |         if (default_str == NULL) { | 
 | 872 |             default_str = PyUnicode_InternFromString("default"); | 
 | 873 |             if (default_str == NULL) | 
 | 874 |                 return NULL; | 
 | 875 |         } | 
 | 876 |         action_obj = default_str; | 
 | 877 |     } | 
| Georg Brandl | 08be72d | 2010-10-24 15:11:22 +0000 | [diff] [blame] | 878 |     else if (!strcmp(action, "always")) { | 
 | 879 |         if (always_str == NULL) { | 
 | 880 |             always_str = PyUnicode_InternFromString("always"); | 
 | 881 |             if (always_str == NULL) | 
 | 882 |                 return NULL; | 
 | 883 |         } | 
 | 884 |         action_obj = always_str; | 
 | 885 |     } | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 886 |     else { | 
 | 887 |         Py_FatalError("unknown action"); | 
 | 888 |     } | 
 | 889 |  | 
 | 890 |     /* This assumes the line number is zero for now. */ | 
 | 891 |     lineno = PyLong_FromLong(0); | 
 | 892 |     if (lineno == NULL) | 
 | 893 |         return NULL; | 
 | 894 |     result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno); | 
 | 895 |     Py_DECREF(lineno); | 
 | 896 |     return result; | 
 | 897 | } | 
 | 898 |  | 
 | 899 | static PyObject * | 
 | 900 | init_filters(void) | 
 | 901 | { | 
| Benjamin Peterson | 7ab4b8d | 2010-06-28 00:01:59 +0000 | [diff] [blame] | 902 |     /* Don't silence DeprecationWarning if -3 was used. */ | 
| Georg Brandl | 08be72d | 2010-10-24 15:11:22 +0000 | [diff] [blame] | 903 |     PyObject *filters = PyList_New(5); | 
| Benjamin Peterson | 7ab4b8d | 2010-06-28 00:01:59 +0000 | [diff] [blame] | 904 |     unsigned int pos = 0;  /* Post-incremented in each use. */ | 
 | 905 |     unsigned int x; | 
| Georg Brandl | 08be72d | 2010-10-24 15:11:22 +0000 | [diff] [blame] | 906 |     const char *bytes_action, *resource_action; | 
| Benjamin Peterson | 7ab4b8d | 2010-06-28 00:01:59 +0000 | [diff] [blame] | 907 |  | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 908 |     if (filters == NULL) | 
 | 909 |         return NULL; | 
 | 910 |  | 
| Benjamin Peterson | 7ab4b8d | 2010-06-28 00:01:59 +0000 | [diff] [blame] | 911 |     PyList_SET_ITEM(filters, pos++, | 
 | 912 |                     create_filter(PyExc_DeprecationWarning, "ignore")); | 
 | 913 |     PyList_SET_ITEM(filters, pos++, | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 914 |                     create_filter(PyExc_PendingDeprecationWarning, "ignore")); | 
| Benjamin Peterson | 7ab4b8d | 2010-06-28 00:01:59 +0000 | [diff] [blame] | 915 |     PyList_SET_ITEM(filters, pos++, | 
 | 916 |                     create_filter(PyExc_ImportWarning, "ignore")); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 917 |     if (Py_BytesWarningFlag > 1) | 
 | 918 |         bytes_action = "error"; | 
 | 919 |     else if (Py_BytesWarningFlag) | 
 | 920 |         bytes_action = "default"; | 
 | 921 |     else | 
 | 922 |         bytes_action = "ignore"; | 
| Benjamin Peterson | 7ab4b8d | 2010-06-28 00:01:59 +0000 | [diff] [blame] | 923 |     PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning, | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 924 |                     bytes_action)); | 
| Georg Brandl | 08be72d | 2010-10-24 15:11:22 +0000 | [diff] [blame] | 925 |     /* resource usage warnings are enabled by default in pydebug mode */ | 
 | 926 | #ifdef Py_DEBUG | 
 | 927 |     resource_action = "always"; | 
 | 928 | #else | 
 | 929 |     resource_action = "ignore"; | 
 | 930 | #endif | 
 | 931 |     PyList_SET_ITEM(filters, pos++, create_filter(PyExc_ResourceWarning, | 
 | 932 |                     resource_action)); | 
| Benjamin Peterson | 7ab4b8d | 2010-06-28 00:01:59 +0000 | [diff] [blame] | 933 |     for (x = 0; x < pos; x += 1) { | 
 | 934 |         if (PyList_GET_ITEM(filters, x) == NULL) { | 
 | 935 |             Py_DECREF(filters); | 
 | 936 |             return NULL; | 
 | 937 |         } | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 938 |     } | 
 | 939 |  | 
 | 940 |     return filters; | 
 | 941 | } | 
 | 942 |  | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 943 | static struct PyModuleDef warningsmodule = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 944 |         PyModuleDef_HEAD_INIT, | 
 | 945 |         MODULE_NAME, | 
 | 946 |         warnings__doc__, | 
 | 947 |         0, | 
 | 948 |         warnings_functions, | 
 | 949 |         NULL, | 
 | 950 |         NULL, | 
 | 951 |         NULL, | 
 | 952 |         NULL | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 953 | }; | 
 | 954 |  | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 955 |  | 
 | 956 | PyMODINIT_FUNC | 
 | 957 | _PyWarnings_Init(void) | 
 | 958 | { | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 959 |     PyObject *m; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 960 |  | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 961 |     m = PyModule_Create(&warningsmodule); | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 962 |     if (m == NULL) | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 963 |         return NULL; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 964 |  | 
 | 965 |     _filters = init_filters(); | 
 | 966 |     if (_filters == NULL) | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 967 |         return NULL; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 968 |     Py_INCREF(_filters); | 
 | 969 |     if (PyModule_AddObject(m, "filters", _filters) < 0) | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 970 |         return NULL; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 971 |  | 
 | 972 |     _once_registry = PyDict_New(); | 
 | 973 |     if (_once_registry == NULL) | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 974 |         return NULL; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 975 |     Py_INCREF(_once_registry); | 
| Brett Cannon | ef0e6c3 | 2010-09-04 18:24:04 +0000 | [diff] [blame] | 976 |     if (PyModule_AddObject(m, "_onceregistry", _once_registry) < 0) | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 977 |         return NULL; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 978 |  | 
| Brett Cannon | 0759dd6 | 2009-04-01 18:13:07 +0000 | [diff] [blame] | 979 |     _default_action = PyUnicode_FromString("default"); | 
 | 980 |     if (_default_action == NULL) | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 981 |         return NULL; | 
| Brett Cannon | ef0e6c3 | 2010-09-04 18:24:04 +0000 | [diff] [blame] | 982 |     if (PyModule_AddObject(m, "_defaultaction", _default_action) < 0) | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 983 |         return NULL; | 
 | 984 |     return m; | 
| Christian Heimes | 33fe809 | 2008-04-13 13:53:33 +0000 | [diff] [blame] | 985 | } |