[Python-checkins] r69126 - in python/branches/py3k-issue1717: Lib/test/test_descr.py Objects/descrobject.c

mark.dickinson python-checkins at python.org
Fri Jan 30 17:20:49 CET 2009


Author: mark.dickinson
Date: Fri Jan 30 17:20:49 2009
New Revision: 69126

Log:
Rich comparisons for method wrappers.


Modified:
   python/branches/py3k-issue1717/Lib/test/test_descr.py
   python/branches/py3k-issue1717/Objects/descrobject.c

Modified: python/branches/py3k-issue1717/Lib/test/test_descr.py
==============================================================================
--- python/branches/py3k-issue1717/Lib/test/test_descr.py	(original)
+++ python/branches/py3k-issue1717/Lib/test/test_descr.py	Fri Jan 30 17:20:49 2009
@@ -3885,8 +3885,6 @@
         # Testing method-wrapper objects...
         # <type 'method-wrapper'> did not support any reflection before 2.5
 
-        return # XXX should methods really support __eq__?
-
         l = []
         self.assertEqual(l.__add__, l.__add__)
         self.assertEqual(l.__add__, [].__add__)

Modified: python/branches/py3k-issue1717/Objects/descrobject.c
==============================================================================
--- python/branches/py3k-issue1717/Objects/descrobject.c	(original)
+++ python/branches/py3k-issue1717/Objects/descrobject.c	Fri Jan 30 17:20:49 2009
@@ -838,12 +838,17 @@
 /* This has no reason to be in this file except that adding new files is a
    bit of a pain */
 
+/* forward */
+static PyTypeObject wrappertype;
+
 typedef struct {
 	PyObject_HEAD
 	PyWrapperDescrObject *descr;
 	PyObject *self;
 } wrapperobject;
 
+#define Wrapper_Check(v) (Py_TYPE(v) == &wrappertype)
+
 static void
 wrapper_dealloc(wrapperobject *wp)
 {
@@ -855,6 +860,62 @@
 	Py_TRASHCAN_SAFE_END(wp)
 }
 
+#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
+
+static PyObject *
+wrapper_richcompare(PyObject *a, PyObject *b, int op)
+{
+	int result;
+	PyObject *v;
+	PyWrapperDescrObject *a_descr, *b_descr;
+
+	assert(a != NULL && b != NULL);
+
+	/* both arguments should be wrapperobjects */
+	if (!Wrapper_Check(a) || !Wrapper_Check(b)) {
+		v = Py_NotImplemented;
+		Py_INCREF(v);
+		return v;
+	}
+
+	/* compare by descriptor address; if the descriptors are the same,
+	   compare by the objects they're bound to */
+	a_descr = ((wrapperobject *)a)->descr;
+	b_descr = ((wrapperobject *)b)->descr;
+	if (a_descr == b_descr) {
+		a = ((wrapperobject *)a)->self;
+		b = ((wrapperobject *)b)->self;
+		return PyObject_RichCompare(a, b, op);
+	}
+
+	result = a_descr - b_descr;
+	switch (op) {
+	case Py_EQ:
+		v = TEST_COND(result == 0);
+		break;
+	case Py_NE:
+		v = TEST_COND(result != 0);
+		break;
+	case Py_LE:
+		v = TEST_COND(result <= 0);
+		break;
+	case Py_GE:
+		v = TEST_COND(result >= 0);
+		break;
+	case Py_LT:
+		v = TEST_COND(result < 0);
+		break;
+	case Py_GT:
+		v = TEST_COND(result > 0);
+		break;
+	default:
+		PyErr_BadArgument();
+		return NULL;
+	}
+	Py_INCREF(v);
+	return v;
+}
+
 static long
 wrapper_hash(wrapperobject *wp)
 {
@@ -977,7 +1038,7 @@
  	0,					/* tp_doc */
 	wrapper_traverse,			/* tp_traverse */
  	0,					/* tp_clear */
-	0,					/* tp_richcompare */
+	wrapper_richcompare,			/* tp_richcompare */
 	0,					/* tp_weaklistoffset */
 	0,					/* tp_iter */
 	0,					/* tp_iternext */


More information about the Python-checkins mailing list