summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>2022-10-07 02:32:53 (GMT)
committerGitHub <noreply@github.com>2022-10-07 02:32:53 (GMT)
commit13d44891426e0faf165f974f2e46907ab5b645a9 (patch)
tree3f86e88601b8a5b551b854d30396ce93f87d17f3 /Python
parent27369ef56ffed8ab68abc201a52b259a065ed8d7 (diff)
downloadcpython-13d44891426e0faf165f974f2e46907ab5b645a9.zip
cpython-13d44891426e0faf165f974f2e46907ab5b645a9.tar.gz
cpython-13d44891426e0faf165f974f2e46907ab5b645a9.tar.bz2
gh-86298: Ensure that __loader__ and __spec__.loader agree in warnings.warn_explicit() (GH-97803)
In `_warnings.c`, in the C equivalent of `warnings.warn_explicit()`, if the module globals are given (and not None), the warning will attempt to get the source line for the issued warning. To do this, it needs the module's loader. Previously, it would only look up `__loader__` in the module globals. In https://github.com/python/cpython/issues/86298 we want to defer to the `__spec__.loader` if available. The first step on this journey is to check that `loader == __spec__.loader` and issue another warning if it is not. This commit does that. Since this is a PoC, only manual testing for now. ```python # /tmp/foo.py import warnings import bar warnings.warn_explicit( 'warning!', RuntimeWarning, 'bar.py', 2, module='bar knee', module_globals=bar.__dict__, ) ``` ```python # /tmp/bar.py import sys import os import pathlib # __loader__ = pathlib.Path() ``` Then running this: `./python.exe -Wdefault /tmp/foo.py` Produces: ``` bar.py:2: RuntimeWarning: warning! import os ``` Uncomment the `__loader__ = ` line in `bar.py` and try it again: ``` sys:1: ImportWarning: Module bar; __loader__ != __spec__.loader (<_frozen_importlib_external.SourceFileLoader object at 0x109f7dfa0> != PosixPath('.')) bar.py:2: RuntimeWarning: warning! import os ``` Automerge-Triggered-By: GH:warsaw
Diffstat (limited to 'Python')
-rw-r--r--Python/_warnings.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/Python/_warnings.c b/Python/_warnings.c
index 1b9e107..0d4c50f 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -977,6 +977,7 @@ warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
static PyObject *
get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno)
{
+ PyObject *external;
PyObject *loader;
PyObject *module_name;
PyObject *get_source;
@@ -984,12 +985,18 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno
PyObject *source_list;
PyObject *source_line;
- /* Check/get the requisite pieces needed for the loader. */
- loader = _PyDict_GetItemWithError(module_globals, &_Py_ID(__loader__));
+ /* stolen from import.c */
+ external = PyObject_GetAttrString(interp->importlib, "_bootstrap_external");
+ if (external == NULL) {
+ return NULL;
+ }
+
+ loader = PyObject_CallMethod(external, "_bless_my_loader", "O", module_globals, NULL);
+ Py_DECREF(external);
if (loader == NULL) {
return NULL;
}
- Py_INCREF(loader);
+
module_name = _PyDict_GetItemWithError(module_globals, &_Py_ID(__name__));
if (!module_name) {
Py_DECREF(loader);