summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2024-03-21 16:07:00 (GMT)
committerGitHub <noreply@github.com>2024-03-21 16:07:00 (GMT)
commit8bea6c411d65cd987616b4ecdb86373e4f21f1c6 (patch)
tree962f984417dab800fbf4d21048a1fd8ba39202f0 /Objects
parent5a76d1be8ef371b75ca65166726923c249b5f615 (diff)
downloadcpython-8bea6c411d65cd987616b4ecdb86373e4f21f1c6.zip
cpython-8bea6c411d65cd987616b4ecdb86373e4f21f1c6.tar.gz
cpython-8bea6c411d65cd987616b4ecdb86373e4f21f1c6.tar.bz2
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.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/object.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/Objects/object.c b/Objects/object.c
index fcb8cf4..0d03292 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -14,6 +14,7 @@
#include "pycore_memoryobject.h" // _PyManagedBuffer_Type
#include "pycore_namespace.h" // _PyNamespace_Type
#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_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
@@ -2991,3 +2992,53 @@ _Py_SetRefcnt(PyObject *ob, Py_ssize_t 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);
+}