Skip to content

Commit 6b4be19

Browse files
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.
1 parent f9169ce commit 6b4be19

19 files changed

+2206
-1991
lines changed

Include/Python.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112

113113
#include "pyarena.h"
114114
#include "modsupport.h"
115+
#include "compile.h"
115116
#include "pythonrun.h"
116117
#include "pylifecycle.h"
117118
#include "ceval.h"
@@ -123,7 +124,6 @@
123124
#include "abstract.h"
124125
#include "bltinmodule.h"
125126

126-
#include "compile.h"
127127
#include "eval.h"
128128

129129
#include "pyctype.h"

Include/compile.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,23 @@ extern "C" {
1111
/* Public interface */
1212
struct _node; /* Declare the existence of this type */
1313
PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);
14+
/* XXX (ncoghlan): Unprefixed type name in a public API! */
15+
16+
#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \
17+
CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \
18+
CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \
19+
CO_FUTURE_GENERATOR_STOP)
20+
#define PyCF_MASK_OBSOLETE (CO_NESTED)
21+
#define PyCF_SOURCE_IS_UTF8 0x0100
22+
#define PyCF_DONT_IMPLY_DEDENT 0x0200
23+
#define PyCF_ONLY_AST 0x0400
24+
#define PyCF_IGNORE_COOKIE 0x0800
25+
26+
#ifndef Py_LIMITED_API
27+
typedef struct {
28+
int cf_flags; /* bitmask of CO_xxx flags relevant to future */
29+
} PyCompilerFlags;
30+
#endif
1431

1532
/* Future feature support */
1633

Include/pylifecycle.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,15 @@ PyAPI_FUNC(const char *) _Py_gitversion(void);
7777
/* Internal -- various one-time initializations */
7878
#ifndef Py_LIMITED_API
7979
PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
80-
PyAPI_FUNC(PyObject *) _PySys_Init(void);
80+
PyAPI_FUNC(PyObject *) _PySys_BeginInit(void);
81+
PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict);
8182
PyAPI_FUNC(void) _PyImport_Init(void);
8283
PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
8384
PyAPI_FUNC(void) _PyImportHooks_Init(void);
8485
PyAPI_FUNC(int) _PyFrame_Init(void);
8586
PyAPI_FUNC(int) _PyFloat_Init(void);
8687
PyAPI_FUNC(int) PyByteArray_Init(void);
87-
PyAPI_FUNC(void) _PyRandom_Init(void);
88+
PyAPI_FUNC(void) _Py_HashRandomization_Init(void);
8889
#endif
8990

9091
/* Various internal finalizers */
@@ -106,7 +107,7 @@ PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void);
106107
PyAPI_FUNC(void) _PyGC_Fini(void);
107108
PyAPI_FUNC(void) PySlice_Fini(void);
108109
PyAPI_FUNC(void) _PyType_Fini(void);
109-
PyAPI_FUNC(void) _PyRandom_Fini(void);
110+
PyAPI_FUNC(void) _Py_HashRandomization_Fini(void);
110111
PyAPI_FUNC(void) PyAsyncGen_Fini(void);
111112

112113
PyAPI_DATA(PyThreadState *) _Py_Finalizing;

Include/pystate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ PyAPI_FUNC(PyObject *) _PyThread_CurrentFrames(void);
302302
/* Routines for advanced debuggers, requested by David Beazley.
303303
Don't use unless you know what you are doing! */
304304
#ifndef Py_LIMITED_API
305+
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Main(void);
305306
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Head(void);
306307
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *);
307308
PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *);

Include/pythonrun.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,6 @@
77
extern "C" {
88
#endif
99

10-
#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \
11-
CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \
12-
CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \
13-
CO_FUTURE_GENERATOR_STOP)
14-
#define PyCF_MASK_OBSOLETE (CO_NESTED)
15-
#define PyCF_SOURCE_IS_UTF8 0x0100
16-
#define PyCF_DONT_IMPLY_DEDENT 0x0200
17-
#define PyCF_ONLY_AST 0x0400
18-
#define PyCF_IGNORE_COOKIE 0x0800
19-
20-
#ifndef Py_LIMITED_API
21-
typedef struct {
22-
int cf_flags; /* bitmask of CO_xxx flags relevant to future */
23-
} PyCompilerFlags;
24-
#endif
25-
2610
#ifndef Py_LIMITED_API
2711
PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *);
2812
PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, const char *, PyCompilerFlags *);

Lib/importlib/_bootstrap.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,12 +1134,15 @@ def _setup(sys_module, _imp_module):
11341134

11351135

