New submission from Keir Mierle:

This an updated version of the patch I submitted earlier to python-3000;
it is almost identical except it extends the test case to cover more of
the code.

----------
components: Interpreter Core
files: dictview_richcompare_ver2.diff
messages: 55275
nosy: keir
severity: normal
status: open
title: [PATCH] Updated patch for rich dict view (dict().keys()) comparisons
versions: Python 3.0

__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1015>
__________________________________
Index: Objects/dictobject.c
===================================================================
--- Objects/dictobject.c	(revision 57414)
+++ Objects/dictobject.c	(working copy)
@@ -2371,6 +2371,7 @@
 # define PyDictViewSet_Check(obj) \
 	(PyDictKeys_Check(obj) || PyDictItems_Check(obj))
 
+/* Return 1 if self is a subset of other */
 static int
 all_contained_in(PyObject *self, PyObject *other)
 {
@@ -2398,41 +2399,61 @@
 static PyObject *
 dictview_richcompare(PyObject *self, PyObject *other, int op)
 {
+        Py_ssize_t len_self, len_other;
+        PyObject *result;
+
 	assert(self != NULL);
 	assert(PyDictViewSet_Check(self));
 	assert(other != NULL);
-	if ((op == Py_EQ || op == Py_NE) &&
-	    (PyAnySet_Check(other) || PyDictViewSet_Check(other)))
-	{
-		Py_ssize_t len_self, len_other;
-		int ok;
-		PyObject *result;
 
-		len_self = PyObject_Size(self);
-		if (len_self < 0)
-			return NULL;
-		len_other = PyObject_Size(other);
-		if (len_other < 0)
-			return NULL;
-		if (len_self != len_other)
-			ok = 0;
-		else if (len_self == 0)
-			ok = 1;
-		else
-			ok = all_contained_in(self, other);
-		if (ok < 0)
-			return NULL;
-		if (ok == (op == Py_EQ))
-			result = Py_True;
-		else
-			result = Py_False;
-		Py_INCREF(result);
-		return result;
-	}
-	else {
+        if (!PyAnySet_Check(other) && !PyDictViewSet_Check(other)) {
 		Py_INCREF(Py_NotImplemented);
 		return Py_NotImplemented;
-	}
+        }
+
+        len_self = PyObject_Size(self);
+        if (len_self < 0)
+                return NULL;
+        len_other = PyObject_Size(other);
+        if (len_other < 0)
+                return NULL;
+
+        result = Py_False;
+        switch(op) {
+	  case Py_NE:
+		if (len_self != len_other ||
+		    len_self == 0 ||
+		    !all_contained_in(self, other))
+			result = Py_True;
+		break;
+	  case Py_EQ:
+		if (len_self == len_other &&
+		    (len_self == 0 || all_contained_in(self, other)))
+			result = Py_True; 
+		break;
+	  case Py_LT:
+		if (len_self < len_other &&
+		    all_contained_in(self, other))
+			result = Py_True;
+		break;
+	  case Py_LE:
+		if (len_self <= len_other &&
+		    all_contained_in(self, other))
+			result = Py_True;
+		break;
+	  case Py_GT:
+		if (len_self > len_other &&
+		    all_contained_in(other, self))
+			result = Py_True;
+		break;
+	  case Py_GE:
+		if (len_self >= len_other &&
+		    all_contained_in(other, self))
+			result = Py_True;
+		break;
+        }
+        Py_INCREF(result);
+        return result;
 }
 
 /*** dict_keys ***/
Index: Lib/test/test_dict.py
===================================================================
--- Lib/test/test_dict.py	(revision 57414)
+++ Lib/test/test_dict.py	(working copy)
@@ -398,6 +398,47 @@
         else:
             self.fail("< didn't raise Exc")
 
+    def test_keys_contained(self):
+        # Test rich comparisons against dict key views, which should behave the
+        # same as sets.
+        empty = dict()
+        empty2 = dict()
+        smaller = {1:1, 2:2}
+        larger = {1:1, 2:2, 3:3}
+        larger2 = {1:1, 2:2, 3:3}
+        larger3 = {4:1, 2:2, 3:3}
+
+        self.assert_(smaller.keys() <  larger.keys())
+        self.assert_(smaller.keys() <= larger.keys())
+        self.assert_(larger.keys() >  smaller.keys())
+        self.assert_(larger.keys() >= smaller.keys())
+
+        self.assertFalse(smaller.keys() >= larger.keys())
+        self.assertFalse(smaller.keys() >  larger.keys())
+        self.assertFalse(larger.keys()  <= smaller.keys())
+        self.assertFalse(larger.keys()  <  smaller.keys())
+
+        self.assertFalse(smaller.keys() <  larger3.keys())
+        self.assertFalse(smaller.keys() <= larger3.keys())
+        self.assertFalse(larger3.keys() >  smaller.keys())
+        self.assertFalse(larger3.keys() >= smaller.keys())
+
+        # Inequality strictness
+        self.assertTrue(larger2.keys() >= larger.keys())
+        self.assertTrue(larger2.keys() <= larger.keys())
+        self.assertFalse(larger2.keys() > larger.keys())
+        self.assertFalse(larger2.keys() < larger.keys())
+
+        self.assertEquals(larger.keys(), larger2.keys())
+        self.assertNotEquals(smaller.keys(), larger.keys())
+
+        # There is an optimization on the zero-element case.
+        self.assertEquals(empty.keys(), empty2.keys())
+        self.assertNotEquals(empty.keys(), smaller.keys())
+
+        # With the same size, an elementwise compare happens
+        self.assertNotEquals(larger.keys(), larger3.keys())
+
     def test_missing(self):
         # Make sure dict doesn't have a __missing__ method
         self.assertEqual(hasattr(dict, "__missing__"), False)
_______________________________________________
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to