[Python-checkins] python/nondist/sandbox/datetime datetime.py,1.102,1.103 obj_datetime.c,1.52,1.53 test_both.py,1.75,1.76

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Fri, 13 Dec 2002 17:33:59 -0800


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

Modified Files:
	datetime.py obj_datetime.c test_both.py 
Log Message:
Repaired Python datetimetz.__hash__ overflow cases; implemented
C datetimetz.__hash__.


Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.102
retrieving revision 1.103
diff -C2 -d -r1.102 -r1.103
*** datetime.py	14 Dec 2002 00:35:04 -0000	1.102
--- datetime.py	14 Dec 2002 01:33:57 -0000	1.103
***************
*** 1527,1536 ****
      def __hash__(self):
          tzoff = self.utcoffset()
!         if not tzoff: # zero or None!
              return super(datetimetz, self).__hash__()
!         # XXX The rest is broken:  can cause OverflowError on the low and
!         # XXX high ends.
!         t = self - timedelta(minutes=tzoff)
!         return super(datetimetz, t).__hash__()
  
      def __getstate__(self):
--- 1527,1535 ----
      def __hash__(self):
          tzoff = self.utcoffset()
!         if tzoff is None:
              return super(datetimetz, self).__hash__()
!         days = _ymd2ord(self.year, self.month, self.day)
!         seconds = self.hour * 3600 + (self.minute - tzoff) * 60 + self.second
!         return hash(timedelta(days, seconds, self.microsecond))
  
      def __getstate__(self):

Index: obj_datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_datetime.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -C2 -d -r1.52 -r1.53
*** obj_datetime.c	14 Dec 2002 01:14:32 -0000	1.52
--- obj_datetime.c	14 Dec 2002 01:33:57 -0000	1.53
***************
*** 498,502 ****
  		}
  		else {
! 			long minutes;
  
  			assert(n == OFFSET_AWARE);
--- 498,504 ----
  		}
  		else {
! 			long days;
! 			long seconds;
! 			PyDateTime_Delta *delta;
  
  			assert(n == OFFSET_AWARE);
***************
*** 512,525 ****
  			 * with hour=6 and offset=0.
  			 */
! 			/* XXX This code makes no sense -- repair it. */
! 			minutes = TIME_GET_HOUR(self) * 60L +
! 				  TIME_GET_MINUTE(self) - offset;
! 			/* The multipliers below are arbitrary. */
! 			self->hashcode = minutes * 3601L +
! 					 TIME_GET_SECOND(self) * 61L +
! 					 TIME_GET_MICROSECOND(self);
! 			if (self->hashcode == -1)
! 				self->hashcode = -2;
! 
  		}
  	}
--- 514,531 ----
  			 * with hour=6 and offset=0.
  			 */
! 			days = ymd_to_ord(GET_YEAR(self),
! 					  GET_MONTH(self),
! 					  GET_DAY(self));
! 			seconds = DATE_GET_HOUR(self) * 3600L +
! 				  (DATE_GET_MINUTE(self) - offset) * 60L +
! 				  DATE_GET_SECOND(self);
! 			delta = (PyDateTime_Delta *)new_delta(days,
! 						seconds,
! 						DATE_GET_MICROSECOND(self),
! 						1);
! 			if (delta == NULL)
! 				return -1;
! 			self->hashcode = delta_hash(delta);
! 			Py_DECREF(delta);
  		}
  	}

Index: test_both.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_both.py,v
retrieving revision 1.75
retrieving revision 1.76
diff -C2 -d -r1.75 -r1.76
*** test_both.py	14 Dec 2002 00:49:39 -0000	1.75
--- test_both.py	14 Dec 2002 01:33:57 -0000	1.76
***************
*** 1882,1885 ****
--- 1882,1896 ----
                  self.assertEqual(derived.tzname(), 'cookie')
  
+     def test_extreme_hashes(self):
+         # If an attempt is made to hash these via subtracting the offset
+         # then hashing a datetime object, OverflowError results.  The
+         # Python implementation used to blow up here.
+         t = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, ""))
+         hash(t)
+         t = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999,
+                           tzinfo=FixedOffset(-1439, ""))
+         hash(t)
+ 
+ 
  def test_suite():
      allsuites = [unittest.makeSuite(klass, 'test')