[Python-checkins] python/nondist/sandbox/datetime datetime.py,1.104,1.105 obj_time.c,1.15,1.16 test_both.py,1.81,1.82

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Sat, 14 Dec 2002 08:50:19 -0800


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

Modified Files:
	datetime.py obj_time.c test_both.py 
Log Message:
Made the timetz hash algorithms the same across the implementations; added
a timetz hash test for cases where subtracting the offset overflows a
basic time object.


Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.104
retrieving revision 1.105
diff -C2 -d -r1.104 -r1.105
*** datetime.py	14 Dec 2002 08:03:14 -0000	1.104
--- datetime.py	14 Dec 2002 16:50:15 -0000	1.105
***************
*** 975,985 ****
              return super(timetz, self).__hash__()
          h, m = divmod(self.hour * 60 + self.minute - tzoff, 60)
-         # Unfortunately it is not possible to construct a new timetz object
-         # and use super().__hash__(), since hour may exceed the range of
-         # allowed values.
          if 0 <= h < 24:
!             return hash(timetz(h, m, self.second, self.microsecond))
!         else:
!             return hash((h, m, self.second, self.microsecond))
  
      # Conversion to string
--- 975,983 ----
              return super(timetz, self).__hash__()
          h, m = divmod(self.hour * 60 + self.minute - tzoff, 60)
          if 0 <= h < 24:
!             return hash(time(h, m, self.second, self.microsecond))
!         # Unfortunately it is not possible to construct a new time object
!         # and use super().__hash__(), since hour is out-of-bounds.
!         return hash((h, m, self.second, self.microsecond))
  
      # Conversion to string

Index: obj_time.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_time.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -C2 -d -r1.15 -r1.16
*** obj_time.c	14 Dec 2002 16:23:34 -0000	1.15
--- obj_time.c	14 Dec 2002 16:50:16 -0000	1.16
***************
*** 202,205 ****
--- 202,206 ----
  		naivety n;
  		long offset;
+ 		PyObject *temp;
  
  		n = classify_object((PyObject *)self, &offset);
***************
*** 207,241 ****
  		if (n == OFFSET_ERROR)
  			return -1;
! 		if (n == OFFSET_NAIVE) {
! 			PyObject *temp = time_getstate(self);
! 			if (temp != NULL) {
! 				self->hashcode = PyObject_Hash(temp);
! 				Py_DECREF(temp);
! 			}
! 		}
  		else {
! 			long minutes;
  
  			assert(n == OFFSET_AWARE);
  			assert(PyTimeTZ_Check(self));
! 			/* It doesn't really matter what we do now, except
! 			 * that we have to ensure that timetz objects that
! 			 * compare equal have equal hashcodes.  So something
! 			 * based on subtracting offset minutes is needed.
! 			 * CAUTION:  it's not OK to return right away if
! 			 * offset==0:  we need to go thru the whole business
! 			 * below so that, e.g., a timetz with hour=5 and
! 			 * offset=-60 gets the same hash code as a timetz
! 			 * with hour=6 and offset=0.
! 			 */
! 			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;
! 
  		}
  	}
--- 208,238 ----
  		if (n == OFFSET_ERROR)
  			return -1;
! 
! 		/* Reduce this to a hash of another object. */
! 		if (offset == 0)
! 			temp = time_getstate(self);
  		else {
! 			long hour;
! 			long minute;
  
  			assert(n == OFFSET_AWARE);
  			assert(PyTimeTZ_Check(self));
! 			hour = divmod(TIME_GET_HOUR(self) * 60 +
! 					TIME_GET_MINUTE(self) - offset,
! 				      60,
! 				      &minute);
! 			if (0 <= hour && hour < 24)
! 				temp = new_time(hour, minute,
! 						TIME_GET_SECOND(self),
! 						TIME_GET_MICROSECOND(self));
! 			else
! 				temp = Py_BuildValue("iiii",
! 					   hour, minute,
! 					   TIME_GET_SECOND(self),
! 					   TIME_GET_MICROSECOND(self));
! 		}
! 		if (temp != NULL) {
! 			self->hashcode = PyObject_Hash(temp);
! 			Py_DECREF(temp);
  		}
  	}

Index: test_both.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_both.py,v
retrieving revision 1.81
retrieving revision 1.82
diff -C2 -d -r1.81 -r1.82
*** test_both.py	14 Dec 2002 09:01:24 -0000	1.81
--- test_both.py	14 Dec 2002 16:50:16 -0000	1.82
***************
*** 1581,1584 ****
--- 1581,1594 ----
  #        self.assertEqual(t3.strftime("%H:%M:%S %Z %z"), "13:47:00 MET +0100")
  
+     def test_hash_edge_cases(self):
+         # Offsets that overflow a basic time.
+         t1 = self.theclass(0, 1, 2, 3, tzinfo=FixedOffset(1439, ""))
+         t2 = self.theclass(0, 0, 2, 3, tzinfo=FixedOffset(1438, ""))
+         self.assertEqual(hash(t1), hash(t2))
+ 
+         t1 = self.theclass(23, 58, 6, 100, tzinfo=FixedOffset(-1000, ""))
+         t2 = self.theclass(23, 48, 6, 100, tzinfo=FixedOffset(-1010, ""))
+         self.assertEqual(hash(t1), hash(t2))
+ 
      def test_utc_offset_out_of_bounds(self):
          class Edgy(tzinfo):