[Python-checkins] r46739 - in python/trunk: Lib/test/test_class.py Lib/test/test_descr.py Objects/classobject.c Objects/descrobject.c

armin.rigo python-checkins at python.org
Thu Jun 8 12:56:25 CEST 2006


Author: armin.rigo
Date: Thu Jun 8 12:56:24 2006
New Revision: 46739
Modified:
 python/trunk/Lib/test/test_class.py
 python/trunk/Lib/test/test_descr.py
 python/trunk/Objects/classobject.c
 python/trunk/Objects/descrobject.c
Log:
(arre, arigo) SF bug #1350060
Give a consistent behavior for comparison and hashing of method objects
(both user- and built-in methods). Now compares the 'self' recursively.
The hash was already asking for the hash of 'self'.
Modified: python/trunk/Lib/test/test_class.py
==============================================================================
--- python/trunk/Lib/test/test_class.py	(original)
+++ python/trunk/Lib/test/test_class.py	Thu Jun 8 12:56:24 2006
@@ -368,3 +368,37 @@
 pass
 else:
 print "attribute error for I.__init__ got masked"
+
+
+# Test comparison and hash of methods
+class A:
+ def __init__(self, x):
+ self.x = x
+ def f(self):
+ pass
+ def g(self):
+ pass
+ def __eq__(self, other):
+ return self.x == other.x
+ def __hash__(self):
+ return self.x
+class B(A):
+ pass
+
+a1 = A(1)
+a2 = A(2)
+assert a1.f == a1.f
+assert a1.f != a2.f
+assert a1.f != a1.g
+assert a1.f == A(1).f
+assert hash(a1.f) == hash(a1.f)
+assert hash(a1.f) == hash(A(1).f)
+
+assert A.f != a1.f
+assert A.f != A.g
+assert B.f == A.f
+assert hash(B.f) == hash(A.f)
+
+# the following triggers a SystemError in 2.4
+a = A(hash(A.f.im_func)^(-1))
+hash(a.f)
Modified: python/trunk/Lib/test/test_descr.py
==============================================================================
--- python/trunk/Lib/test/test_descr.py	(original)
+++ python/trunk/Lib/test/test_descr.py	Thu Jun 8 12:56:24 2006
@@ -4014,11 +4014,24 @@
 
 l = []
 vereq(l.__add__, l.__add__)
- verify(l.__add__ != [].__add__)
+ vereq(l.__add__, [].__add__)
+ verify(l.__add__ != [5].__add__)
+ verify(l.__add__ != l.__mul__)
 verify(l.__add__.__name__ == '__add__')
 verify(l.__add__.__self__ is l)
 verify(l.__add__.__objclass__ is list)
 vereq(l.__add__.__doc__, list.__add__.__doc__)
+ try:
+ hash(l.__add__)
+ except TypeError:
+ pass
+ else:
+ raise TestFailed("no TypeError from hash([].__add__)")
+
+ t = ()
+ t += (7,)
+ vereq(t.__add__, (7,).__add__)
+ vereq(hash(t.__add__), hash((7,).__add__))
 
 def notimplemented():
 # all binary methods should be able to return a NotImplemented
Modified: python/trunk/Objects/classobject.c
==============================================================================
--- python/trunk/Objects/classobject.c	(original)
+++ python/trunk/Objects/classobject.c	Thu Jun 8 12:56:24 2006
@@ -2221,9 +2221,17 @@
 static int
 instancemethod_compare(PyMethodObject *a, PyMethodObject *b)
 {
-	if (a->im_self != b->im_self)
+	int cmp;
+	cmp = PyObject_Compare(a->im_func, b->im_func);
+	if (cmp)
+		return cmp;
+
+	if (a->im_self == b->im_self)
+		return 0;
+	if (a->im_self == NULL || b->im_self == NULL)
 		return (a->im_self < b->im_self) ? -1 : 1;
-	return PyObject_Compare(a->im_func, b->im_func);
+	else
+		return PyObject_Compare(a->im_self, b->im_self);
 }
 
 static PyObject *
@@ -2299,7 +2307,10 @@
 	y = PyObject_Hash(a->im_func);
 	if (y == -1)
 		return -1;
-	return x ^ y;
+	x = x ^ y;
+	if (x == -1)
+		x = -2;
+	return x;
 }
 
 static int
Modified: python/trunk/Objects/descrobject.c
==============================================================================
--- python/trunk/Objects/descrobject.c	(original)
+++ python/trunk/Objects/descrobject.c	Thu Jun 8 12:56:24 2006
@@ -901,16 +901,28 @@
 static int
 wrapper_compare(wrapperobject *a, wrapperobject *b)
 {
-	if (a->descr == b->descr) {
-		if (a->self == b->self)
-			return 0;
-		else
-			return (a->self < b->self) ? -1 : 1;
-	}
+	if (a->descr == b->descr)
+		return PyObject_Compare(a->self, b->self);
 	else
 		return (a->descr < b->descr) ? -1 : 1;
 }
 
+static long
+wrapper_hash(wrapperobject *wp)
+{
+	int x, y;
+	x = _Py_HashPointer(wp->descr);
+	if (x == -1)
+		return -1;
+	y = PyObject_Hash(wp->self);
+	if (y == -1)
+		return -1;
+	x = x ^ y;
+	if (x == -1)
+		x = -2;
+	return x;
+}
+
 static PyObject *
 wrapper_repr(wrapperobject *wp)
 {
@@ -1008,7 +1020,7 @@
 	0,					/* tp_as_number */
 	0,					/* tp_as_sequence */
 	0,		 			/* tp_as_mapping */
-	0,					/* tp_hash */
+	(hashfunc)wrapper_hash,			/* tp_hash */
 	(ternaryfunc)wrapper_call,		/* tp_call */
 	0,					/* tp_str */
 	PyObject_GenericGetAttr,		/* tp_getattro */


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /