[Python-checkins] python/nondist/sandbox/datetime datetime.py,1.151,1.152 test_datetime.py,1.103,1.104

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Fri, 24 Jan 2003 10:56:41 -0800


Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv16915

Modified Files:
	datetime.py test_datetime.py 
Log Message:
date and datetime comparison:  when we don't know how to
compare against "the other" argument, we raise TypeError,
in order to prevent comparison from falling back to the
default (and worse than useless, in this case) comparison
by object address.

That's fine so far as it goes, but leaves no way for
another date/datetime object to make itself comparable
to our objects.  For example, it leaves Marc-Andre no way
to teach mxDateTime dates how to compare against Python
dates.

Discussion on Python-Dev raised a number of impractical
ideas, and the simple one implemented here:  when we don't
know how to compare against "the other" argument, we raise
TypeError *unless* the other object has a timetuple attr.
In that case, we return NotImplemented instead, and Python
will give the other object a shot at handling the
comparison then.

Note that comparisons of time and timedelta objects still
suffer the original problem, though.


Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.151
retrieving revision 1.152
diff -C2 -d -r1.151 -r1.152
*** datetime.py	24 Jan 2003 02:36:46 -0000	1.151
--- datetime.py	24 Jan 2003 18:56:35 -0000	1.152
***************
*** 762,765 ****
--- 762,767 ----
              y2, m2, d2 = other.__year, other.__month, other.__day
              return cmp((y, m, d), (y2, m2, d2))
+         elif hasattr(other, "timetuple"):
+             return NotImplemented
          else:
              raise TypeError, ("can't compare date to %s instance" %
***************
*** 1434,1440 ****
      def __cmp__(self, other):
          if not isinstance(other, datetime):
!             # XXX Buggy in 2.2.2.
!             raise TypeError("can't compare '%s' to '%s'" % (
!                             type(self).__name__, type(other).__name__))
          mytz = self._tzinfo
          ottz = other._tzinfo
--- 1436,1445 ----
      def __cmp__(self, other):
          if not isinstance(other, datetime):
!             if hasattr(other, "timetuple"):
!                 return NotImplemented
!             else:
!                 # XXX Buggy in 2.2.2.
!                 raise TypeError("can't compare '%s' to '%s'" % (
!                                 type(self).__name__, type(other).__name__))
          mytz = self._tzinfo
          ottz = other._tzinfo

Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.103
retrieving revision 1.104
diff -C2 -d -r1.103 -r1.104
*** test_datetime.py	23 Jan 2003 21:22:14 -0000	1.103
--- test_datetime.py	24 Jan 2003 18:56:36 -0000	1.104
***************
*** 879,882 ****
--- 879,914 ----
              self.assertRaises(TypeError, lambda: badarg >= t1)
  
+     def test_mixed_compare(self):
+         our = self.theclass(2000, 4, 5)
+         self.assertRaises(TypeError, cmp, our, 1)
+         self.assertRaises(TypeError, cmp, 1, our)
+ 
+         class AnotherDateTimeClass(object):
+             def __cmp__(self, other):
+                 # Return "equal" so calling this can't be confused with
+                 # compare-by-address (which never says "equal" for distinct
+                 # objects).
+                 return 0
+ 
+         # This still errors, because date and datetime comparison raise
+         # TypeError instead of NotImplemented when they don't know what to
+         # do, in order to stop comparison from falling back to the default
+         # compare-by-address.
+         their = AnotherDateTimeClass()
+         self.assertRaises(TypeError, cmp, our, their)
+         self.assertEqual(cmp(their, our), 0)
+ 
+         # But date and datetime comparison aise NotImplemented instead if the
+         # other object has a timetuple attr.
+         class Comparable(AnotherDateTimeClass):
+             def timetuple(self):
+                 return ()
+ 
+         their = Comparable()
+         self.assertEqual(cmp(our, their), 0)
+         self.assertEqual(cmp(their, our), 0)
+         self.failUnless(our == their)
+         self.failUnless(their == our)
+ 
      def test_bool(self):
          # All dates are considered true.