11361136
def _install(sys_module, _imp_module):
1137-
"""Install importlib as the implementation of import."""
1137+
"""Install importers for builtin and frozen modules"""
11381138
_setup(sys_module, _imp_module)
11391139

11401140
sys.meta_path.append(BuiltinImporter)
11411141
sys.meta_path.append(FrozenImporter)
11421142

1143+
1144+
def _install_external_importers():
1145+
"""Install importers that require external filesystem access"""
11431146
global _bootstrap_external
11441147
import _frozen_importlib_external
11451148
_bootstrap_external = _frozen_importlib_external

Lib/test/coding20731.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#coding:latin1
2-
3-
4-
1+
#coding:latin1
2+
3+
4+

Lib/test/test_cmd_line.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,29 @@ def test_isolatedmode(self):
485485
cwd=tmpdir)
486486
self.assertEqual(out.strip(), b"ok")
487487

488+
489+
class IgnoreEnvironmentTest(unittest.TestCase):
490+
491+
def run_ignoring_vars(self, predicate, **env_vars):
492+
# Runs a subprocess with -E set, even though we're passing
493+
# specific environment variables
494+
# Logical inversion to match predicate check to a zero return
495+
# code indicating success
496+
code = "import sys; sys.stderr.write(str(sys.flags)); sys.exit(not ({}))".format(predicate)
497+
return assert_python_ok('-E', '-c', code, **env_vars)
498+
499+
def test_ignore_PYTHONPATH(self):
500+
path = "should_be_ignored"
501+
self.run_ignoring_vars("'{}' not in sys.path".format(path),
502+
PYTHONPATH=path)
503+
504+
def test_ignore_PYTHONHASHSEED(self):
505+
self.run_ignoring_vars("sys.flags.hash_randomization == 1",
506+
PYTHONHASHSEED="0")
507+
508+
488509
def test_main():
489-
test.support.run_unittest(CmdLineTest)
510+
test.support.run_unittest(CmdLineTest, IgnoreEnvironmentTest)
490511
test.support.reap_children()
491512

492513
if __name__ == "__main__":

Lib/test/test_site.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ def test_addsitedir(self):
183183
@unittest.skipUnless(site.ENABLE_USER_SITE, "requires access to PEP 370 "
184184
"user-site (site.ENABLE_USER_SITE)")
185185
def test_s_option(self):
186+
# (ncoghlan) Change this to use script_helper...
186187
usersite = site.USER_SITE
187188
self.assertIn(usersite, sys.path)
188189

@@ -199,7 +200,7 @@ def test_s_option(self):
199200
if usersite == site.getsitepackages()[0]:
200201
self.assertEqual(rc, 1)
201202
else:
202-
self.assertEqual(rc, 0)
203+
self.assertEqual(rc, 0, "User site still added to path with -s")
203204

204205
env = os.environ.copy()
205206
env["PYTHONNOUSERSITE"] = "1"
@@ -209,14 +210,16 @@ def test_s_option(self):
209210
if usersite == site.getsitepackages()[0]:
210211
self.assertEqual(rc, 1)
211212
else:
212-
self.assertEqual(rc, 0)
213+
self.assertEqual(rc, 0,
214+
"User site still added to path with PYTHONNOUSERSITE")
213215

214216
env = os.environ.copy()
215217
env["PYTHONUSERBASE"] = "/tmp"
216218
rc = subprocess.call([sys.executable, '-c',
217219
'import sys, site; sys.exit(site.USER_BASE.startswith("/tmp"))'],
218220
env=env)
219-
self.assertEqual(rc, 1)
221+
self.assertEqual(rc, 1,
222+
"User base not set by PYTHONUSERBASE")
220223

221224
def test_getuserbase(self):
222225
site.USER_BASE = None

Makefile.pre.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ PYTHON_OBJS= \
349349
Python/pystate.o \
350350
Python/pythonrun.o \
351351
Python/pytime.o \
352-
Python/random.o \
352+
Python/bootstrap_hash.o \
353353
Python/structmember.o \
354354
Python/symtable.o \
355355
Python/sysmodule.o \

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ Core and Builtins
154154
- Issue #28596: The preferred encoding is UTF-8 on Android. Patch written by
155155
Chi Hsuan Yen.
156156

157+
- bpo-22257: Clean up interpreter startup (see PEP 432).
158+
157159
- Issue #26919: On Android, operating system data is now always encoded/decoded
158160
to/from UTF-8, instead of the locale encoding to avoid inconsistencies with
159161
os.fsencode() and os.fsdecode() which are already using UTF-8.

0 commit comments

Comments
 (0)