Fix the C implementation of 'warnings' to infer the filename of the module that
raised an exception properly when __file__ is not set, __name__ == '__main__', and sys.argv[0] is a false value. Closes issue2743.
This commit is contained in:
parent
ab9cc1b7ad
commit
64a4bbeb25
|
@ -229,6 +229,77 @@ class WarnTests(unittest.TestCase):
|
||||||
warning_tests.inner("spam7", stacklevel=9999)
|
warning_tests.inner("spam7", stacklevel=9999)
|
||||||
self.assertEqual(os.path.basename(w.filename), "sys")
|
self.assertEqual(os.path.basename(w.filename), "sys")
|
||||||
|
|
||||||
|
def test_missing_filename_not_main(self):
|
||||||
|
# If __file__ is not specified and __main__ is not the module name,
|
||||||
|
# then __file__ should be set to the module name.
|
||||||
|
filename = warning_tests.__file__
|
||||||
|
try:
|
||||||
|
del warning_tests.__file__
|
||||||
|
with warnings_state(self.module):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
warning_tests.inner("spam8", stacklevel=1)
|
||||||
|
self.assertEqual(w.filename, warning_tests.__name__)
|
||||||
|
finally:
|
||||||
|
warning_tests.__file__ = filename
|
||||||
|
|
||||||
|
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.
|
||||||
|
if not hasattr(sys, 'argv'):
|
||||||
|
return
|
||||||
|
filename = warning_tests.__file__
|
||||||
|
module_name = warning_tests.__name__
|
||||||
|
try:
|
||||||
|
del warning_tests.__file__
|
||||||
|
warning_tests.__name__ = '__main__'
|
||||||
|
with warnings_state(self.module):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
warning_tests.inner('spam9', stacklevel=1)
|
||||||
|
self.assertEqual(w.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 test_support.catch_warning(self.module) as w:
|
||||||
|
warning_tests.inner('spam10', stacklevel=1)
|
||||||
|
self.assertEqual(w.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 test_support.catch_warning(self.module) as w:
|
||||||
|
warning_tests.inner('spam11', stacklevel=1)
|
||||||
|
self.assertEqual(w.filename, '__main__')
|
||||||
|
finally:
|
||||||
|
warning_tests.__file__ = file_name
|
||||||
|
warning_tests.__name__ = module_name
|
||||||
|
sys.argv = argv
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CWarnTests(BaseTest, WarnTests):
|
class CWarnTests(BaseTest, WarnTests):
|
||||||
module = c_warnings
|
module = c_warnings
|
||||||
|
|
|
@ -487,8 +487,21 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
||||||
if (module_str && strcmp(module_str, "__main__") == 0) {
|
if (module_str && strcmp(module_str, "__main__") == 0) {
|
||||||
PyObject *argv = PySys_GetObject("argv");
|
PyObject *argv = PySys_GetObject("argv");
|
||||||
if (argv != NULL && PyList_Size(argv) > 0) {
|
if (argv != NULL && PyList_Size(argv) > 0) {
|
||||||
|
int is_true;
|
||||||
*filename = PyList_GetItem(argv, 0);
|
*filename = PyList_GetItem(argv, 0);
|
||||||
Py_INCREF(*filename);
|
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_DECREF(*filename);
|
||||||
|
*filename = PyString_FromString("__main__");
|
||||||
|
if (*filename == NULL)
|
||||||
|
goto handle_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* embedded interpreters don't have sys.argv, see bug #839151 */
|
/* embedded interpreters don't have sys.argv, see bug #839151 */
|
||||||
|
|
Loading…
Reference in New Issue