]> granicus.if.org Git - python/commitdiff
SF patch #1458476 with modifications based on discussions in python-dev. This
authorBarry Warsaw <barry@python.org>
Thu, 30 Mar 2006 22:45:35 +0000 (22:45 +0000)
committerBarry Warsaw <barry@python.org>
Thu, 30 Mar 2006 22:45:35 +0000 (22:45 +0000)
adds the following API calls: PySet_Clear(), _PySet_Next(), and
_PySet_Update().  The latter two are considered non-public.  Tests and
documentation (for the public API) are included.

Doc/api/concrete.tex
Include/setobject.h
Lib/test/test_set.py
Objects/setobject.c

index 3ab9e33c92b49ca767221036acd91db47907443e..60bba76e80fd9c25d91d56cfcf9ec7d9460d6da7 100644 (file)
@@ -3027,8 +3027,6 @@ or the abstract number protocol (including
 \cfunction{PyNumber_InPlaceAdd()}, \cfunction{PyNumber_InPlaceSubtract()},
 \cfunction{PyNumber_InPlaceOr()}, and \cfunction{PyNumber_InPlaceXor()}).
 
-For example, to clear a set, write:  \code{PyObject_CallMethod(s, "clear", NULL)}
-                      
 \begin{ctypedesc}{PySetObject}
   This subtype of \ctype{PyObject} is used to hold the internal data for
   both \class{set} and \class{frozenset} objects.  It is like a
@@ -3112,7 +3110,6 @@ The following functions and macros are available for instances of
   \class{frozenset}, or an instance of a subtype.                         
 \end{cfuncdesc}
 
-
 The following functions are available for instances of \class{set} or
 its subtypes but not for instances of \class{frozenset} or its subtypes.
 
@@ -3143,4 +3140,6 @@ its subtypes but not for instances of \class{frozenset} or its subtypes.
   of \class{set} or its subtype.                        
 \end{cfuncdesc}
 
-
+\begin{cfuncdesc}{int}{PySet_Clear}{PyObject *set}
+  Empty an existing set of all elements.
+\end{cfuncdesc}
index cea95cc29e6b83a08d74dc5b0c62d0bbdc1df318..cc939687a8e318c48d8361c570746fbe77a51322 100644 (file)
@@ -78,10 +78,13 @@ PyAPI_FUNC(PyObject *) PySet_New(PyObject *);
 PyAPI_FUNC(PyObject *) PyFrozenSet_New(PyObject *);
 PyAPI_FUNC(Py_ssize_t) PySet_Size(PyObject *anyset);
 #define PySet_GET_SIZE(so) (((PySetObject *)(so))->used)
+PyAPI_FUNC(int) PySet_Clear(PyObject *set);
 PyAPI_FUNC(int) PySet_Contains(PyObject *anyset, PyObject *key);
 PyAPI_FUNC(int) PySet_Discard(PyObject *set, PyObject *key);
 PyAPI_FUNC(int) PySet_Add(PyObject *set, PyObject *key);
+PyAPI_FUNC(int) _PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **entry);
 PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set);
+PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable);
 
 #ifdef __cplusplus
 }
index 6ff12154aa0b47ff1e9fc9cab8c3983acd610dfb..1a2cdda1157b034c678f71140c3bae9fa9d81384 100644 (file)
@@ -421,7 +421,7 @@ class TestSet(TestJointOps):
         self.assertRaises(ReferenceError, str, p)
 
     # C API test only available in a debug build
-    if hasattr(sys, "gettotalrefcount"):
+    if hasattr(set, "test_c_api"):
         def test_c_api(self):
             self.assertEqual(set('abc').test_c_api(), True)
 
index 7422e6704441a8bc2b60c27c8a6d60e93b539b17..1a287240fab42b79de9c5691d07f5408c5902795 100644 (file)
@@ -1968,6 +1968,16 @@ PySet_Size(PyObject *anyset)
        return PySet_GET_SIZE(anyset);
 }
 
+int
+PySet_Clear(PyObject *set)
+{
+       if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
+               PyErr_BadInternalCall();
+               return -1;
+       }
+       return set_clear_internal((PySetObject *)set);
+}
+
 int
 PySet_Contains(PyObject *anyset, PyObject *key)
 {
@@ -1998,6 +2008,21 @@ PySet_Add(PyObject *set, PyObject *key)
        return set_add_key((PySetObject *)set, key);
 }
 
+int
+_PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **entry)
+{
+       setentry *entry_ptr;
+
+       if (!PyAnySet_Check(set)) {
+               PyErr_BadInternalCall();
+               return -1;
+       }
+       if (set_next((PySetObject *)set, pos, &entry_ptr) == 0)
+               return 0;
+       *entry = entry_ptr->key;
+       return 1;
+}
+
 PyObject *
 PySet_Pop(PyObject *set)
 {
@@ -2008,6 +2033,15 @@ PySet_Pop(PyObject *set)
        return set_pop((PySetObject *)set);
 }
 
+int
+_PySet_Update(PyObject *set, PyObject *iterable)
+{
+       if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
+               PyErr_BadInternalCall();
+               return -1;
+       }
+       return set_update_internal((PySetObject *)set, iterable);
+}
 
 #ifdef Py_DEBUG
 
@@ -2024,7 +2058,11 @@ PySet_Pop(PyObject *set)
 static PyObject *
 test_c_api(PySetObject *so)
 {
-       PyObject *elem, *dup, *t, *f, *ob = (PyObject *)so;
+       int count;
+       char *s;
+       Py_ssize_t i;
+       PyObject *elem, *dup, *t, *f, *dup2;
+       PyObject *ob = (PyObject *)so;
 
        /* Verify preconditions and exercise type/size checks */
        assert(PyAnySet_Check(ob));
@@ -2055,6 +2093,35 @@ test_c_api(PySetObject *so)
        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);
+       Py_DECREF(f);
+
+       /* Exercise direct iteration */
+       i = 0, count = 0;
+       while (_PySet_Next((PyObject *)dup, &i, &elem)) {
+               s = PyString_AsString(elem);
+               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);