gh-98608: Change _Py_NewInterpreter() to _Py_NewInterpreterFromConfig() (gh-98609)

(see https://github.com/python/cpython/issues/98608)

This change does the following:

1. change the argument to a new `_PyInterpreterConfig` struct
2. rename the function to `_Py_NewInterpreterFromConfig()`, inspired by `Py_InitializeFromConfig()` (takes a `_PyInterpreterConfig`  instead of `isolated_subinterpreter`)
3. split up the boolean `isolated_subinterpreter` into the corresponding multiple granular settings
   * allow_fork
   * allow_subprocess
   * allow_threads
4. add `PyInterpreterState.feature_flags` to store those settings
5. add a function for checking if a feature is enabled on an opaque `PyInterpreterState *`
6. drop `PyConfig._isolated_interpreter`

The existing default (see `Py_NewInterpeter()` and `Py_Initialize*()`) allows fork, subprocess, and threads and the optional "isolated" interpreter (see the `_xxsubinterpreters` module) disables all three.  None of that changes here; the defaults are preserved.

Note that the given `_PyInterpreterConfig` will not be used outside `_Py_NewInterpreterFromConfig()`, nor preserved.  This contrasts with how `PyConfig` is currently preserved, used, and even modified outside `Py_InitializeFromConfig()`.  I'd rather just avoid that mess from the start for `_PyInterpreterConfig`.  We can preserve it later if we find an actual need.

This change allows us to follow up with a number of improvements (e.g. stop disallowing subprocess and support disallowing exec instead).

(Note that this PR adds "private" symbols.  We'll probably make them public, and add docs, in a separate change.)
This commit is contained in:
Eric Snow 2022-10-26 11:16:30 -06:00 committed by GitHub
parent 24c56b4642
commit f32369480d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 295 additions and 39 deletions

View file

@ -496,7 +496,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'check_hash_pycs_mode': 'default',
'pathconfig_warnings': 1,
'_init_main': 1,
'_isolated_interpreter': 0,
'use_frozen_modules': not support.Py_DEBUG,
'safe_path': 0,
'_is_python_build': IGNORE_CONFIG,
@ -881,8 +880,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'check_hash_pycs_mode': 'always',
'pathconfig_warnings': 0,
'_isolated_interpreter': 1,
}
self.check_all_configs("test_init_from_config", config, preconfig,
api=API_COMPAT)
@ -1650,6 +1647,25 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
self.check_all_configs("test_init_use_frozen_modules", config,
api=API_PYTHON, env=env)
def test_init_main_interpreter_settings(self):
THREADS = 1<<10
FORK = 1<<15
SUBPROCESS = 1<<16
expected = {
# All optional features should be enabled.
'feature_flags': THREADS | FORK | SUBPROCESS,
}
out, err = self.run_embedded_interpreter(
'test_init_main_interpreter_settings',
)
self.assertEqual(err, '')
try:
out = json.loads(out)
except json.JSONDecodeError:
self.fail(f'fail to decode stdout: {out!r}')
self.assertEqual(out, expected)
class SetConfigTests(unittest.TestCase):
def test_set_config(self):