mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
bpo-33375: Get filename for warnings from frame.f_code.co_filename (GH-6622)
More consistent with how other parts of Python find the filename (e.g. tracebacks and pdb).
This commit is contained in:
parent
3b0b90c8c3
commit
11a896652e
4 changed files with 19 additions and 155 deletions
|
@ -441,78 +441,14 @@ class WarnTests(BaseTest):
|
||||||
self.assertEqual(len(w), 1)
|
self.assertEqual(len(w), 1)
|
||||||
self.assertEqual(w[0].filename, __file__)
|
self.assertEqual(w[0].filename, __file__)
|
||||||
|
|
||||||
def test_missing_filename_not_main(self):
|
def test_exec_filename(self):
|
||||||
# If __file__ is not specified and __main__ is not the module name,
|
filename = "<warnings-test>"
|
||||||
# then __file__ should be set to the module name.
|
codeobj = compile(("import warnings\n"
|
||||||
filename = warning_tests.__file__
|
"warnings.warn('hello', UserWarning)"),
|
||||||
try:
|
filename, "exec")
|
||||||
del warning_tests.__file__
|
with original_warnings.catch_warnings(record=True) as w:
|
||||||
with warnings_state(self.module):
|
exec(codeobj)
|
||||||
with original_warnings.catch_warnings(record=True,
|
self.assertEqual(w[0].filename, filename)
|
||||||
module=self.module) as w:
|
|
||||||
warning_tests.inner("spam8", stacklevel=1)
|
|
||||||
self.assertEqual(w[-1].filename, warning_tests.__name__)
|
|
||||||
finally:
|
|
||||||
warning_tests.__file__ = filename
|
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(sys, 'argv'), 'test needs sys.argv')
|
|
||||||
def test_missing_filename_main_with_argv(self):
|
|
||||||
# If __file__ is not specified and the caller is __main__ and sys.argv
|
|
||||||
# exists, then use sys.argv[0] as the file.
|
|
||||||
filename = warning_tests.__file__
|
|
||||||
module_name = warning_tests.__name__
|
|
||||||
try:
|
|
||||||
del warning_tests.__file__
|
|
||||||
warning_tests.__name__ = '__main__'
|
|
||||||
with warnings_state(self.module):
|
|
||||||
with original_warnings.catch_warnings(record=True,
|
|
||||||
module=self.module) as w:
|
|
||||||
warning_tests.inner('spam9', stacklevel=1)
|
|
||||||
self.assertEqual(w[-1].filename, sys.argv[0])
|
|
||||||
finally:
|
|
||||||
warning_tests.__file__ = filename
|
|
||||||
warning_tests.__name__ = module_name
|
|
||||||
|
|
||||||
def test_missing_filename_main_without_argv(self):
|
|
||||||
# If __file__ is not specified, the caller is __main__, and sys.argv
|
|
||||||
# is not set, then '__main__' is the file name.
|
|
||||||
filename = warning_tests.__file__
|
|
||||||
module_name = warning_tests.__name__
|
|
||||||
argv = sys.argv
|
|
||||||
try:
|
|
||||||
del warning_tests.__file__
|
|
||||||
warning_tests.__name__ = '__main__'
|
|
||||||
del sys.argv
|
|
||||||
with warnings_state(self.module):
|
|
||||||
with original_warnings.catch_warnings(record=True,
|
|
||||||
module=self.module) as w:
|
|
||||||
warning_tests.inner('spam10', stacklevel=1)
|
|
||||||
self.assertEqual(w[-1].filename, '__main__')
|
|
||||||
finally:
|
|
||||||
warning_tests.__file__ = filename
|
|
||||||
warning_tests.__name__ = module_name
|
|
||||||
sys.argv = argv
|
|
||||||
|
|
||||||
def test_missing_filename_main_with_argv_empty_string(self):
|
|
||||||
# If __file__ is not specified, the caller is __main__, and sys.argv[0]
|
|
||||||
# is the empty string, then '__main__ is the file name.
|
|
||||||
# Tests issue 2743.
|
|
||||||
file_name = warning_tests.__file__
|
|
||||||
module_name = warning_tests.__name__
|
|
||||||
argv = sys.argv
|
|
||||||
try:
|
|
||||||
del warning_tests.__file__
|
|
||||||
warning_tests.__name__ = '__main__'
|
|
||||||
sys.argv = ['']
|
|
||||||
with warnings_state(self.module):
|
|
||||||
with original_warnings.catch_warnings(record=True,
|
|
||||||
module=self.module) as w:
|
|
||||||
warning_tests.inner('spam11', stacklevel=1)
|
|
||||||
self.assertEqual(w[-1].filename, '__main__')
|
|
||||||
finally:
|
|
||||||
warning_tests.__file__ = file_name
|
|
||||||
warning_tests.__name__ = module_name
|
|
||||||
sys.argv = argv
|
|
||||||
|
|
||||||
def test_warn_explicit_non_ascii_filename(self):
|
def test_warn_explicit_non_ascii_filename(self):
|
||||||
with original_warnings.catch_warnings(record=True,
|
with original_warnings.catch_warnings(record=True,
|
||||||
|
@ -1245,9 +1181,7 @@ class A:
|
||||||
a=A()
|
a=A()
|
||||||
"""
|
"""
|
||||||
rc, out, err = assert_python_ok("-c", code)
|
rc, out, err = assert_python_ok("-c", code)
|
||||||
# note: "__main__" filename is not correct, it should be the name
|
self.assertEqual(err.decode(), '<string>:7: UserWarning: test')
|
||||||
# of the script
|
|
||||||
self.assertEqual(err.decode(), '__main__:7: UserWarning: test')
|
|
||||||
|
|
||||||
def test_late_resource_warning(self):
|
def test_late_resource_warning(self):
|
||||||
# Issue #21925: Emitting a ResourceWarning late during the Python
|
# Issue #21925: Emitting a ResourceWarning late during the Python
|
||||||
|
|
|
@ -303,28 +303,16 @@ def warn(message, category=None, stacklevel=1, source=None):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except ValueError:
|
except ValueError:
|
||||||
globals = sys.__dict__
|
globals = sys.__dict__
|
||||||
|
filename = "sys"
|
||||||
lineno = 1
|
lineno = 1
|
||||||
else:
|
else:
|
||||||
globals = frame.f_globals
|
globals = frame.f_globals
|
||||||
|
filename = frame.f_code.co_filename
|
||||||
lineno = frame.f_lineno
|
lineno = frame.f_lineno
|
||||||
if '__name__' in globals:
|
if '__name__' in globals:
|
||||||
module = globals['__name__']
|
module = globals['__name__']
|
||||||
else:
|
else:
|
||||||
module = "<string>"
|
module = "<string>"
|
||||||
filename = globals.get('__file__')
|
|
||||||
if filename:
|
|
||||||
fnl = filename.lower()
|
|
||||||
if fnl.endswith(".pyc"):
|
|
||||||
filename = filename[:-1]
|
|
||||||
else:
|
|
||||||
if module == "__main__":
|
|
||||||
try:
|
|
||||||
filename = sys.argv[0]
|
|
||||||
except AttributeError:
|
|
||||||
# embedded interpreters don't have sys.argv, see bug #839151
|
|
||||||
filename = '__main__'
|
|
||||||
if not filename:
|
|
||||||
filename = module
|
|
||||||
registry = globals.setdefault("__warningregistry__", {})
|
registry = globals.setdefault("__warningregistry__", {})
|
||||||
warn_explicit(message, category, filename, lineno, module, registry,
|
warn_explicit(message, category, filename, lineno, module, registry,
|
||||||
globals, source)
|
globals, source)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
The warnings module now finds the Python file associated with a warning from
|
||||||
|
the code object, rather than the frame's global namespace. This is
|
||||||
|
consistent with how tracebacks and pdb find filenames, and should work
|
||||||
|
better for dynamically executed code.
|
|
@ -671,7 +671,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
||||||
{
|
{
|
||||||
PyObject *globals;
|
PyObject *globals;
|
||||||
|
|
||||||
/* Setup globals and lineno. */
|
/* Setup globals, filename and lineno. */
|
||||||
PyFrameObject *f = PyThreadState_GET()->frame;
|
PyFrameObject *f = PyThreadState_GET()->frame;
|
||||||
// Stack level comparisons to Python code is off by one as there is no
|
// Stack level comparisons to Python code is off by one as there is no
|
||||||
// warnings-related stack level to avoid.
|
// warnings-related stack level to avoid.
|
||||||
|
@ -688,10 +688,13 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
||||||
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
globals = PyThreadState_Get()->interp->sysdict;
|
globals = PyThreadState_Get()->interp->sysdict;
|
||||||
|
*filename = PyUnicode_FromString("sys");
|
||||||
*lineno = 1;
|
*lineno = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
globals = f->f_globals;
|
globals = f->f_globals;
|
||||||
|
*filename = f->f_code->co_filename;
|
||||||
|
Py_INCREF(*filename);
|
||||||
*lineno = PyFrame_GetLineNumber(f);
|
*lineno = PyFrame_GetLineNumber(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,71 +729,6 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
||||||
goto handle_error;
|
goto handle_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup filename. */
|
|
||||||
*filename = PyDict_GetItemString(globals, "__file__");
|
|
||||||
if (*filename != NULL && PyUnicode_Check(*filename)) {
|
|
||||||
Py_ssize_t len;
|
|
||||||
int kind;
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
if (PyUnicode_READY(*filename))
|
|
||||||
goto handle_error;
|
|
||||||
|
|
||||||
len = PyUnicode_GetLength(*filename);
|
|
||||||
kind = PyUnicode_KIND(*filename);
|
|
||||||
data = PyUnicode_DATA(*filename);
|
|
||||||
|
|
||||||
#define ascii_lower(c) ((c <= 127) ? Py_TOLOWER(c) : 0)
|
|
||||||
/* if filename.lower().endswith(".pyc"): */
|
|
||||||
if (len >= 4 &&
|
|
||||||
PyUnicode_READ(kind, data, len-4) == '.' &&
|
|
||||||
ascii_lower(PyUnicode_READ(kind, data, len-3)) == 'p' &&
|
|
||||||
ascii_lower(PyUnicode_READ(kind, data, len-2)) == 'y' &&
|
|
||||||
ascii_lower(PyUnicode_READ(kind, data, len-1)) == 'c')
|
|
||||||
{
|
|
||||||
*filename = PyUnicode_Substring(*filename, 0,
|
|
||||||
PyUnicode_GET_LENGTH(*filename)-1);
|
|
||||||
if (*filename == NULL)
|
|
||||||
goto handle_error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Py_INCREF(*filename);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*filename = NULL;
|
|
||||||
if (*module != Py_None && _PyUnicode_EqualToASCIIString(*module, "__main__")) {
|
|
||||||
PyObject *argv = _PySys_GetObjectId(&PyId_argv);
|
|
||||||
/* PyList_Check() is needed because sys.argv is set to None during
|
|
||||||
Python finalization */
|
|
||||||
if (argv != NULL && PyList_Check(argv) && PyList_Size(argv) > 0) {
|
|
||||||
int is_true;
|
|
||||||
*filename = PyList_GetItem(argv, 0);
|
|
||||||
Py_INCREF(*filename);
|
|
||||||
/* If sys.argv[0] is false, then use '__main__'. */
|
|
||||||
is_true = PyObject_IsTrue(*filename);
|
|
||||||
if (is_true < 0) {
|
|
||||||
Py_DECREF(*filename);
|
|
||||||
goto handle_error;
|
|
||||||
}
|
|
||||||
else if (!is_true) {
|
|
||||||
Py_SETREF(*filename, PyUnicode_FromString("__main__"));
|
|
||||||
if (*filename == NULL)
|
|
||||||
goto handle_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* embedded interpreters don't have sys.argv, see bug #839151 */
|
|
||||||
*filename = PyUnicode_FromString("__main__");
|
|
||||||
if (*filename == NULL)
|
|
||||||
goto handle_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*filename == NULL) {
|
|
||||||
*filename = *module;
|
|
||||||
Py_INCREF(*filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
handle_error:
|
handle_error:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue