From 28ca03f72b03bb01fe41d451604a91d9c2182749 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Tue, 12 May 2026 16:44:13 +0200 Subject: [PATCH 1/5] Add PySentinel_CheckExact(). --- Doc/c-api/sentinel.rst | 13 +++++++++++-- Include/cpython/sentinelobject.h | 5 ++++- Lib/test/test_capi/test_object.py | 2 ++ Modules/_testcapi/object.c | 7 +++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/sentinel.rst b/Doc/c-api/sentinel.rst index 89e0a28bf3b835..e9553c66c591f4 100644 --- a/Doc/c-api/sentinel.rst +++ b/Doc/c-api/sentinel.rst @@ -14,8 +14,17 @@ Sentinel objects .. c:function:: int PySentinel_Check(PyObject *o) - Return true if *o* is a :class:`sentinel` object. The :class:`sentinel` type - does not allow subclasses, so this check is exact. + Return true if *o* is a :class:`sentinel` object or a subtype. The :class:`sentinel` type + does not currently allow subclasses, so this check is exact. + Future CPython versions may choose to allow subtyping. + + .. versionadded:: 3.15 + +.. c:function:: int PySentinel_CheckExact(PyObject *o) + + Return true if *o* is a :class:`sentinel` object, but not a subtype. + The :class:`sentinel` type does not currently allow subclasses. + Future CPython versions may choose to allow subtyping. .. versionadded:: 3.15 diff --git a/Include/cpython/sentinelobject.h b/Include/cpython/sentinelobject.h index 0b6ff0f17e6f8c..8d5b1886ce5436 100644 --- a/Include/cpython/sentinelobject.h +++ b/Include/cpython/sentinelobject.h @@ -9,7 +9,10 @@ extern "C" { PyAPI_DATA(PyTypeObject) PySentinel_Type; -#define PySentinel_Check(op) Py_IS_TYPE((op), &PySentinel_Type) +#define PySentinel_CheckExact(op) Py_IS_TYPE((op), &PySentinel_Type) + +/* Alias as long as subclasses are not allowed. */ +#define PySentinel_Check(op) PySentinel_CheckExact(op) PyAPI_FUNC(PyObject *) PySentinel_New( const char *name, diff --git a/Lib/test/test_capi/test_object.py b/Lib/test/test_capi/test_object.py index 635deaa73f7efa..e6fd068dc20d8d 100644 --- a/Lib/test/test_capi/test_object.py +++ b/Lib/test/test_capi/test_object.py @@ -71,6 +71,8 @@ def test_pysentinel_new(self): self.assertIs(type(marker), sentinel) self.assertTrue(_testcapi.pysentinel_check(marker)) self.assertFalse(_testcapi.pysentinel_check(object())) + self.assertTrue(_testcapi.pysentinel_checkexact(marker)) + self.assertFalse(_testcapi.pysentinel_checkexact(object())) self.assertEqual(marker.__name__, "CAPI_SENTINEL") self.assertEqual(marker.__module__, __name__) self.assertEqual(repr(marker), "CAPI_SENTINEL") diff --git a/Modules/_testcapi/object.c b/Modules/_testcapi/object.c index 6e5c8dcbb725fa..c62dc1144df688 100644 --- a/Modules/_testcapi/object.c +++ b/Modules/_testcapi/object.c @@ -572,6 +572,12 @@ pysentinel_check(PyObject *self, PyObject *obj) return PyBool_FromLong(PySentinel_Check(obj)); } +static PyObject * +pysentinel_checkexact(PyObject *self, PyObject *obj) +{ + return PyBool_FromLong(PySentinel_CheckExact(obj)); +} + static PyMethodDef test_methods[] = { {"call_pyobject_print", call_pyobject_print, METH_VARARGS}, @@ -604,6 +610,7 @@ static PyMethodDef test_methods[] = { {"pyobject_dump", pyobject_dump, METH_VARARGS}, {"pysentinel_new", pysentinel_new, METH_VARARGS}, {"pysentinel_check", pysentinel_check, METH_O}, + {"pysentinel_checkexact", pysentinel_checkexact, METH_O}, {NULL}, }; From 60e8ab71f99fc4abdde9c73f401f2231757b6007 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Tue, 12 May 2026 19:56:10 +0200 Subject: [PATCH 2/5] Add NEWS entry. --- .../next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst diff --git a/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst b/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst new file mode 100644 index 00000000000000..3efd12159b201e --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst @@ -0,0 +1,2 @@ +Add PySentinel_CheckExact() for exact type tests +to accompany the existing PySentinel_Check(). From 090e023c207c70e18b92de5dbb38bc3a0969fe7e Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Tue, 12 May 2026 21:21:08 +0200 Subject: [PATCH 3/5] Update documentation after code review. --- Doc/c-api/sentinel.rst | 9 +++++---- .../C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Doc/c-api/sentinel.rst b/Doc/c-api/sentinel.rst index e9553c66c591f4..bc1348d1a9804d 100644 --- a/Doc/c-api/sentinel.rst +++ b/Doc/c-api/sentinel.rst @@ -14,9 +14,10 @@ Sentinel objects .. c:function:: int PySentinel_Check(PyObject *o) - Return true if *o* is a :class:`sentinel` object or a subtype. The :class:`sentinel` type - does not currently allow subclasses, so this check is exact. - Future CPython versions may choose to allow subtyping. + Return true if *o* is a :class:`sentinel` object or a subtype. + The :class:`sentinel` type does not currently allow subclasses, + so this check is exact. + Future Python versions may choose to allow subtyping. .. versionadded:: 3.15 @@ -24,7 +25,7 @@ Sentinel objects Return true if *o* is a :class:`sentinel` object, but not a subtype. The :class:`sentinel` type does not currently allow subclasses. - Future CPython versions may choose to allow subtyping. + Future Python versions may choose to allow subtyping. .. versionadded:: 3.15 diff --git a/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst b/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst index 3efd12159b201e..e19fcc45cfe829 100644 --- a/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst +++ b/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst @@ -1,2 +1,2 @@ -Add PySentinel_CheckExact() for exact type tests -to accompany the existing PySentinel_Check(). +Add :c:func:`PySentinel_CheckExact` for exact :class:`sentinel` type tests +to accompany the existing :c:func:`PySentinel_Check`. \ No newline at end of file From 0fa965643ec567b1112a5eab1e61ea046380d2e3 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Tue, 12 May 2026 21:29:49 +0200 Subject: [PATCH 4/5] Add missing EOL. --- .../next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst b/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst index e19fcc45cfe829..97721430edbd69 100644 --- a/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst +++ b/Misc/NEWS.d/next/C_API/2026-05-12-16-47-21.gh-issue-149725.HZLBTZ.rst @@ -1,2 +1,2 @@ Add :c:func:`PySentinel_CheckExact` for exact :class:`sentinel` type tests -to accompany the existing :c:func:`PySentinel_Check`. \ No newline at end of file +to accompany the existing :c:func:`PySentinel_Check`. From 03f28f7e56c0776c28df88f43a0b1d2141184ea8 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 13 May 2026 11:41:49 +0200 Subject: [PATCH 5/5] Docs: Add non-failure note to new functions. --- Doc/c-api/sentinel.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/c-api/sentinel.rst b/Doc/c-api/sentinel.rst index bc1348d1a9804d..937cae18e86f50 100644 --- a/Doc/c-api/sentinel.rst +++ b/Doc/c-api/sentinel.rst @@ -18,6 +18,7 @@ Sentinel objects The :class:`sentinel` type does not currently allow subclasses, so this check is exact. Future Python versions may choose to allow subtyping. + This function always succeeds. .. versionadded:: 3.15 @@ -26,6 +27,7 @@ Sentinel objects Return true if *o* is a :class:`sentinel` object, but not a subtype. The :class:`sentinel` type does not currently allow subclasses. Future Python versions may choose to allow subtyping. + This function always succeeds. .. versionadded:: 3.15