Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#30580 closed Bug (needsinfo)

django.db.migrations.optimizer error in indention

Reported by: sijianlin Owned by: nobody
Component: Migrations Version: 2.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The command "makemigrations" yields operations in wrong order; base class gets created later than ones depending on it. After tracing the issue we are certain that the error comes from django.db.migrations.optimizer. In the file optimizer.py method optimizer_inner,the "else" clause is clearly misaligned. We currently disable the optimization to get the migration operations in correct order.

Change History (3)

comment:1 by Simon Charette, 5 years ago

Resolution: needsinfo
Status: newclosed

Hello there, thank you for your report.

It's possible the issue you are experiencing is legitimate but it's unfortunately not possible for triagers to assert whether or not Django is at fault because your report is missing detailed reproduction case.

Please reopen this ticket with a detailed step by step report of how to reproduce the issue. It should contain the models used to the generate the problematic migrations, the Django version you are using, and a sample of the generated migration.

comment:2 by sijianlin, 5 years ago

Please take a look at the the code /django/db/migrations/optimizer.py and this is an apparent indention error- the last "else" is not matching with the if clause.
Please assign to the author and get it fixed.
Thanks

   def optimize_inner(self, operations, app_label=None):
        """Inner optimization loop."""
        new_operations = []
        for i, operation in enumerate(operations):
            right = True  # Should we reduce on the right or on the left.
            # Compare it to each operation after it
            for j, other in enumerate(operations[i + 1:]):
                in_between = operations[i + 1:i + j + 1]
                result = operation.reduce(other, app_label)
                if isinstance(result, list):
                    if right:
                        new_operations.extend(in_between)
                        new_operations.extend(result)
                    elif all(op.reduce(other, app_label) is True for op in in_between):
                        # Perform a left reduction if all of the in-between
                        # operations can optimize through other.
                        new_operations.extend(result)
                        new_operations.extend(in_between)
                    else:
                        # Otherwise keep trying.
                        new_operations.append(operation)
                        break
                    new_operations.extend(operations[i + j + 2:])
                    return new_operations
                elif not result:
                    # Can't perform a right reduction.
                    right = False
            else:
                new_operations.append(operation)
        return new_operations

comment:3 by Simon Charette, 5 years ago

I think you've misinterpreted the code; that's a for else clause that is only executed if nothing break out of the loop.

https://docs.python.org/3/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops

Note: See TracTickets for help on using tickets.
Back to Top