Author: Carl Friedrich Bolz-Tereick <[email protected]>
Branch:
Changeset: r93721:14e8d60878c2
Date: 2018-01-30 13:02 +0100
http://bitbucket.org/pypy/pypy/changeset/14e8d60878c2/
Log: when tp_hash is NULL and either tp_compare or tp_richcompare are
Null then set __hash__ to None making the type unhashable
fixes #2740
diff --git a/pypy/module/cpyext/test/test_typeobject.py
b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -259,6 +259,11 @@
cmpr = module.OldCmpType()
assert cmpr < cmpr
+ def test_unhashable_when_tpcompare(self):
+ module = self.import_module("comparisons")
+ cmpr = module.OldCmpType()
+ raises(TypeError, hash, cmpr)
+
def test_hash(self):
module = self.import_module("comparisons")
cmpr = module.CmpType()
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -340,8 +340,12 @@
if len(slot_names) == 1:
func = getattr(pto, slot_names[0])
if slot_names[0] == 'c_tp_hash':
- if hash_not_impl == func:
- # special case for tp_hash == PyObject_HashNotImplemented
+ # two special cases where __hash__ is explicitly set to None
+ # (which leads to an unhashable type):
+ # 1) tp_hash == PyObject_HashNotImplemented
+ # 2) tp_hash == NULL and either of tp_compare or
tp_richcompare are not NULL
+ if hash_not_impl == func or (
+ not func and (pto.c_tp_compare or
pto.c_tp_richcompare)):
dict_w[method_name] = space.w_None
continue
else:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit