#include "Python.h" /* set object implementation written and maintained by Raymond D. Hettinger derived from sets.py written by Greg V. Wilson, Alex Martelli, Guido van Rossum, Raymond Hettinger, and Tim Peters. Copyright (c) 2003 Python Software Foundation. All rights reserved. */ /* Fast access macros */ #define DICT_CONTAINS(d, k) (d->ob_type->tp_as_sequence->sq_contains(d, k)) #define IS_SET(so) (so->ob_type == &PySet_Type || so->ob_type == &PyFrozenSet_Type) /* set object **********************************************************/ static PyObject * make_new_set(PyTypeObject *type, PyObject *iterable) { PyObject *data; PyObject *it = NULL; PyObject *item; PySetObject *so; /* Get iterator. */ if (iterable != NULL) { it = PyObject_GetIter(iterable); if (it == NULL) return NULL; } data = PyDict_New(); if (data == NULL) { Py_DECREF(it); return NULL; } while (it != NULL && (item = PyIter_Next(it)) != NULL) { if (PyDict_SetItem(data, item, Py_True) == -1) { Py_DECREF(it); Py_DECREF(data); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "all set entries must be immutable"); return NULL; } Py_DECREF(item); } Py_XDECREF(it); if (PyErr_Occurred()) { Py_DECREF(data); return NULL; } /* create PySetObject structure */ so = (PySetObject *)type->tp_alloc(type, 0); if (so == NULL) { Py_DECREF(data); return NULL; } so->data = data; so->hash = -1; return (PyObject *)so; } static PyObject * set_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *iterable = NULL; if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) return NULL; return make_new_set(type, iterable); } static void set_dealloc(PySetObject *so) { PyObject_GC_UnTrack(so); Py_XDECREF(so->data); so->ob_type->tp_free(so); } static int set_traverse(PySetObject *so, visitproc visit, void *arg) { if (so->data) return visit(so->data, arg); return 0; } static PyObject * set_iter(PySetObject *so) { return PyObject_GetIter(so->data); } static int set_len(PySetObject *so) { return PyDict_Size(so->data); } static int set_contains(PySetObject *so, PyObject *key) { return DICT_CONTAINS(so->data, key); } static PyObject * set_copy(PySetObject *so) { PyObject *data; PySetObject *newso; data = PyDict_Copy(so->data); if (data == NULL) return NULL; newso = (PySetObject *)(so->ob_type->tp_alloc(so->ob_type, 0)); if (newso == NULL) { Py_DECREF(data); return NULL; } newso->data = data; newso->hash = so->hash; return (PyObject *)newso; } PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set."); static PyObject * set_union(PySetObject *so, PyObject *other) { PySetObject *result; PyObject *item, *data, *it; result = (PySetObject *)set_copy(so); it = PyObject_GetIter(other); if (it == NULL) { Py_DECREF(result); return NULL; } data = result->data; while ((item = PyIter_Next(it)) != NULL) { if (PyDict_SetItem(data, item, Py_True) == -1) { Py_DECREF(it); Py_DECREF(result); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "all set entries must be immutable"); return NULL; } Py_DECREF(item); } Py_DECREF(it); if (PyErr_Occurred()) { Py_DECREF(result); return NULL; } return (PyObject *)result; } PyDoc_STRVAR(union_doc, "Return the union of two sets as a new set.\n\ \n\ (i.e. all elements that are in either set.)"); static PyObject * set_union_update(PySetObject *so, PyObject *other) { PyObject *item, *data, *it; it = PyObject_GetIter(other); if (it == NULL) return NULL; data = so->data; while ((item = PyIter_Next(it)) != NULL) { if (PyDict_SetItem(data, item, Py_True) == -1) { Py_DECREF(it); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "all set entries must be immutable"); return NULL; } Py_DECREF(item); } Py_DECREF(it); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; } PyDoc_STRVAR(union_update_doc, "Update a set with the union of itself and another."); static PyObject * set_or(PySetObject *so, PyObject *other) { if (!IS_SET(so) || !IS_SET(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return set_union(so, other); } static PyObject * set_ior(PySetObject *so, PyObject *other) { PyObject *result; if (!IS_SET(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } result = set_union_update(so, other); if (result == NULL) return NULL; Py_DECREF(result); Py_INCREF(so); return (PyObject *)so; } static PyObject * set_intersection(PySetObject *so, PyObject *other) { PySetObject *result; PyObject *item, *selfdata, *tgtdata, *it; result = (PySetObject *)make_new_set(so->ob_type, NULL); if (result == NULL) return NULL; it = PyObject_GetIter(other); if (it == NULL) { Py_DECREF(result); return NULL; } selfdata = so->data; tgtdata = result->data; while ((item = PyIter_Next(it)) != NULL) { if (DICT_CONTAINS(selfdata, item)) { if (PyDict_SetItem(tgtdata, item, Py_True) == -1) { Py_DECREF(it); Py_DECREF(result); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "all set entries must be immutable"); return NULL; } } Py_DECREF(item); } Py_DECREF(it); if (PyErr_Occurred()) { Py_DECREF(result); return NULL; } return (PyObject *)result; } PyDoc_STRVAR(intersection_doc, "Return the intersection of two sets as a new set.\n\ \n\ (i.e. all elements that are in both sets.)"); static PyObject * set_intersection_update(PySetObject *so, PyObject *other) { PyObject *item, *selfdata, *it, *newdict, *tmp; newdict = PyDict_New(); if (newdict == NULL) return newdict; it = PyObject_GetIter(other); if (it == NULL) { Py_DECREF(newdict); return NULL; } selfdata = so->data; while ((item = PyIter_Next(it)) != NULL) { if (DICT_CONTAINS(selfdata, item)) { if (PyDict_SetItem(newdict, item, Py_True) == -1) { Py_DECREF(newdict); Py_DECREF(it); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "all set entries must be immutable"); return NULL; } } Py_DECREF(item); } Py_DECREF(it); if (PyErr_Occurred()) { Py_DECREF(newdict); return NULL; } tmp = so->data; so->data = newdict; Py_DECREF(tmp); Py_RETURN_NONE; } PyDoc_STRVAR(intersection_update_doc, "Update a set with the intersection of itself and another."); static PyObject * set_and(PySetObject *so, PyObject *other) { if (!IS_SET(so) || !IS_SET(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return set_intersection(so, other); } static PyObject * set_iand(PySetObject *so, PyObject *other) { PyObject *result; if (!IS_SET(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } result = set_intersection_update(so, other); if (result == NULL) return NULL; Py_DECREF(result); Py_INCREF(so); return (PyObject *)so; } static PyObject * set_difference(PySetObject *so, PyObject *other) { PySetObject *result; PyObject *item, *tgtdata, *it; result = (PySetObject *)set_copy(so); if (result == NULL) return NULL; it = PyObject_GetIter(other); if (it == NULL) { Py_DECREF(result); return NULL; } tgtdata = result->data; while ((item = PyIter_Next(it)) != NULL) { if (PyDict_DelItem(tgtdata, item) == -1) { if (PyErr_ExceptionMatches(PyExc_KeyError)) PyErr_Clear(); else { Py_DECREF(it); Py_DECREF(result); Py_DECREF(item); return NULL; } } Py_DECREF(item); } Py_DECREF(it); if (PyErr_Occurred()) { Py_DECREF(result); return NULL; } return (PyObject *)result; } PyDoc_STRVAR(difference_doc, "Return the difference of two sets as a new set.\n\ \n\ (i.e. all elements that are in this set but not the other.)"); static PyObject * set_difference_update(PySetObject *so, PyObject *other) { PyObject *item, *tgtdata, *it; it = PyObject_GetIter(other); if (it == NULL) return NULL; tgtdata = so->data; while ((item = PyIter_Next(it)) != NULL) { if (PyDict_DelItem(tgtdata, item) == -1) { if (PyErr_ExceptionMatches(PyExc_KeyError)) PyErr_Clear(); else { Py_DECREF(it); Py_DECREF(item); return NULL; } } Py_DECREF(item); } Py_DECREF(it); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; } PyDoc_STRVAR(difference_update_doc, "Remove all elements of another set from this set."); static PyObject * set_sub(PySetObject *so, PyObject *other) { if (!IS_SET(so) || !IS_SET(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return set_difference(so, other); } static PyObject * set_isub(PySetObject *so, PyObject *other) { PyObject *result; if (!IS_SET(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } result = set_difference_update(so, other); if (result == NULL) return NULL; Py_DECREF(result); Py_INCREF(so); return (PyObject *)so; } static PyObject * set_symmetric_difference(PySetObject *so, PyObject *other) { PySetObject *result, *otherset; PyObject *item, *selfdata, *otherdata, *tgtdata, *it; selfdata = so->data; result = (PySetObject *)set_copy(so); if (result == NULL) return NULL; tgtdata = result->data; otherset = (PySetObject *)make_new_set(so->ob_type, other); if (otherset == NULL) { Py_DECREF(result); return NULL; } otherdata = otherset->data; it = PyObject_GetIter(otherdata); if (it == NULL) { Py_DECREF(otherset); Py_DECREF(result); return NULL; } while ((item = PyIter_Next(it)) != NULL) { if (PyDict_DelItem(tgtdata, item) == -1) { PyErr_Clear(); if (PyDict_SetItem(tgtdata, item, Py_True) == -1) { Py_DECREF(it); Py_DECREF(otherset); Py_DECREF(result); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "all set entries must be immutable"); return NULL; } } Py_DECREF(item); } Py_DECREF(it); Py_DECREF(otherset); if (PyErr_Occurred()) { Py_DECREF(result); return NULL; } return (PyObject *)result; } PyDoc_STRVAR(symmetric_difference_doc, "Return the symmetric difference of two sets as a new set.\n\ \n\ (i.e. all elements that are in exactly one of the sets.)"); static PyObject * set_symmetric_difference_update(PySetObject *so, PyObject *other) { PyObject *item, *selfdata, *it, *otherdata; PySetObject *otherset = NULL; selfdata = so->data; if (PyDict_Check(other)) otherdata = other; else if (IS_SET(other)) otherdata = ((PySetObject *)other)->data; else { otherset = (PySetObject *)make_new_set(so->ob_type, other); if (otherset == NULL) return NULL; otherdata = otherset->data; } it = PyObject_GetIter(otherdata); if (it == NULL) return NULL; while ((item = PyIter_Next(it)) != NULL) { if (DICT_CONTAINS(selfdata, item)) { if (PyDict_DelItem(selfdata, item) == -1) { Py_XDECREF(otherset); Py_DECREF(it); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "all set entries must be immutable"); return NULL; } } else { if (PyDict_SetItem(selfdata, item, Py_True) == -1) { Py_XDECREF(otherset); Py_DECREF(it); Py_DECREF(item); PyErr_SetString(PyExc_TypeError, "all set entries must be immutable"); return NULL; } } Py_DECREF(item); } Py_XDECREF(otherset); Py_DECREF(it); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; } PyDoc_STRVAR(symmetric_difference_update_doc, "Update a set with the symmetric difference of itself and another."); static PyObject * set_xor(PySetObject *so, PyObject *other) { if (!IS_SET(so) || !IS_SET(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return set_symmetric_difference(so, other); } static PyObject * set_ixor(PySetObject *so, PyObject *other) { PyObject *result; if (!IS_SET(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } result = set_symmetric_difference_update(so, other); if (result == NULL) return NULL; Py_DECREF(result); Py_INCREF(so); return (PyObject *)so; } static PyObject * set_issubset(PySetObject *so, PyObject *other) { PyObject *otherdata, *it, *item; if (!IS_SET(other)) { PyErr_SetString(PyExc_TypeError, "can only compare to a set"); return NULL; } if (set_len(so) > set_len((PySetObject *)other)) Py_RETURN_FALSE; it = PyObject_GetIter(so->data); if (it == NULL) return NULL; otherdata = ((PySetObject *)other)->data; while ((item = PyIter_Next(it)) != NULL) { if (!DICT_CONTAINS(otherdata, item)) { Py_DECREF(it); Py_DECREF(item); Py_RETURN_FALSE; } Py_DECREF(item); } Py_DECREF(it); Py_RETURN_TRUE; } PyDoc_STRVAR(issubset_doc, "Report whether another set contains this set."); static PyObject * set_issuperset(PySetObject *so, PyObject *other) { if (!IS_SET(other)) { PyErr_SetString(PyExc_TypeError, "can only compare to a set"); return NULL; } return set_issubset((PySetObject *)other, (PyObject *)so); } PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set."); static long set_nohash(PyObject *self) { PyErr_SetString(PyExc_TypeError, "set objects are unhashable"); return -1; } static int set_nocmp(PyObject *self) { PyErr_SetString(PyExc_TypeError, "cannot compare sets using cmp()"); return -1; } static long frozenset_hash(PyObject *self) { PyObject *it, *item; PySetObject *so = (PySetObject *)self; long hash = 0; if (so->hash != -1) return so->hash; it = PyObject_GetIter(((PySetObject *)so)->data); if (it == NULL) return -1; while ((item = PyIter_Next(it)) != NULL) { hash ^= PyObject_Hash(item); Py_DECREF(item); } so->hash = hash; Py_DECREF(it); return hash; } static PyObject * set_richcompare(PySetObject *v, PyObject *w, int op) { /* XXX factor out is_set test */ if (op == Py_EQ && !IS_SET(w)) Py_RETURN_FALSE; else if (op == Py_NE && !IS_SET(w)) Py_RETURN_TRUE; if (!IS_SET(w)) { PyErr_SetString(PyExc_TypeError, "can only compare to a set"); return NULL; } switch (op) { case Py_EQ: case Py_NE: return PyObject_RichCompare(((PySetObject *)v)->data, ((PySetObject *)w)->data, op); case Py_LE: return set_issubset((PySetObject *)v, w); case Py_GE: return set_issuperset((PySetObject *)v, w); case Py_LT: if (set_len(v) >= set_len((PySetObject *)w)) Py_RETURN_FALSE; return set_issubset((PySetObject *)v, w); case Py_GT: if (set_len(v) <= set_len((PySetObject *)w)) Py_RETURN_FALSE; return set_issuperset((PySetObject *)v, w); } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } static PyObject * set_repr(PySetObject *so) { PyObject *keys, *result, *listrepr; keys = PyDict_Keys(so->data); listrepr = PyObject_Repr(keys); Py_DECREF(keys); result = PyString_FromFormat("%s(%s)", so->ob_type->tp_name, PyString_AS_STRING(listrepr)); Py_DECREF(listrepr); return result; } static int set_tp_print(PySetObject *so, FILE *fp, int flags) { PyObject *it, *item; int firstpass=1; it = PyObject_GetIter(so->data); if (it == NULL) return -1; fprintf(fp, "%s([", so->ob_type->tp_name); while ((item = PyIter_Next(it)) != NULL) { if (firstpass == 1) firstpass = 0; else fprintf(fp, ","); if (PyObject_Print(item, fp, 0) != 0) { Py_DECREF(it); Py_DECREF(item); return -1; } Py_DECREF(item); } Py_DECREF(it); fprintf(fp, "])"); return 0; } static PyObject * set_clear(PySetObject *so) { PyDict_Clear(so->data); so->hash = -1; Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); static int set_tp_clear(PySetObject *so) { PyDict_Clear(so->data); so->hash = -1; return 0; } static PyObject * set_add(PySetObject *so, PyObject *item) { if (PyDict_SetItem(so->data, item, Py_True) == -1) return NULL; Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(add_doc, "Add an element to a set.\n\ \n\ This has no effect if the element is already present."); static PyObject * set_remove(PySetObject *so, PyObject *item) { if (PyDict_DelItem(so->data, item) == -1) return NULL; Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(remove_doc, "Remove an element from a set; it must be a member.\n\ \n\ If the element is not a member, raise a KeyError."); static PyObject * set_discard(PySetObject *so, PyObject *item) { if (PyDict_DelItem(so->data, item) == -1) if (PyErr_ExceptionMatches(PyExc_KeyError)) PyErr_Clear(); else return NULL; Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(discard_doc, "Remove an element from a set if it is a member.\n\ \n\ If the element is not a member, do nothing."); static PyObject * set_pop(PySetObject *so) { PyObject *key, *value; int pos = 0; if (!PyDict_Next(so->data, &pos, &key, &value)) { PyErr_SetString(PyExc_KeyError, "pop from an empty set"); return NULL; } Py_INCREF(key); if (PyDict_DelItem(so->data, key) == -1) PyErr_Clear(); return key; } PyDoc_STRVAR(pop_doc, "Remove and return an arbitrary set element."); static PyObject * set_reduce(PySetObject *so) { PyObject *keys=NULL, *args=NULL, *result=NULL; keys = PyDict_Keys(so->data); if (keys == NULL) goto done; args = PyTuple_Pack(1, keys); if (args == NULL) goto done; result = PyTuple_Pack(2, so->ob_type, args); done: Py_XDECREF(args); Py_XDECREF(keys); return result; } PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); static PySequenceMethods set_as_sequence = { (inquiry)set_len, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ (objobjproc)set_contains, /* sq_contains */ }; /* set object ********************************************************/ static PyMethodDef set_methods[] = { {"add", (PyCFunction)set_add, METH_O, add_doc}, {"clear", (PyCFunction)set_clear, METH_NOARGS, clear_doc}, {"copy", (PyCFunction)set_copy, METH_NOARGS, copy_doc}, {"__copy__", (PyCFunction)set_copy, METH_NOARGS, copy_doc}, {"discard", (PyCFunction)set_discard, METH_O, discard_doc}, {"difference", (PyCFunction)set_difference, METH_O, difference_doc}, {"difference_update", (PyCFunction)set_difference_update, METH_O, difference_update_doc}, {"intersection",(PyCFunction)set_intersection, METH_O, intersection_doc}, {"intersection_update",(PyCFunction)set_intersection_update, METH_O, intersection_update_doc}, {"issubset", (PyCFunction)set_issubset, METH_O, issubset_doc}, {"issuperset", (PyCFunction)set_issuperset, METH_O, issuperset_doc}, {"pop", (PyCFunction)set_pop, METH_NOARGS, pop_doc}, {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS, reduce_doc}, {"remove", (PyCFunction)set_remove, METH_O, remove_doc}, {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, symmetric_difference_doc}, {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O, symmetric_difference_update_doc}, {"union", (PyCFunction)set_union, METH_O, union_doc}, {"union_update",(PyCFunction)set_union_update, METH_O, union_update_doc}, {NULL, NULL} /* sentinel */ }; static PyNumberMethods set_as_number = { 0, /*nb_add*/ (binaryfunc)set_sub, /*nb_subtract*/ 0, /*nb_multiply*/ 0, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_negative*/ 0, /*nb_positive*/ 0, /*nb_absolute*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ (binaryfunc)set_and, /*nb_and*/ (binaryfunc)set_xor, /*nb_xor*/ (binaryfunc)set_or, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ 0, /*nb_inplace_add*/ (binaryfunc)set_isub, /*nb_inplace_subtract*/ 0, /*nb_inplace_multiply*/ 0, /*nb_inplace_divide*/ 0, /*nb_inplace_remainder*/ 0, /*nb_inplace_power*/ 0, /*nb_inplace_lshift*/ 0, /*nb_inplace_rshift*/ (binaryfunc)set_iand, /*nb_inplace_and*/ (binaryfunc)set_ixor, /*nb_inplace_xor*/ (binaryfunc)set_ior, /*nb_inplace_or*/ }; PyDoc_STRVAR(set_doc, "set(iterable) --> set object\n\ \n\ Build an unordered collection."); PyTypeObject PySet_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ "set", /* tp_name */ sizeof(PySetObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)set_dealloc, /* tp_dealloc */ (printfunc)set_tp_print, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ (cmpfunc)set_nocmp, /* tp_compare */ (reprfunc)set_repr, /* tp_repr */ &set_as_number, /* tp_as_number */ &set_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ set_nohash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE, /* tp_flags */ set_doc, /* tp_doc */ (traverseproc)set_traverse, /* tp_traverse */ (inquiry)set_tp_clear, /* tp_clear */ (richcmpfunc)set_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)set_iter, /* tp_iter */ 0, /* tp_iternext */ set_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ set_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; /* frozenset object ********************************************************/ static PyMethodDef frozenset_methods[] = { {"copy", (PyCFunction)set_copy, METH_NOARGS, copy_doc}, {"__copy__", (PyCFunction)set_copy, METH_NOARGS, copy_doc}, {"difference",(PyCFunction)set_difference, METH_O, difference_doc}, {"intersection",(PyCFunction)set_intersection, METH_O, intersection_doc}, {"issubset",(PyCFunction)set_issubset, METH_O, issubset_doc}, {"issuperset",(PyCFunction)set_issuperset, METH_O, issuperset_doc}, {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS, reduce_doc}, {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, symmetric_difference_doc}, {"union", (PyCFunction)set_union, METH_O, union_doc}, {NULL, NULL} /* sentinel */ }; static PyNumberMethods frozenset_as_number = { 0, /*nb_add*/ (binaryfunc)set_sub, /*nb_subtract*/ 0, /*nb_multiply*/ 0, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_negative*/ 0, /*nb_positive*/ 0, /*nb_absolute*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ (binaryfunc)set_and, /*nb_and*/ (binaryfunc)set_xor, /*nb_xor*/ (binaryfunc)set_or, /*nb_or*/ }; PyDoc_STRVAR(frozenset_doc, "frozenset(iterable) --> frozenset object\n\ \n\ Build an immutable unordered collection."); PyTypeObject PyFrozenSet_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ "frozenset", /* tp_name */ sizeof(PySetObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)set_dealloc, /* tp_dealloc */ (printfunc)set_tp_print, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ (cmpfunc)set_nocmp, /* tp_compare */ (reprfunc)set_repr, /* tp_repr */ &frozenset_as_number, /* tp_as_number */ &set_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ frozenset_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE, /* tp_flags */ frozenset_doc, /* tp_doc */ (traverseproc)set_traverse, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)set_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)set_iter, /* tp_iter */ 0, /* tp_iternext */ frozenset_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ set_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ };