Refs #32966 -- Refactored out DateTimeCheckMixin._check_if_value_fixed().

This commit is contained in:
Chris Jerdonek 2021-07-29 01:47:24 -04:00 committed by Mariusz Felisiak
parent 6fa5d05dba
commit 6f5e07a84d
1 changed files with 42 additions and 67 deletions

View File

@ -1144,6 +1144,42 @@ class DateTimeCheckMixin:
def _check_fix_default_value(self): def _check_fix_default_value(self):
return [] return []
# Concrete subclasses use this in their implementations of
# _check_fix_default_value().
def _check_if_value_fixed(self, value, now=None):
"""
Check if the given value appears to have been provided as a "fixed"
time value, and include a warning in the returned list if it does. The
value argument must be a date object or aware/naive datetime object. If
now is provided, it must be a naive datetime object.
"""
if now is None:
now = _get_naive_now()
offset = datetime.timedelta(seconds=10)
lower = now - offset
upper = now + offset
if isinstance(value, datetime.datetime):
value = _to_naive(value)
else:
assert isinstance(value, datetime.date)
lower = lower.date()
upper = upper.date()
if lower <= value <= upper:
return [
checks.Warning(
'Fixed default value provided.',
hint=(
'It seems you set a fixed date / time / datetime '
'value as default for this field. This may not be '
'what you want. If you want to have the current date '
'as default, use `django.utils.timezone.now`'
),
obj=self,
id='fields.W161',
)
]
return []
class DateField(DateTimeCheckMixin, Field): class DateField(DateTimeCheckMixin, Field):
empty_strings_allowed = False empty_strings_allowed = False
@ -1175,30 +1211,12 @@ class DateField(DateTimeCheckMixin, Field):
if isinstance(value, datetime.datetime): if isinstance(value, datetime.datetime):
value = _to_naive(value).date() value = _to_naive(value).date()
elif isinstance(value, datetime.date): elif isinstance(value, datetime.date):
# Nothing to do, as dates don't have tz information
pass pass
else: else:
# No explicit date / datetime value -- no checks necessary # No explicit date / datetime value -- no checks necessary
return [] return []
# At this point, value is a date object. # At this point, value is a date object.
today = _get_naive_now().date() return self._check_if_value_fixed(value)
offset = datetime.timedelta(days=1)
lower = today - offset
upper = today + offset
if lower <= value <= upper:
return [
checks.Warning(
'Fixed default value provided.',
hint='It seems you set a fixed date / time / datetime '
'value as default for this field. This may not be '
'what you want. If you want to have the current date '
'as default, use `django.utils.timezone.now`',
obj=self,
id='fields.W161',
)
]
return []
def deconstruct(self): def deconstruct(self):
name, path, args, kwargs = super().deconstruct() name, path, args, kwargs = super().deconstruct()
@ -1309,35 +1327,9 @@ class DateTimeField(DateField):
return [] return []
value = self.default value = self.default
if isinstance(value, datetime.datetime): if isinstance(value, (datetime.datetime, datetime.date)):
value = _to_naive(value) return self._check_if_value_fixed(value)
now = _get_naive_now() # No explicit date / datetime value -- no checks necessary.
offset = datetime.timedelta(seconds=10)
lower = now - offset
upper = now + offset
elif isinstance(value, datetime.date):
now = _get_naive_now()
offset = datetime.timedelta(seconds=10)
lower = now - offset
upper = now + offset
lower = lower.date()
upper = upper.date()
else:
# No explicit date / datetime value -- no checks necessary
return []
if lower <= value <= upper:
return [
checks.Warning(
'Fixed default value provided.',
hint='It seems you set a fixed date / time / datetime '
'value as default for this field. This may not be '
'what you want. If you want to have the current date '
'as default, use `django.utils.timezone.now`',
obj=self,
id='fields.W161',
)
]
return [] return []
def get_internal_type(self): def get_internal_type(self):
@ -2203,7 +2195,7 @@ class TimeField(DateTimeCheckMixin, Field):
value = self.default value = self.default
if isinstance(value, datetime.datetime): if isinstance(value, datetime.datetime):
now = _get_naive_now() now = None
elif isinstance(value, datetime.time): elif isinstance(value, datetime.time):
now = _get_naive_now() now = _get_naive_now()
# This will not use the right date in the race condition where now # This will not use the right date in the race condition where now
@ -2213,24 +2205,7 @@ class TimeField(DateTimeCheckMixin, Field):
# No explicit time / datetime value -- no checks necessary # No explicit time / datetime value -- no checks necessary
return [] return []
# At this point, value is a datetime object. # At this point, value is a datetime object.
offset = datetime.timedelta(seconds=10) return self._check_if_value_fixed(value, now=now)
lower = now - offset
upper = now + offset
value = _to_naive(value)
if lower <= value <= upper:
return [
checks.Warning(
'Fixed default value provided.',
hint='It seems you set a fixed date / time / datetime '
'value as default for this field. This may not be '
'what you want. If you want to have the current date '
'as default, use `django.utils.timezone.now`',
obj=self,
id='fields.W161',
)
]
return []
def deconstruct(self): def deconstruct(self):
name, path, args, kwargs = super().deconstruct() name, path, args, kwargs = super().deconstruct()