Kaydet (Commit) c72dde41 authored tarafından Tim Graham's avatar Tim Graham

Fixed #29595 -- Allowed using timedelta in migrations questioner.

Refs #29600 -- Removed usage of django.utils.datetime_safe in migrations.
üst 3af695ed
import datetime
import importlib import importlib
import os import os
import sys import sys
from django.apps import apps from django.apps import apps
from django.db.models.fields import NOT_PROVIDED from django.db.models.fields import NOT_PROVIDED
from django.utils import datetime_safe, timezone from django.utils import timezone
from .loader import MigrationLoader from .loader import MigrationLoader
...@@ -135,7 +136,7 @@ class InteractiveMigrationQuestioner(MigrationQuestioner): ...@@ -135,7 +136,7 @@ class InteractiveMigrationQuestioner(MigrationQuestioner):
sys.exit(1) sys.exit(1)
else: else:
try: try:
return eval(code, {}, {"datetime": datetime_safe, "timezone": timezone}) return eval(code, {}, {'datetime': datetime, 'timezone': timezone})
except (SyntaxError, NameError) as e: except (SyntaxError, NameError) as e:
print("Invalid input: %s" % e) print("Invalid input: %s" % e)
......
...@@ -12,7 +12,6 @@ import uuid ...@@ -12,7 +12,6 @@ import uuid
from django.db import models from django.db import models
from django.db.migrations.operations.base import Operation from django.db.migrations.operations.base import Operation
from django.db.migrations.utils import COMPILED_REGEX_TYPE, RegexObject from django.db.migrations.utils import COMPILED_REGEX_TYPE, RegexObject
from django.utils import datetime_safe
from django.utils.functional import LazyObject, Promise from django.utils.functional import LazyObject, Promise
from django.utils.timezone import utc from django.utils.timezone import utc
from django.utils.version import get_docs_version from django.utils.version import get_docs_version
...@@ -46,25 +45,21 @@ class BaseSimpleSerializer(BaseSerializer): ...@@ -46,25 +45,21 @@ class BaseSimpleSerializer(BaseSerializer):
return repr(self.value), set() return repr(self.value), set()
class DatetimeSerializer(BaseSerializer): class DateTimeSerializer(BaseSerializer):
"""For datetime.*, except datetime.datetime."""
def serialize(self):
return repr(self.value), {'import datetime'}
class DatetimeDatetimeSerializer(BaseSerializer):
"""For datetime.datetime."""
def serialize(self): def serialize(self):
if self.value.tzinfo is not None and self.value.tzinfo != utc: if self.value.tzinfo is not None and self.value.tzinfo != utc:
self.value = self.value.astimezone(utc) self.value = self.value.astimezone(utc)
value_repr = repr(self.value).replace("<UTC>", "utc")
if isinstance(self.value, datetime_safe.datetime):
value_repr = "datetime.%s" % value_repr
imports = ["import datetime"] imports = ["import datetime"]
if self.value.tzinfo is not None: if self.value.tzinfo is not None:
imports.append("from django.utils.timezone import utc") imports.append("from django.utils.timezone import utc")
return value_repr, set(imports) return repr(self.value).replace('<UTC>', 'utc'), set(imports)
class DateSerializer(BaseSerializer):
def serialize(self):
value_repr = repr(self.value)
if isinstance(self.value, datetime_safe.date):
value_repr = "datetime.%s" % value_repr
return value_repr, {"import datetime"}
class DecimalSerializer(BaseSerializer): class DecimalSerializer(BaseSerializer):
...@@ -246,19 +241,6 @@ class SettingsReferenceSerializer(BaseSerializer): ...@@ -246,19 +241,6 @@ class SettingsReferenceSerializer(BaseSerializer):
return "settings.%s" % self.value.setting_name, {"from django.conf import settings"} return "settings.%s" % self.value.setting_name, {"from django.conf import settings"}
class TimedeltaSerializer(BaseSerializer):
def serialize(self):
return repr(self.value), {"import datetime"}
class TimeSerializer(BaseSerializer):
def serialize(self):
value_repr = repr(self.value)
if isinstance(self.value, datetime_safe.time):
value_repr = "datetime.%s" % value_repr
return value_repr, {"import datetime"}
class TupleSerializer(BaseSequenceSerializer): class TupleSerializer(BaseSequenceSerializer):
def _format(self): def _format(self):
# When len(value)==0, the empty tuple should be serialized as "()", # When len(value)==0, the empty tuple should be serialized as "()",
...@@ -322,13 +304,9 @@ def serializer_factory(value): ...@@ -322,13 +304,9 @@ def serializer_factory(value):
if isinstance(value, enum.Enum): if isinstance(value, enum.Enum):
return EnumSerializer(value) return EnumSerializer(value)
if isinstance(value, datetime.datetime): if isinstance(value, datetime.datetime):
return DatetimeSerializer(value) return DatetimeDatetimeSerializer(value)
if isinstance(value, datetime.date): if isinstance(value, (datetime.date, datetime.timedelta, datetime.time)):
return DateSerializer(value) return DateTimeSerializer(value)
if isinstance(value, datetime.time):
return TimeSerializer(value)
if isinstance(value, datetime.timedelta):
return TimedeltaSerializer(value)
if isinstance(value, SettingsReference): if isinstance(value, SettingsReference):
return SettingsReferenceSerializer(value) return SettingsReferenceSerializer(value)
if isinstance(value, float): if isinstance(value, float):
......
from django.db.migrations.questioner import MigrationQuestioner import datetime
from unittest import mock
from django.db.migrations.questioner import (
InteractiveMigrationQuestioner, MigrationQuestioner,
)
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.test.utils import override_settings from django.test.utils import captured_stdout, override_settings
class QuestionerTests(SimpleTestCase): class QuestionerTests(SimpleTestCase):
...@@ -11,3 +16,10 @@ class QuestionerTests(SimpleTestCase): ...@@ -11,3 +16,10 @@ class QuestionerTests(SimpleTestCase):
def test_ask_initial_with_disabled_migrations(self): def test_ask_initial_with_disabled_migrations(self):
questioner = MigrationQuestioner() questioner = MigrationQuestioner()
self.assertIs(False, questioner.ask_initial('migrations')) self.assertIs(False, questioner.ask_initial('migrations'))
@mock.patch('builtins.input', return_value='datetime.timedelta(days=1)')
def test_timedelta_default(self, mock):
questioner = InteractiveMigrationQuestioner()
with captured_stdout():
value = questioner._ask_default()
self.assertEqual(value, datetime.timedelta(days=1))
...@@ -19,7 +19,6 @@ from django.db.migrations.writer import ( ...@@ -19,7 +19,6 @@ from django.db.migrations.writer import (
MigrationWriter, OperationWriter, SettingsReference, MigrationWriter, OperationWriter, SettingsReference,
) )
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils import datetime_safe
from django.utils.deconstruct import deconstructible from django.utils.deconstruct import deconstructible
from django.utils.functional import SimpleLazyObject from django.utils.functional import SimpleLazyObject
from django.utils.timezone import get_default_timezone, get_fixed_timezone, utc from django.utils.timezone import get_default_timezone, get_fixed_timezone, utc
...@@ -364,20 +363,6 @@ class WriterTests(SimpleTestCase): ...@@ -364,20 +363,6 @@ class WriterTests(SimpleTestCase):
) )
) )
def test_serialize_datetime_safe(self):
self.assertSerializedResultEqual(
datetime_safe.date(2014, 3, 31),
("datetime.date(2014, 3, 31)", {'import datetime'})
)
self.assertSerializedResultEqual(
datetime_safe.time(10, 25),
("datetime.time(10, 25)", {'import datetime'})
)
self.assertSerializedResultEqual(
datetime_safe.datetime(2014, 3, 31, 16, 4, 31),
("datetime.datetime(2014, 3, 31, 16, 4, 31)", {'import datetime'})
)
def test_serialize_fields(self): def test_serialize_fields(self):
self.assertSerializedFieldEqual(models.CharField(max_length=255)) self.assertSerializedFieldEqual(models.CharField(max_length=255))
self.assertSerializedResultEqual( self.assertSerializedResultEqual(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment