On Sat, 2021-07-17 at 03:19 +1000, Daniel Axtens wrote: > When we moved to Python 3, makemigrations wanted to change a bunch of > things, see commit 4ad87ed72aec ("migrations: Add the Python 3 patch"). > > The change is, as observed then, just to make django happy; it's not > supposed to change the database at all. > > So make the migration change the state as seen by Django only. > This makes the migration ~instant, even for a huge database. > > Signed-off-by: Daniel Axtens <d...@axtens.net>
Oh, this is snazzy. This turns out to actually be a really small change. With the patch applied: $ git diff HEAD~ -w diff --git patchwork/migrations/0041_python3.py patchwork/migrations/0041_python3.py index 201c6460..25d5de4b 100644 --- patchwork/migrations/0041_python3.py +++ patchwork/migrations/0041_python3.py @@ -15,6 +15,8 @@ class Migration(migrations.Migration): ] operations = [ + migrations.SeparateDatabaseAndState( + state_operations=[ migrations.AlterField( model_name='check', name='context', @@ -330,4 +332,6 @@ class Migration(migrations.Migration): help_text='Show click-to-copy patch IDs in the list view', ), ), + ], + ), ] I modified this to include a bug and applied it to master. I'll backport it to stable/3.0 shortly. Also, Reviewed-by: Stephen Finucane <step...@that.guru> Thanks! Stephen > --- > patchwork/migrations/0041_python3.py | 632 ++++++++++++++------------- > 1 file changed, 318 insertions(+), 314 deletions(-) > > diff --git a/patchwork/migrations/0041_python3.py > b/patchwork/migrations/0041_python3.py > index 201c6460fb02..25d5de4b66e3 100644 > --- a/patchwork/migrations/0041_python3.py > +++ b/patchwork/migrations/0041_python3.py > @@ -15,319 +15,323 @@ class Migration(migrations.Migration): > ] > > operations = [ > - migrations.AlterField( > - model_name='check', > - name='context', > - field=models.SlugField( > - default='default', > - help_text='A label to discern check from checks of other ' > - 'testing systems.', > - max_length=255, > - ), > - ), > - migrations.AlterField( > - model_name='check', > - name='description', > - field=models.TextField( > - blank=True, > - help_text='A brief description of the check.', > - null=True, > - ), > - ), > - migrations.AlterField( > - model_name='check', > - name='state', > - field=models.SmallIntegerField( > - choices=[ > - (0, 'pending'), > - (1, 'success'), > - (2, 'warning'), > - (3, 'fail'), > - ], > - default=0, > - help_text='The state of the check.', > - ), > - ), > - migrations.AlterField( > - model_name='check', > - name='target_url', > - field=models.URLField( > - blank=True, > - help_text='The target URL to associate with this check. This > ' > - 'should be specific to the patch.', > - null=True, > - ), > - ), > - migrations.AlterField( > - model_name='comment', > - name='submission', > - field=models.ForeignKey( > - on_delete=django.db.models.deletion.CASCADE, > - related_name='comments', > - related_query_name='comment', > - to='patchwork.Submission', > - ), > - ), > - migrations.AlterField( > - model_name='delegationrule', > - name='path', > - field=models.CharField( > - help_text='An fnmatch-style pattern to match filenames ' > - 'against.', > - max_length=255, > - ), > - ), > - migrations.AlterField( > - model_name='delegationrule', > - name='priority', > - field=models.IntegerField( > - default=0, > - help_text='The priority of the rule. Rules with a higher ' > - 'priority will override rules with lower priorities', > - ), > - ), > - migrations.AlterField( > - model_name='delegationrule', > - name='user', > - field=models.ForeignKey( > - help_text='A user to delegate the patch to.', > - on_delete=django.db.models.deletion.CASCADE, > - to=settings.AUTH_USER_MODEL, > - ), > - ), > - migrations.AlterField( > - model_name='emailconfirmation', > - name='type', > - field=models.CharField( > - choices=[ > - ('userperson', 'User-Person association'), > - ('registration', 'Registration'), > - ('optout', 'Email opt-out'), > - ], > - max_length=20, > - ), > - ), > - migrations.AlterField( > - model_name='event', > - name='actor', > - field=models.ForeignKey( > - blank=True, > - help_text='The user that caused/created this event.', > - null=True, > - on_delete=django.db.models.deletion.SET_NULL, > - related_name='+', > - to=settings.AUTH_USER_MODEL, > - ), > - ), > - migrations.AlterField( > - model_name='event', > - name='category', > - field=models.CharField( > - choices=[ > - ('cover-created', 'Cover Letter Created'), > - ('patch-created', 'Patch Created'), > - ('patch-completed', 'Patch Completed'), > - ('patch-state-changed', 'Patch State Changed'), > - ('patch-delegated', 'Patch Delegate Changed'), > - ('patch-relation-changed', 'Patch Relation Changed'), > - ('check-created', 'Check Created'), > - ('series-created', 'Series Created'), > - ('series-completed', 'Series Completed'), > - ], > - db_index=True, > - help_text='The category of the event.', > - max_length=25, > - ), > - ), > - migrations.AlterField( > - model_name='event', > - name='cover', > - field=models.ForeignKey( > - blank=True, > - help_text='The cover letter that this event was created > for.', > - null=True, > - on_delete=django.db.models.deletion.CASCADE, > - related_name='+', > - to='patchwork.CoverLetter', > - ), > - ), > - migrations.AlterField( > - model_name='event', > - name='date', > - field=models.DateTimeField( > - default=datetime.datetime.utcnow, > - help_text='The time this event was created.', > - ), > - ), > - migrations.AlterField( > - model_name='event', > - name='patch', > - field=models.ForeignKey( > - blank=True, > - help_text='The patch that this event was created for.', > - null=True, > - on_delete=django.db.models.deletion.CASCADE, > - related_name='+', > - to='patchwork.Patch', > - ), > - ), > - migrations.AlterField( > - model_name='event', > - name='project', > - field=models.ForeignKey( > - help_text='The project that the events belongs to.', > - on_delete=django.db.models.deletion.CASCADE, > - related_name='+', > - to='patchwork.Project', > - ), > - ), > - migrations.AlterField( > - model_name='event', > - name='series', > - field=models.ForeignKey( > - blank=True, > - help_text='The series that this event was created for.', > - null=True, > - on_delete=django.db.models.deletion.CASCADE, > - related_name='+', > - to='patchwork.Series', > - ), > - ), > - migrations.AlterField( > - model_name='patch', > - name='number', > - field=models.PositiveSmallIntegerField( > - default=None, > - help_text='The number assigned to this patch in the series', > - null=True, > - ), > - ), > - migrations.AlterField( > - model_name='project', > - name='commit_url_format', > - field=models.CharField( > - blank=True, > - help_text='URL format for a particular commit. {} will be ' > - 'replaced by the commit SHA.', > - max_length=2000, > - ), > - ), > - migrations.AlterField( > - model_name='project', > - name='list_archive_url_format', > - field=models.CharField( > - blank=True, > - help_text="URL format for the list archive's Message-ID " > - "redirector. {} will be replaced by the Message-ID.", > - max_length=2000, > - ), > - ), > - migrations.AlterField( > - model_name='project', > - name='subject_match', > - field=models.CharField( > - blank=True, > - default='', > - help_text='Regex to match the subject against if only part ' > - 'of emails sent to the list belongs to this project. Will be > ' > - 'used with IGNORECASE and MULTILINE flags. If rules for more > ' > - 'projects match the first one returned from DB is chosen; ' > - 'empty field serves as a default for every email which has > no ' > - 'other match.', > - max_length=64, > - validators=[patchwork.models.validate_regex_compiles], > - ), > - ), > - migrations.AlterField( > - model_name='series', > - name='name', > - field=models.CharField( > - blank=True, > - help_text='An optional name to associate with the series, ' > - 'e.g. "John\'s PCI series".', > - max_length=255, > - null=True, > - ), > - ), > - migrations.AlterField( > - model_name='series', > - name='total', > - field=models.IntegerField( > - help_text='Number of patches in series as indicated by the ' > - 'subject prefix(es)' > - ), > - ), > - migrations.AlterField( > - model_name='series', > - name='version', > - field=models.IntegerField( > - default=1, > - help_text='Version of series as indicated by the subject ' > - 'prefix(es)', > - ), > - ), > - migrations.AlterField( > - model_name='seriesreference', > - name='series', > - field=models.ForeignKey( > - on_delete=django.db.models.deletion.CASCADE, > - related_name='references', > - related_query_name='reference', > - to='patchwork.Series', > - ), > - ), > - migrations.AlterField( > - model_name='tag', > - name='abbrev', > - field=models.CharField( > - help_text='Short (one-or-two letter) abbreviation for the ' > - 'tag, used in table column headers', > - max_length=2, > - unique=True, > - ), > - ), > - migrations.AlterField( > - model_name='tag', > - name='pattern', > - field=models.CharField( > - help_text='A simple regex to match the tag in the content of > ' > - 'a message. Will be used with MULTILINE and IGNORECASE > flags. ' > - 'eg. ^Acked-by:', > - max_length=50, > - validators=[patchwork.models.validate_regex_compiles], > - ), > - ), > - migrations.AlterField( > - model_name='tag', > - name='show_column', > - field=models.BooleanField( > - default=True, > - help_text="Show a column displaying this tag's count in the " > - "patch list view", > - ), > - ), > - migrations.AlterField( > - model_name='userprofile', > - name='items_per_page', > - field=models.PositiveIntegerField( > - default=100, help_text='Number of items to display per page' > - ), > - ), > - migrations.AlterField( > - model_name='userprofile', > - name='send_email', > - field=models.BooleanField( > - default=False, > - help_text='Selecting this option allows patchwork to send ' > - 'email on your behalf', > - ), > - ), > - migrations.AlterField( > - model_name='userprofile', > - name='show_ids', > - field=models.BooleanField( > - default=False, > - help_text='Show click-to-copy patch IDs in the list view', > - ), > + migrations.SeparateDatabaseAndState( > + state_operations=[ > + migrations.AlterField( > + model_name='check', > + name='context', > + field=models.SlugField( > + default='default', > + help_text='A label to discern check from checks of > other ' > + 'testing systems.', > + max_length=255, > + ), > + ), > + migrations.AlterField( > + model_name='check', > + name='description', > + field=models.TextField( > + blank=True, > + help_text='A brief description of the check.', > + null=True, > + ), > + ), > + migrations.AlterField( > + model_name='check', > + name='state', > + field=models.SmallIntegerField( > + choices=[ > + (0, 'pending'), > + (1, 'success'), > + (2, 'warning'), > + (3, 'fail'), > + ], > + default=0, > + help_text='The state of the check.', > + ), > + ), > + migrations.AlterField( > + model_name='check', > + name='target_url', > + field=models.URLField( > + blank=True, > + help_text='The target URL to associate with this > check. This ' > + 'should be specific to the patch.', > + null=True, > + ), > + ), > + migrations.AlterField( > + model_name='comment', > + name='submission', > + field=models.ForeignKey( > + on_delete=django.db.models.deletion.CASCADE, > + related_name='comments', > + related_query_name='comment', > + to='patchwork.Submission', > + ), > + ), > + migrations.AlterField( > + model_name='delegationrule', > + name='path', > + field=models.CharField( > + help_text='An fnmatch-style pattern to match > filenames ' > + 'against.', > + max_length=255, > + ), > + ), > + migrations.AlterField( > + model_name='delegationrule', > + name='priority', > + field=models.IntegerField( > + default=0, > + help_text='The priority of the rule. Rules with a > higher ' > + 'priority will override rules with lower > priorities', > + ), > + ), > + migrations.AlterField( > + model_name='delegationrule', > + name='user', > + field=models.ForeignKey( > + help_text='A user to delegate the patch to.', > + on_delete=django.db.models.deletion.CASCADE, > + to=settings.AUTH_USER_MODEL, > + ), > + ), > + migrations.AlterField( > + model_name='emailconfirmation', > + name='type', > + field=models.CharField( > + choices=[ > + ('userperson', 'User-Person association'), > + ('registration', 'Registration'), > + ('optout', 'Email opt-out'), > + ], > + max_length=20, > + ), > + ), > + migrations.AlterField( > + model_name='event', > + name='actor', > + field=models.ForeignKey( > + blank=True, > + help_text='The user that caused/created this event.', > + null=True, > + on_delete=django.db.models.deletion.SET_NULL, > + related_name='+', > + to=settings.AUTH_USER_MODEL, > + ), > + ), > + migrations.AlterField( > + model_name='event', > + name='category', > + field=models.CharField( > + choices=[ > + ('cover-created', 'Cover Letter Created'), > + ('patch-created', 'Patch Created'), > + ('patch-completed', 'Patch Completed'), > + ('patch-state-changed', 'Patch State Changed'), > + ('patch-delegated', 'Patch Delegate Changed'), > + ('patch-relation-changed', 'Patch Relation > Changed'), > + ('check-created', 'Check Created'), > + ('series-created', 'Series Created'), > + ('series-completed', 'Series Completed'), > + ], > + db_index=True, > + help_text='The category of the event.', > + max_length=25, > + ), > + ), > + migrations.AlterField( > + model_name='event', > + name='cover', > + field=models.ForeignKey( > + blank=True, > + help_text='The cover letter that this event was > created for.', > + null=True, > + on_delete=django.db.models.deletion.CASCADE, > + related_name='+', > + to='patchwork.CoverLetter', > + ), > + ), > + migrations.AlterField( > + model_name='event', > + name='date', > + field=models.DateTimeField( > + default=datetime.datetime.utcnow, > + help_text='The time this event was created.', > + ), > + ), > + migrations.AlterField( > + model_name='event', > + name='patch', > + field=models.ForeignKey( > + blank=True, > + help_text='The patch that this event was created > for.', > + null=True, > + on_delete=django.db.models.deletion.CASCADE, > + related_name='+', > + to='patchwork.Patch', > + ), > + ), > + migrations.AlterField( > + model_name='event', > + name='project', > + field=models.ForeignKey( > + help_text='The project that the events belongs to.', > + on_delete=django.db.models.deletion.CASCADE, > + related_name='+', > + to='patchwork.Project', > + ), > + ), > + migrations.AlterField( > + model_name='event', > + name='series', > + field=models.ForeignKey( > + blank=True, > + help_text='The series that this event was created > for.', > + null=True, > + on_delete=django.db.models.deletion.CASCADE, > + related_name='+', > + to='patchwork.Series', > + ), > + ), > + migrations.AlterField( > + model_name='patch', > + name='number', > + field=models.PositiveSmallIntegerField( > + default=None, > + help_text='The number assigned to this patch in the > series', > + null=True, > + ), > + ), > + migrations.AlterField( > + model_name='project', > + name='commit_url_format', > + field=models.CharField( > + blank=True, > + help_text='URL format for a particular commit. {} > will be ' > + 'replaced by the commit SHA.', > + max_length=2000, > + ), > + ), > + migrations.AlterField( > + model_name='project', > + name='list_archive_url_format', > + field=models.CharField( > + blank=True, > + help_text="URL format for the list archive's > Message-ID " > + "redirector. {} will be replaced by the > Message-ID.", > + max_length=2000, > + ), > + ), > + migrations.AlterField( > + model_name='project', > + name='subject_match', > + field=models.CharField( > + blank=True, > + default='', > + help_text='Regex to match the subject against if > only part ' > + 'of emails sent to the list belongs to > this project. Will be ' > + 'used with IGNORECASE and MULTILINE flags. > If rules for more ' > + 'projects match the first one returned > from DB is chosen; ' > + 'empty field serves as a default for every > email which has no ' > + 'other match.', > + max_length=64, > + > validators=[patchwork.models.validate_regex_compiles], > + ), > + ), > + migrations.AlterField( > + model_name='series', > + name='name', > + field=models.CharField( > + blank=True, > + help_text='An optional name to associate with the > series, ' > + 'e.g. "John\'s PCI series".', > + max_length=255, > + null=True, > + ), > + ), > + migrations.AlterField( > + model_name='series', > + name='total', > + field=models.IntegerField( > + help_text='Number of patches in series as indicated > by the ' > + 'subject prefix(es)' > + ), > + ), > + migrations.AlterField( > + model_name='series', > + name='version', > + field=models.IntegerField( > + default=1, > + help_text='Version of series as indicated by the > subject ' > + 'prefix(es)', > + ), > + ), > + migrations.AlterField( > + model_name='seriesreference', > + name='series', > + field=models.ForeignKey( > + on_delete=django.db.models.deletion.CASCADE, > + related_name='references', > + related_query_name='reference', > + to='patchwork.Series', > + ), > + ), > + migrations.AlterField( > + model_name='tag', > + name='abbrev', > + field=models.CharField( > + help_text='Short (one-or-two letter) abbreviation > for the ' > + 'tag, used in table column headers', > + max_length=2, > + unique=True, > + ), > + ), > + migrations.AlterField( > + model_name='tag', > + name='pattern', > + field=models.CharField( > + help_text='A simple regex to match the tag in the > content of ' > + 'a message. Will be used with MULTILINE > and IGNORECASE flags. ' > + 'eg. ^Acked-by:', > + max_length=50, > + > validators=[patchwork.models.validate_regex_compiles], > + ), > + ), > + migrations.AlterField( > + model_name='tag', > + name='show_column', > + field=models.BooleanField( > + default=True, > + help_text="Show a column displaying this tag's count > in the " > + "patch list view", > + ), > + ), > + migrations.AlterField( > + model_name='userprofile', > + name='items_per_page', > + field=models.PositiveIntegerField( > + default=100, help_text='Number of items to display > per page' > + ), > + ), > + migrations.AlterField( > + model_name='userprofile', > + name='send_email', > + field=models.BooleanField( > + default=False, > + help_text='Selecting this option allows patchwork to > send ' > + 'email on your behalf', > + ), > + ), > + migrations.AlterField( > + model_name='userprofile', > + name='show_ids', > + field=models.BooleanField( > + default=False, > + help_text='Show click-to-copy patch IDs in the list > view', > + ), > + ), > + ], > ), > ] _______________________________________________ Patchwork mailing list Patchwork@lists.ozlabs.org https://lists.ozlabs.org/listinfo/patchwork