Add a base mutation and a corresponding mutator for upgrade methods.

Review Request #12271 — Created May 6, 2022 and submitted

Django Evolution

This introduces BaseUpgradeMethodMutation, which
MoveToDjangoMigrations now subclasses. It handles the core parts of an
upgrade method mutation, and mandates implementation of

A new UpgradeMethodMutator wraps this, applying the mutation and
updating the stored signature when finalizing.

To explain the importance of this mutation, we must talk about how
AppMutator manages mutations and mutators.

AppMutator normally treats mutations that affect models differently
from mutations that don't. AppMutator.run_mutation() will batch
together subsequent model mutations under the same mutator. Each will be
run as a mutation (queueing up operations to modify the database) and
then as a simulation (immediately updating the staging signature). When
collecting SQL, the mutator is finalized, all the operations get turned
into SQL, and a final simulation is run against the final project
signature (which will be stored in the database).

Any mutation that does not apply to models gets mutated and simulated as
well, but immediately. A final simulation is not applied to the final

While this maybe needs a re-think (we may want to always apply every
mutator at finalization time), short-term, we do need upgrade methods to
be able to modify the final signature at this stage.

This is where UpgradeMethodMutator comes in. If run_mutation() is
passed a subclass of BaseUpgradeMethodMutation, it will be wrapped in
an UpgradeMethodMutator, which will perform a final simulation at
finalization time, ensuring the project signature is correct.

This will be used when applying the upgrade method to move to

All unit tests pass.

Add a base mutation and a corresponding mutator for upgrade methods.
  1. Ship It!
Review request changed

Status: Closed (submitted)

Change Summary:

Pushed to release-2.x (2ee7c22)