Fixed #22363 -- Correctly serialize `django.utils.datetime_safe` objects.

Thanks to linovia for the report.
This commit is contained in:
Simon Charette 2014-03-31 16:16:34 -04:00
parent 0f6ea69e27
commit 074d3183d9
2 changed files with 18 additions and 4 deletions

View File

@ -11,9 +11,9 @@ import types
from django.apps import apps from django.apps import apps
from django.db import models from django.db import models
from django.db.migrations.loader import MigrationLoader from django.db.migrations.loader import MigrationLoader
from django.utils import datetime_safe, six
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.functional import Promise from django.utils.functional import Promise
from django.utils import six
class SettingsReference(str): class SettingsReference(str):
@ -215,10 +215,16 @@ class MigrationWriter(object):
elif isinstance(value, datetime.datetime): elif isinstance(value, datetime.datetime):
if value.tzinfo is not None: if value.tzinfo is not None:
raise ValueError("Cannot serialize datetime values with timezones. Either use a callable value for default or remove the timezone.") raise ValueError("Cannot serialize datetime values with timezones. Either use a callable value for default or remove the timezone.")
return repr(value), set(["import datetime"]) value_repr = repr(value)
if isinstance(value, datetime_safe.datetime):
value_repr = "datetime.%s" % value_repr
return value_repr, set(["import datetime"])
# Dates # Dates
elif isinstance(value, datetime.date): elif isinstance(value, datetime.date):
return repr(value), set(["import datetime"]) value_repr = repr(value)
if isinstance(value, datetime_safe.date):
value_repr = "datetime.%s" % value_repr
return value_repr, set(["import datetime"])
# Settings references # Settings references
elif isinstance(value, SettingsReference): elif isinstance(value, SettingsReference):
return "settings.%s" % value.setting_name, set(["from django.conf import settings"]) return "settings.%s" % value.setting_name, set(["from django.conf import settings"])

View File

@ -10,7 +10,7 @@ from django.db import models, migrations
from django.db.migrations.writer import MigrationWriter, SettingsReference from django.db.migrations.writer import MigrationWriter, SettingsReference
from django.test import TestCase from django.test import TestCase
from django.conf import settings from django.conf import settings
from django.utils import six from django.utils import datetime_safe, six
from django.utils.deconstruct import deconstructible from django.utils.deconstruct import deconstructible
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.timezone import get_default_timezone from django.utils.timezone import get_default_timezone
@ -81,6 +81,14 @@ class WriterTests(TestCase):
self.assertSerializedEqual(datetime.date.today) self.assertSerializedEqual(datetime.date.today)
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
self.assertSerializedEqual(datetime.datetime(2012, 1, 1, 1, 1, tzinfo=get_default_timezone())) self.assertSerializedEqual(datetime.datetime(2012, 1, 1, 1, 1, tzinfo=get_default_timezone()))
safe_date = datetime_safe.date(2014, 3, 31)
string, imports = MigrationWriter.serialize(safe_date)
self.assertEqual(string, repr(datetime.date(2014, 3, 31)))
self.assertEqual(imports, {'import datetime'})
safe_datetime = datetime_safe.datetime(2014, 3, 31, 16, 4, 31)
string, imports = MigrationWriter.serialize(safe_datetime)
self.assertEqual(string, repr(datetime.datetime(2014, 3, 31, 16, 4, 31)))
self.assertEqual(imports, {'import datetime'})
# Classes # Classes
validator = RegexValidator(message="hello") validator = RegexValidator(message="hello")
string, imports = MigrationWriter.serialize(validator) string, imports = MigrationWriter.serialize(validator)