@@ -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)
@@ -583,7 +584,7 @@ static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
583584 return 0 ;
584585 }
585586 *pobj = Py_NewRef (obj);
586- return (*pobj != NULL ) ;
587+ return 1 ;
587588}
588589#endif
589590
@@ -1933,6 +1934,267 @@ PyLongWriter_Finish(PyLongWriter *writer)
19331934#endif
19341935
19351936
1937+ // gh-127350 added Py_fopen() and Py_fclose() to Python 3.14a4
1938+ #if PY_VERSION_HEX < 0x030E00A4
1939+ static inline FILE* Py_fopen (PyObject *path, const char *mode)
1940+ {
1941+ #if 0x030400A2 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
1942+ extern FILE* _Py_fopen_obj (PyObject *path, const char *mode);
1943+ return _Py_fopen_obj (path, mode);
1944+ #else
1945+ FILE *f;
1946+ PyObject *bytes;
1947+ #if PY_VERSION_HEX >= 0x03000000
1948+ if (!PyUnicode_FSConverter (path, &bytes)) {
1949+ return NULL ;
1950+ }
1951+ #else
1952+ if (!PyString_Check (path)) {
1953+ PyErr_SetString (PyExc_TypeError, " except str" );
1954+ return NULL ;
1955+ }
1956+ bytes = Py_NewRef (path);
1957+ #endif
1958+ const char *path_bytes = PyBytes_AS_STRING (bytes);
1959+
1960+ f = fopen (path_bytes, mode);
1961+ Py_DECREF (bytes);
1962+
1963+ if (f == NULL ) {
1964+ PyErr_SetFromErrnoWithFilenameObject (PyExc_OSError, path);
1965+ return NULL ;
1966+ }
1967+ return f;
1968+ #endif
1969+ }
1970+
1971+ static inline int Py_fclose (FILE *file)
1972+ {
1973+ return fclose (file);
1974+ }
1975+ #endif
1976+
1977+
1978+ #if 0x03090000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION)
1979+ static inline PyObject*
1980+ PyConfig_Get (const char *name)
1981+ {
1982+ typedef enum {
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+ typedef struct {
1993+ const char *name;
1994+ size_t offset;
1995+ PyConfigMemberType type;
1996+ const char *sys_attr;
1997+ } PyConfigSpec;
1998+
1999+ #define PYTHONCAPI_COMPAT_SPEC (MEMBER, TYPE, sys_attr ) \
2000+ {#MEMBER, offsetof (PyConfig, MEMBER), \
2001+ _PyConfig_MEMBER_##TYPE, sys_attr}
2002+
2003+ static const 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+ PYTHONCAPI_COMPAT_SPEC (user_site_directory, BOOL, _Py_NULL),
2086+ #if 0x030A0000 <= PY_VERSION_HEX
2087+ PYTHONCAPI_COMPAT_SPEC (warn_default_encoding, BOOL, _Py_NULL),
2088+ #endif
2089+ };
2090+
2091+ #undef PYTHONCAPI_COMPAT_SPEC
2092+
2093+ const PyConfigSpec *spec;
2094+ int found = 0 ;
2095+ for (size_t i=0 ; i < sizeof (config_spec) / sizeof (config_spec[0 ]); i++) {
2096+ spec = &config_spec[i];
2097+ if (strcmp (spec->name , name) == 0 ) {
2098+ found = 1 ;
2099+ break ;
2100+ }
2101+ }
2102+ if (found) {
2103+ if (spec->sys_attr != NULL ) {
2104+ PyObject *value = PySys_GetObject (spec->sys_attr );
2105+ if (value == NULL ) {
2106+ PyErr_Format (PyExc_RuntimeError, " lost sys.%s" , spec->sys_attr );
2107+ return NULL ;
2108+ }
2109+ return Py_NewRef (value);
2110+ }
2111+
2112+ extern const PyConfig* _Py_GetConfig (void );
2113+ const PyConfig *config = _Py_GetConfig ();
2114+ void *member = (char *)config + spec->offset ;
2115+ switch (spec->type ) {
2116+ case _PyConfig_MEMBER_INT:
2117+ case _PyConfig_MEMBER_UINT:
2118+ {
2119+ int value = *(int *)member;
2120+ return PyLong_FromLong (value);
2121+ }
2122+ case _PyConfig_MEMBER_BOOL:
2123+ {
2124+ int value = *(int *)member;
2125+ return PyBool_FromLong (value != 0 );
2126+ }
2127+ case _PyConfig_MEMBER_ULONG:
2128+ {
2129+ unsigned long value = *(unsigned long *)member;
2130+ return PyLong_FromUnsignedLong (value);
2131+ }
2132+ case _PyConfig_MEMBER_WSTR:
2133+ case _PyConfig_MEMBER_WSTR_OPT:
2134+ {
2135+ wchar_t *wstr = *(wchar_t **)member;
2136+ if (wstr != NULL ) {
2137+ return PyUnicode_FromWideChar (wstr, -1 );
2138+ }
2139+ else {
2140+ return Py_NewRef (Py_None);
2141+ }
2142+ }
2143+ case _PyConfig_MEMBER_WSTR_LIST:
2144+ {
2145+ const PyWideStringList *list = (const PyWideStringList *)member;
2146+ PyObject *tuple = PyTuple_New (list->length );
2147+ if (tuple == NULL ) {
2148+ return NULL ;
2149+ }
2150+
2151+ for (Py_ssize_t i = 0 ; i < list->length ; i++) {
2152+ PyObject *item = PyUnicode_FromWideChar (list->items [i], -1 );
2153+ if (item == NULL ) {
2154+ Py_DECREF (tuple);
2155+ return NULL ;
2156+ }
2157+ PyTuple_SET_ITEM (tuple, i, item);
2158+ }
2159+ return tuple;
2160+ }
2161+ default :
2162+ Py_UNREACHABLE ();
2163+ }
2164+ }
2165+
2166+ PyErr_Format (PyExc_ValueError, " unknown config option name: %s" , name);
2167+ return NULL ;
2168+ }
2169+
2170+ static inline int
2171+ PyConfig_GetInt (const char *name, int *value)
2172+ {
2173+ PyObject *obj = PyConfig_Get (name);
2174+ if (obj == NULL ) {
2175+ return -1 ;
2176+ }
2177+
2178+ if (!PyLong_Check (obj)) {
2179+ Py_DECREF (obj);
2180+ PyErr_Format (PyExc_TypeError, " config option %s is not an int" , name);
2181+ return -1 ;
2182+ }
2183+
2184+ int as_int = PyLong_AsInt (obj);
2185+ Py_DECREF (obj);
2186+ if (as_int == -1 && PyErr_Occurred ()) {
2187+ PyErr_Format (PyExc_OverflowError,
2188+ " config option %s value does not fit into a C int" , name);
2189+ return -1 ;
2190+ }
2191+
2192+ *value = as_int;
2193+ return 0 ;
2194+ }
2195+ #endif // PY_VERSION_HEX > 0x03090000 && !defined(PYPY_VERSION)
2196+
2197+
19362198#ifdef __cplusplus
19372199}
19382200#endif
0 commit comments