From 989a2539472677ee0c6059c5afc925adb69059a6 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Fri, 13 Oct 2023 11:06:25 +0300 Subject: [PATCH] gh-110525: Delete `test_c_api` method from `set` object (#110688) --- Lib/test/test_set.py | 4 - Lib/test/test_weakset.py | 2 +- ...-10-11-11-39-22.gh-issue-110688.lB6Q7t.rst | 3 + Objects/setobject.c | 153 ------------------ 4 files changed, 4 insertions(+), 158 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-10-11-11-39-22.gh-issue-110688.lB6Q7t.rst diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 2dd65240f5f..d9102eb98a5 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -635,10 +635,6 @@ class TestSet(TestJointOps, unittest.TestCase): myset >= myobj self.assertTrue(myobj.le_called) - @unittest.skipUnless(hasattr(set, "test_c_api"), - 'C API test only available in a debug build') - def test_c_api(self): - self.assertEqual(set().test_c_api(), True) class SetSubclass(set): pass diff --git a/Lib/test/test_weakset.py b/Lib/test/test_weakset.py index d6c88596cff..76e8e5c8ab7 100644 --- a/Lib/test/test_weakset.py +++ b/Lib/test/test_weakset.py @@ -44,7 +44,7 @@ class TestWeakSet(unittest.TestCase): def test_methods(self): weaksetmethods = dir(WeakSet) for method in dir(set): - if method == 'test_c_api' or method.startswith('_'): + if method.startswith('_'): continue self.assertIn(method, weaksetmethods, "WeakSet missing method " + method) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-10-11-11-39-22.gh-issue-110688.lB6Q7t.rst b/Misc/NEWS.d/next/Core and Builtins/2023-10-11-11-39-22.gh-issue-110688.lB6Q7t.rst new file mode 100644 index 00000000000..4a5a10b36b3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-10-11-11-39-22.gh-issue-110688.lB6Q7t.rst @@ -0,0 +1,3 @@ +Remove undocumented ``test_c_api`` method from :class:`set`, which was only +defined for testing purposes under ``Py_DEBUG``. Now we have proper CAPI +tests. diff --git a/Objects/setobject.c b/Objects/setobject.c index ae3f0b8d5e5..2a3514f2028 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -2022,13 +2022,6 @@ static PySequenceMethods set_as_sequence = { /* set object ********************************************************/ -#ifdef Py_DEBUG -static PyObject *test_c_api(PySetObject *so, PyObject *Py_UNUSED(ignored)); - -PyDoc_STRVAR(test_c_api_doc, "Exercises C API. Returns True.\n\ -All is well if assertions don't fail."); -#endif - static PyMethodDef set_methods[] = { {"add", (PyCFunction)set_add, METH_O, add_doc}, @@ -2066,10 +2059,6 @@ static PyMethodDef set_methods[] = { symmetric_difference_doc}, {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O, symmetric_difference_update_doc}, -#ifdef Py_DEBUG - {"test_c_api", (PyCFunction)test_c_api, METH_NOARGS, - test_c_api_doc}, -#endif {"union", (PyCFunction)set_union, METH_VARARGS, union_doc}, {"update", (PyCFunction)set_update, METH_VARARGS, @@ -2368,148 +2357,6 @@ _PySet_Update(PyObject *set, PyObject *iterable) /* Exported for the gdb plugin's benefit. */ PyObject *_PySet_Dummy = dummy; -#ifdef Py_DEBUG - -/* Test code to be called with any three element set. - Returns True and original set is restored. */ - -#define assertRaises(call_return_value, exception) \ - do { \ - assert(call_return_value); \ - assert(PyErr_ExceptionMatches(exception)); \ - PyErr_Clear(); \ - } while(0) - -static PyObject * -test_c_api(PySetObject *so, PyObject *Py_UNUSED(ignored)) -{ - Py_ssize_t count; - const char *s; - Py_ssize_t i; - PyObject *elem=NULL, *dup=NULL, *t, *f, *dup2, *x=NULL; - PyObject *ob = (PyObject *)so; - Py_hash_t hash; - PyObject *str; - - /* Verify preconditions */ - assert(PyAnySet_Check(ob)); - assert(PyAnySet_CheckExact(ob)); - assert(!PyFrozenSet_CheckExact(ob)); - - /* so.clear(); so |= set("abc"); */ - str = PyUnicode_FromString("abc"); - if (str == NULL) - return NULL; - set_clear_internal(so); - if (set_update_internal(so, str)) { - Py_DECREF(str); - return NULL; - } - Py_DECREF(str); - - /* Exercise type/size checks */ - assert(PySet_Size(ob) == 3); - assert(PySet_GET_SIZE(ob) == 3); - - /* Raise TypeError for non-iterable constructor arguments */ - assertRaises(PySet_New(Py_None) == NULL, PyExc_TypeError); - assertRaises(PyFrozenSet_New(Py_None) == NULL, PyExc_TypeError); - - /* Raise TypeError for unhashable key */ - dup = PySet_New(ob); - assertRaises(PySet_Discard(ob, dup) == -1, PyExc_TypeError); - assertRaises(PySet_Contains(ob, dup) == -1, PyExc_TypeError); - assertRaises(PySet_Add(ob, dup) == -1, PyExc_TypeError); - - /* Exercise successful pop, contains, add, and discard */ - elem = PySet_Pop(ob); - assert(PySet_Contains(ob, elem) == 0); - assert(PySet_GET_SIZE(ob) == 2); - assert(PySet_Add(ob, elem) == 0); - assert(PySet_Contains(ob, elem) == 1); - assert(PySet_GET_SIZE(ob) == 3); - assert(PySet_Discard(ob, elem) == 1); - assert(PySet_GET_SIZE(ob) == 2); - assert(PySet_Discard(ob, elem) == 0); - assert(PySet_GET_SIZE(ob) == 2); - - /* Exercise clear */ - dup2 = PySet_New(dup); - assert(PySet_Clear(dup2) == 0); - assert(PySet_Size(dup2) == 0); - Py_DECREF(dup2); - - /* Raise SystemError on clear or update of frozen set */ - f = PyFrozenSet_New(dup); - assertRaises(PySet_Clear(f) == -1, PyExc_SystemError); - assertRaises(_PySet_Update(f, dup) == -1, PyExc_SystemError); - assert(PySet_Add(f, elem) == 0); - Py_INCREF(f); - assertRaises(PySet_Add(f, elem) == -1, PyExc_SystemError); - Py_DECREF(f); - Py_DECREF(f); - - /* Exercise direct iteration */ - i = 0, count = 0; - while (_PySet_NextEntry((PyObject *)dup, &i, &x, &hash)) { - s = PyUnicode_AsUTF8(x); - assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c')); - count++; - } - assert(count == 3); - - /* Exercise updates */ - dup2 = PySet_New(NULL); - assert(_PySet_Update(dup2, dup) == 0); - assert(PySet_Size(dup2) == 3); - assert(_PySet_Update(dup2, dup) == 0); - assert(PySet_Size(dup2) == 3); - Py_DECREF(dup2); - - /* Raise SystemError when self argument is not a set or frozenset. */ - t = PyTuple_New(0); - assertRaises(PySet_Size(t) == -1, PyExc_SystemError); - assertRaises(PySet_Contains(t, elem) == -1, PyExc_SystemError); - Py_DECREF(t); - - /* Raise SystemError when self argument is not a set. */ - f = PyFrozenSet_New(dup); - assert(PySet_Size(f) == 3); - assert(PyFrozenSet_CheckExact(f)); - assertRaises(PySet_Discard(f, elem) == -1, PyExc_SystemError); - assertRaises(PySet_Pop(f) == NULL, PyExc_SystemError); - Py_DECREF(f); - - /* Raise KeyError when popping from an empty set */ - assert(PyNumber_InPlaceSubtract(ob, ob) == ob); - Py_DECREF(ob); - assert(PySet_GET_SIZE(ob) == 0); - assertRaises(PySet_Pop(ob) == NULL, PyExc_KeyError); - - /* Restore the set from the copy using the PyNumber API */ - assert(PyNumber_InPlaceOr(ob, dup) == ob); - Py_DECREF(ob); - - /* Verify constructors accept NULL arguments */ - f = PySet_New(NULL); - assert(f != NULL); - assert(PySet_GET_SIZE(f) == 0); - Py_DECREF(f); - f = PyFrozenSet_New(NULL); - assert(f != NULL); - assert(PyFrozenSet_CheckExact(f)); - assert(PySet_GET_SIZE(f) == 0); - Py_DECREF(f); - - Py_DECREF(elem); - Py_DECREF(dup); - Py_RETURN_TRUE; -} - -#undef assertRaises - -#endif - /***** Dummy Struct *************************************************/ static PyObject *