this repo has no description
at trunk 152 lines 5.4 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2// _warnings.c implementation 3 4#include <cstdarg> 5 6#include "cpython-data.h" 7#include "cpython-types.h" 8 9#include "api-handle.h" 10#include "modules.h" 11#include "runtime.h" 12#include "utils.h" 13 14namespace py { 15 16static int callWarn(PyObject* category, PyObject* message, 17 Py_ssize_t stack_level, PyObject* source) { 18 if (category == nullptr) { 19 category = PyExc_RuntimeWarning; 20 } 21 if (source == nullptr) { 22 source = Py_None; 23 } 24 // Pop the extra frame pushed for calling managed code below. We need to do 25 // that since we're calling warnings.warn that pushes an extra frame whereas 26 // CPython performs the same task natively. 27 if (stack_level < 0) stack_level = 0; 28 stack_level++; 29 Thread* thread = Thread::current(); 30 HandleScope scope(thread); 31 Object category_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(category))); 32 DCHECK(message != nullptr, "message cannot be null"); 33 Object message_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(message))); 34 Runtime* runtime = thread->runtime(); 35 Int stack_level_obj(&scope, runtime->newInt(stack_level)); 36 Object source_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(source))); 37 // Like CPython, bail out if we are finalizing the runtime 38 if (runtime->isFinalizing()) { 39 return 0; 40 } 41 if (ensureBuiltinModuleById(thread, ID(warnings)).isErrorException()) { 42 return -1; 43 } 44 if (thread 45 ->invokeFunction4(ID(warnings), ID(warn), message_obj, category_obj, 46 stack_level_obj, source_obj) 47 .isErrorException()) { 48 return -1; 49 } 50 return 0; 51} 52 53PY_EXPORT int PyErr_WarnEx(PyObject* category, const char* text, 54 Py_ssize_t stack_level) { 55 PyObject* message = PyUnicode_FromString(text); 56 if (message == nullptr) { 57 return -1; 58 } 59 int res = callWarn(category, message, stack_level, nullptr); 60 Py_DECREF(message); 61 return res; 62} 63 64static int warnFormat(PyObject* source, PyObject* category, 65 Py_ssize_t stack_level, const char* format, 66 va_list vargs) { 67 PyObject* message = PyUnicode_FromFormatV(format, vargs); 68 if (message == nullptr) { 69 return -1; 70 } 71 int res = callWarn(category, message, stack_level, source); 72 Py_DECREF(message); 73 return res; 74} 75 76PY_EXPORT int PyErr_ResourceWarning(PyObject* source, Py_ssize_t stack_level, 77 const char* format, ...) { 78 va_list vargs; 79 va_start(vargs, format); 80 int res = 81 warnFormat(source, PyExc_ResourceWarning, stack_level, format, vargs); 82 va_end(vargs); 83 return res; 84} 85 86PY_EXPORT int PyErr_WarnExplicit(PyObject* /* y */, const char* /* t */, 87 const char* /* r */, int /* o */, 88 const char* /* r */, PyObject* /* y */) { 89 UNIMPLEMENTED("PyErr_WarnExplicit"); 90} 91 92PY_EXPORT int PyErr_WarnExplicitObject(PyObject* category, PyObject* message, 93 PyObject* filename, int lineno, 94 PyObject* module, PyObject* registry) { 95 // module can be None if a warning is emitted late during Python shutdown. 96 // In this case, the Python warnings module was probably unloaded, so filters 97 // are no longer available to choose as actions. It is safer to ignore the 98 // warning and do nothing. 99 if (module == Py_None) { 100 return 0; 101 } 102 if (category == nullptr) { 103 category = PyExc_RuntimeWarning; 104 } 105 if (module == nullptr) { 106 // Signal to Python implementation that the module should be derived from 107 // the filename. 108 module = Py_None; 109 } 110 Thread* thread = Thread::current(); 111 HandleScope scope(thread); 112 DCHECK(category != nullptr, "category cannot be null"); 113 Object category_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(category))); 114 DCHECK(message != nullptr, "message cannot be null"); 115 Object message_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(message))); 116 DCHECK(filename != nullptr, "filename cannot be null"); 117 Object filename_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(filename))); 118 Runtime* runtime = thread->runtime(); 119 Int lineno_obj(&scope, runtime->newInt(lineno)); 120 DCHECK(module != nullptr, "module cannot be null"); 121 Object module_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(module))); 122 Object registry_obj(&scope, 123 registry == nullptr 124 ? NoneType::object() 125 : ApiHandle::asObject(ApiHandle::fromPyObject(registry))); 126 // Like CPython, bail out if we are finalizing the runtime 127 if (runtime->isFinalizing()) { 128 return 0; 129 } 130 if (ensureBuiltinModuleById(thread, ID(warnings)).isErrorException()) { 131 return -1; 132 } 133 if (thread 134 ->invokeFunction6(ID(warnings), ID(warn_explicit), message_obj, 135 category_obj, filename_obj, lineno_obj, module_obj, 136 registry_obj) 137 .isError()) { 138 return -1; 139 } 140 return 0; 141} 142 143PY_EXPORT int PyErr_WarnFormat(PyObject* category, Py_ssize_t stack_level, 144 const char* format, ...) { 145 va_list vargs; 146 va_start(vargs, format); 147 int res = warnFormat(nullptr, category, stack_level, format, vargs); 148 va_end(vargs); 149 return res; 150} 151 152} // namespace py