Cache FixedOffsetTimezone instances

Avoid creating new a new FixedOffsetTimezone instance if one with the
same offset and name has been created before. This will save memory
when returning many rows containing "timestamp with timezone" columns,
and also improves comparability.
This commit is contained in:
Menno Smits 2012-01-25 16:23:19 +00:00 committed by Daniele Varrazzo
parent 1469a56512
commit bca7200b3f
2 changed files with 27 additions and 1 deletions

View File

@ -38,17 +38,36 @@ class FixedOffsetTimezone(datetime.tzinfo):
with a small change to the `!__init__()` method to allow for pickling with a small change to the `!__init__()` method to allow for pickling
and a default name in the form ``sHH:MM`` (``s`` is the sign.). and a default name in the form ``sHH:MM`` (``s`` is the sign.).
The implementation also caches instances. During creation, if a
FixedOffsetTimezone instance has previously been created with the same
offset and name that instance will be returned. This saves memory and
improves comparability.
.. __: http://docs.python.org/library/datetime.html#datetime-tzinfo .. __: http://docs.python.org/library/datetime.html#datetime-tzinfo
""" """
_name = None _name = None
_offset = ZERO _offset = ZERO
_cache = {}
def __init__(self, offset=None, name=None): def __init__(self, offset=None, name=None):
if offset is not None: if offset is not None:
self._offset = datetime.timedelta(minutes = offset) self._offset = datetime.timedelta(minutes = offset)
if name is not None: if name is not None:
self._name = name self._name = name
def __new__(cls, offset=None, name=None):
"""Return a suitable instance created earlier if it exists
"""
key = (offset, name)
try:
return cls._cache[key]
except KeyError:
tz = datetime.tzinfo.__new__(cls, offset, name)
tz.__init__(offset, name)
cls._cache[key] = tz
return tz
def __repr__(self): def __repr__(self):
offset_mins = self._offset.seconds // 60 + self._offset.days * 24 * 60 offset_mins = self._offset.seconds // 60 + self._offset.days * 24 * 60
return "psycopg2.tz.FixedOffsetTimezone(offset=%r, name=%r)" \ return "psycopg2.tz.FixedOffsetTimezone(offset=%r, name=%r)" \

View File

@ -532,6 +532,13 @@ class FixedOffsetTimezoneTests(unittest.TestCase):
tzinfo = FixedOffsetTimezone(name="FOO") tzinfo = FixedOffsetTimezone(name="FOO")
self.assertEqual(repr(tzinfo), "psycopg2.tz.FixedOffsetTimezone(offset=0, name='FOO')") self.assertEqual(repr(tzinfo), "psycopg2.tz.FixedOffsetTimezone(offset=0, name='FOO')")
def test_instance_caching(self):
self.assert_(FixedOffsetTimezone(name="FOO") is FixedOffsetTimezone(name="FOO"))
self.assert_(FixedOffsetTimezone(7 * 60) is FixedOffsetTimezone(7 * 60))
self.assert_(FixedOffsetTimezone(-9 * 60, 'FOO') is FixedOffsetTimezone(-9 * 60, 'FOO'))
self.assert_(FixedOffsetTimezone(9 * 60) is not FixedOffsetTimezone(9 * 60, 'FOO'))
self.assert_(FixedOffsetTimezone(name='FOO') is not FixedOffsetTimezone(9 * 60, 'FOO'))
def test_suite(): def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__) return unittest.TestLoader().loadTestsFromName(__name__)