Skip to content

Commit f3b3471

Browse files
author
brett.cannon
committed
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. git-svn-id: http://svn.python.org/projects/python/trunk@62656 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent e99ffc4 commit f3b3471

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

Lib/test/test_warnings.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,77 @@ def test_stacklevel(self):
229229
warning_tests.inner("spam7", stacklevel=9999)
230230
self.assertEqual(os.path.basename(w.filename), "sys")
231231

232+
def test_missing_filename_not_main(self):
233+
# If __file__ is not specified and __main__ is not the module name,
234+
# then __file__ should be set to the module name.
235+
filename = warning_tests.__file__
236+
try:
237+
del warning_tests.__file__
238+
with warnings_state(self.module):
239+
with test_support.catch_warning(self.module) as w:
240+
warning_tests.inner("spam8", stacklevel=1)
241+
self.assertEqual(w.filename, warning_tests.__name__)
242+
finally:
243+
warning_tests.__file__ = filename
244+
245+
def test_missing_filename_main_with_argv(self):
246+
# If __file__ is not specified and the caller is __main__ and sys.argv
247+
# exists, then use sys.argv[0] as the file.
248+
if not hasattr(sys, 'argv'):
249+
return
250+
filename = warning_tests.__file__
251+
module_name = warning_tests.__name__
252+
try:
253+
del warning_tests.__file__
254+
warning_tests.__name__ = '__main__'
255+
with warnings_state(self.module):
256+
with test_support.catch_warning(self.module) as w:
257+
warning_tests.inner('spam9', stacklevel=1)
258+
self.assertEqual(w.filename, sys.argv[0])
259+
finally:
260+
warning_tests.__file__ = filename
261+
warning_tests.__name__ = module_name
262+
263+
def test_missing_filename_main_without_argv(self):
264+
# If __file__ is not specified, the caller is __main__, and sys.argv
265+
# is not set, then '__main__' is the file name.
266+
filename = warning_tests.__file__
267+
module_name = warning_tests.__name__
268+
argv = sys.argv
269+
try:
270+
del warning_tests.__file__
271+
warning_tests.__name__ = '__main__'
272+
del sys.argv
273+
with warnings_state(self.module):
274+
with test_support.catch_warning(self.module) as w:
275+
warning_tests.inner('spam10', stacklevel=1)
276+
self.assertEqual(w.filename, '__main__')
277+
finally:
278+
warning_tests.__file__ = filename
279+
warning_tests.__name__ = module_name
280+
sys.argv = argv
281+
282+
def test_missing_filename_main_with_argv_empty_string(self):
283+
# If __file__ is not specified, the caller is __main__, and sys.argv[0]
284+
# is the empty string, then '__main__ is the file name.
285+
# Tests issue 2743.
286+
file_name = warning_tests.__file__
287+
module_name = warning_tests.__name__
288+
argv = sys.argv
289+
try:
290+
del warning_tests.__file__
291+
warning_tests.__name__ = '__main__'
292+
sys.argv = ['']
293+
with warnings_state(self.module):
294+
with test_support.catch_warning(self.module) as w:
295+
warning_tests.inner('spam11', stacklevel=1)
296+
self.assertEqual(w.filename, '__main__')
297+
finally:
298+
warning_tests.__file__ = file_name
299+
warning_tests.__name__ = module_name
300+
sys.argv = argv
301+
302+
232303

233304
class CWarnTests(BaseTest, WarnTests):
234305
module = c_warnings

Python/_warnings.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,21 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
487487
if (module_str && strcmp(module_str, "__main__") == 0) {
488488
PyObject *argv = PySys_GetObject("argv");
489489
if (argv != NULL && PyList_Size(argv) > 0) {
490+
int is_true;
490491
*filename = PyList_GetItem(argv, 0);
491492
Py_INCREF(*filename);
493+
/* If sys.argv[0] is false, then use '__main__'. */
494+
is_true = PyObject_IsTrue(*filename);
495+
if (is_true < 0) {
496+
Py_DECREF(*filename);
497+
goto handle_error;
498+
}
499+
else if (!is_true) {
500+
Py_DECREF(*filename);
501+
*filename = PyString_FromString("__main__");
502+
if (*filename == NULL)
503+
goto handle_error;
504+
}
492505
}
493506
else {
494507
/* embedded interpreters don't have sys.argv, see bug #839151 */

0 commit comments

Comments
 (0)