#23733: Following #23556: manage multi-apps dependencies when squashing ----------------------------+-------------------------------------- Reporter: Twidi | Owner: nobody Type: Bug | Status: new Component: Migrations | Version: master Severity: Normal | Resolution: Keywords: | Triage Stage: Unreviewed Has patch: 1 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 ----------------------------+-------------------------------------- Description changed by Twidi:
Old description: > Following ticket #23556 and PR #3280, I found a problem with squashing on > different apps, each one depending on the other at different step > > `app1`: > - `1_auto` > - `2_auto` > - `3_auto`, with dependency on `('app2', '2_auto')` > - `4_auto` > > With this squash: > > - `2_squashed_3` (squash of `2_auto` and `3_auto`) > > And `app2`: > > - `1_auto`, with dependency on `('app1', '1_auto')` > - `2_auto` > > With this squash: > > - `1_squashed_2` (squash of `1_auto` and `2_auto`) > > With this configuration, there is an error in `build_graph`: > > {{{ > #!python > File "django/db/migrations/loader.py", line 224, in build_graph > normal[child_key].dependencies.remove(replaced) > KeyError: ('app1', '3_auto') > }}} > > The reason is simple, `('app1', '3_auto')` where replaced by `('app1', > '2_squashed_3')` > > So I came up with this patch: > > {{{ > #!diff > diff --git a/django/db/migrations/loader.py > b/django/db/migrations/loader.py > index 9f8be33..0ee3794 100644 > --- a/django/db/migrations/loader.py > +++ b/django/db/migrations/loader.py > @@ -219,8 +219,15 @@ class MigrationLoader(object): > for child_key in reverse_dependencies.get(replaced, > set()): > if child_key in migration.replaces: > continue > - normal[child_key].dependencies.remove(replaced) > - normal[child_key].dependencies.append(key) > + # child_key may appear in a replacement > + if child_key in reverse_replacements: > + for replaced_child_key in > reverse_replacements[child_key]: > + if replaced in > replacing[replaced_child_key].dependencies: > + > replacing[replaced_child_key].dependencies.remove(replaced) > + > replacing[replaced_child_key].dependencies.append(key) > + else: > + normal[child_key].dependencies.remove(replaced) > + normal[child_key].dependencies.append(key) > normal[key] = migration > # Mark the replacement as applied if all its replaced ones > are > if all(applied_statuses): > > Note that I loop on reverse_replacements[child_key], but I'm not sure how > we can have many entries here > }}} > > I'll provide a PR with two commits: > > - one with a test showing the failure > - one with the patch New description: Following ticket #23556 and PR #3280, I found a problem with squashing on different apps, each one depending on the other at different step `app1`: - `1_auto` - `2_auto` - `3_auto`, with dependency on `('app2', '2_auto')` - `4_auto` With this squash: - `2_squashed_3` (squash of `2_auto` and `3_auto`) And `app2`: - `1_auto`, with dependency on `('app1', '1_auto')` - `2_auto` With this squash: - `1_squashed_2` (squash of `1_auto` and `2_auto`) With this configuration, there is an error in `build_graph`: {{{ #!python File "django/db/migrations/loader.py", line 224, in build_graph normal[child_key].dependencies.remove(replaced) KeyError: ('app1', '3_auto') }}} The reason is simple, `('app1', '3_auto')` where replaced by `('app1', '2_squashed_3')` So I came up with this patch: {{{ #!diff diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py index 9f8be33..0ee3794 100644 --- a/django/db/migrations/loader.py +++ b/django/db/migrations/loader.py @@ -219,8 +219,15 @@ class MigrationLoader(object): for child_key in reverse_dependencies.get(replaced, set()): if child_key in migration.replaces: continue - normal[child_key].dependencies.remove(replaced) - normal[child_key].dependencies.append(key) + # child_key may appear in a replacement + if child_key in reverse_replacements: + for replaced_child_key in reverse_replacements[child_key]: + if replaced in replacing[replaced_child_key].dependencies: + replacing[replaced_child_key].dependencies.remove(replaced) + replacing[replaced_child_key].dependencies.append(key) + else: + normal[child_key].dependencies.remove(replaced) + normal[child_key].dependencies.append(key) normal[key] = migration # Mark the replacement as applied if all its replaced ones are if all(applied_statuses): }}} Note that I loop on reverse_replacements[child_key], but I'm not sure how we can have many entries here I'll provide a PR with two commits: - one with a test showing the failure - one with the patch -- -- Ticket URL: <https://code.djangoproject.com/ticket/23733#comment:2> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/063.fd8881405f871b8832bbde669f4ef62b%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.