Skip to content

Commit 374c6e1

Browse files
authored
bpo-32030: Add _PyMainInterpreterConfig.warnoptions (#4855)
Add warnoptions and xoptions fields to _PyMainInterpreterConfig.
1 parent 53f7a7c commit 374c6e1

File tree

3 files changed

+104
-47
lines changed

3 files changed

+104
-47
lines changed

Include/pystate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ typedef struct {
5959
int install_signal_handlers;
6060
PyObject *argv; /* sys.argv list, can be NULL */
6161
PyObject *module_search_path; /* sys.path list */
62+
PyObject *warnoptions; /* sys.warnoptions list, can be NULL */
63+
PyObject *xoptions; /* sys._xoptions dict, can be NULL */
6264
} _PyMainInterpreterConfig;
6365

6466
#define _PyMainInterpreterConfig_INIT \

Modules/main.c

Lines changed: 84 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -752,29 +752,67 @@ pymain_parse_cmdline_impl(_PyMain *pymain)
752752

753753

754754
static int
755-
pymain_add_xoptions(_PyMain *pymain)
755+
pymain_add_xoption(PyObject *opts, const wchar_t *s)
756+
{
757+
PyObject *name, *value;
758+
759+
const wchar_t *name_end = wcschr(s, L'=');
760+
if (!name_end) {
761+
name = PyUnicode_FromWideChar(s, -1);
762+
value = Py_True;
763+
Py_INCREF(value);
764+
}
765+
else {
766+
name = PyUnicode_FromWideChar(s, name_end - s);
767+
value = PyUnicode_FromWideChar(name_end + 1, -1);
768+
}
769+
if (name == NULL || value == NULL) {
770+
goto error;
771+
}
772+
if (PyDict_SetItem(opts, name, value) < 0) {
773+
goto error;
774+
}
775+
Py_DECREF(name);
776+
Py_DECREF(value);
777+
return 0;
778+
779+
error:
780+
Py_XDECREF(name);
781+
Py_XDECREF(value);
782+
return -1;
783+
}
784+
785+
static int
786+
pymain_init_xoptions_dict(_PyMain *pymain)
756787
{
757788
_Py_OptList *options = &pymain->cmdline.xoptions;
789+
PyObject *dict = PyDict_New();
790+
if (dict == NULL) {
791+
return -1;
792+
}
793+
758794
for (size_t i=0; i < options->len; i++) {
759795
wchar_t *option = options->options[i];
760-
if (_PySys_AddXOptionWithError(option) < 0) {
761-
pymain->err = _Py_INIT_NO_MEMORY();
796+
if (pymain_add_xoption(dict, option) < 0) {
797+
Py_DECREF(dict);
762798
return -1;
763799
}
764800
}
801+
802+
pymain->config.xoptions = dict;
765803
return 0;
766804
}
767805

768806

769807
static int
770-
pymain_add_warnings_optlist(_Py_OptList *warnings)
808+
pymain_add_warnings_optlist(PyObject *warnoptions, _Py_OptList *warnings)
771809
{
772810
for (size_t i = 0; i < warnings->len; i++) {
773811
PyObject *option = PyUnicode_FromWideChar(warnings->options[i], -1);
774812
if (option == NULL) {
775813
return -1;
776814
}
777-
if (_PySys_AddWarnOptionWithError(option)) {
815+
if (PyList_Append(warnoptions, option)) {
778816
Py_DECREF(option);
779817
return -1;
780818
}
@@ -785,14 +823,14 @@ pymain_add_warnings_optlist(_Py_OptList *warnings)
785823

786824

787825
static int
788-
pymain_add_warning_dev_mode(_PyCoreConfig *core_config)
826+
pymain_add_warning_dev_mode(PyObject *warnoptions, _PyCoreConfig *core_config)
789827
{
790828
if (core_config->dev_mode) {
791829
PyObject *option = PyUnicode_FromString("default");
792830
if (option == NULL) {
793831
return -1;
794832
}
795-
if (_PySys_AddWarnOptionWithError(option)) {
833+
if (PyList_Append(warnoptions, option)) {
796834
Py_DECREF(option);
797835
return -1;
798836
}
@@ -803,33 +841,38 @@ pymain_add_warning_dev_mode(_PyCoreConfig *core_config)
803841

804842

805843
static int
806-
pymain_add_warning_bytes_flag(int bytes_warning_flag)
844+
pymain_add_warning_bytes_flag(PyObject *warnoptions, int bytes_warning_flag)
807845
{
808846
/* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
809847
* don't even try to emit a warning, so we skip setting the filter in that
810848
* case.
811849
*/
812-
if (bytes_warning_flag) {
813-
const char *filter = (bytes_warning_flag > 1) ? "error::BytesWarning":
814-
"default::BytesWarning";
815-
PyObject *option = PyUnicode_FromString(filter);
816-
if (option == NULL) {
817-
return -1;
818-
}
819-
if (_PySys_AddWarnOptionWithError(option)) {
820-
Py_DECREF(option);
821-
return -1;
822-
}
850+
if (!bytes_warning_flag) {
851+
return 0;
852+
}
853+
854+
const char *filter = (bytes_warning_flag > 1) ? "error::BytesWarning":
855+
"default::BytesWarning";
856+
PyObject *option = PyUnicode_FromString(filter);
857+
if (option == NULL) {
858+
return -1;
859+
}
860+
if (PyList_Append(warnoptions, option)) {
823861
Py_DECREF(option);
862+
return -1;
824863
}
864+
Py_DECREF(option);
825865
return 0;
826866
}
827867

828868

829869
static int
830-
pymain_add_warnings_options(_PyMain *pymain)
870+
pymain_init_warnoptions(_PyMain *pymain)
831871
{
832-
PySys_ResetWarnOptions();
872+
PyObject *warnoptions = PyList_New(0);
873+
if (warnoptions == NULL) {
874+
return -1;
875+
}
833876

834877
/* The priority order for warnings configuration is (highest precedence
835878
* first):
@@ -846,23 +889,25 @@ pymain_add_warnings_options(_PyMain *pymain)
846889
* the lowest precedence entries first so that later entries override them.
847890
*/
848891

849-
if (pymain_add_warning_dev_mode(&pymain->core_config) < 0) {
850-
pymain->err = _Py_INIT_NO_MEMORY();
851-
return -1;
892+
if (pymain_add_warning_dev_mode(warnoptions, &pymain->core_config) < 0) {
893+
goto error;
852894
}
853-
if (pymain_add_warnings_optlist(&pymain->env_warning_options) < 0) {
854-
pymain->err = _Py_INIT_NO_MEMORY();
855-
return -1;
895+
if (pymain_add_warnings_optlist(warnoptions, &pymain->env_warning_options) < 0) {
896+
goto error;
856897
}
857-
if (pymain_add_warnings_optlist(&pymain->cmdline.warning_options) < 0) {
858-
pymain->err = _Py_INIT_NO_MEMORY();
859-
return -1;
898+
if (pymain_add_warnings_optlist(warnoptions, &pymain->cmdline.warning_options) < 0) {
899+
goto error;
860900
}
861-
if (pymain_add_warning_bytes_flag(pymain->cmdline.bytes_warning) < 0) {
862-
pymain->err = _Py_INIT_NO_MEMORY();
863-
return -1;
901+
if (pymain_add_warning_bytes_flag(warnoptions, pymain->cmdline.bytes_warning) < 0) {
902+
goto error;
864903
}
904+
905+
pymain->config.warnoptions = warnoptions;
865906
return 0;
907+
908+
error:
909+
Py_DECREF(warnoptions);
910+
return -1;
866911
}
867912

868913

@@ -1092,7 +1137,7 @@ pymain_header(_PyMain *pymain)
10921137

10931138

10941139
static int
1095-
pymain_create_argv_list(_PyMain *pymain)
1140+
pymain_init_argv(_PyMain *pymain)
10961141
{
10971142
int argc = pymain->sys_argc;
10981143
wchar_t** argv = pymain->sys_argv;
@@ -1918,7 +1963,6 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *c
19181963
return err;
19191964
}
19201965
}
1921-
19221966
return _Py_INIT_OK();
19231967
}
19241968

@@ -1941,15 +1985,15 @@ pymain_init_python_core(_PyMain *pymain)
19411985
static int
19421986
pymain_init_python_main(_PyMain *pymain)
19431987
{
1944-
if (pymain_add_xoptions(pymain)) {
1988+
if (pymain_init_xoptions_dict(pymain)) {
1989+
pymain->err = _Py_INIT_NO_MEMORY();
19451990
return -1;
19461991
}
1947-
if (pymain_add_warnings_options(pymain)) {
1992+
if (pymain_init_warnoptions(pymain)) {
1993+
pymain->err = _Py_INIT_NO_MEMORY();
19481994
return -1;
19491995
}
1950-
1951-
/* Create sys.argv list */
1952-
if (pymain_create_argv_list(pymain) < 0) {
1996+
if (pymain_init_argv(pymain) < 0) {
19531997
pymain->err = _Py_INIT_ERR("failed to create sys.argv");
19541998
return -1;
19551999
}

Python/pylifecycle.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,8 @@ _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config)
830830
{
831831
Py_CLEAR(config->argv);
832832
Py_CLEAR(config->module_search_path);
833+
Py_CLEAR(config->warnoptions);
834+
Py_CLEAR(config->xoptions);
833835
}
834836

835837

@@ -883,10 +885,26 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
883885
return _Py_INIT_ERR("can't initialize time");
884886
}
885887

888+
/* Set sys attributes */
886889
assert(interp->config.module_search_path != NULL);
887890
if (PySys_SetObject("path", interp->config.module_search_path) != 0) {
888891
return _Py_INIT_ERR("can't assign sys.path");
889892
}
893+
if (interp->config.argv != NULL) {
894+
if (PySys_SetObject("argv", interp->config.argv) != 0) {
895+
return _Py_INIT_ERR("can't assign sys.argv");
896+
}
897+
}
898+
if (interp->config.warnoptions != NULL) {
899+
if (PySys_SetObject("warnoptions", interp->config.warnoptions)) {
900+
return _Py_INIT_ERR("can't assign sys.warnoptions");
901+
}
902+
}
903+
if (interp->config.xoptions != NULL) {
904+
if (PySys_SetObject("_xoptions", interp->config.xoptions)) {
905+
return _Py_INIT_ERR("can't assign sys._xoptions");
906+
}
907+
}
890908

891909
if (_PySys_EndInit(interp->sysdict) < 0)
892910
return _Py_INIT_ERR("can't finish initializing sys");
@@ -945,13 +963,6 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
945963
return err;
946964
}
947965
}
948-
949-
if (interp->config.argv != NULL) {
950-
if (PySys_SetObject("argv", interp->config.argv) != 0) {
951-
return _Py_INIT_ERR("can't assign sys.argv");
952-
}
953-
}
954-
955966
return _Py_INIT_OK();
956967
}
957968

0 commit comments

Comments
 (0)