summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>2006-03-30 22:45:35 (GMT)
committerBarry Warsaw <barry@python.org>2006-03-30 22:45:35 (GMT)
commit176014ffad8d39820293b63bf7177a7d2953343a (patch)
treef1a112b22c88952a952794d390291ec54a0818d1
parentc259cc9c4c1c90efaeace2c9786786a5813cf950 (diff)
downloadcpython-176014ffad8d39820293b63bf7177a7d2953343a.zip
cpython-176014ffad8d39820293b63bf7177a7d2953343a.tar.gz
cpython-176014ffad8d39820293b63bf7177a7d2953343a.tar.bz2
SF patch #1458476 with modifications based on discussions in python-dev. This
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.
-rw-r--r--Doc/api/concrete.tex7
-rw-r--r--Include/setobject.h3
-rw-r--r--Lib/test/test_set.py2
-rw-r--r--Objects/setobject.c69
4 files changed, 75 insertions, 6 deletions
diff --git a/Doc/api/concrete.tex b/Doc/api/concrete.tex
index 3ab9e33..60bba76 100644
--- a/Doc/api/concrete.tex
+++ b/Doc/api/concrete.tex
@@ -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}
diff --git a/Include/setobject.h b/Include/setobject.h
index cea95cc..cc93968 100644
--- a/Include/setobject.h
+++ b/Include/setobject.h
@@ -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
}
diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py
index 6ff1215..1a2cdda 100644
--- a/Lib/test/test_set.py
+++ b/Lib/test/test_set.py
@@ -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)
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 7422e67..1a28724 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -1969,6 +1969,16 @@ PySet_Size(PyObject *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)
{
if (!PyAnySet_Check(anyset)) {
@@ -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);