Skip to content

Commit 09bbebe

Browse files
authored
bpo-43753: Add Py_Is() and Py_IsNone() functions (GH-25227)
Add the Py_Is(x, y) function to test if the 'x' object is the 'y' object, the same as "x is y" in Python. Add also the Py_IsNone(), Py_IsTrue(), Py_IsFalse() functions to test if an object is, respectively, the None singleton, the True singleton or the False singleton.
1 parent 6e468cb commit 09bbebe

File tree

9 files changed

+198
-38
lines changed

9 files changed

+198
-38
lines changed

‎Doc/c-api/structures.rst‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,37 @@ the definition of all other Python objects.
6262
See documentation of :c:type:`PyVarObject` above.
6363

6464

65+
.. c:function:: int Py_Is(const PyObject *x, const PyObject *y)
66+
67+
Test if the *x* object is the *y* object, the same as ``x is y`` in Python.
68+
69+
.. versionadded:: 3.10
70+
71+
72+
.. c:function:: int Py_IsNone(const PyObject *x)
73+
74+
Test if an object is the ``None`` singleton,
75+
the same as ``x is None`` in Python.
76+
77+
.. versionadded:: 3.10
78+
79+
80+
.. c:function:: int Py_IsTrue(const PyObject *x)
81+
82+
Test if an object is the ``True`` singleton,
83+
the same as ``x is True`` in Python.
84+
85+
.. versionadded:: 3.10
86+
87+
88+
.. c:function:: int Py_IsFalse(const PyObject *x)
89+
90+
Test if an object is the ``False`` singleton,
91+
the same as ``x is False`` in Python.
92+
93+
.. versionadded:: 3.10
94+
95+
6596
.. c:function:: PyTypeObject* Py_TYPE(const PyObject *o)
6697
6798
Get the type of the Python object *o*.

‎Doc/data/stable_abi.dat‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,11 @@ Py_HasFileSystemDefaultEncoding
767767
Py_IncRef
768768
Py_Initialize
769769
Py_InitializeEx
770+
Py_Is
771+
Py_IsFalse
770772
Py_IsInitialized
773+
Py_IsNone
774+
Py_IsTrue
771775
Py_LeaveRecursiveCall
772776
Py_Main
773777
Py_MakePendingCalls

‎Doc/whatsnew/3.10.rst‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,13 @@ New Features
13851385
build (``Py_TRACE_REFS`` macro).
13861386
(Contributed by Victor Stinner in :issue:`43688`.)
13871387
1388+
* Add the :c:func:`Py_Is(x, y) <Py_Is>` function to test if the *x* object is
1389+
the *y* object, the same as ``x is y`` in Python. Add also the
1390+
:c:func:`Py_IsNone`, :c:func:`Py_IsTrue`, :c:func:`Py_IsFalse` functions to
1391+
test if an object is, respectively, the ``None`` singleton, the ``True``
1392+
singleton or the ``False`` singleton.
1393+
(Contributed by Victor Stinner in :issue:`43753`.)
1394+
13881395
Porting to Python 3.10
13891396
----------------------
13901397

‎Include/boolobject.h‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ PyAPI_DATA(struct _longobject) _Py_FalseStruct, _Py_TrueStruct;
2121
#define Py_False ((PyObject *) &_Py_FalseStruct)
2222
#define Py_True ((PyObject *) &_Py_TrueStruct)
2323

24+
// Test if an object is the True singleton, the same as "x is True" in Python.
25+
PyAPI_FUNC(int) Py_IsTrue(PyObject *x);
26+
#define Py_IsTrue(x) Py_Is((x), Py_True)
27+
28+
// Test if an object is the False singleton, the same as "x is False" in Python.
29+
PyAPI_FUNC(int) Py_IsFalse(PyObject *x);
30+
#define Py_IsFalse(x) Py_Is((x), Py_False)
31+
2432
/* Macros for returning Py_True or Py_False, respectively */
2533
#define Py_RETURN_TRUE return Py_NewRef(Py_True)
2634
#define Py_RETURN_FALSE return Py_NewRef(Py_False)

‎Include/object.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ typedef struct {
122122
#define _PyVarObject_CAST_CONST(op) ((const PyVarObject*)(op))
123123

124124

125+
// Test if the 'x' object is the 'y' object, the same as "x is y" in Python.
126+
PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y);
127+
#define Py_Is(x, y) ((x) == (y))
128+
129+
125130
static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) {
126131
return ob->ob_refcnt;
127132
}
@@ -586,6 +591,10 @@ Don't forget to apply Py_INCREF() when returning this value!!!
586591
PyAPI_DATA(PyObject) _Py_NoneStruct; /* Don't use this directly */
587592
#define Py_None (&_Py_NoneStruct)
588593

594+
// Test if an object is the None singleton, the same as "x is None" in Python.
595+
PyAPI_FUNC(int) Py_IsNone(PyObject *x);
596+
#define Py_IsNone(x) Py_Is((x), Py_None)
597+
589598
/* Macro for returning Py_None from a function */
590599
#define Py_RETURN_NONE return Py_NewRef(Py_None)
591600

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Add the :c:func:`Py_Is(x, y) <Py_Is>` function to test if the *x* object is the
2+
*y* object, the same as ``x is y`` in Python. Add also the :c:func:`Py_IsNone`,
3+
:c:func:`Py_IsTrue`, :c:func:`Py_IsFalse` functions to test if an object is,
4+
respectively, the ``None`` singleton, the ``True`` singleton or the ``False``
5+
singleton.
6+
Patch by Victor Stinner.

‎Modules/_testcapimodule.c‎

Lines changed: 90 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5401,32 +5401,98 @@ test_set_type_size(PyObject *self, PyObject *Py_UNUSED(ignored))
54015401
}
54025402

54035403

5404-
// Test Py_NewRef() and Py_XNewRef() functions
5404+
#define TEST_REFCOUNT() \
5405+
do { \
5406+
PyObject *obj = PyList_New(0); \
5407+
if (obj == NULL) { \
5408+
return NULL; \
5409+
} \
5410+
assert(Py_REFCNT(obj) == 1); \
5411+
\
5412+
/* test Py_NewRef() */ \
5413+
PyObject *ref = Py_NewRef(obj); \
5414+
assert(ref == obj); \
5415+
assert(Py_REFCNT(obj) == 2); \
5416+
Py_DECREF(ref); \
5417+
\
5418+
/* test Py_XNewRef() */ \
5419+
PyObject *xref = Py_XNewRef(obj); \
5420+
assert(xref == obj); \
5421+
assert(Py_REFCNT(obj) == 2); \
5422+
Py_DECREF(xref); \
5423+
\
5424+
assert(Py_XNewRef(NULL) == NULL); \
5425+
\
5426+
Py_DECREF(obj); \
5427+
Py_RETURN_NONE; \
5428+
} while (0) \
5429+
5430+
5431+
// Test Py_NewRef() and Py_XNewRef() macros
54055432
static PyObject*
5406-
test_refcount(PyObject *self, PyObject *Py_UNUSED(ignored))
5433+
test_refcount_macros(PyObject *self, PyObject *Py_UNUSED(ignored))
54075434
{
5408-
PyObject *obj = PyList_New(0);
5409-
if (obj == NULL) {
5410-
return NULL;
5411-
}
5412-
assert(Py_REFCNT(obj) == 1);
5435+
TEST_REFCOUNT();
5436+
}
5437+
5438+
#undef Py_NewRef
5439+
#undef Py_XNewRef
5440+
5441+
// Test Py_NewRef() and Py_XNewRef() functions, after undefining macros.
5442+
static PyObject*
5443+
test_refcount_funcs(PyObject *self, PyObject *Py_UNUSED(ignored))
5444+
{
5445+
TEST_REFCOUNT();
5446+
}
54135447

5414-
// Test Py_NewRef()
5415-
PyObject *ref = Py_NewRef(obj);
5416-
assert(ref == obj);
5417-
assert(Py_REFCNT(obj) == 2);
5418-
Py_DECREF(ref);
54195448

