@@ -273,7 +273,7 @@ _PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
273
273
return 0 ;
274
274
}
275
275
276
- PyWideStringList copy = PyWideStringList_INIT ;
276
+ PyWideStringList copy = _PyWideStringList_INIT ;
277
277
278
278
size_t size = list2 -> length * sizeof (list2 -> items [0 ]);
279
279
copy .items = PyMem_RawMalloc (size );
@@ -2095,63 +2095,83 @@ config_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions)
2095
2095
2096
2096
2097
2097
static PyStatus
2098
- config_add_warnoption (PyConfig * config , const wchar_t * option )
2098
+ warnoptions_append (PyConfig * config , PyWideStringList * options ,
2099
+ const wchar_t * option )
2099
2100
{
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. */
2100
2105
if (_PyWideStringList_Find (& config -> warnoptions , option )) {
2101
2106
/* Already present: do nothing */
2102
2107
return _PyStatus_OK ();
2103
2108
}
2104
- return PyWideStringList_Append (& config -> warnoptions , option );
2109
+ if (_PyWideStringList_Find (options , option )) {
2110
+ /* Already present: do nothing */
2111
+ return _PyStatus_OK ();
2112
+ }
2113
+ return PyWideStringList_Append (options , option );
2114
+ }
2115
+
2116
+
2117
+ static PyStatus
2118
+ warnoptions_extend (PyConfig * config , PyWideStringList * options ,
2119
+ const PyWideStringList * options2 )
2120
+ {
2121
+ const Py_ssize_t len = options2 -> length ;
2122
+ wchar_t * const * items = options2 -> items ;
2123
+
2124
+ for (Py_ssize_t i = 0 ; i < len ; i ++ ) {
2125
+ PyStatus status = warnoptions_append (config , options , items [i ]);
2126
+ if (_PyStatus_EXCEPTION (status )) {
2127
+ return status ;
2128
+ }
2129
+ }
2130
+ return _PyStatus_OK ();
2105
2131
}
2106
2132
2107
2133
2108
2134
static PyStatus
2109
2135
config_init_warnoptions (PyConfig * config ,
2110
2136
const PyWideStringList * cmdline_warnoptions ,
2111
- const PyWideStringList * env_warnoptions )
2137
+ const PyWideStringList * env_warnoptions ,
2138
+ const PyWideStringList * sys_warnoptions )
2112
2139
{
2113
2140
PyStatus status ;
2141
+ PyWideStringList options = _PyWideStringList_INIT ;
2114
2142
2115
- /* The priority order for warnings configuration is (highest precedence
2116
- * first):
2143
+ /* Priority of warnings options, lowest to highest:
2117
2144
*
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
2123
2145
* - 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
2124
2153
*
2125
- * All settings except the last are passed to the warnings module via
2126
- * the `sys.warnoptions` list. Since the warnings module works on the basis
2127
- * of "the most recently added filter will be checked first", we add
2128
- * the lowest precedence entries first so that later entries override them.
2154
+ * PyConfig.warnoptions is copied to sys.warnoptions. Since the warnings
2155
+ * module works on the basis of " the most recently added filter will be
2156
+ * checked first", we add the lowest precedence entries first so that later
2157
+ * entries override them.
2129
2158
*/
2130
2159
2131
2160
if (config -> dev_mode ) {
2132
- status = config_add_warnoption (config , L"default" );
2161
+ status = warnoptions_append (config , & options , L"default" );
2133
2162
if (_PyStatus_EXCEPTION (status )) {
2134
- return status ;
2163
+ goto error ;
2135
2164
}
2136
2165
}
2137
2166
2138
- Py_ssize_t i ;
2139
- const PyWideStringList * 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
- return status ;
2146
- }
2167
+ status = warnoptions_extend (config , & options , env_warnoptions );
2168
+ if (_PyStatus_EXCEPTION (status )) {
2169
+ goto error ;
2147
2170
}
2148
2171
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
- return status ;
2154
- }
2172
+ status = warnoptions_extend (config , & options , cmdline_warnoptions );
2173
+ if (_PyStatus_EXCEPTION (status )) {
2174
+ goto error ;
2155
2175
}
2156
2176
2157
2177
/* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
@@ -2166,27 +2186,38 @@ config_init_warnoptions(PyConfig *config,
2166
2186
else {
2167
2187
filter = L"default::BytesWarning" ;
2168
2188
}
2169
- status = config_add_warnoption (config , filter );
2189
+ status = warnoptions_append (config , & options , filter );
2170
2190
if (_PyStatus_EXCEPTION (status )) {
2171
- return status ;
2191
+ goto error ;
2172
2192
}
2173
2193
}
2174
2194
2175
- /* Handle early PySys_AddWarnOption() calls */
2176
- status = _PySys_ReadPreinitWarnOptions (config );
2195
+ status = warnoptions_extend (config , & options , sys_warnoptions );
2177
2196
if (_PyStatus_EXCEPTION (status )) {
2178
- return status ;
2197
+ goto error ;
2198
+ }
2199
+
2200
+ /* Always add all PyConfig.warnoptions options */
2201
+ status = _PyWideStringList_Extend (& options , & config -> warnoptions );
2202
+ if (_PyStatus_EXCEPTION (status )) {
2203
+ goto error ;
2179
2204
}
2180
2205
2206
+ _PyWideStringList_Clear (& config -> warnoptions );
2207
+ config -> warnoptions = options ;
2181
2208
return _PyStatus_OK ();
2209
+
2210
+ error :
2211
+ _PyWideStringList_Clear (& options );
2212
+ return status ;
2182
2213
}
2183
2214
2184
2215
2185
2216
static PyStatus
2186
2217
config_update_argv (PyConfig * config , Py_ssize_t opt_index )
2187
2218
{
2188
2219
const PyWideStringList * cmdline_argv = & config -> argv ;
2189
- PyWideStringList config_argv = PyWideStringList_INIT ;
2220
+ PyWideStringList config_argv = _PyWideStringList_INIT ;
2190
2221
2191
2222
/* Copy argv to be able to modify it (to force -c/-m) */
2192
2223
if (cmdline_argv -> length <= opt_index ) {
@@ -2306,8 +2337,9 @@ static PyStatus
2306
2337
config_read_cmdline (PyConfig * config )
2307
2338
{
2308
2339
PyStatus status ;
2309
- PyWideStringList cmdline_warnoptions = PyWideStringList_INIT ;
2310
- PyWideStringList env_warnoptions = PyWideStringList_INIT ;
2340
+ PyWideStringList cmdline_warnoptions = _PyWideStringList_INIT ;
2341
+ PyWideStringList env_warnoptions = _PyWideStringList_INIT ;
2342
+ PyWideStringList sys_warnoptions = _PyWideStringList_INIT ;
2311
2343
2312
2344
if (config -> parse_argv < 0 ) {
2313
2345
config -> parse_argv = 1 ;
@@ -2351,9 +2383,16 @@ config_read_cmdline(PyConfig *config)
2351
2383
}
2352
2384
}
2353
2385
2386
+ /* Handle early PySys_AddWarnOption() calls */
2387
+ status = _PySys_ReadPreinitWarnOptions (& sys_warnoptions );
2388
+ if (_PyStatus_EXCEPTION (status )) {
2389
+ goto done ;
2390
+ }
2391
+
2354
2392
status = config_init_warnoptions (config ,
2355
2393
& cmdline_warnoptions ,
2356
- & env_warnoptions );
2394
+ & env_warnoptions ,
2395
+ & sys_warnoptions );
2357
2396
if (_PyStatus_EXCEPTION (status )) {
2358
2397
goto done ;
2359
2398
}
@@ -2363,6 +2402,7 @@ config_read_cmdline(PyConfig *config)
2363
2402
done :
2364
2403
_PyWideStringList_Clear (& cmdline_warnoptions );
2365
2404
_PyWideStringList_Clear (& env_warnoptions );
2405
+ _PyWideStringList_Clear (& sys_warnoptions );
2366
2406
return status ;
2367
2407
}
2368
2408
@@ -2433,7 +2473,7 @@ PyStatus
2433
2473
PyConfig_Read (PyConfig * config )
2434
2474
{
2435
2475
PyStatus status ;
2436
- PyWideStringList orig_argv = PyWideStringList_INIT ;
2476
+ PyWideStringList orig_argv = _PyWideStringList_INIT ;
2437
2477
2438
2478
status = config_check_struct_size (config );
2439
2479
if (_PyStatus_EXCEPTION (status )) {
0 commit comments