Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc9ed9e6

Browse files
bpo-38317: Fix PyConfig.warnoptions priority (GH-16478)
Fix warnings options priority: PyConfig.warnoptions has the highestpriority, as stated in the PEP 587.* Document options order in PyConfig.warnoptions documentation.* Make PyWideStringList_INIT macro private: replace "Py" prefix with "_Py".* test_embed: add test_init_warnoptions().(cherry picked from commitfb4ae15)Co-authored-by: Victor Stinner <vstinner@redhat.com>
1 parent19cd595 commitc9ed9e6

File tree

10 files changed

+185
-51
lines changed

10 files changed

+185
-51
lines changed

‎Doc/c-api/init_config.rst‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,13 @@ PyConfig
704704
705705
.. c:member:: PyWideStringList warnoptions
706706
707-
Options of the :mod:`warnings` module to build warnings filters.
707+
:data:`sys.warnoptions`: options of the :mod:`warnings` module to build
708+
warnings filters: lowest to highest priority.
709+
710+
The :mod:`warnings` module adds :data:`sys.warnoptions` in the reverse
711+
order: the last :c:member:`PyConfig.warnoptions` item becomes the first
712+
item of :data:`warnings.filters` which is checked first (highest
713+
priority).
708714
709715
.. c:member:: int write_bytecode
710716

‎Include/cpython/initconfig.h‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ typedef struct {
220220
wchar_t*program_name;
221221

222222
PyWideStringListxoptions;/* Command line -X options */
223-
PyWideStringListwarnoptions;/* Warnings options */
223+
224+
/* Warnings options: lowest to highest priority. warnings.filters
225+
is built in the reverse order (highest to lowest priority). */
226+
PyWideStringListwarnoptions;
224227

225228
/* If equal to zero, disable the import of the module site and the
226229
site-dependent manipulations of sys.path that it entails. Also disable

‎Include/internal/pycore_initconfig.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extern "C" {
4545

4646
/* --- PyWideStringList ------------------------------------------------ */
4747

48-
#definePyWideStringList_INIT (PyWideStringList){.length = 0, .items = NULL}
48+
#define_PyWideStringList_INIT (PyWideStringList){.length = 0, .items = NULL}
4949

5050
#ifndefNDEBUG
5151
PyAPI_FUNC(int)_PyWideStringList_CheckConsistency(constPyWideStringList*list);

‎Include/internal/pycore_pylifecycle.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ extern PyStatus _PySys_Create(
4141
PyInterpreterState*interp,
4242
PyObject**sysmod_p);
4343
externPyStatus_PySys_SetPreliminaryStderr(PyObject*sysdict);
44-
externPyStatus_PySys_ReadPreinitWarnOptions(PyConfig*config);
44+
externPyStatus_PySys_ReadPreinitWarnOptions(PyWideStringList*options);
4545
externPyStatus_PySys_ReadPreinitXOptions(PyConfig*config);
4646
externint_PySys_InitMain(
4747
_PyRuntimeState*runtime,

‎Lib/test/test_embed.py‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,9 @@ def test_init_from_config(self):
746746
'cmdline_xoption',
747747
],
748748
'warnoptions': [
749-
'config_warnoption',
750749
'cmdline_warnoption',
751750
'default::BytesWarning',
751+
'config_warnoption',
752752
],
753753
'run_command':'pass\n',
754754

@@ -951,9 +951,9 @@ def test_init_sys_add(self):
951951
'faulthandler',
952952
],
953953
'warnoptions': [
954-
'ignore:::config_warnoption',
955954
'ignore:::cmdline_warnoption',
956955
'ignore:::sysadd_warnoption',
956+
'ignore:::config_warnoption',
957957
],
958958
}
959959
self.check_all_configs("test_init_sys_add",config,api=API_PYTHON)
@@ -1267,6 +1267,30 @@ def get_func(name):
12671267
self.assertEqual(Py_GetProgramFullPath(),config['executable'])
12681268
self.assertEqual(Py_GetPythonHome(),config['home'])
12691269

