Skip to content

Commit e53de3d

Browse files
committed
#7301: decode $PYTHONWARNINGS in the same way as argv, test non-ascii values
1 parent 9b82f99 commit e53de3d

File tree

4 files changed

+54
-16
lines changed

4 files changed

+54
-16
lines changed

Include/Python.h

+3
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@
123123
/* _Py_Mangle is defined in compile.c */
124124
PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);
125125

126+
/* _Py_char2wchar lives in python.c */
127+
PyAPI_FUNC(wchar_t *) _Py_char2wchar(char *);
128+
126129
/* Convert a possibly signed character to a nonnegative int */
127130
/* XXX This assumes characters are 8 bits wide */
128131
#ifdef __CHAR_UNSIGNED__

Lib/test/test_warnings.py

+13
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,19 @@ def test_envvar_and_command_line(self):
718718
b"['ignore::UnicodeWarning', 'ignore::DeprecationWarning']")
719719
self.assertEqual(p.wait(), 0)
720720

721+
@unittest.skipUnless(sys.getfilesystemencoding() != 'ascii',
722+
'requires non-ascii filesystemencoding')
723+
def test_nonascii(self):
724+
newenv = os.environ.copy()
725+
newenv["PYTHONWARNINGS"] = "ignore:DeprecaciónWarning"
726+
newenv["PYTHONIOENCODING"] = "utf-8"
727+
p = subprocess.Popen([sys.executable,
728+
"-c", "import sys; sys.stdout.write(str(sys.warnoptions))"],
729+
stdout=subprocess.PIPE, env=newenv)
730+
self.assertEqual(p.communicate()[0],
731+
"['ignore:DeprecaciónWarning']".encode('utf-8'))
732+
self.assertEqual(p.wait(), 0)
733+
721734
class CEnvironmentVariableTests(EnvironmentVariableTests):
722735
module = c_warnings
723736

Modules/main.c

+35-13
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ Py_Main(int argc, wchar_t **argv)
266266
wchar_t *module = NULL;
267267
FILE *fp = stdin;
268268
char *p;
269+
#ifdef MS_WINDOWS
270+
wchar_t *wp;
271+
#endif
269272
int skipfirstline = 0;
270273
int stdin_is_interactive = 0;
271274
int help = 0;
@@ -402,29 +405,48 @@ Py_Main(int argc, wchar_t **argv)
402405
(p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0')
403406
Py_NoUserSiteDirectory = 1;
404407

408+
#ifdef MS_WINDOWS
409+
if (!Py_IgnoreEnvironmentFlag && (wp = _wgetenv(L"PYTHONWARNINGS")) &&
410+
*wp != L'\0') {
411+
wchar_t *buf, *warning;
412+
413+
buf = (wchar_t *)malloc((wcslen(wp) + 1) * sizeof(wchar_t));
414+
if (buf == NULL)
415+
Py_FatalError(
416+
"not enough memory to copy PYTHONWARNINGS");
417+
wcscpy(buf, wp);
418+
for (warning = wcstok(buf, L",");
419+
warning != NULL;
420+
warning = wcstok(NULL, L",")) {
421+
PySys_AddWarnOption(warning);
422+
}
423+
free(buf);
424+
}
425+
#else
405426
if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') {
406-
char *buf, *warning;
427+
char *buf, *oldloc;
428+
wchar_t *warning;
407429

430+
/* settle for strtok here as there's no one standard
431+
C89 wcstok */
408432
buf = (char *)malloc(strlen(p) + 1);
409433
if (buf == NULL)
410434
Py_FatalError(
411435
"not enough memory to copy PYTHONWARNINGS");
412436
strcpy(buf, p);
413-
for (warning = strtok(buf, ",");
414-
warning != NULL;
415-
warning = strtok(NULL, ",")) {
416-
wchar_t *wide_warning;
417-
size_t len = strlen(buf);
418-
wide_warning = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
419-
if (wide_warning == NULL)
420-
Py_FatalError(
421-
"not enough memory to copy PYTHONWARNINGS");
422-
mbstowcs(wide_warning, warning, len);
423-
PySys_AddWarnOption(wide_warning);
424-
free(wide_warning);
437+
oldloc = strdup(setlocale(LC_ALL, NULL));
438+
setlocale(LC_ALL, "");
439+
for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) {
440+
if ((warning = _Py_char2wchar(p)) != NULL) {
441+
PySys_AddWarnOption(warning);
442+
free(warning);
443+
}
425444
}
445+
setlocale(LC_ALL, oldloc);
446+
free(oldloc);
426447
free(buf);
427448
}
449+
#endif
428450

429451
if (command == NULL && module == NULL && _PyOS_optind < argc &&
430452
wcscmp(argv[_PyOS_optind], L"-") != 0)

Modules/python.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ wmain(int argc, wchar_t **argv)
1414
return Py_Main(argc, argv);
1515
}
1616
#else
17-
static wchar_t*
18-
char2wchar(char* arg)
17+
wchar_t*
18+
_Py_char2wchar(char* arg)
1919
{
2020
wchar_t *res;
2121
#ifdef HAVE_BROKEN_MBSTOWCS
@@ -143,7 +143,7 @@ main(int argc, char **argv)
143143
oldloc = strdup(setlocale(LC_ALL, NULL));
144144
setlocale(LC_ALL, "");
145145
for (i = 0; i < argc; i++) {
146-
argv_copy2[i] = argv_copy[i] = char2wchar(argv[i]);
146+
argv_copy2[i] = argv_copy[i] = _Py_char2wchar(argv[i]);
147147
if (!argv_copy[i])
148148
return 1;
149149
}

0 commit comments

Comments
 (0)