summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2007-11-22 00:55:51 (GMT)
committerGuido van Rossum <guido@python.org>2007-11-22 00:55:51 (GMT)
commit64c06e327d48150fc548cf18a4a7ae0b890e69fa (patch)
treedaf53ab57c369a3d92c5a9deafc41df2ccd96127 /Objects
parentcc7f26bf207ee17e2c1b3e6545e145942aff612d (diff)
downloadcpython-64c06e327d48150fc548cf18a4a7ae0b890e69fa.zip
cpython-64c06e327d48150fc548cf18a4a7ae0b890e69fa.tar.gz
cpython-64c06e327d48150fc548cf18a4a7ae0b890e69fa.tar.bz2
Backport of _abccoll.py by Benjamin Arangueren, issue 1383.
With some changes of my own thrown in (e.g. backport of r58107).
Diffstat (limited to 'Objects')
-rw-r--r--Objects/dictobject.c9
-rw-r--r--Objects/listobject.c10
-rw-r--r--Objects/object.c2
-rw-r--r--Objects/setobject.c9
-rw-r--r--Objects/typeobject.c60
5 files changed, 46 insertions, 44 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 978071b..bfb891c 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -2127,13 +2127,6 @@ dict_init(PyObject *self, PyObject *args, PyObject *kwds)
return dict_update_common(self, args, kwds, "dict");
}
-static long
-dict_nohash(PyObject *self)
-{
- PyErr_SetString(PyExc_TypeError, "dict objects are unhashable");
- return -1;
-}
-
static PyObject *
dict_iter(PyDictObject *dict)
{
@@ -2165,7 +2158,7 @@ PyTypeObject PyDict_Type = {
0, /* tp_as_number */
&dict_as_sequence, /* tp_as_sequence */
&dict_as_mapping, /* tp_as_mapping */
- dict_nohash, /* tp_hash */
+ 0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
diff --git a/Objects/listobject.c b/Objects/listobject.c
index fb5ce82..deb3ca5 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2393,13 +2393,6 @@ list_init(PyListObject *self, PyObject *args, PyObject *kw)
return 0;
}
-static long
-list_nohash(PyObject *self)
-{
- PyErr_SetString(PyExc_TypeError, "list objects are unhashable");
- return -1;
-}
-
static PyObject *list_iter(PyObject *seq);
static PyObject *list_reversed(PyListObject* seq, PyObject* unused);
@@ -2694,7 +2687,7 @@ PyTypeObject PyList_Type = {
0, /* tp_as_number */
&list_as_sequence, /* tp_as_sequence */
&list_as_mapping, /* tp_as_mapping */
- list_nohash, /* tp_hash */
+ 0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
@@ -2959,4 +2952,3 @@ listreviter_len(listreviterobject *it)
return 0;
return len;
}
-
diff --git a/Objects/object.c b/Objects/object.c
index e75a03d..de385ea 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1902,7 +1902,7 @@ static PyTypeObject PyNone_Type = {
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
- 0, /*tp_hash */
+ (hashfunc)_Py_HashPointer, /*tp_hash */
};
PyObject _Py_NoneStruct = {
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 3cbcd9e..b049d09 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -789,13 +789,6 @@ frozenset_hash(PyObject *self)
return hash;
}
-static long
-set_nohash(PyObject *self)
-{
- PyErr_SetString(PyExc_TypeError, "set objects are unhashable");
- return -1;
-}
-
/***** Set iterator type ***********************************************/
typedef struct {
@@ -2012,7 +2005,7 @@ PyTypeObject PySet_Type = {
&set_as_number, /* tp_as_number */
&set_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
- set_nohash, /* tp_hash */
+ 0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 59dec4a..1a221c8 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -2590,12 +2590,6 @@ object_str(PyObject *self)
return f(self);
}
-static long
-object_hash(PyObject *self)
-{
- return _Py_HashPointer(self);
-}
-
static PyObject *
object_get_class(PyObject *self, void *closure)
{
@@ -3030,7 +3024,7 @@ PyTypeObject PyBaseObject_Type = {
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
- object_hash, /* tp_hash */
+ (hashfunc)_Py_HashPointer, /* tp_hash */
0, /* tp_call */
object_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
@@ -3236,6 +3230,33 @@ inherit_special(PyTypeObject *type, PyTypeObject *base)
type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
}
+/* Map rich comparison operators to their __xx__ namesakes */
+static char *name_op[] = {
+ "__lt__",
+ "__le__",
+ "__eq__",
+ "__ne__",
+ "__gt__",
+ "__ge__",
+ "__cmp__",
+ /* These are only for overrides_hash(): */
+ "__hash__",
+};
+
+static int
+overrides_hash(PyTypeObject *type)
+{
+ int i;
+ PyObject *dict = type->tp_dict;
+
+ assert(dict != NULL);
+ for (i = 0; i < 8; i++) {
+ if (PyDict_GetItemString(dict, name_op[i]) != NULL)
+ return 1;
+ }
+ return 0;
+}
+
static void
inherit_slots(PyTypeObject *type, PyTypeObject *base)
{
@@ -3367,7 +3388,8 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) {
if (type->tp_compare == NULL &&
type->tp_richcompare == NULL &&
- type->tp_hash == NULL)
+ type->tp_hash == NULL &&
+ !overrides_hash(type))
{
type->tp_compare = base->tp_compare;
type->tp_richcompare = base->tp_richcompare;
@@ -3548,6 +3570,18 @@ PyType_Ready(PyTypeObject *type)
}
}
+ /* Hack for tp_hash and __hash__.
+ If after all that, tp_hash is still NULL, and __hash__ is not in
+ tp_dict, set tp_dict['__hash__'] equal to None.
+ This signals that __hash__ is not inherited.
+ */
+ if (type->tp_hash == NULL &&
+ PyDict_GetItemString(type->tp_dict, "__hash__") == NULL &&
+ PyDict_SetItemString(type->tp_dict, "__hash__", Py_None) < 0)
+ {
+ goto error;
+ }
+
/* Some more special stuff */
base = type->tp_base;
if (base != NULL) {
@@ -4937,16 +4971,6 @@ slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value)
return 0;
}
-/* Map rich comparison operators to their __xx__ namesakes */
-static char *name_op[] = {
- "__lt__",
- "__le__",
- "__eq__",
- "__ne__",
- "__gt__",
- "__ge__",
-};
-
static PyObject *
half_richcompare(PyObject *self, PyObject *other, int op)
{