Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8a52253

Browse files
authored
Add PyConfig_Get() (#128)
1 parentb1b2071 commit8a52253

File tree

4 files changed

+296
-2
lines changed

4 files changed

+296
-2
lines changed

‎docs/api.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,17 @@ Python 3.14
177177

178178
See `Py_fclose() documentation <https://docs.python.org/dev/c-api/sys.html#c.Py_fclose>`__.
179179

180+
.. c:function:: PyObject* PyConfig_Get(const char *name)
181+
182+
See `PyConfig_Get() documentation <https://docs.python.org/dev/c-api/init_config.html#c.PyConfig_Get>`__.
183+
184+
.. c:function:: int PyConfig_GetInt(const char *name, int *value)
185+
186+
See `PyConfig_GetInt() documentation <https://docs.python.org/dev/c-api/init_config.html#c.PyConfig_GetInt>`__.
187+
180188

181189
Not supported:
182190

183-
* ``PyConfig_Get()``
184-
* ``PyConfig_GetInt()``
185191
* ``PyConfig_Names()``
186192
* ``PyConfig_Set()``
187193
* ``PyInitConfig_AddModule()``

‎docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Changelog
22
=========
33

4+
* 2025-01-19: Add ``PyConfig_Get()`` functions.
45
* 2025-01-06: Add ``Py_fopen()`` and ``Py_fclose()`` functions.
56
* 2024-12-16: Add ``structmember.h`` constants:
67

‎pythoncapi_compat.h

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extern "C" {
1919
#endif
2020

2121
#include<Python.h>
22+
#include<stddef.h>// offsetof()
2223

2324
// Python 3.11.0b4 added PyFrame_Back() to Python.h
2425
#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
@@ -1974,6 +1975,229 @@ int Py_fclose(FILE *file)
19741975
#endif
19751976

19761977

1978+
#if 0x03090000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION)
1979+
staticinline PyObject*
1980+
PyConfig_Get(constchar *name)
1981+
{
1982+
typedefenum {
1983+
_PyConfig_MEMBER_INT,
1984+
_PyConfig_MEMBER_UINT,
1985+
_PyConfig_MEMBER_ULONG,
1986+
_PyConfig_MEMBER_BOOL,
1987+
_PyConfig_MEMBER_WSTR,
1988+
_PyConfig_MEMBER_WSTR_OPT,
1989+
_PyConfig_MEMBER_WSTR_LIST,
1990+
} PyConfigMemberType;
1991+
1992+
typedefstruct {
1993+
constchar *name;
1994+
size_t offset;
1995+
PyConfigMemberType type;
1996+
constchar *sys_attr;
1997+
} PyConfigSpec;
1998+
1999+
#definePYTHONCAPI_COMPAT_SPEC(MEMBER, TYPE, sys_attr) \
2000+
{#MEMBER,offsetof(PyConfig, MEMBER), \
2001+
_PyConfig_MEMBER_##TYPE, sys_attr}
2002+
2003+
staticconst PyConfigSpec config_spec[] = {
2004+
PYTHONCAPI_COMPAT_SPEC(argv, WSTR_LIST,"argv"),
2005+
PYTHONCAPI_COMPAT_SPEC(base_exec_prefix, WSTR_OPT,"base_exec_prefix"),
2006+
PYTHONCAPI_COMPAT_SPEC(base_executable, WSTR_OPT,"_base_executable"),
2007+
PYTHONCAPI_COMPAT_SPEC(base_prefix, WSTR_OPT,"base_prefix"),
2008+
PYTHONCAPI_COMPAT_SPEC(bytes_warning, UINT, _Py_NULL),
2009+
PYTHONCAPI_COMPAT_SPEC(exec_prefix, WSTR_OPT,"exec_prefix"),
2010+
PYTHONCAPI_COMPAT_SPEC(executable, WSTR_OPT,"executable"),
2011+
PYTHONCAPI_COMPAT_SPEC(inspect, BOOL, _Py_NULL),
2012+
#if 0x030C0000 <= PY_VERSION_HEX
2013+
PYTHONCAPI_COMPAT_SPEC(int_max_str_digits, UINT, _Py_NULL),
2014+
#endif
2015+
PYTHONCAPI_COMPAT_SPEC(interactive, BOOL, _Py_NULL),
2016+
PYTHONCAPI_COMPAT_SPEC(module_search_paths, WSTR_LIST,"path"),
2017+
PYTHONCAPI_COMPAT_SPEC(optimization_level, UINT, _Py_NULL),
2018+
PYTHONCAPI_COMPAT_SPEC(parser_debug, BOOL, _Py_NULL),
2019+
PYTHONCAPI_COMPAT_SPEC(platlibdir, WSTR,"platlibdir"),
2020+
PYTHONCAPI_COMPAT_SPEC(prefix, WSTR_OPT,"prefix"),
2021+
PYTHONCAPI_COMPAT_SPEC(pycache_prefix, WSTR_OPT,"pycache_prefix"),
2022+
PYTHONCAPI_COMPAT_SPEC(quiet, BOOL, _Py_NULL),
2023+
#if 0x030B0000 <= PY_VERSION_HEX
2024+
PYTHONCAPI_COMPAT_SPEC(stdlib_dir, WSTR_OPT,"_stdlib_dir"),
2025+
#endif
2026+
PYTHONCAPI_COMPAT_SPEC(use_environment, BOOL, _Py_NULL),
2027+
PYTHONCAPI_COMPAT_SPEC(verbose, UINT, _Py_NULL),
2028+
PYTHONCAPI_COMPAT_SPEC(warnoptions, WSTR_LIST,"warnoptions"),
2029+
PYTHONCAPI_COMPAT_SPEC(write_bytecode, BOOL, _Py_NULL),
2030+
PYTHONCAPI_COMPAT_SPEC(xoptions, WSTR_LIST,"_xoptions"),
2031+
PYTHONCAPI_COMPAT_SPEC(buffered_stdio, BOOL, _Py_NULL),
2032+
PYTHONCAPI_COMPAT_SPEC(check_hash_pycs_mode, WSTR, _Py_NULL),
2033+
#if 0x030B0000 <= PY_VERSION_HEX
2034+
PYTHONCAPI_COMPAT_SPEC(code_debug_ranges, BOOL, _Py_NULL),
2035+
#endif
2036+
PYTHONCAPI_COMPAT_SPEC(configure_c_stdio, BOOL, _Py_NULL),
2037+
#if 0x030D0000 <= PY_VERSION_HEX
2038+
PYTHONCAPI_COMPAT_SPEC(cpu_count, INT, _Py_NULL),
2039+
#endif
2040+
PYTHONCAPI_COMPAT_SPEC(dev_mode, BOOL, _Py_NULL),
2041+
PYTHONCAPI_COMPAT_SPEC(dump_refs, BOOL, _Py_NULL),
2042+
#if 0x030B0000 <= PY_VERSION_HEX
2043+
PYTHONCAPI_COMPAT_SPEC(dump_refs_file, WSTR_OPT, _Py_NULL),
2044+
#endif
2045+
#ifdef Py_GIL_DISABLED
2046+
PYTHONCAPI_COMPAT_SPEC(enable_gil, INT, _Py_NULL),
2047+
#endif
2048+
PYTHONCAPI_COMPAT_SPEC(faulthandler, BOOL, _Py_NULL),
2049+
PYTHONCAPI_COMPAT_SPEC(filesystem_encoding, WSTR, _Py_NULL),
2050+
PYTHONCAPI_COMPAT_SPEC(filesystem_errors, WSTR, _Py_NULL),
2051+
PYTHONCAPI_COMPAT_SPEC(hash_seed, ULONG, _Py_NULL),
2052+
PYTHONCAPI_COMPAT_SPEC(home, WSTR_OPT, _Py_NULL),
2053+
PYTHONCAPI_COMPAT_SPEC(import_time, BOOL, _Py_NULL),
2054+
PYTHONCAPI_COMPAT_SPEC(install_signal_handlers, BOOL, _Py_NULL),
2055+
PYTHONCAPI_COMPAT_SPEC(isolated, BOOL, _Py_NULL),
2056+
#ifdef MS_WINDOWS
2057+
PYTHONCAPI_COMPAT_SPEC(legacy_windows_stdio, BOOL, _Py_NULL),
2058+
#endif
2059+
PYTHONCAPI_COMPAT_SPEC(malloc_stats, BOOL, _Py_NULL),
2060+
#if 0x030A0000 <= PY_VERSION_HEX
2061+
PYTHONCAPI_COMPAT_SPEC(orig_argv, WSTR_LIST,"orig_argv"),
2062+
#endif
2063+
PYTHONCAPI_COMPAT_SPEC(parse_argv, BOOL, _Py_NULL),
2064+
PYTHONCAPI_COMPAT_SPEC(pathconfig_warnings, BOOL, _Py_NULL),
2065+
#if 0x030C0000 <= PY_VERSION_HEX
2066+
PYTHONCAPI_COMPAT_SPEC(perf_profiling, UINT, _Py_NULL),
2067+
#endif
2068+
PYTHONCAPI_COMPAT_SPEC(program_name, WSTR, _Py_NULL),
2069+
PYTHONCAPI_COMPAT_SPEC(run_command, WSTR_OPT, _Py_NULL),
2070+
PYTHONCAPI_COMPAT_SPEC(run_filename, WSTR_OPT, _Py_NULL),
2071+
PYTHONCAPI_COMPAT_SPEC(run_module, WSTR_OPT, _Py_NULL),
2072+
#if 0x030B0000 <= PY_VERSION_HEX
2073+
PYTHONCAPI_COMPAT_SPEC(safe_path, BOOL, _Py_NULL),
2074+
#endif
2075+
PYTHONCAPI_COMPAT_SPEC(show_ref_count, BOOL, _Py_NULL),
2076+
PYTHONCAPI_COMPAT_SPEC(site_import, BOOL, _Py_NULL),
2077+
PYTHONCAPI_COMPAT_SPEC(skip_source_first_line, BOOL, _Py_NULL),
2078+
PYTHONCAPI_COMPAT_SPEC(stdio_encoding, WSTR, _Py_NULL),
2079+
PYTHONCAPI_COMPAT_SPEC(stdio_errors, WSTR, _Py_NULL),
2080+
PYTHONCAPI_COMPAT_SPEC(tracemalloc, UINT, _Py_NULL),
2081+
#if 0x030B0000 <= PY_VERSION_HEX
2082+
PYTHONCAPI_COMPAT_SPEC(use_frozen_modules, BOOL, _Py_NULL),
2083+
#endif
2084+
PYTHONCAPI_COMPAT_SPEC(use_hash_seed, BOOL, _Py_NULL),
2085+
#if 0x030D0000 <= PY_VERSION_HEX && defined(__APPLE__)
2086+
PYTHONCAPI_COMPAT_SPEC(use_system_logger, BOOL, _Py_NULL),
2087+
#endif
2088+
PYTHONCAPI_COMPAT_SPEC(user_site_directory, BOOL, _Py_NULL),
2089+
#if 0x030A0000 <= PY_VERSION_HEX
2090+
PYTHONCAPI_COMPAT_SPEC(warn_default_encoding, BOOL, _Py_NULL),
2091+
#endif
2092+
};
2093+
2094+
#undef PYTHONCAPI_COMPAT_SPEC
2095+
2096+
const PyConfigSpec *spec;
2097+
int found =0;
2098+
for (size_t i=0; i <Py_ARRAY_LENGTH(config_spec); i++) {
2099+
spec = &config_spec[i];
2100+
if (strcmp(spec->name, name) ==0) {
2101+
found =1;
2102+
break;
2103+
}
2104+
}
2105+
if (found) {
2106+
if (spec->sys_attr !=NULL) {
2107+
PyObject *value =PySys_GetObject(spec->sys_attr);
2108+
if (value ==NULL) {
2109+
PyErr_Format(PyExc_RuntimeError,"lost sys.%s", spec->sys_attr);
2110+
returnNULL;
2111+
}
2112+
returnPy_NewRef(value);
2113+
}
2114+
2115+
externconst PyConfig*_Py_GetConfig(void);
2116+
const PyConfig *config =_Py_GetConfig();
2117+
void *member = (char *)config + spec->offset;
2118+
switch (spec->type) {
2119+
case _PyConfig_MEMBER_INT:
2120+
case _PyConfig_MEMBER_UINT:
2121+
{
2122+
int value = *(int *)member;
2123+
returnPyLong_FromLong(value);
2124+
}
2125+
case _PyConfig_MEMBER_BOOL:
2126+
{
2127+
int value = *(int *)member;
2128+
returnPyBool_FromLong(value !=0);
2129+
}
2130+
case _PyConfig_MEMBER_ULONG:
2131+
{
2132+
unsignedlong value = *(unsignedlong *)member;
2133+
returnPyLong_FromUnsignedLong(value);
2134+
}
2135+
case _PyConfig_MEMBER_WSTR:
2136+
case _PyConfig_MEMBER_WSTR_OPT:
2137+
{
2138+
wchar_t *wstr = *(wchar_t **)member;
2139+
if (wstr !=NULL) {
2140+
returnPyUnicode_FromWideChar(wstr, -1);
2141+
}
2142+
else {
2143+
returnPy_NewRef(Py_None);
2144+
}
2145+
}
2146+
case _PyConfig_MEMBER_WSTR_LIST:
2147+
{
2148+
const PyWideStringList *list = (const PyWideStringList *)member;
2149+
PyObject *tuple =PyTuple_New(list->length);
2150+
if (tuple ==NULL) {
2151+
returnNULL;
2152+
}
2153+
2154+
for (Py_ssize_t i =0; i < list->length; i++) {
2155+
PyObject *item =PyUnicode_FromWideChar(list->items[i], -1);
2156+
if (item ==NULL) {
2157+
Py_DECREF(tuple);
2158+
returnNULL;
2159+
}
2160+
PyTuple_SET_ITEM(tuple, i, item);
2161+
}
2162+
return tuple;
2163+
}
2164+
default:
2165+
Py_UNREACHABLE();
2166+
}
2167+
}
2168+
2169+
PyErr_Format(PyExc_ValueError,"unknown config option name: %s", name);
2170+
returnNULL;
2171+
}
2172+
2173+
staticinlineint
2174+
PyConfig_GetInt(constchar *name,int *value)
2175+
{
2176+
PyObject *obj =PyConfig_Get(name);
2177+
if (obj ==NULL) {
2178+
return -1;
2179+
}
2180+
2181+
if (!PyLong_Check(obj)) {
2182+
Py_DECREF(obj);
2183+
PyErr_Format(PyExc_TypeError,"config option %s is not an int", name);
2184+
return -1;
2185+
}
2186+
2187+
int as_int =PyLong_AsInt(obj);
2188+
Py_DECREF(obj);
2189+
if (as_int == -1 &&PyErr_Occurred()) {
2190+
PyErr_Format(PyExc_OverflowError,
2191+
"config option %s value does not fit into a C int", name);
2192+
return -1;
2193+
}
2194+
2195+
*value = as_int;
2196+
return0;
2197+
}
2198+
#endif// PY_VERSION_HEX > 0x03090000 && !defined(PYPY_VERSION)
2199+
2200+
19772201
#ifdef __cplusplus
19782202
}
19792203
#endif

‎tests/test_pythoncapi_compat_cext.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,66 @@ test_file(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
21122112
}
21132113

21142114

2115+
#if0x03090000 <=PY_VERSION_HEX&& !defined(PYPY_VERSION)
2116+
staticPyObject*
2117+
test_config(PyObject*Py_UNUSED(module),PyObject*Py_UNUSED(args))
2118+
{
2119+
// Test PyConfig_Get()
2120+
PyObject*sys=PyImport_ImportModule("sys");
2121+
if (sys==_Py_NULL) {
2122+
return_Py_NULL;
2123+
}
2124+
2125+
PyObject*obj=PyConfig_Get("argv");
2126+
PyObject*sys_attr=PyObject_GetAttrString(sys,"argv");
2127+
assert(obj==sys_attr);
2128+
Py_DECREF(obj);
2129+
Py_DECREF(sys_attr);
2130+
2131+
obj=PyConfig_Get("module_search_paths");
2132+
sys_attr=PyObject_GetAttrString(sys,"path");
2133+
assert(obj==sys_attr);
2134+
Py_DECREF(obj);
2135+
Py_DECREF(sys_attr);
2136+
2137+
obj=PyConfig_Get("xoptions");
2138+
sys_attr=PyObject_GetAttrString(sys,"_xoptions");
2139+
assert(obj==sys_attr);
2140+
Py_DECREF(obj);
2141+
Py_DECREF(sys_attr);
2142+
2143+
obj=PyConfig_Get("use_environment");
2144+
assert(PyBool_Check(obj));
2145+
Py_DECREF(obj);
2146+
2147+
obj=PyConfig_Get("verbose");
2148+
assert(PyLong_Check(obj));
2149+
Py_DECREF(obj);
2150+
2151+
assert(PyConfig_Get("nonexistent")==NULL);
2152+
assert(PyErr_ExceptionMatches(PyExc_ValueError));
2153+
PyErr_Clear();
2154+
2155+
// Test PyConfig_GetInt()
2156+
intvalue=-3;
2157+
2158+
assert(PyConfig_GetInt("verbose",&value)==0);
2159+
assert(value >=0);
2160+
2161+
assert(PyConfig_GetInt("argv",&value)==-1);
2162+
assert(PyErr_ExceptionMatches(PyExc_TypeError));
2163+
PyErr_Clear();
2164+
2165+
assert(PyConfig_GetInt("nonexistent",&value)==-1);
2166+
assert(PyErr_ExceptionMatches(PyExc_ValueError));
2167+
PyErr_Clear();
2168+
2169+
Py_DECREF(sys);
2170+
Py_RETURN_NONE;
2171+
}
2172+
#endif
2173+
2174+
21152175
staticstructPyMethodDefmethods[]= {
21162176
{"test_object",test_object,METH_NOARGS,_Py_NULL},
21172177
{"test_py_is",test_py_is,METH_NOARGS,_Py_NULL},
@@ -2160,6 +2220,9 @@ static struct PyMethodDef methods[] = {
21602220
{"test_long_stdint",test_long_stdint,METH_NOARGS,_Py_NULL},
21612221
{"test_structmember",test_structmember,METH_NOARGS,_Py_NULL},
21622222
{"test_file",test_file,METH_NOARGS,_Py_NULL},
2223+
#if0x03090000 <=PY_VERSION_HEX&& !defined(PYPY_VERSION)
2224+
{"test_config",test_config,METH_NOARGS,_Py_NULL},
2225+
#endif
21632226
{_Py_NULL,_Py_NULL,0,_Py_NULL}
21642227
};
21652228

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp