diff options
author | Guido van Rossum <guido@python.org> | 2006-08-21 23:36:26 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2006-08-21 23:36:26 (GMT) |
commit | 389381564cfa936c8e50bc51dc53b55cba857652 (patch) | |
tree | 7259a38e0d6c06e5519276336ed26a593166de1d /Objects | |
parent | 5431ee4a499e173c5638297de30a965ed2206c66 (diff) | |
download | cpython-389381564cfa936c8e50bc51dc53b55cba857652.zip cpython-389381564cfa936c8e50bc51dc53b55cba857652.tar.gz cpython-389381564cfa936c8e50bc51dc53b55cba857652.tar.bz2 |
Change the way __hash__ is inherited; when __eq__ or __cmp__ is overridden
but __hash__ is not, set __hash__ explicitly to None (and tp_hash to NULL).
All unit tests pass now!
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/object.c | 9 | ||||
-rw-r--r-- | Objects/typeobject.c | 58 |
2 files changed, 55 insertions, 12 deletions
diff --git a/Objects/object.c b/Objects/object.c index cb60320..80111b4 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -320,9 +320,16 @@ PyObject_Print(PyObject *op, FILE *fp, int flags) return internal_print(op, fp, flags, 0); } +/* For debugging convenience. Set a breakpoint here and call it from your DLL */ +void +_Py_Break(void) +{ +} + /* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */ -void _PyObject_Dump(PyObject* op) +void +_PyObject_Dump(PyObject* op) { if (op == NULL) fprintf(stderr, "NULL\n"); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1578801..f30a826 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2847,6 +2847,33 @@ inherit_special(PyTypeObject *type, PyTypeObject *base) COPYVAL(tp_dictoffset); } +/* Map rich comparison operators to their __xx__ namesakes */ +static char *name_op[] = { + "__lt__", + "__le__", + "__eq__", + "__ne__", + "__gt__", + "__ge__", + /* These are only for overrides_cmp_or_hash(): */ + "__cmp__", + "__hash__", +}; + +static int +overrides_cmp_or_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) { @@ -2970,9 +2997,12 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) COPYSLOT(tp_call); COPYSLOT(tp_str); { + /* Copy comparison-related slots only when + not overriding them anywhere */ if (type->tp_compare == NULL && type->tp_richcompare == NULL && - type->tp_hash == NULL) + type->tp_hash == NULL && + !overrides_cmp_or_hash(type)) { type->tp_compare = base->tp_compare; type->tp_richcompare = base->tp_richcompare; @@ -3020,6 +3050,10 @@ PyType_Ready(PyTypeObject *type) PyTypeObject *base; Py_ssize_t i, n; + if (strcmp(type->tp_name, "C") == 0) { + _Py_Break(); + } + if (type->tp_flags & Py_TPFLAGS_READY) { assert(type->tp_dict != NULL); return 0; @@ -3150,6 +3184,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) { + if (PyDict_GetItemString(type->tp_dict, "__hash__") == NULL) { + if (PyDict_SetItemString(type->tp_dict, "__hash__", Py_None) < 0) + goto error; + } + } + /* Some more special stuff */ base = type->tp_base; if (base != NULL) { @@ -4450,16 +4496,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) { |