SF bug 693121:  Set == non-Set is a TypeError.
Allow mixed-type __eq__ and __ne__ for Set objects.  This is messier than
I'd like because Set *also* implements __cmp__.  I know of one glitch now:
cmp(s, t) returns 0 now when s and t are both Sets and s == t, despite
that Set.__cmp__ unconditionally raises TypeError (and by intent).  The
rub is that __eq__ gets tried first, and the x.__eq__(y) True result
convinces Python that cmp(x, y) is 0 without even calling Set.__cmp__.
diff --git a/Lib/sets.py b/Lib/sets.py
index 0824fb1..e6a509f 100644
--- a/Lib/sets.py
+++ b/Lib/sets.py
@@ -102,20 +102,40 @@
         """
         return self._data.iterkeys()
 
-    # Three-way comparison is not supported
+    # Three-way comparison is not supported.  However, because __eq__ is
+    # tried before __cmp__, if Set x == Set y, x.__eq__(y) returns True and
+    # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this
+    # case).
 
     def __cmp__(self, other):
         raise TypeError, "can't compare sets using cmp()"
 
-    # Equality comparisons using the underlying dicts
+    # Equality comparisons using the underlying dicts.  Mixed-type comparisons
+    # are allowed here, where Set == z for non-Set z always returns False,
+    # and Set != z always True.  This allows expressions like "x in y" to
+    # give the expected result when y is a sequence of mixed types, not
+    # raising a pointless TypeError just because y contains a Set, or x is
+    # a Set and y contain's a non-set ("in" invokes only __eq__).
+    # Subtle:  it would be nicer if __eq__ and __ne__ could return
+    # NotImplemented instead of True or False.  Then the other comparand
+    # would get a chance to determine the result, and if the other comparand
+    # also returned NotImplemented then it would fall back to object address
+    # comparison (which would always return False for __eq__ and always
+    # True for __ne__).  However, that doesn't work, because this type
+    # *also* implements __cmp__:  if, e.g., __eq__ returns NotImplemented,
+    # Python tries __cmp__ next, and the __cmp__ here then raises TypeError.
 
     def __eq__(self, other):
-        self._binary_sanity_check(other)
-        return self._data == other._data
+        if isinstance(other, BaseSet):
+            return self._data == other._data
+        else:
+            return False
 
     def __ne__(self, other):
-        self._binary_sanity_check(other)
-        return self._data != other._data
+        if isinstance(other, BaseSet):
+            return self._data != other._data
+        else:
+            return True
 
     # Copying operations
 
diff --git a/Lib/test/test_sets.py b/Lib/test/test_sets.py
index 9223596..d8b7f3f 100644
--- a/Lib/test/test_sets.py
+++ b/Lib/test/test_sets.py
@@ -232,7 +232,16 @@
 
     def test_cmp(self):
         a, b = Set('a'), Set('b')
-        self.assertRaises(TypeError, cmp, (a,b))
+        self.assertRaises(TypeError, cmp, a, b)
+
+        # You can view this as a buglet:  cmp(a, a) does not raise TypeError,
+        # because __eq__ is tried before __cmp__, and a.__eq__(a) returns,
+        # which Python thinks is good enough to synthesize a cmp() result
+        # without calling __cmp__.
+        self.assertEqual(cmp(a, a), 0)
+
+        self.assertRaises(TypeError, cmp, a, 12)
+        self.assertRaises(TypeError, cmp, "abc", a)
 
 #==============================================================================
 
@@ -476,17 +485,19 @@
 
 class TestOnlySetsInBinaryOps(unittest.TestCase):
 
-    def test_cmp(self):
-        try:
-            self.other == self.set
-            self.fail("expected TypeError")
-        except TypeError:
-            pass
-        try:
-            self.set != self.other
-            self.fail("expected TypeError")
-        except TypeError:
-            pass
+    def test_eq_ne(self):
+        # Unlike the others, this is testing that == and != *are* allowed.
+        self.assertEqual(self.other == self.set, False)
+        self.assertEqual(self.set == self.other, False)
+        self.assertEqual(self.other != self.set, True)
+        self.assertEqual(self.set != self.other, True)
+
+    def test_ge_gt_lt_le(self):
+        # Unlike the others, this is testing that == and != *are* allowed.
+        self.assertRaises(TypeError, lambda: self.set < self.other)
+        self.assertRaises(TypeError, lambda: self.set <= self.other)
+        self.assertRaises(TypeError, lambda: self.set > self.other)
+        self.assertRaises(TypeError, lambda: self.set >= self.other)
 
     def test_union_update(self):
         try: