diff options
-rw-r--r-- | Lib/test/test_warnings.py | 71 | ||||
-rw-r--r-- | Python/_warnings.c | 13 |
2 files changed, 84 insertions, 0 deletions
diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py index 9fca080..5df0b90 100644 --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -229,6 +229,77 @@ class WarnTests(unittest.TestCase): warning_tests.inner("spam7", stacklevel=9999) 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): module = c_warnings diff --git a/Python/_warnings.c b/Python/_warnings.c index 3477fb1..d843af6 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -487,8 +487,21 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, if (module_str && strcmp(module_str, "__main__") == 0) { PyObject *argv = PySys_GetObject("argv"); if (argv != NULL && 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_DECREF(*filename); + *filename = PyString_FromString("__main__"); + if (*filename == NULL) + goto handle_error; + } } else { /* embedded interpreters don't have sys.argv, see bug #839151 */ |