8000 Add a test. · python/cpython@1defec3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1defec3

Browse files
Add a test.
1 parent ad3fe36 commit 1defec3

File tree

3 files changed

+144
-1
lines changed

3 files changed

+144
-1
lines changed

Lib/test/test_capi/check_config.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# This script is used by test_misc.
2+
3+
import _imp
4+
import _testinternalcapi
5+
import json
6+
import os
7+
import sys
8+
9+
10+
def import_singlephase():
11+
assert '_singlephase' not in sys.modules
12+
try:
13+
import _singlephase
14+
except ImportError:
15+
return True
16+
else:
17+
del sys.modules['_singlephase']
18+
return False
19+
20+
21+
def check(override):
22+
settings_before = _testinternalcapi.get_interp_settings()
23+
enabled_initial = import_singlephase()
24+
25+
override_initial = _imp._override_multi_interp_extensions_check(override)
26+
settings_after = _testinternalcapi.get_interp_settings()
27+
enabled_after = import_singlephase()
28+
29+
override_actual = _imp._override_multi_interp_extensions_check(override_initial)
30+
settings_final = _testinternalcapi.get_interp_settings()
31+
override_noop = _imp._override_multi_interp_extensions_check(override_initial)
32+
settings_noop = _testinternalcapi.get_interp_settings()
33+
enabled_restored = import_singlephase()
34+
return {
35+
'settings_before': settings_before,
36+
'enabled_initial': enabled_initial,
37+
'override_initial': override_initial,
38+
'settings_after': settings_after,
39+
'enabled_after': enabled_after,
40+
'override_actual': override_actual,
41+
'settings_final': settings_final,
42+
'override_noop': override_noop,
43+
'settings_noop': settings_noop,
44+
'enabled_restored': enabled_restored,
45+
}
46+
47+
48+
def run_check(override, outfd):
49+
with os.fdopen(outfd, 'w') as outfile:
50+
sys.stdout = outfile
51+
sys.stderr = outfile
52+
results = check(override)
53+
json.dump(results, outfile)

Lib/test/test_capi/test_misc.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
import _testmultiphase
3232
except ImportError:
3333
_testmultiphase = None
34+
try:
35+
import _testsinglephase
36+
except ImportError:
37+
_testsinglephase = None
3438

3539
# Skip this test if the _testcapi module isn't available.
3640
_testcapi = import_helper.import_module('_testcapi')
@@ -1325,12 +1329,92 @@ def test_configured_settings(self):
13251329
json.dump(settings, stdin)
13261330
''')
13271331
with os.fdopen(r) as stdout:
1328-
support.run_in_subinterp_with_config(script, **kwargs)
1332+
ret = support.run_in_subinterp_with_config(script, **kwargs)
1333+
self.assertEqual(ret, 0)
13291334
out = stdout.read()
13301335
settings = json.loads(out)
13311336

13321337
self.assertEqual(settings, expected)
13331338

1339+
@unittest.skipIf(_testsinglephase is None, "test requires _testsinglphase module")
1340+
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
1341+
def test_overridden_setting_extensions_subinterp_check(self):
1342+
"""
1343+
PyInterpreterConfig.check_multi_interp_extensions can be overridden
1344+
with PyInterpreterState.override_multi_interp_extensions_check.
1345+
This verifies that the override works but does not modify
1346+
the underlying setting.
1347+
"""
1348+
import json
1349+
1350+
EXTENSIONS = 1<<8
1351+
THREADS = 1<<10
1352+
DAEMON_THREADS = 1<<11
1353+
FORK = 1<<15
1354+
EXEC = 1<<16
1355+
BASE_FLAGS = FORK | EXEC | THREADS | DAEMON_THREADS
1356+
base_kwargs = {
1357+
'allow_fork': True,
1358+
'allow_exec': True,
1359+
'allow_threads': True,
1360+
'allow_daemon_threads': True,
1361+
}
1362+
1363+
def check(enabled, override):
1364+
kwargs = dict(
1365+
base_kwargs,
1366+
check_multi_interp_extensions=enabled,
1367+
)
1368+
flags = BASE_FLAGS | EXTENSIONS if enabled else BASE_FLAGS
1369+
settings = {
1370+
'feature_flags': flags,
1371+
}
1372+
if override == 0:
1373+
enabled_after = enabled
1374+
else:
1375+
enabled_after = (override > 0)
1376+
expected = {
1377+
'settings_before': settings,
1378+
'enabled_initial': enabled,
1379+
'override_initial': 0,
1380+
'settings_after': settings,
1381+
'enabled_after': enabled_after,
1382+
'override_actual': override,
1383+
'settings_final': settings,
1384+
'override_noop': 0,
1385+
'settings_noop': settings,
1386+
'enabled_restored': enabled,
1387+
}
1388+
1389+
r, w = os.pipe()
1390+
script = textwrap.dedent(f'''
1391+
from test.test_capi.check_config import run_check
1392+
run_check({override}, {w})
1393+
''')
1394+
with os.fdopen(r) as stdout:
1395+
ret = support.run_in_subinterp_with_config(script, **kwargs)
1396+
self.assertEqual(ret, 0)
1397+
out = stdout.read()
1398+
results = json.loads(out)
1399+
1400+
self.assertEqual(results, expected)
1401+
1402+
# setting: check disabled
1403+
with self.subTest('config disabled, override disabled'):
1404+
check(False, -1)
1405+
with self.subTest('config disabled, override cleared'):
1406+
check(False, 0)
1407+
with self.subTest('config disabled, override enabled'):
1408+
check(False, 1)
1409+
1410+
# setting: check enabled
1411+
with self.subTest('config enabled, override disabled'):
1412+
check(True, -1)
1413+
with self.subTest('config enabled, override cleared'):
1414+
check(True, 0)
1415+
with self.subTest('config enabled, override enabled'):
1416+
check(True, 1)
1417+
13341418
def test_mutate_exception(self):
13351419
"""
13361420
Exceptions saved in global module state get shared between

Python/import.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,6 +2388,12 @@ _imp__override_multi_interp_extensions_check_impl(PyObject *module,
23882388
/*[clinic end generated code: output=3ff043af52bbf280 input=e086a2ea181f92ae]*/
23892389
{
23902390
PyInterpreterState *interp = _PyInterpreterState_GET();
2391+
if (_Py_IsMainInterpreter(interp)) {
2392+
PyErr_SetString(PyExc_RuntimeError,
2393+
"_imp._override_multi_interp_extensions_check() "
2394+
"cannot be used in the main interpreter");
2395+
return NULL;
2396+
}
23912397
int oldvalue = interp->override_multi_interp_extensions_check;
23922398
interp->override_multi_interp_extensions_check = override;
23932399
return PyLong_FromLong(oldvalue);

0 commit comments

Comments
 (0)
0