Add support for modern Django app labels.

Review Request #10552 — Created May 13, 2019 and submitted — Latest diff uploaded

Django Evolution

One of the big blockers for modern Django support has been the way in
which app labels have changed. In Django 1.6 and earlier, app labels
were based on an app's module name, and while discouraged, it was
technically legal for multiple apps to share the same name. Django 1.7's
introduction of the app registry and AppConfig classes changed this,
allowing app labels to be more flexible, and removed any support for
duplicate labels.

The Django Evolution project signature grouped models by legacy app
labels, and this meant that it was possible for one app entry to have
models for multiple apps.

This change introduces proper support for modern app labels. Now, both
the legacy app label and the modern app label (which will be the same
thing as the legacy app label on Django 1.6 or older) are stored as part
of the app's signature. When looking up an app signature, either a
modern or legacy app label can be used, with the modern label taking

If the app label is changed, a RenameAppLabel mutation can be added to
an app's evolutions to tell Django Evolution about the old label, new
label, and the current value for the legacy label. It can also take a
list of explicit model names, in case the app's entry needs to be split.
This mutation will create a new app signature for the new app label,
move over any relevant models to it, and delete the old app signature
(if now empty).

When generating a hinted diff, Django Evolution will attempt to find any
renamed apps and generate suitable RenameAppLabel mutations.

The optimizer factors in any RenameAppLabel mutations, updating any
other mutations to use the correct app label and collapsing down
multiple mutations into one final one.

Unit tests pass on Django 1.6 (Python 2.7) and Django 1.11 (Python 2.7
and 3.7).

Tested manually with a simulated Review Board 3.0 to 4.0 upgrade on
Django 1.6 and on 1.11). Verified that on 1.6, it behaved as before.
On 1.11, it noticed the renamed app labels in Djblets and included them
in the hints and diffs. It also applied any listed in those apps'
evolution sequences.