5420-
// Test Py_XNewRef()
5421-
PyObject *xref = Py_XNewRef(obj);
5422-
assert(xref == obj);
5423-
assert(Py_REFCNT(obj) == 2);
5424-
Py_DECREF(xref);
5449+
// Test Py_Is() function
5450+
#define TEST_PY_IS() \
5451+
do { \
5452+
PyObject *o_none = Py_None; \
5453+
PyObject *o_true = Py_True; \
5454+
PyObject *o_false = Py_False; \
5455+
PyObject *obj = PyList_New(0); \
5456+
if (obj == NULL) { \
5457+
return NULL; \
5458+
} \
5459+
\
5460+
/* test Py_Is() */ \
5461+
assert(Py_Is(obj, obj)); \
5462+
assert(!Py_Is(obj, o_none)); \
5463+
\
5464+
/* test Py_None */ \
5465+
assert(Py_Is(o_none, o_none)); \
5466+
assert(!Py_Is(obj, o_none)); \
5467+
\
5468+
/* test Py_True */ \
5469+
assert(Py_Is(o_true, o_true)); \
5470+
assert(!Py_Is(o_false, o_true)); \
5471+
assert(!Py_Is(obj, o_true)); \
5472+
\
5473+
/* test Py_False */ \
5474+
assert(Py_Is(o_false, o_false)); \
5475+
assert(!Py_Is(o_true, o_false)); \
5476+
assert(!Py_Is(obj, o_false)); \
5477+
\
5478+
Py_DECREF(obj); \
5479+
Py_RETURN_NONE; \
5480+
} while (0)
5481+
5482+
// Test Py_Is() macro
5483+
static PyObject*
5484+
test_py_is_macros(PyObject *self, PyObject *Py_UNUSED(ignored))
5485+
{
5486+
TEST_PY_IS();
5487+
}
54255488

5426-
assert(Py_XNewRef(NULL) == NULL);
5489+
#undef Py_Is
54275490

5428-
Py_DECREF(obj);
5429-
Py_RETURN_NONE;
5491+
// Test Py_Is() function, after undefining its macro.
5492+
static PyObject*
5493+
test_py_is_funcs(PyObject *self, PyObject *Py_UNUSED(ignored))
5494+
{
5495+
TEST_PY_IS();
54305496
}
54315497

54325498

@@ -5716,7 +5782,10 @@ static PyMethodDef TestMethods[] = {
57165782
{"pynumber_tobase", pynumber_tobase, METH_VARARGS},
57175783
{"without_gc", without_gc, METH_O},
57185784
{"test_set_type_size", test_set_type_size, METH_NOARGS},
5719-
{"test_refcount", test_refcount, METH_NOARGS},
5785+
{"test_refcount_macros", test_refcount_macros, METH_NOARGS},
5786+
{"test_refcount_funcs", test_refcount_funcs, METH_NOARGS},
5787+
{"test_py_is_macros", test_py_is_macros, METH_NOARGS},
5788+
{"test_py_is_funcs", test_py_is_funcs, METH_NOARGS},
57205789
{"fatal_error", test_fatal_error, METH_VARARGS,
57215790
PyDoc_STR("fatal_error(message, release_gil=False): call Py_FatalError(message)")},
57225791
{NULL, NULL} /* sentinel */

‎Objects/object.c‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,6 +2279,33 @@ Py_XNewRef(PyObject *obj)
22792279
return _Py_XNewRef(obj);
22802280
}
22812281

2282+
#undef Py_Is
2283+
#undef Py_IsNone
2284+
#undef Py_IsTrue
2285+
#undef Py_IsFalse
2286+
2287+
// Export Py_Is(), Py_IsNone(), Py_IsTrue(), Py_IsFalse() as regular functions
2288+
// for the stable ABI.
2289+
int Py_Is(PyObject *x, PyObject *y)
2290+
{
2291+
return (x == y);
2292+
}
2293+
2294+
int Py_IsNone(PyObject *x)
2295+
{
2296+
return Py_Is(x, Py_None);
2297+
}
2298+
2299+
int Py_IsTrue(PyObject *x)
2300+
{
2301+
return Py_Is(x, Py_True);
2302+
}
2303+
2304+
int Py_IsFalse(PyObject *x)
2305+
{
2306+
return Py_Is(x, Py_False);
2307+
}
2308+
22822309
#ifdef __cplusplus
22832310
}
22842311
#endif

0 commit comments

Comments
 (0)