Skip to content

Commit

Permalink
pythongh-115754: Get singletons by function calls in lmited C API 3.13
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vstinner committed Mar 11, 2024
1 parent 729bfb3 commit f8fc1c5
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 8 deletions.
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.13.rst
Expand Up @@ -1645,6 +1645,11 @@ New Features
between native integer types and Python :class:`int` objects.
(Contributed by Steve Dower in :gh:`111140`.)

* 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.
(Contributed by Victor Stinner in :gh:`115754`.)

Porting to Python 3.13
----------------------
Expand Down
13 changes: 10 additions & 3 deletions Include/boolobject.h
Expand Up @@ -16,10 +16,17 @@ extern "C" {
/* Don't use these directly */
PyAPI_DATA(PyLongObject) _Py_FalseStruct;
PyAPI_DATA(PyLongObject) _Py_TrueStruct;
PyAPI_FUNC(PyObject*) _Py_GetFalse(void);
PyAPI_FUNC(PyObject*) _Py_GetTrue(void);

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030D0000
# define Py_False _Py_GetFalse()
# define Py_True _Py_GetTrue()
#else
# define Py_False _PyObject_CAST(&_Py_FalseStruct)
# define Py_True _PyObject_CAST(&_Py_TrueStruct)
#endif

/* Use these macros */
#define Py_False _PyObject_CAST(&_Py_FalseStruct)
#define Py_True _PyObject_CAST(&_Py_TrueStruct)

// Test if an object is the True singleton, the same as "x is True" in Python.
PyAPI_FUNC(int) Py_IsTrue(PyObject *x);
Expand Down
16 changes: 14 additions & 2 deletions Include/object.h
Expand Up @@ -1070,7 +1070,13 @@ _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').
*/
PyAPI_DATA(PyObject) _Py_NoneStruct; /* Don't use this directly */
#define Py_None (&_Py_NoneStruct)
PyAPI_FUNC(PyObject*) _Py_GetNone(void);

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030D0000
# define Py_None _Py_GetNone()
#else
# define Py_None (&_Py_NoneStruct)
#endif

// Test if an object is the None singleton, the same as "x is None" in Python.
PyAPI_FUNC(int) Py_IsNone(PyObject *x);
Expand All @@ -1084,7 +1090,13 @@ Py_NotImplemented is a singleton used to signal that an operation is
not implemented for a given type combination.
*/
PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
#define Py_NotImplemented (&_Py_NotImplementedStruct)
PyAPI_FUNC(PyObject*) _Py_GetNotImplemented(void);

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030D0000
# define Py_NotImplemented _Py_GetNotImplemented()
#else
# define Py_NotImplemented (&_Py_NotImplementedStruct)
#endif

/* Macro for returning Py_NotImplemented from a function */
#define Py_RETURN_NOTIMPLEMENTED return Py_NotImplemented
Expand Down
7 changes: 6 additions & 1 deletion Include/sliceobject.h
Expand Up @@ -7,8 +7,13 @@ extern "C" {
/* The unique ellipsis object "..." */

PyAPI_DATA(PyObject) _Py_EllipsisObject; /* Don't use this directly */
PyAPI_FUNC(PyObject*) _Py_GetEllipsis(void);

#define Py_Ellipsis (&_Py_EllipsisObject)
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030D0000
# define Py_Ellipsis _Py_GetEllipsis()
#else
# define Py_Ellipsis (&_Py_EllipsisObject)
#endif

/* Slice object interface */

Expand Down
@@ -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.
10 changes: 10 additions & 0 deletions Misc/stable_abi.toml
Expand Up @@ -2496,3 +2496,13 @@
[typedef.PyCFunctionFastWithKeywords]
added = '3.13'
# "abi-only" since 3.10. (Same story as PyCFunctionFast.)
[typedef._Py_GetNone]
added = '3.13'
[typedef._Py_GetFalse]
added = '3.13'
[typedef._Py_GetTrue]
added = '3.13'
[typedef._Py_GetEllipsis]
added = '3.13'
[typedef._Py_GetNotImplemented]
added = '3.13'
11 changes: 9 additions & 2 deletions Objects/longobject.c
Expand Up @@ -6592,16 +6592,23 @@ _PyLong_FiniTypes(PyInterpreterState *interp)
_PyStructSequence_FiniBuiltin(interp, &Int_InfoType);
}

#undef PyUnstable_Long_IsCompact

// -- Stable ABI ------------------------------------------------------------

#undef PyUnstable_Long_IsCompact
int
PyUnstable_Long_IsCompact(const PyLongObject* op) {
return _PyLong_IsCompact(op);
}

#undef PyUnstable_Long_CompactValue

Py_ssize_t
PyUnstable_Long_CompactValue(const PyLongObject* op) {
return _PyLong_CompactValue(op);
}

PyObject* _Py_GetFalse(void)
{ return _PyObject_CAST(&_Py_FalseStruct); }

PyObject* _Py_GetTrue(void)
{ return _PyObject_CAST(&_Py_TrueStruct); }
8 changes: 8 additions & 0 deletions Objects/object.c
Expand Up @@ -2920,6 +2920,8 @@ PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
}


// -- Stable ABI ------------------------------------------------------------

#undef Py_NewRef
#undef Py_XNewRef

Expand Down Expand Up @@ -2970,3 +2972,9 @@ _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
{
Py_SET_REFCNT(ob, refcnt);
}

PyObject* _Py_GetNone(void)
{ return &_Py_NoneStruct; }

PyObject* _Py_GetNotImplemented(void)
{ return &_Py_NotImplementedStruct; }
6 changes: 6 additions & 0 deletions Objects/sliceobject.c
Expand Up @@ -721,3 +721,9 @@ PyTypeObject PySlice_Type = {
0, /* tp_alloc */
slice_new, /* tp_new */
};


// -- Stable ABI ------------------------------------------------------------

PyObject* _Py_GetEllipsis(void)
{ return &_Py_EllipsisObject; }

0 comments on commit f8fc1c5

Please sign in to comment.