gh-115754: Add Py_GetConstant() function (#116883)

Add Py_GetConstant() and Py_GetConstantBorrowed() functions.

In the limited C API version 3.13, getting Py_None, Py_False,
Py_True, Py_Ellipsis and Py_NotImplemented singletons is now
implemented as function calls at the stable ABI level to hide
implementation details. Getting these constants still return borrowed
references.

Add _testlimitedcapi/object.c and test_capi/test_object.py to test
Py_GetConstant() and Py_GetConstantBorrowed() functions.
This commit is contained in:
Victor Stinner 2024-03-21 17:07:00 +01:00 committed by GitHub
parent 5a76d1be8e
commit 8bea6c411d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 312 additions and 6 deletions

View File

@ -6,6 +6,55 @@ Object Protocol
=============== ===============
.. c:function:: PyObject* Py_GetConstant(unsigned int constant_id)
Get a :term:`strong reference` to a constant.
Set an exception and return ``NULL`` if *constant_id* is invalid.
*constant_id* must be one of these constant identifiers:
.. c:namespace:: NULL
======================================== ===== =========================
Constant Identifier Value Returned object
======================================== ===== =========================
.. c:macro:: Py_CONSTANT_NONE ``0`` :py:data:`None`
.. c:macro:: Py_CONSTANT_FALSE ``1`` :py:data:`False`
.. c:macro:: Py_CONSTANT_TRUE ``2`` :py:data:`True`
.. c:macro:: Py_CONSTANT_ELLIPSIS ``3`` :py:data:`Ellipsis`
.. c:macro:: Py_CONSTANT_NOT_IMPLEMENTED ``4`` :py:data:`NotImplemented`
.. c:macro:: Py_CONSTANT_ZERO ``5`` ``0``
.. c:macro:: Py_CONSTANT_ONE ``6`` ``1``
.. c:macro:: Py_CONSTANT_EMPTY_STR ``7`` ``''``
.. c:macro:: Py_CONSTANT_EMPTY_BYTES ``8`` ``b''``
.. c:macro:: Py_CONSTANT_EMPTY_TUPLE ``9`` ``()``
======================================== ===== =========================
Numeric values are only given for projects which cannot use the constant
identifiers.
.. versionadded:: 3.13
.. impl-detail::
In CPython, all of these constants are :term:`immortal`.
.. c:function:: PyObject* Py_GetConstantBorrowed(unsigned int constant_id)
Similar to :c:func:`Py_GetConstant`, but return a :term:`borrowed
reference`.
This function is primarily intended for backwards compatibility:
using :c:func:`Py_GetConstant` is recommended for new code.
The reference is borrowed from the interpreter, and is valid until the
interpreter finalization.
.. versionadded:: 3.13
.. c:var:: PyObject* Py_NotImplemented .. c:var:: PyObject* Py_NotImplemented
The ``NotImplemented`` singleton, used to signal that an operation is The ``NotImplemented`` singleton, used to signal that an operation is

View File

@ -838,6 +838,8 @@ function,Py_GenericAlias,3.9,,
var,Py_GenericAliasType,3.9,, var,Py_GenericAliasType,3.9,,
function,Py_GetBuildInfo,3.2,, function,Py_GetBuildInfo,3.2,,
function,Py_GetCompiler,3.2,, function,Py_GetCompiler,3.2,,
function,Py_GetConstant,3.13,,
function,Py_GetConstantBorrowed,3.13,,
function,Py_GetCopyright,3.2,, function,Py_GetCopyright,3.2,,
function,Py_GetExecPrefix,3.2,, function,Py_GetExecPrefix,3.2,,
function,Py_GetPath,3.2,, function,Py_GetPath,3.2,,

View File

@ -1731,6 +1731,11 @@ New Features
more information. more information.
(Contributed by Victor Stinner in :gh:`111696`.) (Contributed by Victor Stinner in :gh:`111696`.)
* Add :c:func:`Py_GetConstant` and :c:func:`Py_GetConstantBorrowed` functions
to get constants. For example, ``Py_GetConstant(Py_CONSTANT_ZERO)`` returns a
:term:`strong reference` to the constant zero.
(Contributed by Victor Stinner in :gh:`115754`.)
Porting to Python 3.13 Porting to Python 3.13
---------------------- ----------------------

View File

@ -18,8 +18,13 @@ PyAPI_DATA(PyLongObject) _Py_FalseStruct;
PyAPI_DATA(PyLongObject) _Py_TrueStruct; PyAPI_DATA(PyLongObject) _Py_TrueStruct;
/* Use these macros */ /* Use these macros */
#define Py_False _PyObject_CAST(&_Py_FalseStruct) #if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030D0000
#define Py_True _PyObject_CAST(&_Py_TrueStruct) # define Py_False Py_GetConstantBorrowed(Py_CONSTANT_FALSE)
# define Py_True Py_GetConstantBorrowed(Py_CONSTANT_TRUE)
#else
# define Py_False _PyObject_CAST(&_Py_FalseStruct)
# define Py_True _PyObject_CAST(&_Py_TrueStruct)
#endif
// Test if an object is the True singleton, the same as "x is True" in Python. // Test if an object is the True singleton, the same as "x is True" in Python.
PyAPI_FUNC(int) Py_IsTrue(PyObject *x); PyAPI_FUNC(int) Py_IsTrue(PyObject *x);

View File

@ -716,6 +716,8 @@ PyAPI_DATA(PyTypeObject) _PyNotImplemented_Type;
// Export for the stable ABI. // Export for the stable ABI.
PyAPI_DATA(int) _Py_SwappedOp[]; PyAPI_DATA(int) _Py_SwappedOp[];
extern void _Py_GetConstant_Init(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1068,12 +1068,34 @@ static inline PyObject* _Py_XNewRef(PyObject *obj)
#endif #endif
#define Py_CONSTANT_NONE 0
#define Py_CONSTANT_FALSE 1
#define Py_CONSTANT_TRUE 2
#define Py_CONSTANT_ELLIPSIS 3
#define Py_CONSTANT_NOT_IMPLEMENTED 4
#define Py_CONSTANT_ZERO 5
#define Py_CONSTANT_ONE 6
#define Py_CONSTANT_EMPTY_STR 7
#define Py_CONSTANT_EMPTY_BYTES 8
#define Py_CONSTANT_EMPTY_TUPLE 9
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000
PyAPI_FUNC(PyObject*) Py_GetConstant(unsigned int constant_id);
PyAPI_FUNC(PyObject*) Py_GetConstantBorrowed(unsigned int constant_id);
#endif
/* /*
_Py_NoneStruct is an object of undefined type which can be used in contexts _Py_NoneStruct is an object of undefined type which can be used in contexts
where NULL (nil) is not suitable (since NULL often means 'error'). where NULL (nil) is not suitable (since NULL often means 'error').
*/ */
PyAPI_DATA(PyObject) _Py_NoneStruct; /* Don't use this directly */ PyAPI_DATA(PyObject) _Py_NoneStruct; /* Don't use this directly */
#define Py_None (&_Py_NoneStruct)
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030D0000
# define Py_None Py_GetConstantBorrowed(Py_CONSTANT_NONE)
#else
# define Py_None (&_Py_NoneStruct)
#endif
// Test if an object is the None singleton, the same as "x is None" in Python. // Test if an object is the None singleton, the same as "x is None" in Python.
PyAPI_FUNC(int) Py_IsNone(PyObject *x); PyAPI_FUNC(int) Py_IsNone(PyObject *x);
@ -1087,7 +1109,12 @@ Py_NotImplemented is a singleton used to signal that an operation is
not implemented for a given type combination. not implemented for a given type combination.
*/ */
PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */ PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
#define Py_NotImplemented (&_Py_NotImplementedStruct)
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030D0000
# define Py_NotImplemented Py_GetConstantBorrowed(Py_CONSTANT_NOT_IMPLEMENTED)
#else
# define Py_NotImplemented (&_Py_NotImplementedStruct)
#endif
/* Macro for returning Py_NotImplemented from a function */ /* Macro for returning Py_NotImplemented from a function */
#define Py_RETURN_NOTIMPLEMENTED return Py_NotImplemented #define Py_RETURN_NOTIMPLEMENTED return Py_NotImplemented

View File

@ -8,7 +8,11 @@ extern "C" {
PyAPI_DATA(PyObject) _Py_EllipsisObject; /* Don't use this directly */ PyAPI_DATA(PyObject) _Py_EllipsisObject; /* Don't use this directly */
#define Py_Ellipsis (&_Py_EllipsisObject) #if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030D0000
# define Py_Ellipsis Py_GetConstantBorrowed(Py_CONSTANT_ELLIPSIS)
#else
# define Py_Ellipsis (&_Py_EllipsisObject)
#endif
/* Slice object interface */ /* Slice object interface */

View File

@ -0,0 +1,54 @@
import enum
import unittest
from test.support import import_helper
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
class Constant(enum.IntEnum):
Py_CONSTANT_NONE = 0
Py_CONSTANT_FALSE = 1
Py_CONSTANT_TRUE = 2
Py_CONSTANT_ELLIPSIS = 3
Py_CONSTANT_NOT_IMPLEMENTED = 4
Py_CONSTANT_ZERO = 5
Py_CONSTANT_ONE = 6
Py_CONSTANT_EMPTY_STR = 7
Py_CONSTANT_EMPTY_BYTES = 8
Py_CONSTANT_EMPTY_TUPLE = 9
INVALID_CONSTANT = Py_CONSTANT_EMPTY_TUPLE + 1
class CAPITest(unittest.TestCase):
def check_get_constant(self, get_constant):
self.assertIs(get_constant(Constant.Py_CONSTANT_NONE), None)
self.assertIs(get_constant(Constant.Py_CONSTANT_FALSE), False)
self.assertIs(get_constant(Constant.Py_CONSTANT_TRUE), True)
self.assertIs(get_constant(Constant.Py_CONSTANT_ELLIPSIS), Ellipsis)
self.assertIs(get_constant(Constant.Py_CONSTANT_NOT_IMPLEMENTED), NotImplemented)
for constant_id, constant_type, value in (
(Constant.Py_CONSTANT_ZERO, int, 0),
(Constant.Py_CONSTANT_ONE, int, 1),
(Constant.Py_CONSTANT_EMPTY_STR, str, ""),
(Constant.Py_CONSTANT_EMPTY_BYTES, bytes, b""),
(Constant.Py_CONSTANT_EMPTY_TUPLE, tuple, ()),
):
with self.subTest(constant_id=constant_id):
obj = get_constant(constant_id)
self.assertEqual(type(obj), constant_type, obj)
self.assertEqual(obj, value)
with self.assertRaises(SystemError):
get_constant(Constant.INVALID_CONSTANT)
def test_get_constant(self):
self.check_get_constant(_testlimitedcapi.get_constant)
def test_get_constant_borrowed(self):
self.check_get_constant(_testlimitedcapi.get_constant_borrowed)
if __name__ == "__main__":
unittest.main()

View File

@ -856,6 +856,8 @@ SYMBOL_NAMES = (
"Py_GetArgcArgv", "Py_GetArgcArgv",
"Py_GetBuildInfo", "Py_GetBuildInfo",
"Py_GetCompiler", "Py_GetCompiler",
"Py_GetConstant",
"Py_GetConstantBorrowed",
"Py_GetCopyright", "Py_GetCopyright",
"Py_GetExecPrefix", "Py_GetExecPrefix",
"Py_GetPath", "Py_GetPath",

View File

@ -0,0 +1,3 @@
Add :c:func:`Py_GetConstant` and :c:func:`Py_GetConstantBorrowed` functions to
get constants. For example, ``Py_GetConstant(Py_CONSTANT_ZERO)`` returns a
:term:`strong reference` to the constant zero. Patch by Victor Stinner.

View File

@ -0,0 +1,5 @@
In the limited C API version 3.13, getting ``Py_None``, ``Py_False``,
``Py_True``, ``Py_Ellipsis`` and ``Py_NotImplemented`` singletons is now
implemented as function calls at the stable ABI level to hide implementation
details. Getting these constants still return borrowed references. Patch by
Victor Stinner.

View File

@ -2500,3 +2500,7 @@
added = '3.13' added = '3.13'
[function.PyType_GetModuleName] [function.PyType_GetModuleName]
added = '3.13' added = '3.13'
[function.Py_GetConstant]
added = '3.13'
[function.Py_GetConstantBorrowed]
added = '3.13'

View File

@ -163,7 +163,7 @@
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c @MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c @MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c @MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c

View File

@ -53,6 +53,9 @@ PyInit__testlimitedcapi(void)
if (_PyTestLimitedCAPI_Init_Long(mod) < 0) { if (_PyTestLimitedCAPI_Init_Long(mod) < 0) {
return NULL; return NULL;
} }
if (_PyTestLimitedCAPI_Init_Object(mod) < 0) {
return NULL;
}
if (_PyTestLimitedCAPI_Init_PyOS(mod) < 0) { if (_PyTestLimitedCAPI_Init_PyOS(mod) < 0) {
return NULL; return NULL;
} }

View File

@ -0,0 +1,80 @@
// Need limited C API version 3.13 for Py_GetConstant()
#include "pyconfig.h" // Py_GIL_DISABLED
#if !defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API )
# define Py_LIMITED_API 0x030d0000
#endif
#include "parts.h"
#include "util.h"
/* Test Py_GetConstant() */
static PyObject *
get_constant(PyObject *Py_UNUSED(module), PyObject *args)
{
int constant_id;
if (!PyArg_ParseTuple(args, "i", &constant_id)) {
return NULL;
}
PyObject *obj = Py_GetConstant(constant_id);
if (obj == NULL) {
assert(PyErr_Occurred());
return NULL;
}
return obj;
}
/* Test Py_GetConstantBorrowed() */
static PyObject *
get_constant_borrowed(PyObject *Py_UNUSED(module), PyObject *args)
{
int constant_id;
if (!PyArg_ParseTuple(args, "i", &constant_id)) {
return NULL;
}
PyObject *obj = Py_GetConstantBorrowed(constant_id);
if (obj == NULL) {
assert(PyErr_Occurred());
return NULL;
}
return Py_NewRef(obj);
}
/* Test constants */
static PyObject *
test_constants(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
// Test that implementation of constants in the limited C API:
// check that the C code compiles.
//
// Test also that constants and Py_GetConstant() return the same
// objects.
assert(Py_None == Py_GetConstant(Py_CONSTANT_NONE));
assert(Py_False == Py_GetConstant(Py_CONSTANT_FALSE));
assert(Py_True == Py_GetConstant(Py_CONSTANT_TRUE));
assert(Py_Ellipsis == Py_GetConstant(Py_CONSTANT_ELLIPSIS));
assert(Py_NotImplemented == Py_GetConstant(Py_CONSTANT_NOT_IMPLEMENTED));
// Other constants are tested in test_capi.test_object
Py_RETURN_NONE;
}
static PyMethodDef test_methods[] = {
{"get_constant", get_constant, METH_VARARGS},
{"get_constant_borrowed", get_constant_borrowed, METH_VARARGS},
{"test_constants", test_constants, METH_NOARGS},
{NULL},
};
int
_PyTestLimitedCAPI_Init_Object(PyObject *m)
{
if (PyModule_AddFunctions(m, test_methods) < 0) {
return -1;
}
return 0;
}

View File

@ -29,6 +29,7 @@ int _PyTestLimitedCAPI_Init_Complex(PyObject *module);
int _PyTestLimitedCAPI_Init_Dict(PyObject *module); int _PyTestLimitedCAPI_Init_Dict(PyObject *module);
int _PyTestLimitedCAPI_Init_Float(PyObject *module); int _PyTestLimitedCAPI_Init_Float(PyObject *module);
int _PyTestLimitedCAPI_Init_HeaptypeRelative(PyObject *module); int _PyTestLimitedCAPI_Init_HeaptypeRelative(PyObject *module);
int _PyTestLimitedCAPI_Init_Object(PyObject *module);
int _PyTestLimitedCAPI_Init_List(PyObject *module); int _PyTestLimitedCAPI_Init_List(PyObject *module);
int _PyTestLimitedCAPI_Init_Long(PyObject *module); int _PyTestLimitedCAPI_Init_Long(PyObject *module);
int _PyTestLimitedCAPI_Init_PyOS(PyObject *module); int _PyTestLimitedCAPI_Init_PyOS(PyObject *module);

View File

@ -14,6 +14,7 @@
#include "pycore_memoryobject.h" // _PyManagedBuffer_Type #include "pycore_memoryobject.h" // _PyManagedBuffer_Type
#include "pycore_namespace.h" // _PyNamespace_Type #include "pycore_namespace.h" // _PyNamespace_Type
#include "pycore_object.h" // PyAPI_DATA() _Py_SwappedOp definition #include "pycore_object.h" // PyAPI_DATA() _Py_SwappedOp definition
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_optimizer.h" // _PyUOpExecutor_Type, _PyUOpOptimizer_Type, ... #include "pycore_optimizer.h" // _PyUOpExecutor_Type, _PyUOpOptimizer_Type, ...
#include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pymem.h" // _PyMem_IsPtrFreed()
@ -2991,3 +2992,53 @@ _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
{ {
Py_SET_REFCNT(ob, refcnt); Py_SET_REFCNT(ob, refcnt);
} }
static PyObject* constants[] = {
&_Py_NoneStruct, // Py_CONSTANT_NONE
(PyObject*)(&_Py_FalseStruct), // Py_CONSTANT_FALSE
(PyObject*)(&_Py_TrueStruct), // Py_CONSTANT_TRUE
&_Py_EllipsisObject, // Py_CONSTANT_ELLIPSIS
&_Py_NotImplementedStruct, // Py_CONSTANT_NOT_IMPLEMENTED
NULL, // Py_CONSTANT_ZERO
NULL, // Py_CONSTANT_ONE
NULL, // Py_CONSTANT_EMPTY_STR
NULL, // Py_CONSTANT_EMPTY_BYTES
NULL, // Py_CONSTANT_EMPTY_TUPLE
};
void
_Py_GetConstant_Init(void)
{
constants[Py_CONSTANT_ZERO] = _PyLong_GetZero();
constants[Py_CONSTANT_ONE] = _PyLong_GetOne();
constants[Py_CONSTANT_EMPTY_STR] = PyUnicode_New(0, 0);
constants[Py_CONSTANT_EMPTY_BYTES] = PyBytes_FromStringAndSize(NULL, 0);
constants[Py_CONSTANT_EMPTY_TUPLE] = PyTuple_New(0);
#ifndef NDEBUG
for (size_t i=0; i < Py_ARRAY_LENGTH(constants); i++) {
assert(constants[i] != NULL);
assert(_Py_IsImmortal(constants[i]));
}
#endif
}
PyObject*
Py_GetConstant(unsigned int constant_id)
{
if (constant_id < Py_ARRAY_LENGTH(constants)) {
return constants[constant_id];
}
else {
PyErr_BadInternalCall();
return NULL;
}
}
PyObject*
Py_GetConstantBorrowed(unsigned int constant_id)
{
// All constants are immortal
return Py_GetConstant(constant_id);
}

2
PC/python3dll.c generated
View File

@ -55,6 +55,8 @@ EXPORT_FUNC(Py_GenericAlias)
EXPORT_FUNC(Py_GetArgcArgv) EXPORT_FUNC(Py_GetArgcArgv)
EXPORT_FUNC(Py_GetBuildInfo) EXPORT_FUNC(Py_GetBuildInfo)
EXPORT_FUNC(Py_GetCompiler) EXPORT_FUNC(Py_GetCompiler)
EXPORT_FUNC(Py_GetConstant)
EXPORT_FUNC(Py_GetConstantBorrowed)
EXPORT_FUNC(Py_GetCopyright) EXPORT_FUNC(Py_GetCopyright)
EXPORT_FUNC(Py_GetExecPrefix) EXPORT_FUNC(Py_GetExecPrefix)
EXPORT_FUNC(Py_GetPath) EXPORT_FUNC(Py_GetPath)

View File

@ -103,6 +103,7 @@
<ClCompile Include="..\Modules\_testlimitedcapi\heaptype_relative.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\heaptype_relative.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\list.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\list.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\long.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\long.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\object.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\pyos.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\pyos.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\set.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\set.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\sys.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\sys.c" />

View File

@ -18,6 +18,7 @@
<ClCompile Include="..\Modules\_testlimitedcapi\heaptype_relative.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\heaptype_relative.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\list.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\list.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\long.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\long.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\object.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\pyos.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\pyos.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\set.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\set.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\sys.c" /> <ClCompile Include="..\Modules\_testlimitedcapi\sys.c" />

View File

@ -687,6 +687,10 @@ pycore_init_global_objects(PyInterpreterState *interp)
_PyUnicode_InitState(interp); _PyUnicode_InitState(interp);
if (_Py_IsMainInterpreter(interp)) {
_Py_GetConstant_Init();
}
return _PyStatus_OK(); return _PyStatus_OK();
} }

View File

@ -742,3 +742,4 @@ Modules/_sqlite/module.c - _sqlite3module -
Modules/clinic/md5module.c.h _md5_md5 _keywords - Modules/clinic/md5module.c.h _md5_md5 _keywords -
Modules/clinic/grpmodule.c.h grp_getgrgid _keywords - Modules/clinic/grpmodule.c.h grp_getgrgid _keywords -
Modules/clinic/grpmodule.c.h grp_getgrnam _keywords - Modules/clinic/grpmodule.c.h grp_getgrnam _keywords -
Objects/object.c - constants static PyObject*[]

Can't render this file because it has a wrong number of fields in line 4.