#35882: Loop on all errors in `InteractiveMigrationQuestioner._ask_default()`
-------------------------------------+-------------------------------------
     Reporter:  Adam Johnson         |                     Type:
                                     |  Cleanup/optimization
       Status:  new                  |                Component:
                                     |  Migrations
      Version:  dev                  |                 Severity:  Normal
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
 When changing some fields, the migration questioner can ask for new field
 default values entered through a Python prompt.

 Yesterday, I made a typo which made the makemigrations process exit. This
 was a little frustrating as there were several fields to fix, and my work
 answering for the first fields was lost.

 Currently, the questioner loops on `SyntaxError` and `NameError`
 
([https://github.com/django/django/blob/1feedc8ef8a34484cb5afe33f5c45b543b860210/django/db/migrations/questioner.py#L163
 source]).  My mistake lead to an `AttributeError`, hence the crash and
 lost work. I propose we extend this clause to `Exception` - there's little
 harm in displaying the error and looping.

 Here's a reproducing example. Say you drop `null=True`  from two model
 fields:

 {{{#!diff
 diff --git example/models.py example/models.py
 index 816fe37..9743877 100644
 --- example/models.py
 +++ example/models.py
 @@ -2,5 +2,5 @@


  class Book(models.Model):
 -    title = models.CharField(max_length=100, null=True)
 -    published_date = models.DateField(null=True)
 +    title = models.CharField(max_length=100)
 +    published_date = models.DateField()
 }}}

 `makemigrations` asks you about the first one:

 {{{
 $ ./manage.py makemigrations example
 It is impossible to change a nullable field 'title' on book to non-
 nullable without providing a default. This is because the database needs
 something to populate existing rows.
 Please select a fix:
  1) Provide a one-off default now (will be set on all existing rows with a
 null value for this column)
  2) Ignore for now. Existing rows that contain NULL values will have to be
 handled manually, for example with a RunPython or RunSQL operation.
  3) Quit and manually define a default value in models.py.
 Select an option: 1
 Please enter the default value as valid Python.
 The datetime and django.utils.timezone modules are available, so it is
 possible to provide e.g. timezone.now as a value.
 Type 'exit' to exit this prompt
 >>> "Unknown book"
 }}}

 Immediately after this, it asks about the second field. Making a typo like
 `.dat()` instead of `.date()` crashes the process:

 {{{
 It is impossible to change a nullable field 'published_date' on book to
 non-nullable without providing a default. This is because the database
 needs something to populate existing rows.
 Please select a fix:
  1) Provide a one-off default now (will be set on all existing rows with a
 null value for this column)
  2) Ignore for now. Existing rows that contain NULL values will have to be
 handled manually, for example with a RunPython or RunSQL operation.
  3) Quit and manually define a default value in models.py.
 Select an option: 1
 Please enter the default value as valid Python.
 The datetime and django.utils.timezone modules are available, so it is
 possible to provide e.g. timezone.now as a value.
 Type 'exit' to exit this prompt
 >>> datetime.dat(1970, 1, 1)
 Traceback (most recent call last):
   File "/..././manage.py", line 21, in <module>
     main()
   ...
   File "/.../.venv/.../django/db/migrations/questioner.py", line 162, in
 _ask_default
     return eval(code, {}, {"datetime": datetime, "timezone": timezone})
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "<string>", line 1, in <module>
 AttributeError: module 'datetime' has no attribute 'dat'. Did you mean:
 'date'?
 }}}

 But if you instead made a typo in the `datetime` name, it would loop:

 {{{
 >>> datetme.date(1970,1,1)
 Invalid input: name 'datetme' is not defined
 >>>
 }}}
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35882>
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 view this discussion visit 
https://groups.google.com/d/msgid/django-updates/01070192ebd50720-58e10527-f6dd-44b0-b2c4-4e66c7e364a3-000000%40eu-central-1.amazonses.com.

Reply via email to