Commit 6b4be195 authored by Eric Snow's avatar Eric Snow Committed by GitHub

bpo-22257: Small changes for PEP 432. (#1728)

PEP 432 specifies a number of large changes to interpreter startup code, including exposing a cleaner C-API. The major changes depend on a number of smaller changes. This patch includes all those smaller changes.
parent f9169ce6
...@@ -112,6 +112,7 @@ ...@@ -112,6 +112,7 @@
#include "pyarena.h" #include "pyarena.h"
#include "modsupport.h" #include "modsupport.h"
#include "compile.h"
#include "pythonrun.h" #include "pythonrun.h"
#include "pylifecycle.h" #include "pylifecycle.h"
#include "ceval.h" #include "ceval.h"
...@@ -123,7 +124,6 @@ ...@@ -123,7 +124,6 @@
#include "abstract.h" #include "abstract.h"
#include "bltinmodule.h" #include "bltinmodule.h"
#include "compile.h"
#include "eval.h" #include "eval.h"
#include "pyctype.h" #include "pyctype.h"
......
...@@ -11,6 +11,23 @@ extern "C" { ...@@ -11,6 +11,23 @@ extern "C" {
/* Public interface */ /* Public interface */
struct _node; /* Declare the existence of this type */ struct _node; /* Declare the existence of this type */
PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *); PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);
/* XXX (ncoghlan): Unprefixed type name in a public API! */
#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \
CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \
CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \
CO_FUTURE_GENERATOR_STOP)
#define PyCF_MASK_OBSOLETE (CO_NESTED)
#define PyCF_SOURCE_IS_UTF8 0x0100
#define PyCF_DONT_IMPLY_DEDENT 0x0200
#define PyCF_ONLY_AST 0x0400
#define PyCF_IGNORE_COOKIE 0x0800
#ifndef Py_LIMITED_API
typedef struct {
int cf_flags; /* bitmask of CO_xxx flags relevant to future */
} PyCompilerFlags;
#endif
/* Future feature support */ /* Future feature support */
......
...@@ -77,14 +77,15 @@ PyAPI_FUNC(const char *) _Py_gitversion(void); ...@@ -77,14 +77,15 @@ PyAPI_FUNC(const char *) _Py_gitversion(void);
/* Internal -- various one-time initializations */ /* Internal -- various one-time initializations */
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void); PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
PyAPI_FUNC(PyObject *) _PySys_Init(void); PyAPI_FUNC(PyObject *) _PySys_BeginInit(void);
PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict);
PyAPI_FUNC(void) _PyImport_Init(void); PyAPI_FUNC(void) _PyImport_Init(void);
PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod); PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
PyAPI_FUNC(void) _PyImportHooks_Init(void); PyAPI_FUNC(void) _PyImportHooks_Init(void);
PyAPI_FUNC(int) _PyFrame_Init(void); PyAPI_FUNC(int) _PyFrame_Init(void);
PyAPI_FUNC(int) _PyFloat_Init(void); PyAPI_FUNC(int) _PyFloat_Init(void);
PyAPI_FUNC(int) PyByteArray_Init(void); PyAPI_FUNC(int) PyByteArray_Init(void);
PyAPI_FUNC(void) _PyRandom_Init(void); PyAPI_FUNC(void) _Py_HashRandomization_Init(void);
#endif #endif
/* Various internal finalizers */ /* Various internal finalizers */
...@@ -106,7 +107,7 @@ PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); ...@@ -106,7 +107,7 @@ PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void);
PyAPI_FUNC(void) _PyGC_Fini(void); PyAPI_FUNC(void) _PyGC_Fini(void);
PyAPI_FUNC(void) PySlice_Fini(void); PyAPI_FUNC(void) PySlice_Fini(void);
PyAPI_FUNC(void) _PyType_Fini(void); PyAPI_FUNC(void) _PyType_Fini(void);
PyAPI_FUNC(void) _PyRandom_Fini(void); PyAPI_FUNC(void) _Py_HashRandomization_Fini(void);
PyAPI_FUNC(void) PyAsyncGen_Fini(void); PyAPI_FUNC(void) PyAsyncGen_Fini(void);
PyAPI_DATA(PyThreadState *) _Py_Finalizing; PyAPI_DATA(PyThreadState *) _Py_Finalizing;
......
...@@ -302,6 +302,7 @@ PyAPI_FUNC(PyObject *) _PyThread_CurrentFrames(void); ...@@ -302,6 +302,7 @@ PyAPI_FUNC(PyObject *) _PyThread_CurrentFrames(void);
/* Routines for advanced debuggers, requested by David Beazley. /* Routines for advanced debuggers, requested by David Beazley.
Don't use unless you know what you are doing! */ Don't use unless you know what you are doing! */
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Main(void);
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Head(void); PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Head(void);
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *); PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *); PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *);
......
...@@ -7,22 +7,6 @@ ...@@ -7,22 +7,6 @@
extern "C" { extern "C" {
#endif #endif
#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \
CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \
CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \
CO_FUTURE_GENERATOR_STOP)
#define PyCF_MASK_OBSOLETE (CO_NESTED)
#define PyCF_SOURCE_IS_UTF8 0x0100
#define PyCF_DONT_IMPLY_DEDENT 0x0200
#define PyCF_ONLY_AST 0x0400
#define PyCF_IGNORE_COOKIE 0x0800
#ifndef Py_LIMITED_API
typedef struct {
int cf_flags; /* bitmask of CO_xxx flags relevant to future */
} PyCompilerFlags;
#endif
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *); PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *);
PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, const char *, PyCompilerFlags *); PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, const char *, PyCompilerFlags *);
......
...@@ -1134,12 +1134,15 @@ def _setup(sys_module, _imp_module): ...@@ -1134,12 +1134,15 @@ def _setup(sys_module, _imp_module):
def _install(sys_module, _imp_module): def _install(sys_module, _imp_module):
"""Install importlib as the implementation of import.""" """Install importers for builtin and frozen modules"""
_setup(sys_module, _imp_module) _setup(sys_module, _imp_module)
sys.meta_path.append(BuiltinImporter) sys.meta_path.append(BuiltinImporter)
sys.meta_path.append(FrozenImporter) sys.meta_path.append(FrozenImporter)
def _install_external_importers():
"""Install importers that require external filesystem access"""
global _bootstrap_external global _bootstrap_external
import _frozen_importlib_external import _frozen_importlib_external
_bootstrap_external = _frozen_importlib_external _bootstrap_external = _frozen_importlib_external
......
...@@ -485,8 +485,29 @@ class CmdLineTest(unittest.TestCase): ...@@ -485,8 +485,29 @@ class CmdLineTest(unittest.TestCase):
cwd=tmpdir) cwd=tmpdir)
self.assertEqual(out.strip(), b"ok") self.assertEqual(out.strip(), b"ok")
class IgnoreEnvironmentTest(unittest.TestCase):
def run_ignoring_vars(self, predicate, **env_vars):
# Runs a subprocess with -E set, even though we're passing
# specific environment variables
# Logical inversion to match predicate check to a zero return
# code indicating success
code = "import sys; sys.stderr.write(str(sys.flags)); sys.exit(not ({}))".format(predicate)
return assert_python_ok('-E', '-c', code, **env_vars)
def test_ignore_PYTHONPATH(self):
path = "should_be_ignored"
self.run_ignoring_vars("'{}' not in sys.path".format(path),
PYTHONPATH=path)
def test_ignore_PYTHONHASHSEED(self):
self.run_ignoring_vars("sys.flags.hash_randomization == 1",
PYTHONHASHSEED="0")
def test_main(): def test_main():
test.support.run_unittest(CmdLineTest) test.support.run_unittest(CmdLineTest, IgnoreEnvironmentTest)
test.support.reap_children() test.support.reap_children()
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -183,6 +183,7 @@ class HelperFunctionsTests(unittest.TestCase): ...@@ -183,6 +183,7 @@ class HelperFunctionsTests(unittest.TestCase):
@unittest.skipUnless(site.ENABLE_USER_SITE, "requires access to PEP 370 " @unittest.skipUnless(site.ENABLE_USER_SITE, "requires access to PEP 370 "
"user-site (site.ENABLE_USER_SITE)") "user-site (site.ENABLE_USER_SITE)")
def test_s_option(self): def test_s_option(self):
# (ncoghlan) Change this to use script_helper...
usersite = site.USER_SITE usersite = site.USER_SITE
self.assertIn(usersite, sys.path) self.assertIn(usersite, sys.path)
...@@ -199,7 +200,7 @@ class HelperFunctionsTests(unittest.TestCase): ...@@ -199,7 +200,7 @@ class HelperFunctionsTests(unittest.TestCase):
if usersite == site.getsitepackages()[0]: if usersite == site.getsitepackages()[0]:
self.assertEqual(rc, 1) self.assertEqual(rc, 1)
else: else:
self.assertEqual(rc, 0) self.assertEqual(rc, 0, "User site still added to path with -s")
env = os.environ.copy() env = os.environ.copy()
env["PYTHONNOUSERSITE"] = "1" env["PYTHONNOUSERSITE"] = "1"
...@@ -209,14 +210,16 @@ class HelperFunctionsTests(unittest.TestCase): ...@@ -209,14 +210,16 @@ class HelperFunctionsTests(unittest.TestCase):
if usersite == site.getsitepackages()[0]: if usersite == site.getsitepackages()[0]:
self.assertEqual(rc, 1) self.assertEqual(rc, 1)
else: else:
self.assertEqual(rc, 0) self.assertEqual(rc, 0,
"User site still added to path with PYTHONNOUSERSITE")
env = os.environ.copy() env = os.environ.copy()
env["PYTHONUSERBASE"] = "/tmp" env["PYTHONUSERBASE"] = "/tmp"
rc = subprocess.call([sys.executable, '-c', rc = subprocess.call([sys.executable, '-c',
'import sys, site; sys.exit(site.USER_BASE.startswith("/tmp"))'], 'import sys, site; sys.exit(site.USER_BASE.startswith("/tmp"))'],
env=env) env=env)
self.assertEqual(rc, 1) self.assertEqual(rc, 1,
"User base not set by PYTHONUSERBASE")
def test_getuserbase(self): def test_getuserbase(self):
site.USER_BASE = None site.USER_BASE = None
......
...@@ -349,7 +349,7 @@ PYTHON_OBJS= \ ...@@ -349,7 +349,7 @@ PYTHON_OBJS= \
Python/pystate.o \ Python/pystate.o \
Python/pythonrun.o \ Python/pythonrun.o \
Python/pytime.o \ Python/pytime.o \
Python/random.o \ Python/bootstrap_hash.o \
Python/structmember.o \ Python/structmember.o \
Python/symtable.o \ Python/symtable.o \
Python/sysmodule.o \ Python/sysmodule.o \
......
...@@ -154,6 +154,8 @@ Core and Builtins ...@@ -154,6 +154,8 @@ Core and Builtins
- Issue #28596: The preferred encoding is UTF-8 on Android. Patch written by - Issue #28596: The preferred encoding is UTF-8 on Android. Patch written by
Chi Hsuan Yen. Chi Hsuan Yen.
- bpo-22257: Clean up interpreter startup (see PEP 432).
- Issue #26919: On Android, operating system data is now always encoded/decoded - Issue #26919: On Android, operating system data is now always encoded/decoded
to/from UTF-8, instead of the locale encoding to avoid inconsistencies with to/from UTF-8, instead of the locale encoding to avoid inconsistencies with
os.fsencode() and os.fsdecode() which are already using UTF-8. os.fsencode() and os.fsdecode() which are already using UTF-8.
......
...@@ -343,49 +343,44 @@ run_file(FILE *fp, const wchar_t *filename, PyCompilerFlags *p_cf) ...@@ -343,49 +343,44 @@ run_file(FILE *fp, const wchar_t *filename, PyCompilerFlags *p_cf)
/* Main program */ /* Main program */
int /*TODO: Add arg processing to PEP 432 as a new configuration setup API
Py_Main(int argc, wchar_t **argv) */
typedef struct {
wchar_t *filename; /* Trailing arg without -c or -m */
wchar_t *command; /* -c argument */
wchar_t *module; /* -m argument */
PyObject *warning_options; /* -W options */
PyObject *extra_options; /* -X options */
int print_help; /* -h, -? options */
int print_version; /* -V option */
int bytes_warning; /* Py_BytesWarningFlag */
int debug; /* Py_DebugFlag */
int inspect; /* Py_InspectFlag */
int interactive; /* Py_InteractiveFlag */
int isolated; /* Py_IsolatedFlag */
int optimization_level; /* Py_OptimizeFlag */
int dont_write_bytecode; /* Py_DontWriteBytecodeFlag */
int no_user_site_directory; /* Py_NoUserSiteDirectory */
int no_site_import; /* Py_NoSiteFlag */
int use_unbuffered_io; /* Py_UnbufferedStdioFlag */
int verbosity; /* Py_VerboseFlag */
int quiet_flag; /* Py_QuietFlag */
int skip_first_line; /* -x option */
} _Py_CommandLineDetails;
#define _Py_CommandLineDetails_INIT \
{NULL, NULL, NULL, NULL, NULL, \
0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0}
static int
read_command_line(int argc, wchar_t **argv, _Py_CommandLineDetails *cmdline)
{ {
int c; PyObject *warning_option = NULL;
int sts;
wchar_t *command = NULL; wchar_t *command = NULL;
wchar_t *filename = NULL;
wchar_t *module = NULL; wchar_t *module = NULL;
FILE *fp = stdin; char c;
char *p;
#ifdef MS_WINDOWS
wchar_t *wp;
#endif
int skipfirstline = 0;
int stdin_is_interactive = 0;
int help = 0;
int version = 0;
int saw_unbuffered_flag = 0;
char *opt; char *opt;
PyCompilerFlags cf;
PyObject *main_importer_path = NULL;
PyObject *warning_option = NULL;
PyObject *warning_options = NULL;
cf.cf_flags = 0;
orig_argc = argc; /* For Py_GetArgcArgv() */
orig_argv = argv;
/* Hash randomization needed early for all string operations
(including -W and -X options). */
_PyOS_opterr = 0; /* prevent printing the error in 1st pass */
while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
if (c == 'm' || c == 'c') {
/* -c / -m is the last option: following arguments are
not interpreter options. */
break;
}
if (c == 'E') {
Py_IgnoreEnvironmentFlag++;
break;
}
}
opt = Py_GETENV("PYTHONMALLOC"); opt = Py_GETENV("PYTHONMALLOC");
if (_PyMem_SetupAllocators(opt) < 0) { if (_PyMem_SetupAllocators(opt) < 0) {
...@@ -394,10 +389,11 @@ Py_Main(int argc, wchar_t **argv) ...@@ -394,10 +389,11 @@ Py_Main(int argc, wchar_t **argv)
exit(1); exit(1);
} }
// TODO: Move these to core runtime init.
Py_HashRandomizationFlag = 1; Py_HashRandomizationFlag = 1;
_PyRandom_Init(); _Py_HashRandomization_Init();
PySys_ResetWarnOptions(); PySys_ResetWarnOptions();
_PyOS_ResetGetOpt(); _PyOS_ResetGetOpt();
while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) { while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
...@@ -415,6 +411,7 @@ Py_Main(int argc, wchar_t **argv) ...@@ -415,6 +411,7 @@ Py_Main(int argc, wchar_t **argv)
wcscpy(command, _PyOS_optarg); wcscpy(command, _PyOS_optarg);
command[len - 2] = '\n'; command[len - 2] = '\n';
command[len - 1] = 0; command[len - 1] = 0;
cmdline->command = command;
break; break;
} }
...@@ -423,49 +420,49 @@ Py_Main(int argc, wchar_t **argv) ...@@ -423,49 +420,49 @@ Py_Main(int argc, wchar_t **argv)
that look like options are left for the that look like options are left for the
module to interpret. */ module to interpret. */
module = _PyOS_optarg; module = _PyOS_optarg;
cmdline->module = module;
break; break;
} }
switch (c) { switch (c) {
case 'b': case 'b':
Py_BytesWarningFlag++; cmdline->bytes_warning++;
break; break;
case 'd': case 'd':
Py_DebugFlag++; cmdline->debug++;
break; break;
case 'i': case 'i':
Py_InspectFlag++; cmdline->inspect++;
Py_InteractiveFlag++; cmdline->interactive++;
break; break;
case 'I': case 'I':
Py_IsolatedFlag++; cmdline->isolated++;
Py_NoUserSiteDirectory++; cmdline->no_user_site_directory++;
Py_IgnoreEnvironmentFlag++;
break; break;
/* case 'J': reserved for Jython */ /* case 'J': reserved for Jython */
case 'O': case 'O':
Py_OptimizeFlag++; cmdline->optimization_level++;
break; break;
case 'B': case 'B':
Py_DontWriteBytecodeFlag++; cmdline->dont_write_bytecode++;
break; break;
case 's': case 's':
Py_NoUserSiteDirectory++; cmdline->no_user_site_directory++;
break; break;
case 'S': case 'S':
Py_NoSiteFlag++; cmdline->no_site_import++;
break; break;
case 'E': case 'E':
/* Already handled above */ /* Handled prior to core initialization */
break; break;
case 't': case 't':
...@@ -473,46 +470,46 @@ Py_Main(int argc, wchar_t **argv) ...@@ -473,46 +470,46 @@ Py_Main(int argc, wchar_t **argv)
break; break;
case 'u': case 'u':
Py_UnbufferedStdioFlag = 1; cmdline->use_unbuffered_io = 1;
saw_unbuffered_flag = 1;
break; break;
case 'v': case 'v':
Py_VerboseFlag++; cmdline->verbosity++;
break; break;
case 'x': case 'x':
skipfirstline = 1; cmdline->skip_first_line = 1;
break; break;
case 'h': case 'h':
case '?': case '?':
help++; cmdline->print_help++;
break; break;
case 'V': case 'V':
version++; cmdline->print_version++;
break; break;
case 'W': case 'W':
if (warning_options == NULL) if (cmdline->warning_options == NULL)
warning_options = PyList_New(0); cmdline->warning_options = PyList_New(0);
if (warning_options == NULL) if (cmdline->warning_options == NULL)
Py_FatalError("failure in handling of -W argument"); Py_FatalError("failure in handling of -W argument");
warning_option = PyUnicode_FromWideChar(_PyOS_optarg, -1); warning_option = PyUnicode_FromWideChar(_PyOS_optarg, -1);
if (warning_option == NULL) if (warning_option == NULL)
Py_FatalError("failure in handling of -W argument"); Py_FatalError("failure in handling of -W argument");
if (PyList_Append(warning_options, warning_option) == -1) if (PyList_Append(cmdline->warning_options, warning_option) == -1)
Py_FatalError("failure in handling of -W argument"); Py_FatalError("failure in handling of -W argument");
Py_DECREF(warning_option); Py_DECREF(warning_option);
break; break;
case 'X': case 'X':
/* TODO: Delay addition of X options to sys module */
PySys_AddXOption(_PyOS_optarg); PySys_AddXOption(_PyOS_optarg);
break; break;
case 'q': case 'q':
Py_QuietFlag++; cmdline->quiet_flag++;
break; break;
case 'R': case 'R':
...@@ -522,30 +519,110 @@ Py_Main(int argc, wchar_t **argv) ...@@ -522,30 +519,110 @@ Py_Main(int argc, wchar_t **argv)
/* This space reserved for other options */ /* This space reserved for other options */
default: default:
return usage(2, argv[0]); return -1;
/*NOTREACHED*/ /*NOTREACHED*/
} }
} }
if (help) if (command == NULL && module == NULL && _PyOS_optind < argc &&
return usage(0, argv[0]); wcscmp(argv[_PyOS_optind], L"-") != 0)
{
if (version) { cmdline->filename = argv[_PyOS_optind];
printf("Python %s\n", version >= 2 ? Py_GetVersion() : PY_VERSION);
return 0;
} }
return 0;
}
static int
apply_command_line_and_environment(_Py_CommandLineDetails *cmdline)
{
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 && if (!Py_InspectFlag &&
(p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') {
Py_InspectFlag = 1; Py_InspectFlag = 1;
if (!saw_unbuffered_flag && cmdline->inspect = 1;
(p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') }
if (!cmdline->use_unbuffered_io &&
(p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') {
Py_UnbufferedStdioFlag = 1; Py_UnbufferedStdioFlag = 1;
cmdline->use_unbuffered_io = 1;
}
if (!Py_NoUserSiteDirectory && if (!Py_NoUserSiteDirectory &&
(p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0') (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0') {
Py_NoUserSiteDirectory = 1; Py_NoUserSiteDirectory = 1;
cmdline->no_user_site_directory = 1;
}
/* TODO: Apply PYTHONWARNINGS & -W options to sys module here */
/* TODO: Apply -X options to sys module here */
return 0;
}
int
Py_Main(int argc, wchar_t **argv)
{
int c;
int sts;
FILE *fp = stdin;
char *p;
#ifdef MS_WINDOWS
wchar_t *wp;
#endif
int stdin_is_interactive = 0;
_Py_CommandLineDetails cmdline = _Py_CommandLineDetails_INIT;
PyCompilerFlags cf;
PyObject *main_importer_path = NULL;
cf.cf_flags = 0;
orig_argc = argc; /* For Py_GetArgcArgv() */
orig_argv = argv;
/* Hash randomization needed early for all string operations
(including -W and -X options). */
_PyOS_opterr = 0; /* prevent printing the error in 1st pass */
while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
if (c == 'm' || c == 'c') {
/* -c / -m is the last option: following arguments are
not interpreter options. */
break;
}
if (c == 'E' || c == 'I') {
Py_IgnoreEnvironmentFlag++;
break;
}
}
/* Reprocess the command line with the language runtime available */
if (read_command_line(argc, argv, &cmdline)) {
return usage(2, argv[0]);
}
if (cmdline.print_help) {
return usage(0, argv[0]);
}
if (cmdline.print_version) {
printf("Python %s\n", cmdline.print_version >= 2 ? Py_GetVersion() : PY_VERSION);
return 0;
}
PySys_ResetWarnOptions();
apply_command_line_and_environment(&cmdline);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
if (!Py_IgnoreEnvironmentFlag && (wp = _wgetenv(L"PYTHONWARNINGS")) && if (!Py_IgnoreEnvironmentFlag && (wp = _wgetenv(L"PYTHONWARNINGS")) &&
...@@ -598,19 +675,13 @@ Py_Main(int argc, wchar_t **argv) ...@@ -598,19 +675,13 @@ Py_Main(int argc, wchar_t **argv)
PyMem_RawFree(buf); PyMem_RawFree(buf);
} }
#endif #endif
if (warning_options != NULL) { if (cmdline.warning_options != NULL) {
Py_ssize_t i; Py_ssize_t i;
for (i = 0; i < PyList_GET_SIZE(warning_options); i++) { for (i = 0; i < PyList_GET_SIZE(cmdline.warning_options); i++) {
PySys_AddWarnOptionUnicode(PyList_GET_ITEM(warning_options, i)); PySys_AddWarnOptionUnicode(PyList_GET_ITEM(cmdline.warning_options, i));
} }
} }
if (command == NULL && module == NULL && _PyOS_optind < argc &&
wcscmp(argv[_PyOS_optind], L"-") != 0)
{
filename = argv[_PyOS_optind];
}
stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0); stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);
#if defined(MS_WINDOWS) || defined(__CYGWIN__) #if defined(MS_WINDOWS) || defined(__CYGWIN__)
...@@ -697,31 +768,31 @@ Py_Main(int argc, wchar_t **argv) ...@@ -697,31 +768,31 @@ Py_Main(int argc, wchar_t **argv)
Py_SetProgramName(argv[0]); Py_SetProgramName(argv[0]);
#endif #endif
Py_Initialize(); Py_Initialize();
Py_XDECREF(warning_options); Py_XDECREF(cmdline.warning_options);
if (!Py_QuietFlag && (Py_VerboseFlag || if (!Py_QuietFlag && (Py_VerboseFlag ||
(command == NULL && filename == NULL && (cmdline.command == NULL && cmdline.filename == NULL &&
module == NULL && stdin_is_interactive))) { cmdline.module == NULL && stdin_is_interactive))) {
fprintf(stderr, "Python %s on %s\n", fprintf(stderr, "Python %s on %s\n",
Py_GetVersion(), Py_GetPlatform()); Py_GetVersion(), Py_GetPlatform());
if (!Py_NoSiteFlag) if (!Py_NoSiteFlag)
fprintf(stderr, "%s\n", COPYRIGHT); fprintf(stderr, "%s\n", COPYRIGHT);
} }
if (command != NULL) { if (cmdline.command != NULL) {
/* Backup _PyOS_optind and force sys.argv[0] = '-c' */ /* Backup _PyOS_optind and force sys.argv[0] = '-c' */
_PyOS_optind--; _PyOS_optind--;
argv[_PyOS_optind] = L"-c"; argv[_PyOS_optind] = L"-c";
} }
if (module != NULL) { if (cmdline.module != NULL) {
/* Backup _PyOS_optind and force sys.argv[0] = '-m'*/ /* Backup _PyOS_optind and force sys.argv[0] = '-m'*/
_PyOS_optind--; _PyOS_optind--;
argv[_PyOS_optind] = L"-m"; argv[_PyOS_optind] = L"-m";
} }
if (filename != NULL) { if (cmdline.filename != NULL) {
main_importer_path = AsImportPathEntry(filename); main_importer_path = AsImportPathEntry(cmdline.filename);
} }
if (main_importer_path != NULL) { if (main_importer_path != NULL) {
...@@ -732,9 +803,11 @@ Py_Main(int argc, wchar_t **argv) ...@@ -732,9 +803,11 @@ Py_Main(int argc, wchar_t **argv)
PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind); PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
} }
if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) && if ((Py_InspectFlag || (cmdline.command == NULL &&
isatty(fileno(stdin)) && cmdline.filename == NULL &&
!Py_IsolatedFlag) { cmdline.module == NULL)) &&
isatty(fileno(stdin)) &&
!Py_IsolatedFlag) {
PyObject *v; PyObject *v;
v = PyImport_ImportModule("readline"); v = PyImport_ImportModule("readline");
if (v == NULL) if (v == NULL)
...@@ -743,15 +816,15 @@ Py_Main(int argc, wchar_t **argv) ...@@ -743,15 +816,15 @@ Py_Main(int argc, wchar_t **argv)
Py_DECREF(v); Py_DECREF(v);
} }
if (command) { if (cmdline.command) {
sts = run_command(command, &cf); sts = run_command(cmdline.command, &cf);
PyMem_RawFree(command); PyMem_RawFree(cmdline.command);
} else if (module) { } else if (cmdline.module) {
sts = (RunModule(module, 1) != 0); sts = (RunModule(cmdline.module, 1) != 0);
} }
else { else {
if (filename == NULL && stdin_is_interactive) { if (cmdline.filename == NULL && stdin_is_interactive) {
Py_InspectFlag = 0; /* do exit on SystemExit */ Py_InspectFlag = 0; /* do exit on SystemExit */
RunStartupFile(&cf); RunStartupFile(&cf);
RunInteractiveHook(); RunInteractiveHook();
...@@ -764,13 +837,13 @@ Py_Main(int argc, wchar_t **argv) ...@@ -764,13 +837,13 @@ Py_Main(int argc, wchar_t **argv)
sts = RunMainFromImporter(main_importer_path); sts = RunMainFromImporter(main_importer_path);
} }
if (sts==-1 && filename != NULL) { if (sts==-1 && cmdline.filename != NULL) {
fp = _Py_wfopen(filename, L"r"); fp = _Py_wfopen(cmdline.filename, L"r");
if (fp == NULL) { if (fp == NULL) {
char *cfilename_buffer; char *cfilename_buffer;
const char *cfilename; const char *cfilename;
int err = errno; int err = errno;
cfilename_buffer = Py_EncodeLocale(filename, NULL); cfilename_buffer = Py_EncodeLocale(cmdline.filename, NULL);
if (cfilename_buffer != NULL) if (cfilename_buffer != NULL)
cfilename = cfilename_buffer; cfilename = cfilename_buffer;
else else
...@@ -781,7 +854,7 @@ Py_Main(int argc, wchar_t **argv) ...@@ -781,7 +854,7 @@ Py_Main(int argc, wchar_t **argv)
PyMem_Free(cfilename_buffer); PyMem_Free(cfilename_buffer);
return 2; return 2;
} }
else if (skipfirstline) { else if (cmdline.skip_first_line) {
int ch; int ch;
/* Push back first newline so line numbers /* Push back first newline so line numbers
remain the same */ remain the same */
...@@ -798,7 +871,7 @@ Py_Main(int argc, wchar_t **argv) ...@@ -798,7 +871,7 @@ Py_Main(int argc, wchar_t **argv)
S_ISDIR(sb.st_mode)) { S_ISDIR(sb.st_mode)) {
fprintf(stderr, fprintf(stderr,
"%ls: '%ls' is a directory, cannot continue\n", "%ls: '%ls' is a directory, cannot continue\n",
argv[0], filename); argv[0], cmdline.filename);
fclose(fp); fclose(fp);
return 1; return 1;
} }
...@@ -806,7 +879,7 @@ Py_Main(int argc, wchar_t **argv) ...@@ -806,7 +879,7 @@ Py_Main(int argc, wchar_t **argv)
} }
if (sts == -1) if (sts == -1)
sts = run_file(fp, filename, &cf); sts = run_file(fp, cmdline.filename, &cf);
} }
/* Check this environment variable at the end, to give programs the /* Check this environment variable at the end, to give programs the
...@@ -819,7 +892,7 @@ Py_Main(int argc, wchar_t **argv) ...@@ -819,7 +892,7 @@ Py_Main(int argc, wchar_t **argv)
} }
if (Py_InspectFlag && stdin_is_interactive && if (Py_InspectFlag && stdin_is_interactive &&
(filename != NULL || command != NULL || module != NULL)) { (cmdline.filename != NULL || cmdline.command != NULL || cmdline.module != NULL)) {
Py_InspectFlag = 0; Py_InspectFlag = 0;
RunInteractiveHook(); RunInteractiveHook();
/* XXX */ /* XXX */
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
...@@ -349,11 +349,11 @@ ...@@ -349,11 +349,11 @@
<ClCompile Include="..\PC\getpathp.c" /> <ClCompile Include="..\PC\getpathp.c" />
<ClCompile Include="..\PC\msvcrtmodule.c" /> <ClCompile Include="..\PC\msvcrtmodule.c" />
<ClCompile Include="..\Python\pyhash.c" /> <ClCompile Include="..\Python\pyhash.c" />
<ClCompile Include="..\Python\random.c" />
<ClCompile Include="..\Python\_warnings.c" /> <ClCompile Include="..\Python\_warnings.c" />
<ClCompile Include="..\Python\asdl.c" /> <ClCompile Include="..\Python\asdl.c" />
<ClCompile Include="..\Python\ast.c" /> <ClCompile Include="..\Python\ast.c" />
<ClCompile Include="..\Python\bltinmodule.c" /> <ClCompile Include="..\Python\bltinmodule.c" />
<ClCompile Include="..\Python\bootstrap_hash.c" />
<ClCompile Include="..\Python\ceval.c" /> <ClCompile Include="..\Python\ceval.c" />
<ClCompile Include="..\Python\codecs.c" /> <ClCompile Include="..\Python\codecs.c" />
<ClCompile Include="..\Python\compile.c" /> <ClCompile Include="..\Python\compile.c" />
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Include"> <Filter Include="Include">
...@@ -971,7 +971,7 @@ ...@@ -971,7 +971,7 @@
<ClCompile Include="..\Python\traceback.c"> <ClCompile Include="..\Python\traceback.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Python\random.c"> <ClCompile Include="..\Python\bootstrap_hash.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Modules\_winapi.c"> <ClCompile Include="..\Modules\_winapi.c">
......
...@@ -533,44 +533,57 @@ _PyOS_URandomNonblock(void *buffer, Py_ssize_t size) ...@@ -533,44 +533,57 @@ _PyOS_URandomNonblock(void *buffer, Py_ssize_t size)
return pyurandom(buffer, size, 0, 1); return pyurandom(buffer, size, 0, 1);
} }
void int Py_ReadHashSeed(char *seed_text,
_PyRandom_Init(void) int *use_hash_seed,
unsigned long *hash_seed)
{ {
char *env;
unsigned char *secret = (unsigned char *)&_Py_HashSecret.uc;
Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc)); Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc));
/* Convert a text seed to a numeric one */
if (_Py_HashSecret_Initialized) if (seed_text && *seed_text != '\0' && strcmp(seed_text, "random") != 0) {
return; char *endptr = seed_text;
_Py_HashSecret_Initialized = 1;
/*
Hash randomization is enabled. Generate a per-process secret,
using PYTHONHASHSEED if provided.
*/
env = Py_GETENV("PYTHONHASHSEED");
if (env && *env != '\0' && strcmp(env, "random") != 0) {
char *endptr = env;
unsigned long seed; unsigned long seed;
seed = strtoul(env, &endptr, 10); seed = strtoul(seed_text, &endptr, 10);
if (*endptr != '\0' if (*endptr != '\0'
|| seed > 4294967295UL || seed > 4294967295UL
|| (errno == ERANGE && seed == ULONG_MAX)) || (errno == ERANGE && seed == ULONG_MAX))
{ {
Py_FatalError("PYTHONHASHSEED must be \"random\" or an integer " return -1;
"in range [0; 4294967295]");
} }
if (seed == 0) { /* Use a specific hash */
*use_hash_seed = 1;
*hash_seed = seed;
}
else {
/* Use a random hash */
*use_hash_seed = 0;
*hash_seed = 0;
}
return 0;
}
static void
init_hash_secret(int use_hash_seed,
unsigned long hash_seed)
{
void *secret = &_Py_HashSecret;
Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
if (_Py_HashSecret_Initialized)
return;
_Py_HashSecret_Initialized = 1;
if (use_hash_seed) {
if (hash_seed == 0) {
/* disable the randomized hash */ /* disable the randomized hash */
memset(secret, 0, secret_size); memset(secret, 0, secret_size);
} }
else { else {
lcg_urandom(seed, secret, secret_size); /* use the specified hash seed */
lcg_urandom(hash_seed, secret, secret_size);
} }
} }
else { else {
/* use a random hash seed */
int res; int res;
/* _PyRandom_Init() is called very early in the Python initialization /* _PyRandom_Init() is called very early in the Python initialization
...@@ -586,7 +599,24 @@ _PyRandom_Init(void) ...@@ -586,7 +599,24 @@ _PyRandom_Init(void)
} }
void void
_PyRandom_Fini(void) _Py_HashRandomization_Init(void)
{
char *seed_text;
int use_hash_seed = -1;
unsigned long hash_seed;
if (use_hash_seed < 0) {
seed_text = Py_GETENV("PYTHONHASHSEED");
if (Py_ReadHashSeed(seed_text, &use_hash_seed, &hash_seed) < 0) {
Py_FatalError("PYTHONHASHSEED must be \"random\" or an integer "
"in range [0; 4294967295]");
}
}
init_hash_secret(use_hash_seed, hash_seed);
}
void
_Py_HashRandomization_Fini(void)
{ {
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
if (hCryptProv) { if (hCryptProv) {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -291,6 +291,9 @@ import_init(PyInterpreterState *interp, PyObject *sysmod) ...@@ -291,6 +291,9 @@ import_init(PyInterpreterState *interp, PyObject *sysmod)
/* Install importlib as the implementation of import */ /* Install importlib as the implementation of import */
value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod); value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
if (value != NULL)
value = PyObject_CallMethod(importlib,
"_install_external_importers", "");
if (value == NULL) { if (value == NULL) {
PyErr_Print(); PyErr_Print();
Py_FatalError("Py_Initialize: importlib install failed"); Py_FatalError("Py_Initialize: importlib install failed");
...@@ -331,8 +334,8 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) ...@@ -331,8 +334,8 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p); Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p);
if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0') if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0')
Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p); Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p);
/* The variable is only tested for existence here; _PyRandom_Init will /* The variable is only tested for existence here;
check its value further. */ _Py_HashRandomization_Init will check its value further. */
if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0') if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0')
Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p); Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
...@@ -342,7 +345,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) ...@@ -342,7 +345,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
Py_LegacyWindowsStdioFlag = add_flag(Py_LegacyWindowsStdioFlag, p); Py_LegacyWindowsStdioFlag = add_flag(Py_LegacyWindowsStdioFlag, p);
#endif #endif
_PyRandom_Init(); _Py_HashRandomization_Init();
_PyInterpreterState_Init(); _PyInterpreterState_Init();
interp = PyInterpreterState_New(); interp = PyInterpreterState_New();
...@@ -402,13 +405,15 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) ...@@ -402,13 +405,15 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
/* initialize builtin exceptions */ /* initialize builtin exceptions */
_PyExc_Init(bimod); _PyExc_Init(bimod);
sysmod = _PySys_Init(); sysmod = _PySys_BeginInit();
if (sysmod == NULL) if (sysmod == NULL)
Py_FatalError("Py_Initialize: can't initialize sys"); Py_FatalError("Py_Initialize: can't initialize sys");
interp->sysdict = PyModule_GetDict(sysmod); interp->sysdict = PyModule_GetDict(sysmod);
if (interp->sysdict == NULL) if (interp->sysdict == NULL)
Py_FatalError("Py_Initialize: can't initialize sys dict"); Py_FatalError("Py_Initialize: can't initialize sys dict");
Py_INCREF(interp->sysdict); Py_INCREF(interp->sysdict);
if (_PySys_EndInit(interp->sysdict) < 0)
Py_FatalError("Py_Initialize: can't initialize sys");
_PyImport_FixupBuiltin(sysmod, "sys"); _PyImport_FixupBuiltin(sysmod, "sys");
PySys_SetPath(Py_GetPath()); PySys_SetPath(Py_GetPath());
PyDict_SetItemString(interp->sysdict, "modules", PyDict_SetItemString(interp->sysdict, "modules",
...@@ -694,7 +699,7 @@ Py_FinalizeEx(void) ...@@ -694,7 +699,7 @@ Py_FinalizeEx(void)
PyDict_Fini(); PyDict_Fini();
PySlice_Fini(); PySlice_Fini();
_PyGC_Fini(); _PyGC_Fini();
_PyRandom_Fini(); _Py_HashRandomization_Fini();
_PyArg_Fini(); _PyArg_Fini();
PyAsyncGen_Fini(); PyAsyncGen_Fini();
......
...@@ -46,6 +46,7 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */ ...@@ -46,6 +46,7 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
/* The single PyInterpreterState used by this process' /* The single PyInterpreterState used by this process'
GILState implementation GILState implementation
*/ */
/* TODO: Given interp_main, it may be possible to kill this ref */
static PyInterpreterState *autoInterpreterState = NULL; static PyInterpreterState *autoInterpreterState = NULL;
static int autoTLSkey = -1; static int autoTLSkey = -1;
#else #else
...@@ -55,6 +56,7 @@ static int autoTLSkey = -1; ...@@ -55,6 +56,7 @@ static int autoTLSkey = -1;
#endif #endif
static PyInterpreterState *interp_head = NULL; static PyInterpreterState *interp_head = NULL;
static PyInterpreterState *interp_main = NULL;
/* Assuming the current thread holds the GIL, this is the /* Assuming the current thread holds the GIL, this is the
PyThreadState for the current thread. */ PyThreadState for the current thread. */
...@@ -119,6 +121,9 @@ PyInterpreterState_New(void) ...@@ -119,6 +121,9 @@ PyInterpreterState_New(void)
HEAD_LOCK(); HEAD_LOCK();
interp->next = interp_head; interp->next = interp_head;
if (interp_main == NULL) {
interp_main = interp;
}
interp_head = interp; interp_head = interp;
if (_next_interp_id < 0) { if (_next_interp_id < 0) {
/* overflow or Py_Initialize() not called! */ /* overflow or Py_Initialize() not called! */
...@@ -185,6 +190,11 @@ PyInterpreterState_Delete(PyInterpreterState *interp) ...@@ -185,6 +190,11 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
if (interp->tstate_head != NULL) if (interp->tstate_head != NULL)
Py_FatalError("PyInterpreterState_Delete: remaining threads"); Py_FatalError("PyInterpreterState_Delete: remaining threads");
*p = interp->next; *p = interp->next;
if (interp_main == interp) {
interp_main = NULL;
if (interp_head != NULL)
Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters");
}
HEAD_UNLOCK(); HEAD_UNLOCK();
PyMem_RawFree(interp); PyMem_RawFree(interp);
#ifdef WITH_THREAD #ifdef WITH_THREAD
...@@ -661,6 +671,12 @@ PyInterpreterState_Head(void) ...@@ -661,6 +671,12 @@ PyInterpreterState_Head(void)
return interp_head; return interp_head;
} }
PyInterpreterState *
PyInterpreterState_Main(void)
{
return interp_main;
}
PyInterpreterState * PyInterpreterState *
PyInterpreterState_Next(PyInterpreterState *interp) { PyInterpreterState_Next(PyInterpreterState *interp) {
return interp->next; return interp->next;
......
...@@ -1900,16 +1900,7 @@ static struct PyModuleDef sysmodule = { ...@@ -1900,16 +1900,7 @@ static struct PyModuleDef sysmodule = {
NULL NULL
}; };
PyObject * /* Updating the sys namespace, returning NULL pointer on error */
_PySys_Init(void)
{
PyObject *m, *sysdict, *version_info;
int res;
m = PyModule_Create(&sysmodule);
if (m == NULL)
return NULL;
sysdict = PyModule_GetDict(m);
#define SET_SYS_FROM_STRING_BORROW(key, value) \ #define SET_SYS_FROM_STRING_BORROW(key, value) \
do { \ do { \
PyObject *v = (value); \ PyObject *v = (value); \
...@@ -1932,6 +1923,17 @@ _PySys_Init(void) ...@@ -1932,6 +1923,17 @@ _PySys_Init(void)
} \ } \
} while (0) } while (0)
PyObject *
_PySys_BeginInit(void)
{
PyObject *m, *sysdict, *version_info;
int res;
m = PyModule_Create(&sysmodule);
if (m == NULL)
return NULL;
sysdict = PyModule_GetDict(m);
/* Check that stdin is not a directory /* Check that stdin is not a directory
Using shell redirection, you can redirect stdin to a directory, Using shell redirection, you can redirect stdin to a directory,
crashing the Python interpreter. Catch this common mistake here crashing the Python interpreter. Catch this common mistake here
...@@ -1963,25 +1965,12 @@ _PySys_Init(void) ...@@ -1963,25 +1965,12 @@ _PySys_Init(void)
SET_SYS_FROM_STRING("_git", SET_SYS_FROM_STRING("_git",
Py_BuildValue("(szz)", "CPython", _Py_gitidentifier(), Py_BuildValue("(szz)", "CPython", _Py_gitidentifier(),
_Py_gitversion())); _Py_gitversion()));
SET_SYS_FROM_STRING("dont_write_bytecode",
PyBool_FromLong(Py_DontWriteBytecodeFlag));
SET_SYS_FROM_STRING("api_version", SET_SYS_FROM_STRING("api_version",
PyLong_FromLong(PYTHON_API_VERSION)); PyLong_FromLong(PYTHON_API_VERSION));
SET_SYS_FROM_STRING("copyright", SET_SYS_FROM_STRING("copyright",
PyUnicode_FromString(Py_GetCopyright())); PyUnicode_FromString(Py_GetCopyright()));
SET_SYS_FROM_STRING("platform", SET_SYS_FROM_STRING("platform",
PyUnicode_FromString(Py_GetPlatform())); PyUnicode_FromString(Py_GetPlatform()));
SET_SYS_FROM_STRING("executable",
PyUnicode_FromWideChar(
Py_GetProgramFullPath(), -1));
SET_SYS_FROM_STRING("prefix",
PyUnicode_FromWideChar(Py_GetPrefix(), -1));
SET_SYS_FROM_STRING("exec_prefix",
PyUnicode_FromWideChar(Py_GetExecPrefix(), -1));
SET_SYS_FROM_STRING("base_prefix",
PyUnicode_FromWideChar(Py_GetPrefix(), -1));
SET_SYS_FROM_STRING("base_exec_prefix",
PyUnicode_FromWideChar(Py_GetExecPrefix(), -1));
SET_SYS_FROM_STRING("maxsize", SET_SYS_FROM_STRING("maxsize",
PyLong_FromSsize_t(PY_SSIZE_T_MAX)); PyLong_FromSsize_t(PY_SSIZE_T_MAX));
SET_SYS_FROM_STRING("float_info", SET_SYS_FROM_STRING("float_info",
...@@ -2017,17 +2006,6 @@ _PySys_Init(void) ...@@ -2017,17 +2006,6 @@ _PySys_Init(void)
SET_SYS_FROM_STRING("abiflags", SET_SYS_FROM_STRING("abiflags",
PyUnicode_FromString(ABIFLAGS)); PyUnicode_FromString(ABIFLAGS));
#endif #endif
if (warnoptions == NULL) {
warnoptions = PyList_New(0);
if (warnoptions == NULL)
return NULL;
}
else {
Py_INCREF(warnoptions);
}
SET_SYS_FROM_STRING_BORROW("warnoptions", warnoptions);
SET_SYS_FROM_STRING_BORROW("_xoptions", get_xoptions());
/* version_info */ /* version_info */
if (VersionInfoType.tp_name == NULL) { if (VersionInfoType.tp_name == NULL) {
...@@ -2052,13 +2030,8 @@ _PySys_Init(void) ...@@ -2052,13 +2030,8 @@ _PySys_Init(void)
if (PyStructSequence_InitType2(&FlagsType, &flags_desc) < 0) if (PyStructSequence_InitType2(&FlagsType, &flags_desc) < 0)
return NULL; return NULL;
} }
/* Set flags to their default values */
SET_SYS_FROM_STRING("flags", make_flags()); SET_SYS_FROM_STRING("flags", make_flags());
/* prevent user from creating new instances */
FlagsType.tp_init = NULL;
FlagsType.tp_new = NULL;
res = PyDict_DelItemString(FlagsType.tp_dict, "__new__");
if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
PyErr_Clear();
#if defined(MS_WINDOWS) #if defined(MS_WINDOWS)
/* getwindowsversion */ /* getwindowsversion */
...@@ -2095,13 +2068,89 @@ _PySys_Init(void) ...@@ -2095,13 +2068,89 @@ _PySys_Init(void)
} }
} }
#undef SET_SYS_FROM_STRING
#undef SET_SYS_FROM_STRING_BORROW
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
return m; return m;
} }
#undef SET_SYS_FROM_STRING
#undef SET_SYS_FROM_STRING_BORROW
/* Updating the sys namespace, returning integer error codes */
#define SET_SYS_FROM_STRING_BORROW_INT_RESULT(key, value) \
do { \
PyObject *v = (value); \
if (v == NULL) \
return -1; \
res = PyDict_SetItemString(sysdict, key, v); \
if (res < 0) { \
return res; \
} \
} while (0)
#define SET_SYS_FROM_STRING_INT_RESULT(key, value) \
do { \
PyObject *v = (value); \
if (v == NULL) \
return -1; \
res = PyDict_SetItemString(sysdict, key, v); \
Py_DECREF(v); \
if (res < 0) { \
return res; \
} \
} while (0)
int
_PySys_EndInit(PyObject *sysdict)
{
int res;
/* Set flags to their final values */
SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags());
/* prevent user from creating new instances */
FlagsType.tp_init = NULL;
FlagsType.tp_new = NULL;
res = PyDict_DelItemString(FlagsType.tp_dict, "__new__");
if (res < 0) {
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
return res;
}
PyErr_Clear();
}
SET_SYS_FROM_STRING_INT_RESULT("dont_write_bytecode",
PyBool_FromLong(Py_DontWriteBytecodeFlag));
SET_SYS_FROM_STRING_INT_RESULT("executable",
PyUnicode_FromWideChar(
Py_GetProgramFullPath(), -1));
SET_SYS_FROM_STRING_INT_RESULT("prefix",
PyUnicode_FromWideChar(Py_GetPrefix(), -1));
SET_SYS_FROM_STRING_INT_RESULT("exec_prefix",
PyUnicode_FromWideChar(Py_GetExecPrefix(), -1));
SET_SYS_FROM_STRING_INT_RESULT("base_prefix",
PyUnicode_FromWideChar(Py_GetPrefix(), -1));
SET_SYS_FROM_STRING_INT_RESULT("base_exec_prefix",
PyUnicode_FromWideChar(Py_GetExecPrefix(), -1));
if (warnoptions == NULL) {
warnoptions = PyList_New(0);
if (warnoptions == NULL)
return -1;
}
else {
Py_INCREF(warnoptions);
}
SET_SYS_FROM_STRING_BORROW_INT_RESULT("warnoptions", warnoptions);
SET_SYS_FROM_STRING_BORROW_INT_RESULT("_xoptions", get_xoptions());
if (PyErr_Occurred())
return -1;
return 0;
}
#undef SET_SYS_FROM_STRING_INT_RESULT
#undef SET_SYS_FROM_STRING_BORROW_INT_RESULT
static PyObject * static PyObject *
makepathobject(const wchar_t *path, wchar_t delim) makepathobject(const wchar_t *path, wchar_t delim)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment