[Python-checkins] python/nondist/sandbox/datetime datetime.py,1.154,1.155 test_datetime.py,1.107,1.108

gvanrossum@users.sourceforge.net gvanrossum@users.sourceforge.net
Thu, 30 Jan 2003 14:01:49 -0800


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

Modified Files:
	datetime.py test_datetime.py 
Log Message:
Switched the pickling strategy around again.  Never mind protocol 2 in
Python 2.3 or the copy_reg registry, we can do just as well with
__reduce__.  Pay special attention to tzinfo.__reduce__, which calls
self.__getinitargs__ and self.__getstate__ if they exist, and defaults
to self.__dict__ if it exists and is non-empty.  The other __reduce__
implementations simply recycle __getstate__.  All __reduce__
implementations return self.__class__ as the callable.


Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.154
retrieving revision 1.155
diff -C2 -d -r1.154 -r1.155
*** datetime.py	30 Jan 2003 14:54:13 -0000	1.154
--- datetime.py	30 Jan 2003 22:01:30 -0000	1.155
***************
*** 612,626 ****
  
      # Pickle support.
!     # This magic class attr is necessary for pickle compatibility with the
!     # C implementation.
!     __safe_for_unpickling__ = True
  
      def __getstate__(self):
          return (self.__days, self.__seconds, self.__microseconds)
-     __getnewargs__ = __getstate__
  
      def __setstate__(self, tup):
          self.__days, self.__seconds, self.__microseconds = tup
  
  timedelta.min = timedelta(-999999999)
  timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
--- 612,627 ----
  
      # Pickle support.
! 
!     __safe_for_unpickling__ = True      # For Python 2.2
  
      def __getstate__(self):
          return (self.__days, self.__seconds, self.__microseconds)
  
      def __setstate__(self, tup):
          self.__days, self.__seconds, self.__microseconds = tup
  
+     def __reduce__(self):
+         return (self.__class__, self.__getstate__())
+ 
  timedelta.min = timedelta(-999999999)
  timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
***************
*** 853,860 ****
      # Pickle support.
  
      def __getstate__(self):
          yhi, ylo = divmod(self.__year, 256)
          return ("%c%c%c%c" % (yhi, ylo, self.__month, self.__day), )
-     __getnewargs__ = __getstate__
  
      def __setstate__(self, t):
--- 854,862 ----
      # Pickle support.
  
+     __safe_for_unpickling__ = True      # For Python 2.2
+ 
      def __getstate__(self):
          yhi, ylo = divmod(self.__year, 256)
          return ("%c%c%c%c" % (yhi, ylo, self.__month, self.__day), )
  
      def __setstate__(self, t):
***************
*** 865,868 ****
--- 867,873 ----
          self.__year = yhi * 256 + ylo
  
+     def __reduce__(self):
+         return (self.__class__, self.__getstate__())
+ 
  _date_class = date  # so functions w/ args named "date" can get at the class
  
***************
*** 923,926 ****
--- 928,951 ----
              return dt
  
+     # Pickle support.
+ 
+     __safe_for_unpickling__ = True      # For Python 2.2
+ 
+     def __reduce__(self):
+         getinitargs = getattr(self, "__getinitargs__", None)
+         if getinitargs:
+             args = getinitargs()
+         else:
+             args = ()
+         getstate = getattr(self, "__getstate__", None)
+         if getstate:
+             state = getstate()
+         else:
+             state = getattr(self, "__dict__", None) or None
+         if state is None:
+             return (self.__class__, args)
+         else:
+             return (self.__class__, args, state)
+ 
  _tzinfo_class = tzinfo   # so functions w/ args named "tinfo" can get at it
  
***************
*** 1153,1156 ****
--- 1178,1183 ----
      # Pickle support.
  
+     __safe_for_unpickling__ = True      # For Python 2.2
+ 
      def __getstate__(self):
          us2, us3 = divmod(self.__microsecond, 256)
***************
*** 1162,1166 ****
          else:
              return (basestate, self._tzinfo)
-     __getnewargs__ = __getstate__
  
      def __setstate__(self, state):
--- 1189,1192 ----
***************
*** 1180,1183 ****
--- 1206,1212 ----
              self._tzinfo = state[1]
  
