Index: Include/Python.h =================================================================== --- Include/Python.h (revision 79880) +++ Include/Python.h (working copy) @@ -123,6 +123,9 @@ /* _Py_Mangle is defined in compile.c */ PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); +/* _Py_char2wchar lives in python.c */ +PyAPI_FUNC(wchar_t *) _Py_char2wchar(char *); + /* Convert a possibly signed character to a nonnegative int */ /* XXX This assumes characters are 8 bits wide */ #ifdef __CHAR_UNSIGNED__ Index: Misc/python.man =================================================================== --- Misc/python.man (revision 79880) +++ Misc/python.man (working copy) @@ -394,6 +394,9 @@ If this is set to a non-empty string it is equivalent to specifying the \fB\-v\fP option. If set to an integer, it is equivalent to specifying \fB\-v\fP multiple times. +.IP PYTHONWARNINGS +If this is set to a comma-separated string it is equivalent to +specifying the \fB\-W\fP option for each separate value. .SH AUTHOR The Python Software Foundation: http://www.python.org/psf .SH INTERNET RESOURCES Index: Doc/using/cmdline.rst =================================================================== --- Doc/using/cmdline.rst (revision 79880) +++ Doc/using/cmdline.rst (working copy) @@ -1,5 +1,8 @@ .. highlightlang:: none +.. ATTENTION: You probably should update Misc/python.man, too, if you modify +.. this file. + .. _using-on-general: Command line and environment @@ -306,6 +309,8 @@ :pep:`230` -- Warning framework + :envvar:`PYTHONWARNINGS` + .. cmdoption:: -x @@ -469,6 +474,12 @@ value instead of the value got through the C runtime. Only works on Mac OS X. +.. envvar:: PYTHONWARNINGS + + This is the equivalent to the :option:`-W` option. If set to a comma + separated string, it is equivalent to specifying :option:`-W` multiple + times. + Debug-mode variables ~~~~~~~~~~~~~~~~~~~~ Index: Lib/test/test_warnings.py =================================================================== --- Lib/test/test_warnings.py (revision 79880) +++ Lib/test/test_warnings.py (working copy) @@ -4,6 +4,7 @@ from io import StringIO import sys import unittest +import subprocess from test import support from test import warning_tests @@ -685,6 +686,52 @@ module = py_warnings +class EnvironmentVariableTests(BaseTest): + + def test_single_warning(self): + newenv = os.environ.copy() + newenv["PYTHONWARNINGS"] = "ignore::DeprecationWarning" + p = subprocess.Popen([sys.executable, + "-c", "import sys; sys.stdout.write(str(sys.warnoptions))"], + stdout=subprocess.PIPE, env=newenv) + self.assertEqual(p.stdout.read(), b"['ignore::DeprecationWarning']") + + def test_comma_separated_warnings(self): + newenv = os.environ.copy() + newenv["PYTHONWARNINGS"] = ("ignore::DeprecationWarning," + "ignore::UnicodeWarning") + p = subprocess.Popen([sys.executable, + "-c", "import sys; sys.stdout.write(str(sys.warnoptions))"], + stdout=subprocess.PIPE, env=newenv) + self.assertEqual(p.stdout.read(), + b"['ignore::DeprecationWarning', 'ignore::UnicodeWarning']") + + def test_envvar_and_command_line(self): + newenv = os.environ.copy() + newenv["PYTHONWARNINGS"] = "ignore::DeprecationWarning" + p = subprocess.Popen([sys.executable, "-W" "ignore::UnicodeWarning", + "-c", "import sys; sys.stdout.write(str(sys.warnoptions))"], + stdout=subprocess.PIPE, env=newenv) + self.assertEqual(p.stdout.read(), + b"['ignore::UnicodeWarning', 'ignore::DeprecationWarning']") + + def test_nonascii(self): + newenv = os.environ.copy() + newenv["PYTHONWARNINGS"] = "ignore:DeprecaciónWarning" + newenv["PYTHONIOENCODING"] = "utf-8" + p = subprocess.Popen([sys.executable, + "-c", "import sys; sys.stdout.write(str(sys.warnoptions))"], + stdout=subprocess.PIPE, env=newenv) + self.assertEqual(p.stdout.read(), + "['ignore:DeprecaciónWarning']".encode('utf-8')) + +class CEnvironmentVariableTests(EnvironmentVariableTests): + module = c_warnings + +class PyEnvironmentVariableTests(EnvironmentVariableTests): + module = py_warnings + + def test_main(): py_warnings.onceregistry.clear() c_warnings.onceregistry.clear() @@ -696,6 +743,8 @@ _WarningsTests, CWarningsDisplayTests, PyWarningsDisplayTests, CCatchWarningTests, PyCatchWarningTests, + CEnvironmentVariableTests, + PyEnvironmentVariableTests ) Index: Modules/python.c =================================================================== --- Modules/python.c (revision 79880) +++ Modules/python.c (working copy) @@ -14,8 +14,8 @@ return Py_Main(argc, argv); } #else -static wchar_t* -char2wchar(char* arg) +wchar_t* +_Py_char2wchar(char* arg) { wchar_t *res; #ifdef HAVE_BROKEN_MBSTOWCS @@ -143,7 +143,7 @@ oldloc = strdup(setlocale(LC_ALL, NULL)); setlocale(LC_ALL, ""); for (i = 0; i < argc; i++) { - argv_copy2[i] = argv_copy[i] = char2wchar(argv[i]); + argv_copy2[i] = argv_copy[i] = _Py_char2wchar(argv[i]); if (!argv_copy[i]) return 1; } Index: Modules/main.c =================================================================== --- Modules/main.c (revision 79880) +++ Modules/main.c (working copy) @@ -82,6 +82,7 @@ can be supplied multiple times to increase verbosity\n\ -V : print the Python version number and exit (also --version)\n\ -W arg : warning control; arg is action:message:category:module:lineno\n\ + also PYTHONWARNINGS=arg\n\ -x : skip first line of source, allowing use of non-Unix forms of #!cmd\n\ "; static char *usage_4 = "\ @@ -265,6 +266,9 @@ wchar_t *module = NULL; FILE *fp = stdin; char *p; +#ifdef MS_WINDOWS + wchar_t *wp; +#endif int skipfirstline = 0; int stdin_is_interactive = 0; int help = 0; @@ -401,6 +405,47 @@ (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0') Py_NoUserSiteDirectory = 1; +#ifdef MS_WINDOWS + if (!Py_IgnoreEnvironmentFlag && (wp = _wgetenv(L"PYTHONWARNINGS")) && + *wp != L'\0') { + wchar_t *buf, *warning; + + buf = (wchar_t *)malloc((wcslen(wp) + 1) * sizeof(wchar_t)); + if (buf == NULL) + Py_FatalError( + "not enough memory to copy PYTHONWARNINGS"); + wcscpy(buf, wp); + for (warning = wcstok(buf, L","); + warning != NULL; + warning = wcstok(NULL, L",")) { + PySys_AddWarnOption(warning); + } + free(buf); + } +#else + if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') { + char *buf, *oldloc; + wchar_t *warning; + + buf = (char *)malloc(strlen(p) + 1); + if (buf == NULL) + Py_FatalError( + "not enough memory to copy PYTHONWARNINGS"); + strcpy(buf, p); + oldloc = strdup(setlocale(LC_ALL, NULL)); + setlocale(LC_ALL, ""); + for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) { + if ((warning = _Py_char2wchar(p)) != NULL) { + PySys_AddWarnOption(warning); + free(warning); + } + } + setlocale(LC_ALL, oldloc); + free(oldloc); + free(buf); + } +#endif + if (command == NULL && module == NULL && _PyOS_optind < argc && wcscmp(argv[_PyOS_optind], L"-") != 0) {