Kaydet (Commit) 176014ff authored tarafından Barry Warsaw's avatar Barry Warsaw

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.
üst c259cc9c
...@@ -3027,8 +3027,6 @@ or the abstract number protocol (including ...@@ -3027,8 +3027,6 @@ or the abstract number protocol (including
\cfunction{PyNumber_InPlaceAdd()}, \cfunction{PyNumber_InPlaceSubtract()}, \cfunction{PyNumber_InPlaceAdd()}, \cfunction{PyNumber_InPlaceSubtract()},
\cfunction{PyNumber_InPlaceOr()}, and \cfunction{PyNumber_InPlaceXor()}). \cfunction{PyNumber_InPlaceOr()}, and \cfunction{PyNumber_InPlaceXor()}).
For example, to clear a set, write: \code{PyObject_CallMethod(s, "clear", NULL)}
\begin{ctypedesc}{PySetObject} \begin{ctypedesc}{PySetObject}
This subtype of \ctype{PyObject} is used to hold the internal data for This subtype of \ctype{PyObject} is used to hold the internal data for
both \class{set} and \class{frozenset} objects. It is like a 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 ...@@ -3112,7 +3110,6 @@ The following functions and macros are available for instances of
\class{frozenset}, or an instance of a subtype. \class{frozenset}, or an instance of a subtype.
\end{cfuncdesc} \end{cfuncdesc}
The following functions are available for instances of \class{set} or The following functions are available for instances of \class{set} or
its subtypes but not for instances of \class{frozenset} or its subtypes. 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. ...@@ -3143,4 +3140,6 @@ its subtypes but not for instances of \class{frozenset} or its subtypes.
of \class{set} or its subtype. of \class{set} or its subtype.
\end{cfuncdesc} \end{cfuncdesc}
\begin{cfuncdesc}{int}{PySet_Clear}{PyObject *set}
Empty an existing set of all elements.
\end{cfuncdesc}
...@@ -78,10 +78,13 @@ PyAPI_FUNC(PyObject *) PySet_New(PyObject *); ...@@ -78,10 +78,13 @@ PyAPI_FUNC(PyObject *) PySet_New(PyObject *);
PyAPI_FUNC(PyObject *) PyFrozenSet_New(PyObject *); PyAPI_FUNC(PyObject *) PyFrozenSet_New(PyObject *);
PyAPI_FUNC(Py_ssize_t) PySet_Size(PyObject *anyset); PyAPI_FUNC(Py_ssize_t) PySet_Size(PyObject *anyset);
#define PySet_GET_SIZE(so) (((PySetObject *)(so))->used) #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_Contains(PyObject *anyset, PyObject *key);
PyAPI_FUNC(int) PySet_Discard(PyObject *set, PyObject *key); PyAPI_FUNC(int) PySet_Discard(PyObject *set, PyObject *key);
PyAPI_FUNC(int) PySet_Add(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(PyObject *) PySet_Pop(PyObject *set);
PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -421,7 +421,7 @@ class TestSet(TestJointOps): ...@@ -421,7 +421,7 @@ class TestSet(TestJointOps):
self.assertRaises(ReferenceError, str, p) self.assertRaises(ReferenceError, str, p)
# C API test only available in a debug build # C API test only available in a debug build
if hasattr(sys, "gettotalrefcount"): if hasattr(set, "test_c_api"):
def test_c_api(self): def test_c_api(self):
self.assertEqual(set('abc').test_c_api(), True) self.assertEqual(set('abc').test_c_api(), True)
......
...@@ -1968,6 +1968,16 @@ PySet_Size(PyObject *anyset) ...@@ -1968,6 +1968,16 @@ PySet_Size(PyObject *anyset)
return PySet_GET_SIZE(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 int
PySet_Contains(PyObject *anyset, PyObject *key) PySet_Contains(PyObject *anyset, PyObject *key)
{ {
...@@ -1998,6 +2008,21 @@ PySet_Add(PyObject *set, PyObject *key) ...@@ -1998,6 +2008,21 @@ PySet_Add(PyObject *set, PyObject *key)
return set_add_key((PySetObject *)set, 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 * PyObject *
PySet_Pop(PyObject *set) PySet_Pop(PyObject *set)
{ {
...@@ -2008,6 +2033,15 @@ PySet_Pop(PyObject *set) ...@@ -2008,6 +2033,15 @@ PySet_Pop(PyObject *set)
return set_pop((PySetObject *)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 #ifdef Py_DEBUG
...@@ -2024,7 +2058,11 @@ PySet_Pop(PyObject *set) ...@@ -2024,7 +2058,11 @@ PySet_Pop(PyObject *set)
static PyObject * static PyObject *
test_c_api(PySetObject *so) 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 */ /* Verify preconditions and exercise type/size checks */
assert(PyAnySet_Check(ob)); assert(PyAnySet_Check(ob));
...@@ -2055,6 +2093,35 @@ test_c_api(PySetObject *so) ...@@ -2055,6 +2093,35 @@ test_c_api(PySetObject *so)
assert(PySet_Discard(ob, elem) == 0); assert(PySet_Discard(ob, elem) == 0);
assert(PySet_GET_SIZE(ob) == 2); 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. */ /* Raise SystemError when self argument is not a set or frozenset. */
t = PyTuple_New(0); t = PyTuple_New(0);
assertRaises(PySet_Size(t) == -1, PyExc_SystemError); assertRaises(PySet_Size(t) == -1, PyExc_SystemError);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment