summaryrefslogtreecommitdiffstats
path: root/Python/_warnings.c
diff options
context:
space:
mode:
authorNathaniel J. Smith <njs@pobox.com>2018-01-21 14:44:07 (GMT)
committerYury Selivanov <yury@magic.io>2018-01-21 14:44:07 (GMT)
commitfc2f407829d9817ddacccae6944dd0879cfaca24 (patch)
tree1775a28a8181975363798f9b3e7cb2bb100e49a2 /Python/_warnings.c
parent1211c9a9897a174b7261ca258cabf289815a40d8 (diff)
downloadcpython-fc2f407829d9817ddacccae6944dd0879cfaca24.zip
cpython-fc2f407829d9817ddacccae6944dd0879cfaca24.tar.gz
cpython-fc2f407829d9817ddacccae6944dd0879cfaca24.tar.bz2
bpo-32591: Add native coroutine origin tracking (#5250)
* Add coro.cr_origin and sys.set_coroutine_origin_tracking_depth * Use coroutine origin information in the unawaited coroutine warning * Stop using set_coroutine_wrapper in asyncio debug mode * In BaseEventLoop.set_debug, enable debugging in the correct thread
Diffstat (limited to 'Python/_warnings.c')
-rw-r--r--Python/_warnings.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/Python/_warnings.c b/Python/_warnings.c
index c286364..c3417cc 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -1153,6 +1153,53 @@ exit:
return ret;
}
+void
+_PyErr_WarnUnawaitedCoroutine(PyObject *coro)
+{
+ /* First, we attempt to funnel the warning through
+ warnings._warn_unawaited_coroutine.
+
+ This could raise an exception, due to:
+ - a bug
+ - some kind of shutdown-related brokenness
+ - succeeding, but with an "error" warning filter installed, so the
+ warning is converted into a RuntimeWarning exception
+
+ In the first two cases, we want to print the error (so we know what it
+ is!), and then print a warning directly as a fallback. In the last
+ case, we want to print the error (since it's the warning!), but *not*
+ do a fallback. And after we print the error we can't check for what
+ type of error it was (because PyErr_WriteUnraisable clears it), so we
+ need a flag to keep track.
+
+ Since this is called from __del__ context, it's careful to never raise
+ an exception.
+ */
+ _Py_IDENTIFIER(_warn_unawaited_coroutine);
+ int warned = 0;
+ PyObject *fn = get_warnings_attr(&PyId__warn_unawaited_coroutine, 1);
+ if (fn) {
+ PyObject *res = PyObject_CallFunctionObjArgs(fn, coro, NULL);
+ Py_DECREF(fn);
+ if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
+ warned = 1;
+ }
+ Py_XDECREF(res);
+ }
+
+ if (PyErr_Occurred()) {
+ PyErr_WriteUnraisable(coro);
+ }
+ if (!warned) {
+ PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
+ "coroutine '%.50S' was never awaited",
+ ((PyCoroObject *)coro)->cr_qualname);
+ /* Maybe *that* got converted into an exception */
+ if (PyErr_Occurred()) {
+ PyErr_WriteUnraisable(coro);
+ }
+ }
+}
PyDoc_STRVAR(warn_explicit_doc,
"Low-level inferface to warnings functionality.");