From f5f2e2c092ced4b41379496cb7b447a12ec3e387 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 21 Oct 2012 21:12:02 +0100 Subject: [PATCH 1/3] Dropped redundant call to FixedOffsetTimezone.__init__ --- lib/tz.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/tz.py b/lib/tz.py index cc99025b..a9adcd8f 100644 --- a/lib/tz.py +++ b/lib/tz.py @@ -64,7 +64,6 @@ class FixedOffsetTimezone(datetime.tzinfo): return cls._cache[key] except KeyError: tz = datetime.tzinfo.__new__(cls, offset, name) - tz.__init__(offset, name) cls._cache[key] = tz return tz From a33c0670fd1d6e3f5b9fbec20fef8e9e835b67a7 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 21 Oct 2012 21:16:52 +0100 Subject: [PATCH 2/3] More idiomatic way to call FixedOffsetTimezone.__new__ superclass --- lib/tz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tz.py b/lib/tz.py index a9adcd8f..ec63f6c0 100644 --- a/lib/tz.py +++ b/lib/tz.py @@ -63,7 +63,7 @@ class FixedOffsetTimezone(datetime.tzinfo): try: return cls._cache[key] except KeyError: - tz = datetime.tzinfo.__new__(cls, offset, name) + tz = super(FixedOffsetTimezone, cls).__new__(cls, offset, name) cls._cache[key] = tz return tz From 1feb179fba9a569731d047ae2d4de848e35fc58f Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 21 Oct 2012 21:47:32 +0100 Subject: [PATCH 3/3] Fixed pickling of FixedOffsetTimezone objects I have also verified that the fixed class can unpickle instance pickled with the buggy one and viceversa. Fixes ticket #135. --- NEWS | 1 + lib/tz.py | 7 +++++-- tests/test_dates.py | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index cde58b69..0efd9622 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,7 @@ What's new in psycopg 2.4.6 - connect() raises an exception instead of swallowing keyword arguments when a connection string is specified as well (ticket #131). - Discard any result produced by 'executemany()' (ticket #133). + - Fixed pickling of FixedOffsetTimezone objects (ticket #135). - 'errorcodes' map updated to PostgreSQL 9.2. diff --git a/lib/tz.py b/lib/tz.py index ec63f6c0..695a9253 100644 --- a/lib/tz.py +++ b/lib/tz.py @@ -72,6 +72,10 @@ class FixedOffsetTimezone(datetime.tzinfo): return "psycopg2.tz.FixedOffsetTimezone(offset=%r, name=%r)" \ % (offset_mins, self._name) + def __getinitargs__(self): + offset_mins = self._offset.seconds // 60 + self._offset.days * 24 * 60 + return (offset_mins, self._name) + def utcoffset(self, dt): return self._offset @@ -86,7 +90,7 @@ class FixedOffsetTimezone(datetime.tzinfo): return "%+03d:%d" % (hours, minutes) else: return "%+03d" % hours - + def dst(self, dt): return ZERO @@ -103,7 +107,6 @@ class LocalTimezone(datetime.tzinfo): This is the exact implementation from the Python 2.3 documentation. """ - def utcoffset(self, dt): if self._isdst(dt): return DSTOFFSET diff --git a/tests/test_dates.py b/tests/test_dates.py index 9be68a2c..0d18f663 100755 --- a/tests/test_dates.py +++ b/tests/test_dates.py @@ -539,6 +539,24 @@ class FixedOffsetTimezoneTests(unittest.TestCase): self.assert_(FixedOffsetTimezone(9 * 60) is not FixedOffsetTimezone(9 * 60, 'FOO')) self.assert_(FixedOffsetTimezone(name='FOO') is not FixedOffsetTimezone(9 * 60, 'FOO')) + def test_pickle(self): + # ticket #135 + import pickle + + tz11 = FixedOffsetTimezone(60) + tz12 = FixedOffsetTimezone(120) + for proto in [-1, 0, 1, 2]: + tz21, tz22 = pickle.loads(pickle.dumps([tz11, tz12], proto)) + self.assertEqual(tz11, tz21) + self.assertEqual(tz12, tz22) + + tz11 = FixedOffsetTimezone(60, name='foo') + tz12 = FixedOffsetTimezone(120, name='bar') + for proto in [-1, 0, 1, 2]: + tz21, tz22 = pickle.loads(pickle.dumps([tz11, tz12], proto)) + self.assertEqual(tz11, tz21) + self.assertEqual(tz12, tz22) + def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__)