+     def __reduce__(self):
+         return (self.__class__, self.__getstate__())
+ 
  _time_class = time  # so functions w/ args named "time" can get at the class
  
***************
*** 1543,1546 ****
--- 1572,1579 ----
          return hash(timedelta(days, seconds, self.microsecond))
  
+     # Pickle support.
+ 
+     __safe_for_unpickling__ = True      # For Python 2.2
+ 
      def __getstate__(self):
          yhi, ylo = divmod(self.__year, 256)
***************
*** 1554,1558 ****
          else:
              return (basestate, self._tzinfo)
-     __getnewargs__ = __getstate__
  
      def __setstate__(self, state):
--- 1587,1590 ----
***************
*** 1573,1576 ****
--- 1605,1611 ----
              self._tzinfo = state[1]
  
+     def __reduce__(self):
+         return (self.__class__, self.__getstate__())
+ 
  
  datetime.min = datetime(1, 1, 1)
***************
*** 1589,1632 ****
          week1monday += 7
      return week1monday
- 
- # Pickle support.  __getstate__ and __setstate__ work fine on their own,
- # but only because the classes here are implemented in Python.  The C
- # implementation had to get much trickier, and the code following emulates
- # what the C code had to do, so that pickles produced by the Python
- # implementation can be read by the C implementation, and vice versa.
- 
- def _date_pickler(date):
-     state = date.__getstate__()
-     return _date_unpickler, (state,)
- 
- def _date_unpickler(state):
-     self = date(1, 1, 1)
-     self.__setstate__(state)
-     return self
- 
- def _tzinfo_pickler(tz):
-     return _tzinfo_unpickler, ()
- 
- def _tzinfo_unpickler():
-     self = tzinfo()
-     return self
- 
- def _time_pickler(tz):
-     state = tz.__getstate__()
-     return _time_unpickler, (state,)
- 
- def _time_unpickler(state):
-     self = time()
-     self.__setstate__(state)
-     return self
- 
- def _datetime_pickler(dtz):
-     state = dtz.__getstate__()
-     return _datetime_unpickler, (state,)
- 
- def _datetime_unpickler(state):
-     self = datetime(1, 1, 1)
-     self.__setstate__(state)
-     return self
  
  """
--- 1624,1627 ----

Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.107
retrieving revision 1.108
diff -C2 -d -r1.107 -r1.108
*** test_datetime.py	30 Jan 2003 06:01:07 -0000	1.107
--- test_datetime.py	30 Jan 2003 22:01:39 -0000	1.108
***************
*** 5,8 ****
--- 5,10 ----
  
  import sys
+ import pickle
+ import cPickle
  import unittest
  
***************
*** 14,17 ****
--- 16,35 ----
  
  
+ pickle_choices = [
+     (pickle, pickle, 0),
+     (pickle, pickle, 1),
+     (pickle, pickle, 2),
+     (cPickle, cPickle, 0),
+     (cPickle, cPickle, 1),
+ ##    (cPickle, cPickle, 2),
+     (pickle, cPickle, 0),
+     (pickle, cPickle, 1),
+ ##    (pickle, cPickle, 2),
+     (cPickle, pickle, 0),
+     (cPickle, pickle, 1),
+ ##    (cPickle, pickle, 2),
+     ]
+ 
+ 
  # XXX The test suite uncovered a bug in Python 2.2.2:  if x and y are
  # XXX instances of new-style classes (like date and time) that both
***************
*** 99,104 ****
  
      def test_pickling_base(self):
-         import pickle, cPickle
- 
          # There's no point to pickling tzinfo objects on their own (they
          # carry no data), but they need to be picklable anyway else
--- 117,120 ----
***************
*** 106,118 ****
          orig = tzinfo.__new__(tzinfo)
          self.failUnless(type(orig) is tzinfo)
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.failUnless(type(derived) is tzinfo)
  
      def test_pickling_subclass(self):
-         import pickle, cPickle
- 
          # Make sure we can pickle/unpickle an instance of a subclass.
          offset = timedelta(minutes=-300)
--- 122,131 ----
          orig = tzinfo.__new__(tzinfo)
          self.failUnless(type(orig) is tzinfo)
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.failUnless(type(derived) is tzinfo)
  
      def test_pickling_subclass(self):
          # Make sure we can pickle/unpickle an instance of a subclass.
          offset = timedelta(minutes=-300)
***************
*** 122,129 ****
          self.assertEqual(orig.utcoffset(None), offset)
          self.assertEqual(orig.tzname(None), 'cookie')
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.failUnless(isinstance(derived, tzinfo))
                  self.failUnless(type(derived) is PicklableFixedOffset)
--- 135,141 ----
          self.assertEqual(orig.utcoffset(None), offset)
          self.assertEqual(orig.tzname(None), 'cookie')
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.failUnless(isinstance(derived, tzinfo))
                  self.failUnless(type(derived) is PicklableFixedOffset)
***************
*** 263,267 ****
  
      def test_pickling(self):
-         import pickle, cPickle
          args = 12, 34, 56
          orig = timedelta(*args)
--- 275,278 ----
***************
*** 271,278 ****
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.assertEqual(orig, derived)
  
--- 282,288 ----
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.assertEqual(orig, derived)
  
***************
*** 822,837 ****
  
      def test_pickling(self):
-         import pickle, cPickle
          args = 6, 7, 23
          orig = self.theclass(*args)
          state = orig.__getstate__()
!         self.assertEqual(state, ('\x00\x06\x07\x17',))
          derived = self.theclass(1, 1, 1)
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.assertEqual(orig, derived)
  
--- 832,845 ----
  
      def test_pickling(self):
          args = 6, 7, 23
          orig = self.theclass(*args)
          state = orig.__getstate__()
!         self.assertEqual(state, ('\x00\x06\x07\x17',), self.theclass)
          derived = self.theclass(1, 1, 1)
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.assertEqual(orig, derived)
  
***************
*** 1181,1185 ****
  
      def test_pickling(self):
-         import pickle, cPickle
          args = 6, 7, 23, 20, 59, 1, 64**2
          orig = self.theclass(*args)
--- 1189,1192 ----
***************
*** 1189,1196 ****
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.assertEqual(orig, derived)
  
--- 1196,1202 ----
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.assertEqual(orig, derived)
  
***************
*** 1567,1571 ****
  
      def test_pickling(self):
-         import pickle, cPickle
          args = 20, 59, 16, 64**2
          orig = self.theclass(*args)
--- 1573,1576 ----
***************
*** 1575,1582 ****
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.assertEqual(orig, derived)
  
--- 1580,1586 ----
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.assertEqual(orig, derived)
  
***************
*** 1881,1886 ****
  
      def test_pickling(self):
-         import pickle, cPickle
- 
          # Try one without a tzinfo.
          args = 20, 59, 16, 64**2
--- 1885,1888 ----
***************
*** 1891,1898 ****
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.assertEqual(orig, derived)
  
--- 1893,1899 ----
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.assertEqual(orig, derived)
  
***************
*** 1908,1915 ****
          self.assertEqual(derived.tzname(), 'cookie')
  
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.assertEqual(orig, derived)
                  self.failUnless(isinstance(derived.tzinfo,
--- 1909,1915 ----
          self.assertEqual(derived.tzname(), 'cookie')
  
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.assertEqual(orig, derived)
                  self.failUnless(isinstance(derived.tzinfo,
***************
*** 2100,2105 ****
  
      def test_pickling(self):
-         import pickle, cPickle
- 
          # Try one without a tzinfo.
          args = 6, 7, 23, 20, 59, 1, 64**2
--- 2100,2103 ----
***************
*** 2110,2117 ****
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.assertEqual(orig, derived)
  
--- 2108,2114 ----
          derived.__setstate__(state)
          self.assertEqual(orig, derived)
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.assertEqual(orig, derived)
  
***************
*** 2127,2134 ****
          self.assertEqual(derived.tzname(), 'cookie')
  
!         for pickler in pickle, cPickle:
!             for proto in 0, 1, 2:
                  green = pickler.dumps(orig, proto)
!                 derived = pickler.loads(green)
                  self.assertEqual(orig, derived)
                  self.failUnless(isinstance(derived.tzinfo,
--- 2124,2130 ----
          self.assertEqual(derived.tzname(), 'cookie')
  
!         for pickler, unpickler, proto in pickle_choices:
                  green = pickler.dumps(orig, proto)
!                 derived = unpickler.loads(green)
                  self.assertEqual(orig, derived)
                  self.failUnless(isinstance(derived.tzinfo,