From 1b7046b99e2369175c19532a788e722daf7c65f0 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Wed, 23 Jun 2010 21:40:15 +0000 Subject: [PATCH] Issue #9051: Instances of timezone class can now be pickled. --- Lib/test/test_datetime.py | 33 +++++++++++++++++++-------------- Modules/datetimemodule.c | 11 +++++++++++ Python/Python-ast.c | 4 ++-- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py index b86c020bb30..7048a11d24f 100644 --- a/Lib/test/test_datetime.py +++ b/Lib/test/test_datetime.py @@ -19,8 +19,8 @@ from datetime import timezone from datetime import date, datetime import time as _time -pickle_choices = [(pickle, pickle, proto) for proto in range(3)] -assert len(pickle_choices) == 3 +pickle_choices = [(pickle, pickle, proto) for proto in range(4)] +assert len(pickle_choices) == 4 # An arbitrary collection of objects of non-datetime types, for testing # mixed-type comparisons. @@ -122,18 +122,23 @@ class TestTZInfo(unittest.TestCase): def test_pickling_subclass(self): # Make sure we can pickle/unpickle an instance of a subclass. offset = timedelta(minutes=-300) - orig = PicklableFixedOffset(offset, 'cookie') - self.assertIsInstance(orig, tzinfo) - self.assertTrue(type(orig) is PicklableFixedOffset) - 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.assertIsInstance(derived, tzinfo) - self.assertTrue(type(derived) is PicklableFixedOffset) - self.assertEqual(derived.utcoffset(None), offset) - self.assertEqual(derived.tzname(None), 'cookie') + for otype, args in [ + (PicklableFixedOffset, (offset, 'cookie')), + (timezone, (offset,)), + (timezone, (offset, "EST"))]: + orig = otype(*args) + oname = orig.tzname(None) + self.assertIsInstance(orig, tzinfo) + self.assertIs(type(orig), otype) + self.assertEqual(orig.utcoffset(None), offset) + self.assertEqual(orig.tzname(None), oname) + for pickler, unpickler, proto in pickle_choices: + green = pickler.dumps(orig, proto) + derived = unpickler.loads(green) + self.assertIsInstance(derived, tzinfo) + self.assertIs(type(derived), otype) + self.assertEqual(derived.utcoffset(None), offset) + self.assertEqual(derived.tzname(None), oname) class TestTimeZone(unittest.TestCase): diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 8b3cc06e7c7..507d2bb4e64 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -3469,6 +3469,14 @@ timezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt) return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1); } +static PyObject * +timezone_getinitargs(PyDateTime_TimeZone *self) +{ + if (self->name == NULL) + return Py_BuildValue("(O)", self->offset); + return Py_BuildValue("(OO)", self->offset, self->name); +} + static PyMethodDef timezone_methods[] = { {"tzname", (PyCFunction)timezone_tzname, METH_O, PyDoc_STR("If name is specified when timezone is created, returns the name." @@ -3483,6 +3491,9 @@ static PyMethodDef timezone_methods[] = { {"fromutc", (PyCFunction)timezone_fromutc, METH_O, PyDoc_STR("datetime in UTC -> datetime in local time.")}, + {"__getinitargs__", (PyCFunction)timezone_getinitargs, METH_NOARGS, + PyDoc_STR("pickle support")}, + {NULL, NULL} }; diff --git a/Python/Python-ast.c b/Python/Python-ast.c index bedd7d7de71..54c4e0160d0 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 73626. + __version__ 82163. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6773,7 +6773,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "73626") < 0) + if (PyModule_AddStringConstant(m, "__version__", "82163") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL;