#28980: Make the autodetector validate the type of one-off default values
--------------------------------------+------------------------------------
Reporter: Nikos Katsos | Owner: Jeff
Type: Cleanup/optimization | Status: assigned
Component: Migrations | Version: 2.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------
Comment (by Jeff):
If anyone is willing to give me a hand, I am close to a viable patch, see
[https://github.com/jeffyancey/django/commit/a6b9ee29e06ae10c8eda58a21485ad833a241adc
commit], however I am currently wrangling with an existing test
`tests/migrations/test_commands.py` -
`MakeMigrationsTests.test_makemigrations_auto_now_add_interactive`. The
test is failing like so:
{{{
======================================================================
ERROR: test_makemigrations_auto_now_add_interactive
(migrations.test_commands.MakeMigrationsTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.6/unittest/case.py", line 59, in testPartExecutor
yield
File "/usr/lib/python3.6/unittest/case.py", line 605, in run
testMethod()
File "/usr/lib/python3.6/unittest/mock.py", line 1179, in patched
return func(*args, **keywargs)
File "/home/jy/Django/forks/django-
repo/tests/migrations/test_commands.py", line 1300, in
test_makemigrations_auto_now_add_interactive
call_command('makemigrations', 'migrations', interactive=True,
stdout=out)
File "/home/jy/Django/forks/django-
repo/django/core/management/__init__.py", line 148, in call_command
return command.execute(*args, **defaults)
File "/home/jy/Django/forks/django-repo/django/core/management/base.py",
line 354, in execute
output = self.handle(*args, **options)
File "/home/jy/Django/forks/django-repo/django/core/management/base.py",
line 83, in wrapped
res = handle_func(*args, **kwargs)
File "/home/jy/Django/forks/django-
repo/django/core/management/commands/makemigrations.py", line 161, in
handle
migration_name=self.migration_name,
File "/home/jy/Django/forks/django-
repo/django/db/migrations/autodetector.py", line 44, in changes
changes = self._detect_changes(convert_apps, graph)
File "/home/jy/Django/forks/django-
repo/django/db/migrations/autodetector.py", line 183, in _detect_changes
self.generate_added_fields()
File "/home/jy/Django/forks/django-
repo/django/db/migrations/autodetector.py", line 835, in
generate_added_fields
self._generate_added_field(app_label, model_name, field_name)
File "/home/jy/Django/forks/django-
repo/django/db/migrations/autodetector.py", line 854, in
_generate_added_field
field.default = self.questioner.ask_auto_now_add_addition(field,
model_name)
File "/home/jy/Django/forks/django-
repo/django/db/migrations/questioner.py", line 224, in
ask_auto_now_add_addition
return self._ask_default(field_instance, default='timezone.now')
File "/home/jy/Django/forks/django-
repo/django/db/migrations/questioner.py", line 139, in _ask_default
if field_instance.to_python(code):
File "/home/jy/Django/forks/django-
repo/django/db/models/fields/__init__.py", line 1369, in to_python
parsed = parse_datetime(value)
File "/home/jy/Django/forks/django-repo/django/utils/dateparse.py", line
106, in parse_datetime
match = datetime_re.match(value)
TypeError: expected string or bytes-like object
}}}
I have confirmed that at this point the value being passed to `to_python`
is the integer 1, which should indeed be an invalid default/one-off value
to pass for a DateTime field.
At the moment what seems to be blocking me, I believe, is figuring out how
`unittest.mock.patch()` works, and how that value is being set for the
interactive test:
{{{
@mock.patch('builtins.input', return_value='1')
@mock.patch('django.db.migrations.questioner.sys.stdin',
mock.MagicMock(encoding=sys.getdefaultencoding()))
def test_makemigrations_auto_now_add_interactive(self, *args):
"""
makemigrations prompts the user when adding auto_now_add to an
existing
model.
"""
class Entry(models.Model):
title = models.CharField(max_length=255)
creation_date = models.DateTimeField(auto_now_add=True)
class Meta:
app_label = 'migrations'
# Monkeypatch interactive questioner to auto accept
with mock.patch('django.db.migrations.questioner.sys.stdout',
new_callable=io.StringIO) as prompt_stdout:
out = io.StringIO()
with
self.temporary_migration_module(module='migrations.test_auto_now_add'):
call_command('makemigrations', 'migrations', interactive=True,
stdout=out)
output = out.getvalue()
prompt_output = prompt_stdout.getvalue()
self.assertIn("You can accept the default 'timezone.now' by
pressing 'Enter'", prompt_output)
self.assertIn("Add field creation_date to entry", output)
}}}
If anyone could provide some guidance on how to properly work with this
test, I'd appreciate it.
--
Ticket URL: <https://code.djangoproject.com/ticket/28980#comment:3>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/064.e44425ddf8d2f237a4634a26bee368fb%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.