@@ -84,17 +84,24 @@ _PySys_GetObjectId(_Py_Identifier *key)
8484 return sys_get_object_id (tstate , key );
8585}
8686
87+ static PyObject *
88+ _PySys_GetObject (PyThreadState * tstate , const char * name )
89+ {
90+ PyObject * sysdict = tstate -> interp -> sysdict ;
91+ if (sysdict == NULL ) {
92+ return NULL ;
93+ }
94+ return _PyDict_GetItemStringWithError (sysdict , name );
95+ }
96+
8797PyObject *
8898PySys_GetObject (const char * name )
8999{
90100 PyThreadState * tstate = _PyThreadState_GET ();
91- PyObject * sd = tstate -> interp -> sysdict ;
92- if (sd == NULL ) {
93- return NULL ;
94- }
101+
95102 PyObject * exc_type , * exc_value , * exc_tb ;
96103 _PyErr_Fetch (tstate , & exc_type , & exc_value , & exc_tb );
97- PyObject * value = _PyDict_GetItemStringWithError ( sd , name );
104+ PyObject * value = _PySys_GetObject ( tstate , name );
98105 /* XXX Suppress a new exception if it was raised and restore
99106 * the old one. */
100107 _PyErr_Restore (tstate , exc_type , exc_value , exc_tb );
@@ -2464,8 +2471,6 @@ static PyStructSequence_Field flags_fields[] = {
24642471 {"no_site" , "-S" },
24652472 {"ignore_environment" , "-E" },
24662473 {"verbose" , "-v" },
2467- /* {"unbuffered", "-u"}, */
2468- /* {"skip_first", "-x"}, */
24692474 {"bytes_warning" , "-b" },
24702475 {"quiet" , "-q" },
24712476 {"hash_randomization" , "-R" },
@@ -2482,21 +2487,27 @@ static PyStructSequence_Desc flags_desc = {
24822487 15
24832488};
24842489
2485- static PyObject *
2486- make_flags ( PyThreadState * tstate )
2490+ static int
2491+ set_flags_from_config ( PyObject * flags , PyThreadState * tstate )
24872492{
24882493 PyInterpreterState * interp = tstate -> interp ;
24892494 const PyPreConfig * preconfig = & interp -> runtime -> preconfig ;
24902495 const PyConfig * config = _PyInterpreterState_GetConfig (interp );
24912496
2492- PyObject * seq = PyStructSequence_New (& FlagsType );
2493- if (seq == NULL ) {
2494- return NULL ;
2495- }
2496-
2497- int pos = 0 ;
2498- #define SetFlag (flag ) \
2499- PyStructSequence_SET_ITEM(seq, pos++, PyLong_FromLong(flag))
2497+ // _PySys_UpdateConfig() modifies sys.flags in-place:
2498+ // Py_XDECREF() is needed in this case.
2499+ Py_ssize_t pos = 0 ;
2500+ #define SetFlagObj (expr ) \
2501+ do { \
2502+ PyObject *value = (expr); \
2503+ if (value == NULL) { \
2504+ return -1; \
2505+ } \
2506+ Py_XDECREF(PyStructSequence_GET_ITEM(flags, pos)); \
2507+ PyStructSequence_SET_ITEM(flags, pos, value); \
2508+ pos++; \
2509+ } while (0)
2510+ #define SetFlag (expr ) SetFlagObj(PyLong_FromLong(expr))
25002511
25012512 SetFlag (config -> parser_debug );
25022513 SetFlag (config -> inspect );
@@ -2507,23 +2518,34 @@ make_flags(PyThreadState *tstate)
25072518 SetFlag (!config -> site_import );
25082519 SetFlag (!config -> use_environment );
25092520 SetFlag (config -> verbose );
2510- /* SetFlag(saw_unbuffered_flag); */
2511- /* SetFlag(skipfirstline); */
25122521 SetFlag (config -> bytes_warning );
25132522 SetFlag (config -> quiet );
25142523 SetFlag (config -> use_hash_seed == 0 || config -> hash_seed != 0 );
25152524 SetFlag (config -> isolated );
2516- PyStructSequence_SET_ITEM ( seq , pos ++ , PyBool_FromLong (config -> dev_mode ));
2525+ SetFlagObj ( PyBool_FromLong (config -> dev_mode ));
25172526 SetFlag (preconfig -> utf8_mode );
2527+ #undef SetFlagObj
25182528#undef SetFlag
2529+ return 0 ;
2530+ }
25192531
2520- if (_PyErr_Occurred (tstate )) {
2521- Py_DECREF (seq );
2532+
2533+ static PyObject *
2534+ make_flags (PyThreadState * tstate )
2535+ {
2536+ PyObject * flags = PyStructSequence_New (& FlagsType );
2537+ if (flags == NULL ) {
25222538 return NULL ;
25232539 }
2524- return seq ;
2540+
2541+ if (set_flags_from_config (flags , tstate ) < 0 ) {
2542+ Py_DECREF (flags );
2543+ return NULL ;
2544+ }
2545+ return flags ;
25252546}
25262547
2548+
25272549PyDoc_STRVAR (version_info__doc__ ,
25282550"sys.version_info\n\
25292551\n\
@@ -2767,14 +2789,23 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
27672789 /* implementation */
27682790 SET_SYS ("implementation" , make_impl_info (version_info ));
27692791
2770- /* flags */
2792+ // sys. flags: updated in-place later by _PySys_UpdateConfig()
27712793 if (FlagsType .tp_name == 0 ) {
27722794 if (PyStructSequence_InitType2 (& FlagsType , & flags_desc ) < 0 ) {
27732795 goto type_init_failed ;
27742796 }
27752797 }
2776- /* Set flags to their default values (updated by _PySys_InitMain()) */
27772798 SET_SYS ("flags" , make_flags (tstate ));
2799+ /* prevent user from creating new instances */
2800+ FlagsType .tp_init = NULL ;
2801+ FlagsType .tp_new = NULL ;
2802+ res = PyDict_DelItemString (FlagsType .tp_dict , "__new__" );
2803+ if (res < 0 ) {
2804+ if (!_PyErr_ExceptionMatches (tstate , PyExc_KeyError )) {
2805+ goto err_occurred ;
2806+ }
2807+ _PyErr_Clear (tstate );
2808+ }
27782809
27792810#if defined(MS_WINDOWS )
27802811 /* getwindowsversion */
@@ -2876,8 +2907,10 @@ sys_create_xoptions_dict(const PyConfig *config)
28762907}
28772908
28782909
2910+ // Update sys attributes for a new PyConfig configuration.
2911+ // This function also adds attributes that _PySys_InitCore() didn't add.
28792912int
2880- _PySys_InitMain (PyThreadState * tstate )
2913+ _PySys_UpdateConfig (PyThreadState * tstate )
28812914{
28822915 PyObject * sysdict = tstate -> interp -> sysdict ;
28832916 const PyConfig * config = _PyInterpreterState_GetConfig (tstate -> interp );
@@ -2914,28 +2947,16 @@ _PySys_InitMain(PyThreadState *tstate)
29142947#undef COPY_LIST
29152948#undef SET_SYS_FROM_WSTR
29162949
2917-
2918- /* Set flags to their final values */
2919- SET_SYS ("flags" , make_flags (tstate ));
2920- /* prevent user from creating new instances */
2921- FlagsType .tp_init = NULL ;
2922- FlagsType .tp_new = NULL ;
2923- res = PyDict_DelItemString (FlagsType .tp_dict , "__new__" );
2924- if (res < 0 ) {
2925- if (!_PyErr_ExceptionMatches (tstate , PyExc_KeyError )) {
2926- return res ;
2927- }
2928- _PyErr_Clear (tstate );
2950+ // sys.flags
2951+ PyObject * flags = _PySys_GetObject (tstate , "flags" ); // borrowed ref
2952+ if (flags == NULL ) {
2953+ return -1 ;
29292954 }
2930-
2931- SET_SYS ("dont_write_bytecode" , PyBool_FromLong (!config -> write_bytecode ));
2932-
2933- if (get_warnoptions (tstate ) == NULL ) {
2955+ if (set_flags_from_config (flags , tstate ) < 0 ) {
29342956 return -1 ;
29352957 }
29362958
2937- if (get_xoptions (tstate ) == NULL )
2938- return -1 ;
2959+ SET_SYS ("dont_write_bytecode" , PyBool_FromLong (!config -> write_bytecode ));
29392960
29402961 if (_PyErr_Occurred (tstate )) {
29412962 goto err_occurred ;
@@ -2977,8 +2998,8 @@ _PySys_SetPreliminaryStderr(PyObject *sysdict)
29772998}
29782999
29793000
2980- /* Create sys module without all attributes: _PySys_InitMain() should be called
2981- later to add remaining attributes. */
3001+ /* Create sys module without all attributes.
3002+ _PySys_UpdateConfig() should be called later to add remaining attributes. */
29823003PyStatus
29833004_PySys_Create (PyThreadState * tstate , PyObject * * sysmod_p )
29843005{
0 commit comments