[Checkins] SVN: DateTime/trunk/ Make DateTime a new-style class and limit its available attributes via a slots definition. The pickle size increases to 110 bytes thanks to the `ccopy_reg\n_reconstructor` stanza. But the memory size drops from 3kb to 500 bytes for each instance.

Hanno Schlichting hannosch at hannosch.eu
Sun May 8 07:13:06 EDT 2011


Log message for revision 121577:
  Make DateTime a new-style class and limit its available attributes via a slots definition. The pickle size increases to 110 bytes thanks to the `ccopy_reg\n_reconstructor` stanza. But the memory size drops from 3kb to 500 bytes for each instance.
  

Changed:
  U   DateTime/trunk/CHANGES.txt
  U   DateTime/trunk/src/DateTime/DateTime.py
  U   DateTime/trunk/src/DateTime/DateTime.txt
  U   DateTime/trunk/src/DateTime/tests/testDateTime.py

-=-
Modified: DateTime/trunk/CHANGES.txt
===================================================================
--- DateTime/trunk/CHANGES.txt	2011-05-08 10:42:32 UTC (rev 121576)
+++ DateTime/trunk/CHANGES.txt	2011-05-08 11:13:05 UTC (rev 121577)
@@ -4,6 +4,10 @@
 3.0 (unreleased)
 ----------------
 
+- Make DateTime a new-style class and limit its available attributes via a
+  slots definition. The pickle size increases to 110 bytes thanks to the
+  `ccopy_reg\n_reconstructor` stanza. But the memory size drops from 3kb to
+  500 bytes for each instance.
 
 3.0a1 (2011-05-06)
 ------------------

Modified: DateTime/trunk/src/DateTime/DateTime.py
===================================================================
--- DateTime/trunk/src/DateTime/DateTime.py	2011-05-08 10:42:32 UTC (rev 121576)
+++ DateTime/trunk/src/DateTime/DateTime.py	2011-05-08 11:13:05 UTC (rev 121577)
@@ -281,7 +281,7 @@
     return "%+03d:%02d" % divmod( (seconds/60), 60)
 
 
-class DateTime:
+class DateTime(object):
     """DateTime objects represent instants in time and provide
        interfaces for controlling its representation without
        affecting the absolute value of the object.
@@ -327,8 +327,8 @@
     implements(IDateTime)
 
     # For security machinery:
-    __roles__=None
-    __allow_access_to_unprotected_subobjects__=1
+    __roles__ = None
+    __allow_access_to_unprotected_subobjects__ = 1
 
     # Make class-specific exceptions available as attributes.
     DateError = DateError
@@ -336,6 +336,38 @@
     DateTimeError = DateTimeError
     SyntaxError = SyntaxError
 
+    # Limit the amount of instance attributes
+    __slots__ = (
+        '_timezone_naive',
+        '_tz',
+        '_pm',
+        '_pmhour',
+        '_dayoffset',
+        '_fmon',
+        '_amon',
+        '_pmon',
+        '_months',
+        '_months_a',
+        '_months_p',
+        '_fday',
+        '_aday',
+        '_pday',
+        '_days',
+        '_days_a',
+        '_days_p',
+        '_year',
+        '_month',
+        '_day',
+        '_hour',
+        '_minute',
+        '_second',
+        '_nearsec',
+        '_d',
+        '_t',
+        '_micros',
+        'time',
+    )
+
     def __init__(self, *args, **kw):
         """Return a new date-time object"""
         if args and args[0] is None:
@@ -349,20 +381,17 @@
             raise SyntaxError('Unable to parse %s, %s' % (args, kw))
 
     def __getstate__(self):
-        state = self.__dict__
-        return (state['_micros'] / 1000000.0,
-            state.get('_timezone_naive', False),
-            state['_tz'])
+        return (self._micros / 1000000.0, self._timezone_naive, self._tz)
 
     def __setstate__(self, value):
-        state = self.__dict__
         if isinstance(value, tuple):
             self._parse_args(value[0], value[2])
-            state['_micros'] = long(value[0] * 1000000)
-            state['_timezone_naive'] = value[1]
+            self._micros = long(value[0] * 1000000)
+            self._timezone_naive = value[1]
         else:
-            state.clear()
-            state.update(value)
+            for k,v in value.items():
+                if k in self.__slots__:
+                    setattr(self, k, v)
 
     def _parse_args(self, *args, **kw):
         """Return a new date-time object.
@@ -1050,7 +1079,7 @@
     def __getattr__(self, name):
         if '%' in name:
             return strftimeFormatter(self, name)
-        raise AttributeError, name
+        raise AttributeError(name)
 
     # Conversion and comparison methods
     def timeTime(self):

Modified: DateTime/trunk/src/DateTime/DateTime.txt
===================================================================
--- DateTime/trunk/src/DateTime/DateTime.txt	2011-05-08 10:42:32 UTC (rev 121576)
+++ DateTime/trunk/src/DateTime/DateTime.txt	2011-05-08 11:13:05 UTC (rev 121577)
@@ -758,7 +758,7 @@
   >>> 1 - dt
   Traceback (most recent call last):
   ...
-  TypeError: unsupported operand type(s) for -: 'int' and 'instance'
+  TypeError: unsupported operand type(s) for -: 'int' and 'DateTime'
 
 DateTimes can also be converted to integers (number of seconds since
 the epoch), longs (not too long ;)) and floats:

Modified: DateTime/trunk/src/DateTime/tests/testDateTime.py
===================================================================
--- DateTime/trunk/src/DateTime/tests/testDateTime.py	2011-05-08 10:42:32 UTC (rev 121576)
+++ DateTime/trunk/src/DateTime/tests/testDateTime.py	2011-05-08 11:13:05 UTC (rev 121577)
@@ -202,19 +202,22 @@
         dt = DateTime()
         data = cPickle.dumps(dt, 1)
         new = cPickle.loads(data)
-        self.assertEqual(dt.__dict__, new.__dict__)
+        for key in DateTime.__slots__:
+            self.assertEqual(getattr(dt, key), getattr(new, key))
 
     def test_pickle_with_tz(self):
         dt = DateTime('2002/5/2 8:00am GMT+8')
         data = cPickle.dumps(dt, 1)
         new = cPickle.loads(data)
-        self.assertEqual(dt.__dict__, new.__dict__)
+        for key in DateTime.__slots__:
+            self.assertEqual(getattr(dt, key), getattr(new, key))
 
     def test_pickle_with_micros(self):
         dt = DateTime('2002/5/2 8:00:14.123 GMT+8')
         data = cPickle.dumps(dt, 1)
         new = cPickle.loads(data)
-        self.assertEqual(dt.__dict__, new.__dict__)
+        for key in DateTime.__slots__:
+            self.assertEqual(getattr(dt, key), getattr(new, key))
 
     def test_pickle_old(self):
         dt = DateTime('2002/5/2 8:00am GMT+0')
@@ -231,7 +234,8 @@
             '\x00U\x07_pmhourq\x1dK\x08U\n_dayoffsetq\x1eK\x04U\x04timeq'
             '\x1fG?\xd5UUUV\x00\x00ub.')
         new = cPickle.loads(data)
-        self.assertEqual(dt.__dict__, new.__dict__)
+        for key in DateTime.__slots__:
+            self.assertEqual(getattr(dt, key), getattr(new, key))
 
     def testTZ2(self):
         # Time zone manipulation test 2



More information about the checkins mailing list