File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -368,3 +368,37 @@ class I:
368368 pass
369369else :
370370 print "attribute error for I.__init__ got masked"
371+
372+
373+ # Test comparison and hash of methods
374+ class A :
375+ def __init__ (self , x ):
376+ self .x = x
377+ def f (self ):
378+ pass
379+ def g (self ):
380+ pass
381+ def __eq__ (self , other ):
382+ return self .x == other .x
383+ def __hash__ (self ):
384+ return self .x
385+ class B (A ):
386+ pass
387+
388+ a1 = A (1 )
389+ a2 = A (2 )
390+ assert a1 .f == a1 .f
391+ assert a1 .f != a2 .f
392+ assert a1 .f != a1 .g
393+ assert a1 .f == A (1 ).f
394+ assert hash (a1 .f ) == hash (a1 .f )
395+ assert hash (a1 .f ) == hash (A (1 ).f )
396+
397+ assert A .f != a1 .f
398+ assert A .f != A .g
399+ assert B .f == A .f
400+ assert hash (B .f ) == hash (A .f )
401+
402+ # the following triggers a SystemError in 2.4
403+ a = A (hash (A .f .im_func )^ (- 1 ))
404+ hash (a .f )
Original file line number Diff line number Diff line change @@ -4014,11 +4014,24 @@ def methodwrapper():
40144014
40154015 l = []
40164016 vereq (l .__add__ , l .__add__ )
4017- verify (l .__add__ != [].__add__ )
4017+ vereq (l .__add__ , [].__add__ )
4018+ verify (l .__add__ != [5 ].__add__ )
4019+ verify (l .__add__ != l .__mul__ )
40184020 verify (l .__add__ .__name__ == '__add__' )
40194021 verify (l .__add__ .__self__ is l )
40204022 verify (l .__add__ .__objclass__ is list )
40214023 vereq (l .__add__ .__doc__ , list .__add__ .__doc__ )
4024+ try :
4025+ hash (l .__add__ )
4026+ except TypeError :
4027+ pass
4028+ else :
4029+ raise TestFailed ("no TypeError from hash([].__add__)" )
4030+
4031+ t = ()
4032+ t += (7 ,)
4033+ vereq (t .__add__ , (7 ,).__add__ )
4034+ vereq (hash (t .__add__ ), hash ((7 ,).__add__ ))
40224035
40234036def notimplemented ():
40244037 # all binary methods should be able to return a NotImplemented
Original file line number Diff line number Diff line change @@ -2221,9 +2221,17 @@ instancemethod_dealloc(register PyMethodObject *im)
22212221static int
22222222instancemethod_compare (PyMethodObject * a , PyMethodObject * b )
22232223{
2224- if (a -> im_self != b -> im_self )
2224+ int cmp ;
2225+ cmp = PyObject_Compare (a -> im_func , b -> im_func );
2226+ if (cmp )
2227+ return cmp ;
2228+
2229+ if (a -> im_self == b -> im_self )
2230+ return 0 ;
2231+ if (a -> im_self == NULL || b -> im_self == NULL )
22252232 return (a -> im_self < b -> im_self ) ? -1 : 1 ;
2226- return PyObject_Compare (a -> im_func , b -> im_func );
2233+ else
2234+ return PyObject_Compare (a -> im_self , b -> im_self );
22272235}
22282236
22292237static PyObject *
@@ -2299,7 +2307,10 @@ instancemethod_hash(PyMethodObject *a)
22992307 y = PyObject_Hash (a -> im_func );
23002308 if (y == -1 )
23012309 return -1 ;
2302- return x ^ y ;
2310+ x = x ^ y ;
2311+ if (x == -1 )
2312+ x = -2 ;
2313+ return x ;
23032314}
23042315
23052316static int
Original file line number Diff line number Diff line change @@ -901,16 +901,28 @@ wrapper_dealloc(wrapperobject *wp)
901901static int
902902wrapper_compare (wrapperobject * a , wrapperobject * b )
903903{
904- if (a -> descr == b -> descr ) {
905- if (a -> self == b -> self )
906- return 0 ;
907- else
908- return (a -> self < b -> self ) ? -1 : 1 ;
909- }
904+ if (a -> descr == b -> descr )
905+ return PyObject_Compare (a -> self , b -> self );
910906 else
911907 return (a -> descr < b -> descr ) ? -1 : 1 ;
912908}
913909
910+ static long
911+ wrapper_hash (wrapperobject * wp )
912+ {
913+ int x , y ;
914+ x = _Py_HashPointer (wp -> descr );
915+ if (x == -1 )
916+ return -1 ;
917+ y = PyObject_Hash (wp -> self );
918+ if (y == -1 )
919+ return -1 ;
920+ x = x ^ y ;
921+ if (x == -1 )
922+ x = -2 ;
923+ return x ;
924+ }
925+
914926static PyObject *
915927wrapper_repr (wrapperobject * wp )
916928{
@@ -1008,7 +1020,7 @@ static PyTypeObject wrappertype = {
10081020 0 , /* tp_as_number */
10091021 0 , /* tp_as_sequence */
10101022 0 , /* tp_as_mapping */
1011- 0 , /* tp_hash */
1023+ ( hashfunc ) wrapper_hash , /* tp_hash */
10121024 (ternaryfunc )wrapper_call , /* tp_call */
10131025 0 , /* tp_str */
10141026 PyObject_GenericGetAttr , /* tp_getattro */
You can’t perform that action at this time.
0 commit comments