Introduce a top-level concept of a simulation.
Review Request #9539 — Created Jan. 25, 2018 and submitted — Latest diff uploaded
Mutation simulations are an integral part of Django Evolution. They're
responsible for validating that a mutation can be performed against part
of a database signature, and modifying that signature for storage. The
way they worked before is that each mutation had asimulate()
method
that took in several pieces of state, and it was the responsibility of
the method to look up data (and handle errors during lookup) from the
signatures and, if necessary, raise aSimulationFailure
if the
simulation could not be applied.This change formalizes some of this process and simplifies the work
required in thesimulate()
methods. There's now a top-level
Simulation
class, which olds all the state for a simulation, provides
helpful accessors for getting parts of the signature (raising errors if
not found), and providing a way to fail a simulation.Each mutation now has a standard error message describing a simulation
failure for that mutation, which is called when failing the simulation.
This can reference variables on the class or from calls to
Simulation.fail
.Each mutation's
simulate()
method takes only aSimulation
and no
other state, and can use that to look up the signatures. Since they no
longer have to handle signature-related lookup failures, each mutation
is now a bit smaller than it was when the improved error messages were
introduced.Speaking of error messages, now that we have a standard way of failing a
simulation, the remaining error messages now provide detailed context,
helping to debug problems when a mutation fails.In order to benefit
SQLMutation
, itsupdate_func
(which is needed to
do a simulation and update the signature) can now take either a legacy
app_label, project_sig
argument, or a new-styleSimulation
. Newer
evolution files should use the latter.
Unit tests pass.