mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 11:49:12 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1127 lines
		
	
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1127 lines
		
	
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "Python.h"
 | 
						|
 | 
						|
/* set object implementation 
 | 
						|
   written and maintained by Raymond D. Hettinger <python@rcn.com>
 | 
						|
   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.
 | 
						|
*/
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_update(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PyObject *item, *data, *it;
 | 
						|
 | 
						|
	if (PyAnySet_Check(other)) {
 | 
						|
		if (PyDict_Merge(so->data, ((PySetObject *)other)->data, 1) == -1) 
 | 
						|
			return NULL;
 | 
						|
		Py_RETURN_NONE;
 | 
						|
	}
 | 
						|
 | 
						|
	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);
 | 
						|
			return NULL;
 | 
						|
                } 
 | 
						|
		Py_DECREF(item);
 | 
						|
	}
 | 
						|
	Py_DECREF(it);
 | 
						|
	if (PyErr_Occurred())
 | 
						|
		return NULL;
 | 
						|
	Py_RETURN_NONE;
 | 
						|
}
 | 
						|
 | 
						|
PyDoc_STRVAR(update_doc, 
 | 
						|
"Update a set with the union of itself and another.");
 | 
						|
 | 
						|
static PyObject *
 | 
						|
make_new_set(PyTypeObject *type, PyObject *iterable)
 | 
						|
{
 | 
						|
	PyObject *data = NULL;
 | 
						|
	PyObject *tmp;
 | 
						|
	PySetObject *so = NULL;
 | 
						|
 | 
						|
	data = PyDict_New();
 | 
						|
	if (data == NULL) 
 | 
						|
		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;
 | 
						|
 | 
						|
	if (iterable != NULL) {
 | 
						|
		tmp = set_update(so, iterable);
 | 
						|
		if (tmp == NULL) {
 | 
						|
			Py_DECREF(so);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
		Py_DECREF(tmp);
 | 
						|
	}
 | 
						|
 | 
						|
	return (PyObject *)so;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 | 
						|
{
 | 
						|
	PyObject *iterable = NULL;
 | 
						|
 | 
						|
	if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable))
 | 
						|
		return NULL;
 | 
						|
	if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
 | 
						|
		Py_INCREF(iterable);
 | 
						|
		return iterable;
 | 
						|
	}
 | 
						|
	return make_new_set(type, iterable);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 | 
						|
{
 | 
						|
	return make_new_set(type, NULL);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
frozenset_dict_wrapper(PyObject *d)
 | 
						|
{
 | 
						|
	PySetObject *w;
 | 
						|
 | 
						|
	assert(PyDict_Check(d));
 | 
						|
	w = (PySetObject *)make_new_set(&PyFrozenSet_Type, NULL);
 | 
						|
	if (w == NULL)
 | 
						|
		return NULL;
 | 
						|
	Py_DECREF(w->data);
 | 
						|
	Py_INCREF(d);
 | 
						|
	w->data = d;
 | 
						|
	return (PyObject *)w;
 | 
						|
}
 | 
						|
 | 
						|
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)
 | 
						|
{
 | 
						|
	PyObject *tmp;
 | 
						|
	int result;
 | 
						|
 | 
						|
	result = PyDict_Contains(so->data, key);
 | 
						|
	if (result == -1 && PyAnySet_Check(key)) {
 | 
						|
		PyErr_Clear();
 | 
						|
		tmp = frozenset_dict_wrapper(((PySetObject *)(key))->data);
 | 
						|
		if (tmp == NULL)
 | 
						|
			return -1;
 | 
						|
		result = PyDict_Contains(so->data, tmp);
 | 
						|
		Py_DECREF(tmp);
 | 
						|
	}
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_direct_contains(PySetObject *so, PyObject *key)
 | 
						|
{
 | 
						|
	long result;
 | 
						|
 | 
						|
	result = set_contains(so, key);
 | 
						|
	if (result == -1)
 | 
						|
		return NULL;
 | 
						|
	return PyBool_FromLong(result);
 | 
						|
}
 | 
						|
 | 
						|
PyDoc_STRVAR(contains_doc, "x.__contains__(y) <==> y in x.");
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_copy(PySetObject *so)
 | 
						|
{
 | 
						|
	return make_new_set(so->ob_type, (PyObject *)so);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
frozenset_copy(PySetObject *so)
 | 
						|
{
 | 
						|
	if (PyFrozenSet_CheckExact(so)) {
 | 
						|
		Py_INCREF(so);
 | 
						|
		return (PyObject *)so;
 | 
						|
	}
 | 
						|
	return set_copy(so);
 | 
						|
}
 | 
						|
 | 
						|
PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set.");
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_union(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PySetObject *result;
 | 
						|
	PyObject *rv;
 | 
						|
 | 
						|
	result = (PySetObject *)set_copy(so);
 | 
						|
	if (result == NULL)
 | 
						|
		return NULL;
 | 
						|
	rv = set_update(result, other);
 | 
						|
	if (rv == NULL) {
 | 
						|
		Py_DECREF(result);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	Py_DECREF(rv);
 | 
						|
	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_or(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
 | 
						|
		Py_INCREF(Py_NotImplemented);
 | 
						|
		return Py_NotImplemented;
 | 
						|
	}
 | 
						|
	return set_union(so, other);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_ior(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PyObject *result;
 | 
						|
 | 
						|
	if (!PyAnySet_Check(other)) {
 | 
						|
		Py_INCREF(Py_NotImplemented);
 | 
						|
		return Py_NotImplemented;
 | 
						|
	}
 | 
						|
	result = set_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, *tmp;
 | 
						|
 | 
						|
	result = (PySetObject *)make_new_set(so->ob_type, NULL);
 | 
						|
	if (result == NULL)
 | 
						|
		return NULL;
 | 
						|
	tgtdata = result->data;
 | 
						|
	selfdata = so->data;
 | 
						|
 | 
						|
	if (PyAnySet_Check(other))
 | 
						|
		other = ((PySetObject *)other)->data;
 | 
						|
 | 
						|
	if (PyDict_Check(other) && PyDict_Size(other) > PyDict_Size(selfdata)) {
 | 
						|
		tmp = selfdata;
 | 
						|
		selfdata = other;
 | 
						|
		other = tmp;
 | 
						|
	}
 | 
						|
 | 
						|
	if (PyDict_CheckExact(other)) {
 | 
						|
		PyObject *value;
 | 
						|
		int pos = 0;
 | 
						|
		while (PyDict_Next(other, &pos, &item, &value)) {
 | 
						|
			if (PyDict_Contains(selfdata, item)) {
 | 
						|
				if (PyDict_SetItem(tgtdata, item, Py_True) == -1) {
 | 
						|
					Py_DECREF(result);
 | 
						|
					return NULL;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return (PyObject *)result;
 | 
						|
	}
 | 
						|
 | 
						|
	it = PyObject_GetIter(other);
 | 
						|
	if (it == NULL) {
 | 
						|
		Py_DECREF(result);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	while ((item = PyIter_Next(it)) != NULL) {
 | 
						|
		if (PyDict_Contains(selfdata, item)) {
 | 
						|
			if (PyDict_SetItem(tgtdata, item, Py_True) == -1) {
 | 
						|
				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(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 (PyDict_Contains(selfdata, item)) {
 | 
						|
			if (PyDict_SetItem(newdict, item, Py_True) == -1) {
 | 
						|
				Py_DECREF(newdict);
 | 
						|
				Py_DECREF(it);
 | 
						|
				Py_DECREF(item);
 | 
						|
				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 (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
 | 
						|
		Py_INCREF(Py_NotImplemented);
 | 
						|
		return Py_NotImplemented;
 | 
						|
	}
 | 
						|
	return set_intersection(so, other);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_iand(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PyObject *result;
 | 
						|
 | 
						|
	if (!PyAnySet_Check(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_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_difference(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PyObject *result, *tmp;
 | 
						|
	PyObject *otherdata, *tgtdata;
 | 
						|
	PyObject *key, *value;
 | 
						|
	int pos = 0;
 | 
						|
 | 
						|
	if (PyDict_Check(other))
 | 
						|
		otherdata = other;
 | 
						|
	else if (PyAnySet_Check(other))
 | 
						|
		otherdata = ((PySetObject *)other)->data;
 | 
						|
	else {
 | 
						|
		result = set_copy(so);
 | 
						|
		if (result == NULL)
 | 
						|
			return result;
 | 
						|
		tmp = set_difference_update((PySetObject *)result, other);
 | 
						|
		if (tmp != NULL) {
 | 
						|
			Py_DECREF(tmp);
 | 
						|
			return result;
 | 
						|
		}
 | 
						|
		Py_DECREF(result);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	
 | 
						|
	result = make_new_set(so->ob_type, NULL);
 | 
						|
	if (result == NULL)
 | 
						|
		return NULL;
 | 
						|
	tgtdata = ((PySetObject *)result)->data;
 | 
						|
 | 
						|
	while (PyDict_Next(so->data, &pos, &key, &value)) {
 | 
						|
		if (!PyDict_Contains(otherdata, key)) {
 | 
						|
			if (PyDict_SetItem(tgtdata, key, Py_True) == -1)
 | 
						|
				return NULL;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return 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_sub(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
 | 
						|
		Py_INCREF(Py_NotImplemented);
 | 
						|
		return Py_NotImplemented;
 | 
						|
	}
 | 
						|
	return set_difference(so, other);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_isub(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PyObject *result;
 | 
						|
 | 
						|
	if (!PyAnySet_Check(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_update(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PyObject *selfdata, *otherdata;
 | 
						|
	PySetObject *otherset = NULL;
 | 
						|
	PyObject *key, *value;
 | 
						|
	int pos = 0;
 | 
						|
 | 
						|
	selfdata = so->data;
 | 
						|
	if (PyDict_Check(other))
 | 
						|
		otherdata = other;
 | 
						|
	else if (PyAnySet_Check(other))
 | 
						|
		otherdata = ((PySetObject *)other)->data;
 | 
						|
	else {
 | 
						|
		otherset = (PySetObject *)make_new_set(so->ob_type, other);
 | 
						|
		if (otherset == NULL)
 | 
						|
			return NULL;
 | 
						|
		otherdata = otherset->data;
 | 
						|
	}
 | 
						|
 | 
						|
	while (PyDict_Next(otherdata, &pos, &key, &value)) {
 | 
						|
		if (PyDict_Contains(selfdata, key)) {
 | 
						|
			if (PyDict_DelItem(selfdata, key) == -1) {
 | 
						|
				Py_XDECREF(otherset);
 | 
						|
				return NULL;
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			if (PyDict_SetItem(selfdata, key, Py_True) == -1) {
 | 
						|
				Py_XDECREF(otherset);
 | 
						|
				return NULL;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	Py_XDECREF(otherset);
 | 
						|
	Py_RETURN_NONE;
 | 
						|
}
 | 
						|
 | 
						|
PyDoc_STRVAR(symmetric_difference_update_doc,
 | 
						|
"Update a set with the symmetric difference of itself and another.");
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_symmetric_difference(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PySetObject *result;
 | 
						|
	PyObject *selfdata, *otherdata, *tgtdata, *rv, *otherset;
 | 
						|
	PyObject *key, *value;
 | 
						|
	int pos = 0;
 | 
						|
 | 
						|
	if (PyDict_Check(other))
 | 
						|
		otherdata = other;
 | 
						|
	else if (PyAnySet_Check(other))
 | 
						|
		otherdata = ((PySetObject *)other)->data;
 | 
						|
	else {
 | 
						|
		otherset = make_new_set(so->ob_type, other);
 | 
						|
		if (otherset == NULL)
 | 
						|
			return NULL;
 | 
						|
		rv = set_symmetric_difference_update((PySetObject *)otherset, (PyObject *)so);
 | 
						|
		if (rv == NULL)
 | 
						|
			return NULL;
 | 
						|
		Py_DECREF(rv);
 | 
						|
		return otherset;
 | 
						|
	}	
 | 
						|
 | 
						|
	result = (PySetObject *)make_new_set(so->ob_type, NULL);
 | 
						|
	if (result == NULL)
 | 
						|
		return NULL;
 | 
						|
	tgtdata = result->data;
 | 
						|
	selfdata = so->data;
 | 
						|
 | 
						|
	while (PyDict_Next(otherdata, &pos, &key, &value)) {
 | 
						|
		if (!PyDict_Contains(selfdata, key)) {
 | 
						|
			if (PyDict_SetItem(tgtdata, key, Py_True) == -1) {
 | 
						|
				Py_DECREF(result);
 | 
						|
				return NULL;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	pos = 0;
 | 
						|
	while (PyDict_Next(selfdata, &pos, &key, &value)) {
 | 
						|
		if (!PyDict_Contains(otherdata, key)) {
 | 
						|
			if (PyDict_SetItem(tgtdata, key, Py_True) == -1) {
 | 
						|
				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_xor(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	if (!PyAnySet_Check(so) || !PyAnySet_Check(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 (!PyAnySet_Check(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, *tmp, *result;
 | 
						|
	PyObject *key, *value;
 | 
						|
	int pos = 0;
 | 
						|
 | 
						|
	if (!PyAnySet_Check(other)) {
 | 
						|
		tmp = make_new_set(&PySet_Type, other);
 | 
						|
		if (tmp == NULL)
 | 
						|
			return NULL;
 | 
						|
		result = set_issubset(so, tmp);
 | 
						|
		Py_DECREF(tmp);
 | 
						|
		return result;
 | 
						|
	}
 | 
						|
	if (set_len(so) > set_len((PySetObject *)other)) 
 | 
						|
		Py_RETURN_FALSE;
 | 
						|
 | 
						|
	otherdata = ((PySetObject *)other)->data;
 | 
						|
	while (PyDict_Next(((PySetObject *)so)->data, &pos, &key, &value)) {
 | 
						|
		if (!PyDict_Contains(otherdata, key))
 | 
						|
			Py_RETURN_FALSE;
 | 
						|
	}
 | 
						|
	Py_RETURN_TRUE;
 | 
						|
}
 | 
						|
 | 
						|
PyDoc_STRVAR(issubset_doc, "Report whether another set contains this set.");
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_issuperset(PySetObject *so, PyObject *other)
 | 
						|
{
 | 
						|
	PyObject *tmp, *result;
 | 
						|
 | 
						|
	if (!PyAnySet_Check(other)) {
 | 
						|
		tmp = make_new_set(&PySet_Type, other);
 | 
						|
		if (tmp == NULL)
 | 
						|
			return NULL;
 | 
						|
		result = set_issuperset(so, tmp);
 | 
						|
		Py_DECREF(tmp);
 | 
						|
		return result;
 | 
						|
	}
 | 
						|
	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)
 | 
						|
{
 | 
						|
	PySetObject *so = (PySetObject *)self;
 | 
						|
	PyObject *key, *value;
 | 
						|
	int pos = 0;
 | 
						|
	long hash = 0;
 | 
						|
 | 
						|
	if (so->hash != -1)
 | 
						|
		return so->hash;
 | 
						|
 | 
						|
	while (PyDict_Next(so->data, &pos, &key, &value)) {
 | 
						|
		/* Multiplying by a large prime increases the bit dispersion for
 | 
						|
		   closely spaced hash values.  The is important because some
 | 
						|
		   use cases have many combinations of a small number of 
 | 
						|
		   elements with nearby hashes so that many distinct combinations
 | 
						|
		   collapse to only a handful of distinct hash values. */
 | 
						|
		hash ^= PyObject_Hash(key) * 3644798167u;
 | 
						|
	}
 | 
						|
	so->hash = hash;
 | 
						|
	return hash;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_richcompare(PySetObject *v, PyObject *w, int op)
 | 
						|
{
 | 
						|
	if(!PyAnySet_Check(w)) {
 | 
						|
		if (op == Py_EQ)
 | 
						|
			Py_RETURN_FALSE;
 | 
						|
		if (op == Py_NE)
 | 
						|
			Py_RETURN_TRUE;
 | 
						|
		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);
 | 
						|
	if (keys == NULL)
 | 
						|
		return NULL;
 | 
						|
	listrepr = PyObject_Repr(keys);
 | 
						|
	Py_DECREF(keys);
 | 
						|
	if (listrepr == NULL)
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	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 *key, *value;
 | 
						|
	int pos=0;
 | 
						|
	char *emit = "";	/* No separator emitted on first pass */
 | 
						|
	char *separator = ", ";
 | 
						|
 | 
						|
	fprintf(fp, "%s([", so->ob_type->tp_name);
 | 
						|
	while (PyDict_Next(so->data, &pos, &key, &value)) {
 | 
						|
		fputs(emit, fp);
 | 
						|
		emit = separator;
 | 
						|
		if (PyObject_Print(key, fp, 0) != 0)
 | 
						|
			return -1;
 | 
						|
	}
 | 
						|
	fputs("])", fp);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *
 | 
						|
set_clear(PySetObject *so)
 | 
						|
{
 | 
						|
	PyDict_Clear(so->data);
 | 
						|
	so->hash = -1;
 | 
						|
	Py_RETURN_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_RETURN_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)
 | 
						|
{
 | 
						|
	PyObject *tmp, *result;
 | 
						|
 | 
						|
	if (PyType_IsSubtype(item->ob_type, &PySet_Type)) {
 | 
						|
		tmp = frozenset_dict_wrapper(((PySetObject *)(item))->data);
 | 
						|
		if (tmp == NULL)
 | 
						|
			return NULL;
 | 
						|
		result = set_remove(so, tmp);
 | 
						|
		Py_DECREF(tmp);
 | 
						|
		return result;
 | 
						|
	}
 | 
						|
 | 
						|
	if (PyDict_DelItem(so->data, item) == -1) 
 | 
						|
		return NULL;
 | 
						|
	Py_RETURN_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)
 | 
						|
{
 | 
						|
	PyObject *tmp, *result;
 | 
						|
 | 
						|
	if (PyType_IsSubtype(item->ob_type, &PySet_Type)) {
 | 
						|
		tmp = frozenset_dict_wrapper(((PySetObject *)(item))->data);
 | 
						|
		if (tmp == NULL)
 | 
						|
			return NULL;
 | 
						|
		result = set_discard(so, tmp);
 | 
						|
		Py_DECREF(tmp);
 | 
						|
		return result;
 | 
						|
	}
 | 
						|
 | 
						|
	if (PyDict_DelItem(so->data, item) == -1) {
 | 
						|
		if (!PyErr_ExceptionMatches(PyExc_KeyError))
 | 
						|
			return NULL;
 | 
						|
		PyErr_Clear();
 | 
						|
	}
 | 
						|
	Py_RETURN_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) {
 | 
						|
		Py_DECREF(key);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	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 int
 | 
						|
set_init(PySetObject *self, PyObject *args, PyObject *kwds)
 | 
						|
{
 | 
						|
	PyObject *iterable = NULL;
 | 
						|
	PyObject *result;
 | 
						|
 | 
						|
	if (!PyAnySet_Check(self))
 | 
						|
		return -1;
 | 
						|
	if (!PyArg_UnpackTuple(args, self->ob_type->tp_name, 0, 1, &iterable))
 | 
						|
		return -1;
 | 
						|
	PyDict_Clear(self->data);
 | 
						|
	self->hash = -1;
 | 
						|
	if (iterable == NULL)
 | 
						|
		return 0;
 | 
						|
	result = set_update(self, iterable);
 | 
						|
	if (result != NULL) {
 | 
						|
		Py_DECREF(result);
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
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},
 | 
						|
	{"__contains__",(PyCFunction)set_direct_contains,	METH_O | METH_COEXIST,
 | 
						|
	 contains_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},
 | 
						|
	{"update",	(PyCFunction)set_update,	METH_O,
 | 
						|
	 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 */
 | 
						|
	(initproc)set_init,		/* tp_init */
 | 
						|
	PyType_GenericAlloc,		/* tp_alloc */
 | 
						|
	set_new,			/* tp_new */
 | 
						|
	PyObject_GC_Del,		/* tp_free */
 | 
						|
};
 | 
						|
 | 
						|
/* frozenset object ********************************************************/
 | 
						|
 | 
						|
 | 
						|
static PyMethodDef frozenset_methods[] = {
 | 
						|
	{"__contains__",(PyCFunction)set_direct_contains,	METH_O | METH_COEXIST,
 | 
						|
	 contains_doc},
 | 
						|
	{"copy",	(PyCFunction)frozenset_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 */
 | 
						|
	frozenset_new,			/* tp_new */
 | 
						|
	PyObject_GC_Del,		/* tp_free */
 | 
						|
};
 |