diff options
-rw-r--r-- | Lib/test/test_cmd_line.py | 35 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2017-10-24-21-27-32.bpo-31845.8OS-k3.rst | 1 | ||||
-rw-r--r-- | Modules/main.c | 54 | ||||
-rw-r--r-- | Python/pylifecycle.c | 37 |
4 files changed, 82 insertions, 45 deletions
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 28ddb2ba1b..1b584ebb7c 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -12,7 +12,6 @@ from test.support.script_helper import ( spawn_python, kill_python, assert_python_ok, assert_python_failure ) - # XXX (ncoghlan): Move to script_helper and make consistent with run_python def _kill_python_and_exit_code(p): data = kill_python(p) @@ -486,6 +485,26 @@ class CmdLineTest(unittest.TestCase): cwd=tmpdir) self.assertEqual(out.strip(), b"ok") + def test_sys_flags_set(self): + # Issue 31845: a startup refactoring broke reading flags from env vars + for value, expected in (("", 0), ("1", 1), ("text", 1), ("2", 2)): + env_vars = dict( + PYTHONDEBUG=value, + PYTHONOPTIMIZE=value, + PYTHONDONTWRITEBYTECODE=value, + PYTHONVERBOSE=value, + ) + code = ( + "import sys; " + "sys.stderr.write(str(sys.flags)); " + f"""sys.exit(not ( + sys.flags.debug == sys.flags.optimize == + sys.flags.dont_write_bytecode == sys.flags.verbose == + {expected} + ))""" + ) + with self.subTest(envar_value=value): + assert_python_ok('-c', code, **env_vars) class IgnoreEnvironmentTest(unittest.TestCase): @@ -506,6 +525,20 @@ class IgnoreEnvironmentTest(unittest.TestCase): self.run_ignoring_vars("sys.flags.hash_randomization == 1", PYTHONHASHSEED="0") + def test_sys_flags_not_set(self): + # Issue 31845: a startup refactoring broke reading flags from env vars + expected_outcome = """ + (sys.flags.debug == sys.flags.optimize == + sys.flags.dont_write_bytecode == sys.flags.verbose == 0) + """ + self.run_ignoring_vars( + expected_outcome, + PYTHONDEBUG="1", + PYTHONOPTIMIZE="1", + PYTHONDONTWRITEBYTECODE="1", + PYTHONVERBOSE="1", + ) + def test_main(): test.support.run_unittest(CmdLineTest, IgnoreEnvironmentTest) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-24-21-27-32.bpo-31845.8OS-k3.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-24-21-27-32.bpo-31845.8OS-k3.rst new file mode 100644 index 0000000000..ddaf630638 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-10-24-21-27-32.bpo-31845.8OS-k3.rst @@ -0,0 +1 @@ +Environment variables are once more read correctly at interpreter startup. diff --git a/Modules/main.c b/Modules/main.c index e862113310..846ecb6170 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -522,39 +522,33 @@ read_command_line(int argc, wchar_t **argv, _Py_CommandLineDetails *cmdline) return 0; } -static int -apply_command_line_and_environment(_Py_CommandLineDetails *cmdline) +static void +maybe_set_flag(int *flag, int value) { - char *p; - Py_BytesWarningFlag = cmdline->bytes_warning; - Py_DebugFlag = cmdline->debug; - Py_InspectFlag = cmdline->inspect; - Py_InteractiveFlag = cmdline->interactive; - Py_IsolatedFlag = cmdline->isolated; - Py_OptimizeFlag = cmdline->optimization_level; - Py_DontWriteBytecodeFlag = cmdline->dont_write_bytecode; - Py_NoUserSiteDirectory = cmdline->no_user_site_directory; - Py_NoSiteFlag = cmdline->no_site_import; - Py_UnbufferedStdioFlag = cmdline->use_unbuffered_io; - Py_VerboseFlag = cmdline->verbosity; - Py_QuietFlag = cmdline->quiet_flag; - - if (!Py_InspectFlag && - (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') { - Py_InspectFlag = 1; - cmdline->inspect = 1; - } - if (!cmdline->use_unbuffered_io && - (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') { - Py_UnbufferedStdioFlag = 1; - cmdline->use_unbuffered_io = 1; + /* Helper to set flag variables from command line options + * - uses the higher of the two values if they're both set + * - otherwise leaves the flag unset + */ + if (*flag < value) { + *flag = value; } +} - if (!Py_NoUserSiteDirectory && - (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0') { - Py_NoUserSiteDirectory = 1; - cmdline->no_user_site_directory = 1; - } +static int +apply_command_line_and_environment(_Py_CommandLineDetails *cmdline) +{ + maybe_set_flag(&Py_BytesWarningFlag, cmdline->bytes_warning); + maybe_set_flag(&Py_DebugFlag, cmdline->debug); + maybe_set_flag(&Py_InspectFlag, cmdline->inspect); + maybe_set_flag(&Py_InteractiveFlag, cmdline->interactive); + maybe_set_flag(&Py_IsolatedFlag, cmdline->isolated); + maybe_set_flag(&Py_OptimizeFlag, cmdline->optimization_level); + maybe_set_flag(&Py_DontWriteBytecodeFlag, cmdline->dont_write_bytecode); + maybe_set_flag(&Py_NoUserSiteDirectory, cmdline->no_user_site_directory); + maybe_set_flag(&Py_NoSiteFlag, cmdline->no_site_import); + maybe_set_flag(&Py_UnbufferedStdioFlag, cmdline->use_unbuffered_io); + maybe_set_flag(&Py_VerboseFlag, cmdline->verbosity); + maybe_set_flag(&Py_QuietFlag, cmdline->quiet_flag); /* TODO: Apply PYTHONWARNINGS & -W options to sys module here */ /* TODO: Apply -X options to sys module here */ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 5b13bc4582..4e8bbb662e 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -217,15 +217,18 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) */ -static int -add_flag(int flag, const char *envs) +static void +set_flag(int *flag, const char *envs) { + /* Helper to set flag variables from environment variables: + * - uses the higher of the two values if they're both set + * - otherwise sets the flag to 1 + */ int env = atoi(envs); - if (flag < env) - flag = env; - if (flag < 1) - flag = 1; - return flag; + if (*flag < env) + *flag = env; + if (*flag < 1) + *flag = 1; } static char* @@ -612,22 +615,28 @@ void _Py_InitializeCore(const _PyCoreConfig *config) #endif if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0') - Py_DebugFlag = add_flag(Py_DebugFlag, p); + set_flag(&Py_DebugFlag, p); if ((p = Py_GETENV("PYTHONVERBOSE")) && *p != '\0') - Py_VerboseFlag = add_flag(Py_VerboseFlag, p); + set_flag(&Py_VerboseFlag, p); if ((p = Py_GETENV("PYTHONOPTIMIZE")) && *p != '\0') - Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p); + set_flag(&Py_OptimizeFlag, p); + if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') + set_flag(&Py_InspectFlag, p); if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0') - Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p); + set_flag(&Py_DontWriteBytecodeFlag, p); + if ((p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0') + set_flag(&Py_NoUserSiteDirectory, p); + if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') + set_flag(&Py_UnbufferedStdioFlag, p); /* The variable is only tested for existence here; _Py_HashRandomization_Init will check its value further. */ if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0') - Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p); + set_flag(&Py_HashRandomizationFlag, p); #ifdef MS_WINDOWS if ((p = Py_GETENV("PYTHONLEGACYWINDOWSFSENCODING")) && *p != '\0') - Py_LegacyWindowsFSEncodingFlag = add_flag(Py_LegacyWindowsFSEncodingFlag, p); + set_flag(&Py_LegacyWindowsFSEncodingFlag, p); if ((p = Py_GETENV("PYTHONLEGACYWINDOWSSTDIO")) && *p != '\0') - Py_LegacyWindowsStdioFlag = add_flag(Py_LegacyWindowsStdioFlag, p); + set_flag(&Py_LegacyWindowsStdioFlag, p); #endif _Py_HashRandomization_Init(&core_config); |