Skip to content

Commit 60d4eb3

Browse files
committed
pythongh-107954: Allow setting cpu_count in PyConfig_Set()
1 parent 17718b0 commit 60d4eb3

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

Lib/test/test_capi/test_config.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Tests PyConfig_Get() and PyConfig_Set() C API (PEP 741).
33
"""
4+
import os
45
import sys
56
import sysconfig
67
import types
@@ -374,12 +375,23 @@ def expect_bool_not(value):
374375
finally:
375376
config_set(name, old_value)
376377

378+
def test_config_set_cpu_count(self):
379+
config_get = _testcapi.config_get
380+
config_set = _testcapi.config_set
381+
382+
old_value = config_get('cpu_count')
383+
try:
384+
config_set('cpu_count', 123)
385+
self.assertEqual(os.cpu_count(), 123)
386+
finally:
387+
config_set('cpu_count', old_value)
388+
377389
def test_config_set_read_only(self):
378390
# Test PyConfig_Set() on read-only options
379391
config_set = _testcapi.config_set
380392
for name, value in (
381393
("allocator", 0), # PyPreConfig member
382-
("cpu_count", 8),
394+
("perf_profiling", 8),
383395
("dev_mode", True),
384396
("filesystem_encoding", "utf-8"),
385397
):

Python/initconfig.c

+23-7
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ static const PyConfigSpec PYCONFIG_SPEC[] = {
110110
SPEC(base_executable, WSTR_OPT, PUBLIC, SYS_ATTR("_base_executable")),
111111
SPEC(base_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_prefix")),
112112
SPEC(bytes_warning, UINT, PUBLIC, SYS_FLAG(9)),
113+
SPEC(cpu_count, INT, PUBLIC, NO_SYS),
113114
SPEC(exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("exec_prefix")),
114115
SPEC(executable, WSTR_OPT, PUBLIC, SYS_ATTR("executable")),
115116
SPEC(inspect, BOOL, PUBLIC, SYS_FLAG(1)),
@@ -138,7 +139,6 @@ static const PyConfigSpec PYCONFIG_SPEC[] = {
138139
SPEC(check_hash_pycs_mode, WSTR, READ_ONLY, NO_SYS),
139140
SPEC(code_debug_ranges, BOOL, READ_ONLY, NO_SYS),
140141
SPEC(configure_c_stdio, BOOL, READ_ONLY, NO_SYS),
141-
SPEC(cpu_count, INT, READ_ONLY, NO_SYS),
142142
SPEC(dev_mode, BOOL, READ_ONLY, NO_SYS), // sys.flags.dev_mode
143143
SPEC(dump_refs, BOOL, READ_ONLY, NO_SYS),
144144
SPEC(dump_refs_file, WSTR_OPT, READ_ONLY, NO_SYS),
@@ -4524,6 +4524,18 @@ config_set_sys_flag(const PyConfigSpec *spec, int int_value)
45244524
}
45254525

45264526

4527+
// Set PyConfig.ATTR integer member
4528+
static int
4529+
config_set_int_attr(const PyConfigSpec *spec, int value)
4530+
{
4531+
PyInterpreterState *interp = _PyInterpreterState_GET();
4532+
PyConfig *config = &interp->config;
4533+
int *member = config_get_spec_member(config, spec);
4534+
*member = value;
4535+
return 0;
4536+
}
4537+
4538+
45274539
int
45284540
PyConfig_Set(const char *name, PyObject *value)
45294541
{
@@ -4632,17 +4644,21 @@ PyConfig_Set(const char *name, PyObject *value)
46324644
Py_UNREACHABLE();
46334645
}
46344646

4635-
46364647
if (spec->sys.attr != NULL) {
46374648
// Set the sys attribute, but don't set PyInterpreterState.config
46384649
// to keep the code simple.
46394650
return PySys_SetObject(spec->sys.attr, value);
46404651
}
4641-
else if (spec->sys.flag_index >= 0 && has_int_value) {
4642-
return config_set_sys_flag(spec, int_value);
4643-
}
4644-
else if (strcmp(spec->name, "int_max_str_digits") == 0 && has_int_value) {
4645-
return _PySys_SetIntMaxStrDigits(int_value);
4652+
else if (has_int_value) {
4653+
if (spec->sys.flag_index >= 0) {
4654+
return config_set_sys_flag(spec, int_value);
4655+
}
4656+
else if (strcmp(spec->name, "int_max_str_digits") == 0) {
4657+
return _PySys_SetIntMaxStrDigits(int_value);
4658+
}
4659+
else {
4660+
return config_set_int_attr(spec, int_value);
4661+
}
46464662
}
46474663

46484664
cannot_set:

0 commit comments

Comments
 (0)