1270+
deftest_init_warnoptions(self):
1271+
# lowest to highest priority
1272+
warnoptions= [
1273+
'ignore:::PyConfig_Insert0',# PyWideStringList_Insert(0)
1274+
'default',# PyConfig.dev_mode=1
1275+
'ignore:::env1',# PYTHONWARNINGS env var
1276+
'ignore:::env2',# PYTHONWARNINGS env var
1277+
'ignore:::cmdline1',# -W opt command line option
1278+
'ignore:::cmdline2',# -W opt command line option
1279+
'default::BytesWarning',# PyConfig.bytes_warnings=1
1280+
'ignore:::PySys_AddWarnOption1',# PySys_AddWarnOption()
1281+
'ignore:::PySys_AddWarnOption2',# PySys_AddWarnOption()
1282+
'ignore:::PyConfig_BeforeRead',# PyConfig.warnoptions
1283+
'ignore:::PyConfig_AfterRead']# PyWideStringList_Append()
1284+
preconfig=dict(allocator=PYMEM_ALLOCATOR_DEBUG)
1285+
config= {
1286+
'dev_mode':1,
1287+
'faulthandler':1,
1288+
'bytes_warning':1,
1289+
'warnoptions':warnoptions,
1290+
}
1291+
self.check_all_configs("test_init_warnoptions",config,preconfig,
1292+
api=API_PYTHON)
1293+
12701294

12711295
classAuditingTests(EmbeddingTestsMixin,unittest.TestCase):
12721296
deftest_open_code_hook(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix warnings options priority: ``PyConfig.warnoptions`` has the highest
2+
priority, as stated in the:pep:`587`.

‎Programs/_testembed.c‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,64 @@ static int test_init_setpythonhome(void)
16031603
}
16041604

16051605

1606+
staticinttest_init_warnoptions(void)
1607+
{
1608+
PyStatusstatus;
1609+
putenv("PYTHONWARNINGS=ignore:::env1,ignore:::env2");
1610+
1611+
PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption1");
1612+
PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption2");
1613+
1614+
PyConfigconfig;
1615+
config.struct_size=sizeof(PyConfig);
1616+
1617+
status=PyConfig_InitPythonConfig(&config);
1618+
if (PyStatus_Exception(status)) {
1619+
Py_ExitStatusException(status);
1620+
}
1621+
1622+
config.dev_mode=1;
1623+
config.bytes_warning=1;
1624+
1625+
config_set_program_name(&config);
1626+
1627+
status=PyWideStringList_Append(&config.warnoptions,
1628+
L"ignore:::PyConfig_BeforeRead");
1629+
if (PyStatus_Exception(status)) {
1630+
Py_ExitStatusException(status);
1631+
}
1632+
1633+
wchar_t*argv[]= {
1634+
L"python3",
1635+
L"-Wignore:::cmdline1",
1636+
L"-Wignore:::cmdline2"};
1637+
config_set_argv(&config,Py_ARRAY_LENGTH(argv),argv);
1638+
config.parse_argv=1;
1639+
1640+
status=PyConfig_Read(&config);
1641+
if (PyStatus_Exception(status)) {
1642+
Py_ExitStatusException(status);
1643+
}
1644+
1645+
status=PyWideStringList_Append(&config.warnoptions,
1646+
L"ignore:::PyConfig_AfterRead");
1647+
if (PyStatus_Exception(status)) {
1648+
Py_ExitStatusException(status);
1649+
}
1650+
1651+
status=PyWideStringList_Insert(&config.warnoptions,
1652+
0,L"ignore:::PyConfig_Insert0");
1653+
if (PyStatus_Exception(status)) {
1654+
Py_ExitStatusException(status);
1655+
}
1656+
1657+
init_from_config_clear(&config);
1658+
dump_config();
1659+
Py_Finalize();
1660+
return0;
1661+
}
1662+
1663+
16061664
staticvoidconfigure_init_main(PyConfig*config)
16071665
{
16081666
wchar_t*argv[]= {
@@ -1746,6 +1804,7 @@ static struct TestCase TestCases[] = {
17461804
{"test_init_setpath",test_init_setpath},
17471805
{"test_init_setpath_config",test_init_setpath_config},
17481806
{"test_init_setpythonhome",test_init_setpythonhome},
1807+
{"test_init_warnoptions",test_init_warnoptions},
17491808
{"test_run_main",test_run_main},
17501809

17511810
{"test_open_code_hook",test_open_code_hook},

‎Python/initconfig.c‎

Lines changed: 82 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ _PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
273273
return0;
274274
}
275275

276-
PyWideStringListcopy=PyWideStringList_INIT;
276+
PyWideStringListcopy=_PyWideStringList_INIT;
277277

278278
size_tsize=list2->length*sizeof(list2->items[0]);
279279
copy.items=PyMem_RawMalloc(size);
@@ -2095,63 +2095,83 @@ config_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions)
20952095

20962096

20972097
staticPyStatus
2098-
config_add_warnoption(PyConfig*config,constwchar_t*option)
2098+
warnoptions_append(PyConfig*config,PyWideStringList*options,
2099+
constwchar_t*option)
20992100
{
2101+
/* config_init_warnoptions() add existing config warnoptions at the end:
2102+
ensure that the new option is not already present in this list to
2103+
prevent change the options order whne config_init_warnoptions() is
2104+
called twice. */
21002105
if (_PyWideStringList_Find(&config->warnoptions,option)) {
21012106
/* Already present: do nothing */
21022107
return_PyStatus_OK();
21032108
}
2104-
returnPyWideStringList_Append(&config->warnoptions,option);
2109+
if (_PyWideStringList_Find(options,option)) {
2110+
/* Already present: do nothing */
2111+
return_PyStatus_OK();
2112+
}
2113+
returnPyWideStringList_Append(options,option);
2114+
}
2115+
2116+
2117+
staticPyStatus
2118+
warnoptions_extend(PyConfig*config,PyWideStringList*options,
2119+
constPyWideStringList*options2)
2120+
{
2121+
constPy_ssize_tlen=options2->length;
2122+
wchar_t*const*items=options2->items;
2123+
2124+
for (Py_ssize_ti=0;i<len;i++) {
2125+
PyStatusstatus=warnoptions_append(config,options,items[i]);
2126+
if (_PyStatus_EXCEPTION(status)) {
2127+
returnstatus;
2128+
}
2129+
}
2130+
return_PyStatus_OK();
21052131
}
21062132

21072133

21082134
staticPyStatus
21092135
config_init_warnoptions(PyConfig*config,
21102136
constPyWideStringList*cmdline_warnoptions,
2111-
constPyWideStringList*env_warnoptions)
2137+
constPyWideStringList*env_warnoptions,
2138+
constPyWideStringList*sys_warnoptions)
21122139
{
21132140
PyStatusstatus;
2141+
PyWideStringListoptions=_PyWideStringList_INIT;
21142142

2115-
/* The priority order for warnings configuration is (highest precedence
2116-
* first):
2143+
/* Priority of warnings options, lowest to highest:
21172144
*
2118-
* - early PySys_AddWarnOption() calls
2119-
* - the BytesWarning filter, if needed ('-b', '-bb')
2120-
* - any '-W' command line options; then
2121-
* - the 'PYTHONWARNINGS' environment variable; then
2122-
* - the dev mode filter ('-X dev', 'PYTHONDEVMODE'); then
21232145
* - any implicit filters added by _warnings.c/warnings.py
2146+
* - PyConfig.dev_mode: "default" filter
2147+
* - PYTHONWARNINGS environment variable
2148+
* - '-W' command line options
2149+
* - PyConfig.bytes_warning ('-b' and '-bb' command line options):
2150+
* "default::BytesWarning" or "error::BytesWarning" filter
2151+
* - early PySys_AddWarnOption() calls
2152+
* - PyConfig.warnoptions
21242153
*
2125-
*All settings except the last are passed tothe warnings module via
2126-
*the `sys.warnoptions` list. Sincethewarnings module works on the basis
2127-
*of "the most recently added filter will be checkedfirst", we add
2128-
*the lowest precedence entries first so that laterentries override them.
2154+
*PyConfig.warnoptions is copied to sys.warnoptions. Sincethe warnings
2155+
*module works on the basis of "themost recently added filter will be
2156+
*checked first", we add the lowest precedence entriesfirst so that later
2157+
* entries override them.
21292158
*/
21302159

21312160
if (config->dev_mode) {
2132-
status=config_add_warnoption(config,L"default");
2161+
status=warnoptions_append(config,&options,L"default");
21332162
if (_PyStatus_EXCEPTION(status)) {
2134-
returnstatus;
2163+
gotoerror;
21352164
}
21362165
}
21372166

2138-
Py_ssize_ti;
2139-
constPyWideStringList*options;
2140-
2141-
options=env_warnoptions;
2142-
for (i=0;i<options->length;i++) {
2143-
status=config_add_warnoption(config,options->items[i]);
2144-
if (_PyStatus_EXCEPTION(status)) {
2145-
returnstatus;
2146-
}
2167+
status=warnoptions_extend(config,&options,env_warnoptions);
2168+
if (_PyStatus_EXCEPTION(status)) {
2169+
gotoerror;
21472170
}
21482171

2149-
options=cmdline_warnoptions;
2150-
for (i=0;i<options->length;i++) {
2151-
status=config_add_warnoption(config,options->items[i]);
2152-
if (_PyStatus_EXCEPTION(status)) {
2153-
returnstatus;
2154-
}
2172+
status=warnoptions_extend(config,&options,cmdline_warnoptions);
2173+
if (_PyStatus_EXCEPTION(status)) {
2174+
gotoerror;
21552175
}
21562176

21572177
/* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
@@ -2166,27 +2186,38 @@ config_init_warnoptions(PyConfig *config,
21662186
else {
21672187
filter=L"default::BytesWarning";
21682188
}
2169-
status=config_add_warnoption(config,filter);
2189+
status=warnoptions_append(config,&options,filter);
21702190
if (_PyStatus_EXCEPTION(status)) {
2171-
returnstatus;
2191+
gotoerror;
21722192
}
21732193
}
21742194

2175-
/* Handle early PySys_AddWarnOption() calls */
2176-
status=_PySys_ReadPreinitWarnOptions(config);
2195+
status=warnoptions_extend(config,&options,sys_warnoptions);
21772196
if (_PyStatus_EXCEPTION(status)) {
2178-
returnstatus;
2197+
gotoerror;
2198+
}
2199+
2200+
/* Always add all PyConfig.warnoptions options */
2201+
status=_PyWideStringList_Extend(&options,&config->warnoptions);
2202+
if (_PyStatus_EXCEPTION(status)) {
2203+
gotoerror;
21792204
}
21802205

2206+
_PyWideStringList_Clear(&config->warnoptions);
2207+
config->warnoptions=options;
21812208
return_PyStatus_OK();
2209+
2210+
error:
2211+
_PyWideStringList_Clear(&options);
2212+
returnstatus;
21822213
}
21832214

21842215

21852216
staticPyStatus
21862217
config_update_argv(PyConfig*config,Py_ssize_topt_index)
21872218
{
21882219
constPyWideStringList*cmdline_argv=&config->argv;
2189-
PyWideStringListconfig_argv=PyWideStringList_INIT;
2220+
PyWideStringListconfig_argv=_PyWideStringList_INIT;
21902221

21912222
/* Copy argv to be able to modify it (to force -c/-m) */
21922223
if (cmdline_argv->length <=opt_index) {
@@ -2270,8 +2301,9 @@ static PyStatus
22702301
config_read_cmdline(PyConfig*config)
22712302
{
22722303
PyStatusstatus;
2273-
PyWideStringListcmdline_warnoptions=PyWideStringList_INIT;
2274-
PyWideStringListenv_warnoptions=PyWideStringList_INIT;
2304+
PyWideStringListcmdline_warnoptions=_PyWideStringList_INIT;
2305+
PyWideStringListenv_warnoptions=_PyWideStringList_INIT;
2306+
PyWideStringListsys_warnoptions=_PyWideStringList_INIT;
22752307

22762308
if (config->parse_argv<0) {
22772309
config->parse_argv=1;
@@ -2304,9 +2336,16 @@ config_read_cmdline(PyConfig *config)
23042336
}
23052337
}
23062338

2339+
/* Handle early PySys_AddWarnOption() calls */
2340+
status=_PySys_ReadPreinitWarnOptions(&sys_warnoptions);
2341+
if (_PyStatus_EXCEPTION(status)) {
2342+
gotodone;
2343+
}
2344+
23072345
status=config_init_warnoptions(config,
23082346
&cmdline_warnoptions,
2309-
&env_warnoptions);
2347+
&env_warnoptions,
2348+
&sys_warnoptions);
23102349
if (_PyStatus_EXCEPTION(status)) {
23112350
gotodone;
23122351
}
@@ -2316,6 +2355,7 @@ config_read_cmdline(PyConfig *config)
23162355
done:
23172356
_PyWideStringList_Clear(&cmdline_warnoptions);
23182357
_PyWideStringList_Clear(&env_warnoptions);
2358+
_PyWideStringList_Clear(&sys_warnoptions);
23192359
returnstatus;
23202360
}
23212361

@@ -2386,7 +2426,7 @@ PyStatus
23862426
PyConfig_Read(PyConfig*config)
23872427
{
23882428
PyStatusstatus;
2389-
PyWideStringListorig_argv=PyWideStringList_INIT;
2429+
PyWideStringListorig_argv=_PyWideStringList_INIT;
23902430

23912431
status=config_check_struct_size(config);
23922432
if (_PyStatus_EXCEPTION(status)) {

‎Python/preconfig.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ _Py_SetFileSystemEncoding(const char *encoding, const char *errors)
7575
PyStatus
7676
_PyArgv_AsWstrList(const_PyArgv*args,PyWideStringList*list)
7777
{
78-
PyWideStringListwargv=PyWideStringList_INIT;
78+
PyWideStringListwargv=_PyWideStringList_INIT;
7979
if (args->use_bytes_argv) {
8080
size_tsize=sizeof(wchar_t*)*args->argc;
8181
wargv.items= (wchar_t**)PyMem_RawMalloc(size);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2026 Movatter.jp