summaryrefslogtreecommitdiff
path: root/tests/migrations
diff options
context:
space:
mode:
Diffstat (limited to 'tests/migrations')
-rw-r--r--tests/migrations/deprecated_field_migrations/0001_initial.py17
-rw-r--r--tests/migrations/deprecated_field_migrations/0002_remove_ipaddressfield_ip.py6
-rw-r--r--tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0001_initial.py14
-rw-r--r--tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0002_alter_id.py8
-rw-r--r--tests/migrations/migrations_test_apps/alter_fk/book_app/migrations/0001_initial.py15
-rw-r--r--tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py2
-rw-r--r--tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py2
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_a/migrations/0001_initial.py15
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_a/migrations/0002_a2.py14
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_a/migrations/0003_a3.py22
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_a/migrations/0004_a4.py14
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_a/models.py4
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_b/migrations/0001_initial.py15
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_b/migrations/0002_b2.py18
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_b/migrations/0003_b3.py14
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_b/models.py2
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_c/migrations/0001_initial.py15
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_c/migrations/0002_c2.py18
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_c/migrations/0003_c3.py14
-rw-r--r--tests/migrations/migrations_test_apps/lookuperror_c/models.py2
-rw-r--r--tests/migrations/migrations_test_apps/migrated_app/migrations/0001_initial.py5
-rw-r--r--tests/migrations/migrations_test_apps/migrated_unapplied_app/migrations/0001_initial.py2
-rw-r--r--tests/migrations/migrations_test_apps/mutate_state_a/migrations/0001_initial.py29
-rw-r--r--tests/migrations/migrations_test_apps/mutate_state_b/migrations/0001_initial.py30
-rw-r--r--tests/migrations/migrations_test_apps/mutate_state_b/migrations/0002_add_field.py19
-rw-r--r--tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py1
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py5
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py2
-rw-r--r--tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py7
-rw-r--r--tests/migrations/models.py8
-rw-r--r--tests/migrations/routers.py8
-rw-r--r--tests/migrations/test_add_many_to_many_field_initial/0001_initial.py33
-rw-r--r--tests/migrations/test_add_many_to_many_field_initial/0002_initial.py6
-rw-r--r--tests/migrations/test_auto_now_add/0001_initial.py14
-rw-r--r--tests/migrations/test_autodetector.py4775
-rw-r--r--tests/migrations/test_base.py304
-rw-r--r--tests/migrations/test_commands.py1767
-rw-r--r--tests/migrations/test_deprecated_fields.py5
-rw-r--r--tests/migrations/test_exceptions.py7
-rw-r--r--tests/migrations/test_executor.py486
-rw-r--r--tests/migrations/test_fake_initial_case_insensitive/fake_initial/0001_initial.py22
-rw-r--r--tests/migrations/test_fake_initial_case_insensitive/initial/0001_initial.py19
-rw-r--r--tests/migrations/test_graph.py151
-rw-r--r--tests/migrations/test_loader.py358
-rw-r--r--tests/migrations/test_migrations/0001_initial.py8
-rw-r--r--tests/migrations/test_migrations/0002_second.py12
-rw-r--r--tests/migrations/test_migrations_atomic_operation/0001_initial.py6
-rw-r--r--tests/migrations/test_migrations_backwards_deps_1/0002_second.py2
-rw-r--r--tests/migrations/test_migrations_clashing_prefix/ab.py2
-rw-r--r--tests/migrations/test_migrations_conflict/0001_initial.py5
-rw-r--r--tests/migrations/test_migrations_conflict/0002_conflicting_second.py2
-rw-r--r--tests/migrations/test_migrations_conflict/0002_second.py12
-rw-r--r--tests/migrations/test_migrations_conflict_long_name/0001_initial.py4
-rw-r--r--tests/migrations/test_migrations_conflict_long_name/0002_conflicting_second_migration_with_long_name.py6
-rw-r--r--tests/migrations/test_migrations_conflict_long_name/0002_second.py6
-rw-r--r--tests/migrations/test_migrations_custom_user/0001_initial.py12
-rw-r--r--tests/migrations/test_migrations_fake_split_initial/0001_initial.py4
-rw-r--r--tests/migrations/test_migrations_fake_split_initial/0002_second.py5
-rw-r--r--tests/migrations/test_migrations_first/second.py12
-rw-r--r--tests/migrations/test_migrations_first/thefirst.py5
-rw-r--r--tests/migrations/test_migrations_initial_false/0001_not_initial.py4
-rw-r--r--tests/migrations/test_migrations_manual_porting/0001_initial.py6
-rw-r--r--tests/migrations/test_migrations_manual_porting/0002_second.py2
-rw-r--r--tests/migrations/test_migrations_no_ancestor/0001_initial.py5
-rw-r--r--tests/migrations/test_migrations_no_ancestor/0002_conflicting_second.py15
-rw-r--r--tests/migrations/test_migrations_no_ancestor/0002_second.py12
-rw-r--r--tests/migrations/test_migrations_no_changes/0001_initial.py5
-rw-r--r--tests/migrations/test_migrations_no_changes/0002_second.py12
-rw-r--r--tests/migrations/test_migrations_no_changes/0003_third.py30
-rw-r--r--tests/migrations/test_migrations_no_default/0001_initial.py20
-rw-r--r--tests/migrations/test_migrations_non_atomic/0001_initial.py13
-rw-r--r--tests/migrations/test_migrations_order/0001.py3
-rw-r--r--tests/migrations/test_migrations_plan/0001_initial.py8
-rw-r--r--tests/migrations/test_migrations_plan/0002_second.py12
-rw-r--r--tests/migrations/test_migrations_plan/0003_third.py11
-rw-r--r--tests/migrations/test_migrations_plan/0004_fourth.py4
-rw-r--r--tests/migrations/test_migrations_plan/0005_fifth.py2
-rw-r--r--tests/migrations/test_migrations_run_before/0001_initial.py2
-rw-r--r--tests/migrations/test_migrations_run_before/0002_second.py7
-rw-r--r--tests/migrations/test_migrations_run_before/0003_third.py2
-rw-r--r--tests/migrations/test_migrations_squashed/0001_initial.py5
-rw-r--r--tests/migrations/test_migrations_squashed/0001_squashed_0002.py8
-rw-r--r--tests/migrations/test_migrations_squashed/0002_second.py12
-rw-r--r--tests/migrations/test_migrations_squashed_complex/1_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex/2_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex/3_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex/3_squashed_5.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex/4_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex/5_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex/6_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex/7_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py4
-rw-r--r--tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/1_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/2_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py4
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/6_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_erroneous/7_auto.py4
-rw-r--r--tests/migrations/test_migrations_squashed_no_replaces/0001_squashed_0002.py5
-rw-r--r--tests/migrations/test_migrations_unmigdep/0001_initial.py2
-rw-r--r--tests/migrations/test_multidb.py34
-rw-r--r--tests/migrations/test_operations.py3265
-rw-r--r--tests/migrations/test_optimizer.py621
-rw-r--r--tests/migrations/test_questioner.py54
-rw-r--r--tests/migrations/test_state.py1383
-rw-r--r--tests/migrations/test_writer.py567
112 files changed, 9345 insertions, 5267 deletions
diff --git a/tests/migrations/deprecated_field_migrations/0001_initial.py b/tests/migrations/deprecated_field_migrations/0001_initial.py
index 8665d5b2ff..b5d606c8ad 100644
--- a/tests/migrations/deprecated_field_migrations/0001_initial.py
+++ b/tests/migrations/deprecated_field_migrations/0001_initial.py
@@ -3,15 +3,22 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='IPAddressField',
+ name="IPAddressField",
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('ip', models.IPAddressField(null=True, blank=True)),
+ (
+ "id",
+ models.AutoField(
+ verbose_name="ID",
+ serialize=False,
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
+ ("ip", models.IPAddressField(null=True, blank=True)),
],
),
]
diff --git a/tests/migrations/deprecated_field_migrations/0002_remove_ipaddressfield_ip.py b/tests/migrations/deprecated_field_migrations/0002_remove_ipaddressfield_ip.py
index 1b27bf536d..019b80fddf 100644
--- a/tests/migrations/deprecated_field_migrations/0002_remove_ipaddressfield_ip.py
+++ b/tests/migrations/deprecated_field_migrations/0002_remove_ipaddressfield_ip.py
@@ -4,12 +4,12 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
- ('migrations', '0001_initial'),
+ ("migrations", "0001_initial"),
]
operations = [
migrations.RemoveField(
- model_name='ipaddressfield',
- name='ip',
+ model_name="ipaddressfield",
+ name="ip",
),
]
diff --git a/tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0001_initial.py
index 48664b2a04..c7cf43a233 100644
--- a/tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0001_initial.py
@@ -3,15 +3,19 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='Author',
+ name="Author",
fields=[
- ('id', models.AutoField(serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=50)),
+ (
+ "id",
+ models.AutoField(
+ serialize=False, auto_created=True, primary_key=True
+ ),
+ ),
+ ("name", models.CharField(max_length=50)),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0002_alter_id.py b/tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0002_alter_id.py
index 18bc91ad72..cd18df17f3 100644
--- a/tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0002_alter_id.py
+++ b/tests/migrations/migrations_test_apps/alter_fk/author_app/migrations/0002_alter_id.py
@@ -4,14 +4,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('author_app', '0001_initial'),
- ('book_app', '0001_initial'), # Forces the book table to alter the FK
+ ("author_app", "0001_initial"),
+ ("book_app", "0001_initial"), # Forces the book table to alter the FK
]
operations = [
migrations.AlterField(
- model_name='author',
- name='id',
+ model_name="author",
+ name="id",
field=models.CharField(max_length=10, primary_key=True),
),
]
diff --git a/tests/migrations/migrations_test_apps/alter_fk/book_app/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/alter_fk/book_app/migrations/0001_initial.py
index 46543caeee..72c11285d6 100644
--- a/tests/migrations/migrations_test_apps/alter_fk/book_app/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/alter_fk/book_app/migrations/0001_initial.py
@@ -4,16 +4,21 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('author_app', '0001_initial'),
+ ("author_app", "0001_initial"),
]
operations = [
migrations.CreateModel(
- name='Book',
+ name="Book",
fields=[
- ('id', models.AutoField(serialize=False, auto_created=True, primary_key=True)),
- ('title', models.CharField(max_length=50)),
- ('author', models.ForeignKey('author_app.Author', models.CASCADE)),
+ (
+ "id",
+ models.AutoField(
+ serialize=False, auto_created=True, primary_key=True
+ ),
+ ),
+ ("title", models.CharField(max_length=50)),
+ ("author", models.ForeignKey("author_app.Author", models.CASCADE)),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py
index ddf070a8cd..59ad944f67 100644
--- a/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0001_initial.py
@@ -20,5 +20,5 @@ class Migration(migrations.Migration):
("id", models.AutoField(primary_key=True)),
("fluffy", models.BooleanField(default=True)),
],
- )
+ ),
]
diff --git a/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py
index d612af5726..7c581f158f 100644
--- a/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py
+++ b/tests/migrations/migrations_test_apps/conflicting_app_with_dependencies/migrations/0002_second.py
@@ -17,5 +17,5 @@ class Migration(migrations.Migration):
[
("id", models.AutoField(primary_key=True)),
],
- )
+ ),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0001_initial.py
index 6351b0d212..eef91811cb 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0001_initial.py
@@ -3,14 +3,21 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='A1',
+ name="A1",
fields=[
- ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
+ (
+ "id",
+ models.AutoField(
+ serialize=False,
+ verbose_name="ID",
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0002_a2.py b/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0002_a2.py
index ab943b9c77..573909f9a7 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0002_a2.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0002_a2.py
@@ -4,14 +4,22 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('lookuperror_a', '0001_initial'),
+ ("lookuperror_a", "0001_initial"),
]
operations = [
migrations.CreateModel(
- name='A2',
+ name="A2",
fields=[
- ('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
+ (
+ "id",
+ models.AutoField(
+ verbose_name="ID",
+ primary_key=True,
+ serialize=False,
+ auto_created=True,
+ ),
+ ),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0003_a3.py b/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0003_a3.py
index 42b5853d3c..d1caeb2284 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0003_a3.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0003_a3.py
@@ -4,18 +4,26 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('lookuperror_c', '0002_c2'),
- ('lookuperror_b', '0002_b2'),
- ('lookuperror_a', '0002_a2'),
+ ("lookuperror_c", "0002_c2"),
+ ("lookuperror_b", "0002_b2"),
+ ("lookuperror_a", "0002_a2"),
]
operations = [
migrations.CreateModel(
- name='A3',
+ name="A3",
fields=[
- ('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')),
- ('b2', models.ForeignKey('lookuperror_b.B2', models.CASCADE)),
- ('c2', models.ForeignKey('lookuperror_c.C2', models.CASCADE)),
+ (
+ "id",
+ models.AutoField(
+ serialize=False,
+ auto_created=True,
+ primary_key=True,
+ verbose_name="ID",
+ ),
+ ),
+ ("b2", models.ForeignKey("lookuperror_b.B2", models.CASCADE)),
+ ("c2", models.ForeignKey("lookuperror_c.C2", models.CASCADE)),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0004_a4.py b/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0004_a4.py
index b7a0bcb8a7..060bc499f5 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0004_a4.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_a/migrations/0004_a4.py
@@ -4,14 +4,22 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('lookuperror_a', '0003_a3'),
+ ("lookuperror_a", "0003_a3"),
]
operations = [
migrations.CreateModel(
- name='A4',
+ name="A4",
fields=[
- ('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ serialize=False,
+ verbose_name="ID",
+ primary_key=True,
+ ),
+ ),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_a/models.py b/tests/migrations/migrations_test_apps/lookuperror_a/models.py
index 9428f952eb..fbc4cb6809 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_a/models.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_a/models.py
@@ -10,8 +10,8 @@ class A2(models.Model):
class A3(models.Model):
- b2 = models.ForeignKey('lookuperror_b.B2', models.CASCADE)
- c2 = models.ForeignKey('lookuperror_c.C2', models.CASCADE)
+ b2 = models.ForeignKey("lookuperror_b.B2", models.CASCADE)
+ c2 = models.ForeignKey("lookuperror_c.C2", models.CASCADE)
class A4(models.Model):
diff --git a/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0001_initial.py
index def52ae789..af48c80d3c 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0001_initial.py
@@ -3,14 +3,21 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='B1',
+ name="B1",
fields=[
- ('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')),
+ (
+ "id",
+ models.AutoField(
+ serialize=False,
+ auto_created=True,
+ primary_key=True,
+ verbose_name="ID",
+ ),
+ ),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0002_b2.py b/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0002_b2.py
index a2ac5e1ba7..87ab4c3194 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0002_b2.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0002_b2.py
@@ -4,16 +4,24 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('lookuperror_a', '0002_a2'),
- ('lookuperror_b', '0001_initial'),
+ ("lookuperror_a", "0002_a2"),
+ ("lookuperror_b", "0001_initial"),
]
operations = [
migrations.CreateModel(
- name='B2',
+ name="B2",
fields=[
- ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
- ('a1', models.ForeignKey('lookuperror_a.A1', models.CASCADE)),
+ (
+ "id",
+ models.AutoField(
+ primary_key=True,
+ verbose_name="ID",
+ auto_created=True,
+ serialize=False,
+ ),
+ ),
+ ("a1", models.ForeignKey("lookuperror_a.A1", models.CASCADE)),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0003_b3.py b/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0003_b3.py
index 1c76e73ec1..e068563dd1 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0003_b3.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_b/migrations/0003_b3.py
@@ -4,14 +4,22 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('lookuperror_b', '0002_b2'),
+ ("lookuperror_b", "0002_b2"),
]
operations = [
migrations.CreateModel(
- name='B3',
+ name="B3",
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, primary_key=True, auto_created=True)),
+ (
+ "id",
+ models.AutoField(
+ verbose_name="ID",
+ serialize=False,
+ primary_key=True,
+ auto_created=True,
+ ),
+ ),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_b/models.py b/tests/migrations/migrations_test_apps/lookuperror_b/models.py
index ed78c48e68..0bca4e68ec 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_b/models.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_b/models.py
@@ -6,7 +6,7 @@ class B1(models.Model):
class B2(models.Model):
- a1 = models.ForeignKey('lookuperror_a.A1', models.CASCADE)
+ a1 = models.ForeignKey("lookuperror_a.A1", models.CASCADE)
class B3(models.Model):
diff --git a/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0001_initial.py
index 8453148b87..523259fd26 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0001_initial.py
@@ -3,14 +3,21 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='C1',
+ name="C1",
fields=[
- ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
+ (
+ "id",
+ models.AutoField(
+ serialize=False,
+ verbose_name="ID",
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0002_c2.py b/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0002_c2.py
index a928da9ae0..3699db274b 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0002_c2.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0002_c2.py
@@ -4,16 +4,24 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('lookuperror_a', '0002_a2'),
- ('lookuperror_c', '0001_initial'),
+ ("lookuperror_a", "0002_a2"),
+ ("lookuperror_c", "0001_initial"),
]
operations = [
migrations.CreateModel(
- name='C2',
+ name="C2",
fields=[
- ('id', models.AutoField(auto_created=True, verbose_name='ID', primary_key=True, serialize=False)),
- ('a1', models.ForeignKey('lookuperror_a.A1', models.CASCADE)),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ verbose_name="ID",
+ primary_key=True,
+ serialize=False,
+ ),
+ ),
+ ("a1", models.ForeignKey("lookuperror_a.A1", models.CASCADE)),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0003_c3.py b/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0003_c3.py
index 58119ac8ac..8be34afa6b 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0003_c3.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_c/migrations/0003_c3.py
@@ -4,14 +4,22 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('lookuperror_c', '0002_c2'),
+ ("lookuperror_c", "0002_c2"),
]
operations = [
migrations.CreateModel(
- name='C3',
+ name="C3",
fields=[
- ('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ serialize=False,
+ verbose_name="ID",
+ primary_key=True,
+ ),
+ ),
],
),
]
diff --git a/tests/migrations/migrations_test_apps/lookuperror_c/models.py b/tests/migrations/migrations_test_apps/lookuperror_c/models.py
index 5dc28ae5ba..dbf5bca6b8 100644
--- a/tests/migrations/migrations_test_apps/lookuperror_c/models.py
+++ b/tests/migrations/migrations_test_apps/lookuperror_c/models.py
@@ -6,7 +6,7 @@ class C1(models.Model):
class C2(models.Model):
- a1 = models.ForeignKey('lookuperror_a.A1', models.CASCADE)
+ a1 = models.ForeignKey("lookuperror_a.A1", models.CASCADE)
class C3(models.Model):
diff --git a/tests/migrations/migrations_test_apps/migrated_app/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/migrated_app/migrations/0001_initial.py
index 344bebdfe3..59ad944f67 100644
--- a/tests/migrations/migrations_test_apps/migrated_app/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/migrated_app/migrations/0001_initial.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -15,13 +14,11 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
migrations.CreateModel(
"Tribble",
[
("id", models.AutoField(primary_key=True)),
("fluffy", models.BooleanField(default=True)),
],
- )
-
+ ),
]
diff --git a/tests/migrations/migrations_test_apps/migrated_unapplied_app/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/migrated_unapplied_app/migrations/0001_initial.py
index 800ceed7e4..551f597562 100644
--- a/tests/migrations/migrations_test_apps/migrated_unapplied_app/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/migrated_unapplied_app/migrations/0001_initial.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"OtherAuthor",
[
@@ -15,5 +14,4 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
]
diff --git a/tests/migrations/migrations_test_apps/mutate_state_a/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/mutate_state_a/migrations/0001_initial.py
index 37c9bf7377..4da5347412 100644
--- a/tests/migrations/migrations_test_apps/mutate_state_a/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/mutate_state_a/migrations/0001_initial.py
@@ -4,16 +4,27 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('mutate_state_b', '0001_initial'),
+ ("mutate_state_b", "0001_initial"),
]
operations = [
- migrations.SeparateDatabaseAndState([], [
- migrations.CreateModel(
- name='A',
- fields=[
- ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
- ],
- ),
- ])
+ migrations.SeparateDatabaseAndState(
+ [],
+ [
+ migrations.CreateModel(
+ name="A",
+ fields=[
+ (
+ "id",
+ models.AutoField(
+ serialize=False,
+ verbose_name="ID",
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
+ ],
+ ),
+ ],
+ )
]
diff --git a/tests/migrations/migrations_test_apps/mutate_state_b/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/mutate_state_b/migrations/0001_initial.py
index 51c022dd7f..4d5e712d66 100644
--- a/tests/migrations/migrations_test_apps/mutate_state_b/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/mutate_state_b/migrations/0001_initial.py
@@ -3,16 +3,26 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
- migrations.SeparateDatabaseAndState([], [
- migrations.CreateModel(
- name='B',
- fields=[
- ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
- ],
- ),
- ])
+ migrations.SeparateDatabaseAndState(
+ [],
+ [
+ migrations.CreateModel(
+ name="B",
+ fields=[
+ (
+ "id",
+ models.AutoField(
+ serialize=False,
+ verbose_name="ID",
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
+ ],
+ ),
+ ],
+ )
]
diff --git a/tests/migrations/migrations_test_apps/mutate_state_b/migrations/0002_add_field.py b/tests/migrations/migrations_test_apps/mutate_state_b/migrations/0002_add_field.py
index ae968382eb..fcd8a9337a 100644
--- a/tests/migrations/migrations_test_apps/mutate_state_b/migrations/0002_add_field.py
+++ b/tests/migrations/migrations_test_apps/mutate_state_b/migrations/0002_add_field.py
@@ -4,15 +4,18 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('mutate_state_b', '0001_initial'),
+ ("mutate_state_b", "0001_initial"),
]
operations = [
- migrations.SeparateDatabaseAndState([], [
- migrations.AddField(
- model_name='B',
- name='added',
- field=models.TextField(),
- ),
- ])
+ migrations.SeparateDatabaseAndState(
+ [],
+ [
+ migrations.AddField(
+ model_name="B",
+ name="added",
+ field=models.TextField(),
+ ),
+ ],
+ )
]
diff --git a/tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py b/tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py
index 785d040800..5119205b9a 100644
--- a/tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py
+++ b/tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py
@@ -6,4 +6,5 @@ class UnmigratedModel(models.Model):
A model that is in a migration-less app (which this app is
if its migrations directory has not been repointed)
"""
+
pass
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py
index 344bebdfe3..59ad944f67 100644
--- a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0001_initial.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -15,13 +14,11 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
migrations.CreateModel(
"Tribble",
[
("id", models.AutoField(primary_key=True)),
("fluffy", models.BooleanField(default=True)),
],
- )
-
+ ),
]
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py
index ad44031030..385420e98b 100644
--- a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_conflicting_second.py
@@ -6,12 +6,10 @@ class Migration(migrations.Migration):
dependencies = [("unspecified_app_with_conflict", "0001_initial")]
operations = [
-
migrations.CreateModel(
"Something",
[
("id", models.AutoField(primary_key=True)),
],
)
-
]
diff --git a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py
index fbf5a9110c..8da324aaff 100644
--- a/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py
+++ b/tests/migrations/migrations_test_apps/unspecified_app_with_conflict/migrations/0002_second.py
@@ -6,18 +6,13 @@ class Migration(migrations.Migration):
dependencies = [("unspecified_app_with_conflict", "0001_initial")]
operations = [
-
migrations.DeleteModel("Tribble"),
-
migrations.RemoveField("Author", "silly_field"),
-
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
],
- )
-
+ ),
]
diff --git a/tests/migrations/models.py b/tests/migrations/models.py
index 440aa582d6..0d728561d0 100644
--- a/tests/migrations/models.py
+++ b/tests/migrations/models.py
@@ -11,13 +11,13 @@ class ModelWithCustomBase(models.Model, metaclass=CustomModelBase):
class UnicodeModel(models.Model):
- title = models.CharField('ÚÑÍ¢ÓÐÉ', max_length=20, default='“Ðjáñgó”')
+ title = models.CharField("ÚÑÍ¢ÓÐÉ", max_length=20, default="“Ðjáñgó”")
class Meta:
# Disable auto loading of this model as we load it on our own
apps = Apps()
- verbose_name = 'úñí©óðé µóðéø'
- verbose_name_plural = 'úñí©óðé µóðéøß'
+ verbose_name = "úñí©óðé µóðéø"
+ verbose_name_plural = "úñí©óðé µóðéøß"
def __str__(self):
return self.title
@@ -27,6 +27,7 @@ class Unserializable:
"""
An object that migration doesn't know how to serialize.
"""
+
pass
@@ -43,6 +44,7 @@ class UnmigratedModel(models.Model):
A model that is in a migration-less app (which this app is
if its migrations directory has not been repointed)
"""
+
pass
diff --git a/tests/migrations/routers.py b/tests/migrations/routers.py
index bc036382a7..211c189772 100644
--- a/tests/migrations/routers.py
+++ b/tests/migrations/routers.py
@@ -1,6 +1,6 @@
class DefaultOtherRouter:
def allow_migrate(self, db, app_label, model_name=None, **hints):
- return db in {'default', 'other'}
+ return db in {"default", "other"}
class TestRouter:
@@ -8,7 +8,7 @@ class TestRouter:
"""
The Tribble model should be the only one to appear in the 'other' db.
"""
- if model_name == 'tribble':
- return db == 'other'
- elif db != 'default':
+ if model_name == "tribble":
+ return db == "other"
+ elif db != "default":
return False
diff --git a/tests/migrations/test_add_many_to_many_field_initial/0001_initial.py b/tests/migrations/test_add_many_to_many_field_initial/0001_initial.py
index 50fd06a35f..e7e7d59633 100644
--- a/tests/migrations/test_add_many_to_many_field_initial/0001_initial.py
+++ b/tests/migrations/test_add_many_to_many_field_initial/0001_initial.py
@@ -5,25 +5,40 @@ class Migration(migrations.Migration):
initial = True
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='Project',
+ name="Project",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
],
),
migrations.CreateModel(
- name='Task',
+ name="Task",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
],
),
migrations.AddField(
- model_name='project',
- name='tasks',
- field=models.ManyToManyField(to='Task'),
+ model_name="project",
+ name="tasks",
+ field=models.ManyToManyField(to="Task"),
),
]
diff --git a/tests/migrations/test_add_many_to_many_field_initial/0002_initial.py b/tests/migrations/test_add_many_to_many_field_initial/0002_initial.py
index 1bc6c8aafa..928e4ea1c9 100644
--- a/tests/migrations/test_add_many_to_many_field_initial/0002_initial.py
+++ b/tests/migrations/test_add_many_to_many_field_initial/0002_initial.py
@@ -11,8 +11,8 @@ class Migration(migrations.Migration):
operations = [
migrations.AddField(
- model_name='task',
- name='projects',
- field=models.ManyToManyField(to='Project'),
+ model_name="task",
+ name="projects",
+ field=models.ManyToManyField(to="Project"),
),
]
diff --git a/tests/migrations/test_auto_now_add/0001_initial.py b/tests/migrations/test_auto_now_add/0001_initial.py
index f1bfb44657..e7fafc96c6 100644
--- a/tests/migrations/test_auto_now_add/0001_initial.py
+++ b/tests/migrations/test_auto_now_add/0001_initial.py
@@ -7,10 +7,18 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- name='Entry',
+ name="Entry",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('title', models.CharField(max_length=255)),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("title", models.CharField(max_length=255)),
],
),
]
diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py
index dddd4e0c94..cadc8cef30 100644
--- a/tests/migrations/test_autodetector.py
+++ b/tests/migrations/test_autodetector.py
@@ -28,11 +28,7 @@ class DeconstructibleObject:
self.kwargs = kwargs
def deconstruct(self):
- return (
- self.__module__ + '.' + self.__class__.__name__,
- self.args,
- self.kwargs
- )
+ return (self.__module__ + "." + self.__class__.__name__, self.args, self.kwargs)
class AutodetectorTests(TestCase):
@@ -40,427 +36,911 @@ class AutodetectorTests(TestCase):
Tests the migration autodetector.
"""
- author_empty = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True))])
- author_name = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ])
- author_name_null = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, null=True)),
- ])
- author_name_longer = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=400)),
- ])
- author_name_renamed = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("names", models.CharField(max_length=200)),
- ])
- author_name_default = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default='Ada Lovelace')),
- ])
- author_name_check_constraint = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ],
- {'constraints': [models.CheckConstraint(check=models.Q(name__contains='Bob'), name='name_contains_bob')]},
+ author_empty = ModelState(
+ "testapp", "Author", [("id", models.AutoField(primary_key=True))]
+ )
+ author_name = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ],
+ )
+ author_name_null = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200, null=True)),
+ ],
+ )
+ author_name_longer = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=400)),
+ ],
+ )
+ author_name_renamed = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("names", models.CharField(max_length=200)),
+ ],
+ )
+ author_name_default = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200, default="Ada Lovelace")),
+ ],
+ )
+ author_name_check_constraint = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ],
+ {
+ "constraints": [
+ models.CheckConstraint(
+ check=models.Q(name__contains="Bob"), name="name_contains_bob"
+ )
+ ]
+ },
+ )
+ author_dates_of_birth_auto_now = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("date_of_birth", models.DateField(auto_now=True)),
+ ("date_time_of_birth", models.DateTimeField(auto_now=True)),
+ ("time_of_birth", models.TimeField(auto_now=True)),
+ ],
+ )
+ author_dates_of_birth_auto_now_add = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("date_of_birth", models.DateField(auto_now_add=True)),
+ ("date_time_of_birth", models.DateTimeField(auto_now_add=True)),
+ ("time_of_birth", models.TimeField(auto_now_add=True)),
+ ],
+ )
+ author_name_deconstructible_1 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200, default=DeconstructibleObject())),
+ ],
+ )
+ author_name_deconstructible_2 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200, default=DeconstructibleObject())),
+ ],
+ )
+ author_name_deconstructible_3 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200, default=models.IntegerField())),
+ ],
+ )
+ author_name_deconstructible_4 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200, default=models.IntegerField())),
+ ],
+ )
+ author_name_deconstructible_list_1 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200, default=[DeconstructibleObject(), 123]
+ ),
+ ),
+ ],
+ )
+ author_name_deconstructible_list_2 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200, default=[DeconstructibleObject(), 123]
+ ),
+ ),
+ ],
+ )
+ author_name_deconstructible_list_3 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200, default=[DeconstructibleObject(), 999]
+ ),
+ ),
+ ],
+ )
+ author_name_deconstructible_tuple_1 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200, default=(DeconstructibleObject(), 123)
+ ),
+ ),
+ ],
+ )
+ author_name_deconstructible_tuple_2 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200, default=(DeconstructibleObject(), 123)
+ ),
+ ),
+ ],
+ )
+ author_name_deconstructible_tuple_3 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200, default=(DeconstructibleObject(), 999)
+ ),
+ ),
+ ],
+ )
+ author_name_deconstructible_dict_1 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default={"item": DeconstructibleObject(), "otheritem": 123},
+ ),
+ ),
+ ],
+ )
+ author_name_deconstructible_dict_2 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default={"item": DeconstructibleObject(), "otheritem": 123},
+ ),
+ ),
+ ],
+ )
+ author_name_deconstructible_dict_3 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default={"item": DeconstructibleObject(), "otheritem": 999},
+ ),
+ ),
+ ],
+ )
+ author_name_nested_deconstructible_1 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default=DeconstructibleObject(
+ DeconstructibleObject(1),
+ (
+ DeconstructibleObject("t1"),
+ DeconstructibleObject("t2"),
+ ),
+ a=DeconstructibleObject("A"),
+ b=DeconstructibleObject(B=DeconstructibleObject("c")),
+ ),
+ ),
+ ),
+ ],
+ )
+ author_name_nested_deconstructible_2 = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default=DeconstructibleObject(
+ DeconstructibleObject(1),
+ (
+ DeconstructibleObject("t1"),
+ DeconstructibleObject("t2"),
+ ),
+ a=DeconstructibleObject("A"),
+ b=DeconstructibleObject(B=DeconstructibleObject("c")),
+ ),
+ ),
+ ),
+ ],
+ )
+ author_name_nested_deconstructible_changed_arg = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default=DeconstructibleObject(
+ DeconstructibleObject(1),
+ (
+ DeconstructibleObject("t1"),
+ DeconstructibleObject("t2-changed"),
+ ),
+ a=DeconstructibleObject("A"),
+ b=DeconstructibleObject(B=DeconstructibleObject("c")),
+ ),
+ ),
+ ),
+ ],
+ )
+ author_name_nested_deconstructible_extra_arg = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default=DeconstructibleObject(
+ DeconstructibleObject(1),
+ (
+ DeconstructibleObject("t1"),
+ DeconstructibleObject("t2"),
+ ),
+ None,
+ a=DeconstructibleObject("A"),
+ b=DeconstructibleObject(B=DeconstructibleObject("c")),
+ ),
+ ),
+ ),
+ ],
+ )
+ author_name_nested_deconstructible_changed_kwarg = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default=DeconstructibleObject(
+ DeconstructibleObject(1),
+ (
+ DeconstructibleObject("t1"),
+ DeconstructibleObject("t2"),
+ ),
+ a=DeconstructibleObject("A"),
+ b=DeconstructibleObject(B=DeconstructibleObject("c-changed")),
+ ),
+ ),
+ ),
+ ],
+ )
+ author_name_nested_deconstructible_extra_kwarg = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ default=DeconstructibleObject(
+ DeconstructibleObject(1),
+ (
+ DeconstructibleObject("t1"),
+ DeconstructibleObject("t2"),
+ ),
+ a=DeconstructibleObject("A"),
+ b=DeconstructibleObject(B=DeconstructibleObject("c")),
+ c=None,
+ ),
+ ),
+ ),
+ ],
+ )
+ author_custom_pk = ModelState(
+ "testapp", "Author", [("pk_field", models.IntegerField(primary_key=True))]
+ )
+ author_with_biography_non_blank = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField()),
+ ("biography", models.TextField()),
+ ],
+ )
+ author_with_biography_blank = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(blank=True)),
+ ("biography", models.TextField(blank=True)),
+ ],
+ )
+ author_with_book = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ],
+ )
+ author_with_book_order_wrt = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ],
+ options={"order_with_respect_to": "book"},
+ )
+ author_renamed_with_book = ModelState(
+ "testapp",
+ "Writer",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ],
+ )
+ author_with_publisher_string = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("publisher_name", models.CharField(max_length=200)),
+ ],
+ )
+ author_with_publisher = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
+ ],
+ )
+ author_with_user = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("user", models.ForeignKey("auth.User", models.CASCADE)),
+ ],
+ )
+ author_with_custom_user = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("user", models.ForeignKey("thirdapp.CustomUser", models.CASCADE)),
+ ],
+ )
+ author_proxy = ModelState(
+ "testapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author",)
+ )
+ author_proxy_options = ModelState(
+ "testapp",
+ "AuthorProxy",
+ [],
+ {
+ "proxy": True,
+ "verbose_name": "Super Author",
+ },
+ ("testapp.author",),
+ )
+ author_proxy_notproxy = ModelState(
+ "testapp", "AuthorProxy", [], {}, ("testapp.author",)
+ )
+ author_proxy_third = ModelState(
+ "thirdapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author",)
+ )
+ author_proxy_third_notproxy = ModelState(
+ "thirdapp", "AuthorProxy", [], {}, ("testapp.author",)
+ )
+ author_proxy_proxy = ModelState(
+ "testapp", "AAuthorProxyProxy", [], {"proxy": True}, ("testapp.authorproxy",)
+ )
+ author_unmanaged = ModelState(
+ "testapp", "AuthorUnmanaged", [], {"managed": False}, ("testapp.author",)
+ )
+ author_unmanaged_managed = ModelState(
+ "testapp", "AuthorUnmanaged", [], {}, ("testapp.author",)
+ )
+ author_unmanaged_default_pk = ModelState(
+ "testapp", "Author", [("id", models.AutoField(primary_key=True))]
+ )
+ author_unmanaged_custom_pk = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("pk_field", models.IntegerField(primary_key=True)),
+ ],
+ )
+ author_with_m2m = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("publishers", models.ManyToManyField("testapp.Publisher")),
+ ],
+ )
+ author_with_m2m_blank = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("publishers", models.ManyToManyField("testapp.Publisher", blank=True)),
+ ],
+ )
+ author_with_m2m_through = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "publishers",
+ models.ManyToManyField("testapp.Publisher", through="testapp.Contract"),
+ ),
+ ],
+ )
+ author_with_renamed_m2m_through = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "publishers",
+ models.ManyToManyField("testapp.Publisher", through="testapp.Deal"),
+ ),
+ ],
+ )
+ author_with_former_m2m = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("publishers", models.CharField(max_length=100)),
+ ],
+ )
+ author_with_options = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ {
+ "permissions": [("can_hire", "Can hire")],
+ "verbose_name": "Authi",
+ },
+ )
+ author_with_db_table_options = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ {"db_table": "author_one"},
+ )
+ author_with_new_db_table_options = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ {"db_table": "author_two"},
+ )
+ author_renamed_with_db_table_options = ModelState(
+ "testapp",
+ "NewAuthor",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ {"db_table": "author_one"},
+ )
+ author_renamed_with_new_db_table_options = ModelState(
+ "testapp",
+ "NewAuthor",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ {"db_table": "author_three"},
+ )
+ contract = ModelState(
+ "testapp",
+ "Contract",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
+ ],
+ )
+ contract_renamed = ModelState(
+ "testapp",
+ "Deal",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
+ ],
+ )
+ publisher = ModelState(
+ "testapp",
+ "Publisher",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=100)),
+ ],
+ )
+ publisher_with_author = ModelState(
+ "testapp",
+ "Publisher",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("name", models.CharField(max_length=100)),
+ ],
+ )
+ publisher_with_aardvark_author = ModelState(
+ "testapp",
+ "Publisher",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Aardvark", models.CASCADE)),
+ ("name", models.CharField(max_length=100)),
+ ],
+ )
+ publisher_with_book = ModelState(
+ "testapp",
+ "Publisher",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ("name", models.CharField(max_length=100)),
+ ],
+ )
+ other_pony = ModelState(
+ "otherapp",
+ "Pony",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
+ other_pony_food = ModelState(
+ "otherapp",
+ "Pony",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ managers=[
+ ("food_qs", FoodQuerySet.as_manager()),
+ ("food_mgr", FoodManager("a", "b")),
+ ("food_mgr_kwargs", FoodManager("x", "y", 3, 4)),
+ ],
+ )
+ other_stable = ModelState(
+ "otherapp", "Stable", [("id", models.AutoField(primary_key=True))]
+ )
+ third_thing = ModelState(
+ "thirdapp", "Thing", [("id", models.AutoField(primary_key=True))]
+ )
+ book = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_proxy_fk = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("thirdapp.AuthorProxy", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_proxy_proxy_fk = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.AAuthorProxyProxy", models.CASCADE)),
+ ],
+ )
+ book_migrations_fk = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("migrations.UnmigratedModel", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_with_no_author_fk = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.IntegerField()),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_with_no_author = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_with_author_renamed = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Writer", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_with_field_and_author_renamed = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("writer", models.ForeignKey("testapp.Writer", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_with_multiple_authors = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("authors", models.ManyToManyField("testapp.Author")),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_with_multiple_authors_through_attribution = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "authors",
+ models.ManyToManyField(
+ "testapp.Author", through="otherapp.Attribution"
+ ),
+ ),
+ ("title", models.CharField(max_length=200)),
+ ],
+ )
+ book_indexes = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ {
+ "indexes": [
+ models.Index(fields=["author", "title"], name="book_title_author_idx")
+ ],
+ },
+ )
+ book_unordered_indexes = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ {
+ "indexes": [
+ models.Index(fields=["title", "author"], name="book_author_title_idx")
+ ],
+ },
+ )
+ book_foo_together = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ {
+ "index_together": {("author", "title")},
+ "unique_together": {("author", "title")},
+ },
+ )
+ book_foo_together_2 = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ {
+ "index_together": {("title", "author")},
+ "unique_together": {("title", "author")},
+ },
+ )
+ book_foo_together_3 = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("newfield", models.IntegerField()),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ {
+ "index_together": {("title", "newfield")},
+ "unique_together": {("title", "newfield")},
+ },
+ )
+ book_foo_together_4 = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("newfield2", models.IntegerField()),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ {
+ "index_together": {("title", "newfield2")},
+ "unique_together": {("title", "newfield2")},
+ },
+ )
+ attribution = ModelState(
+ "otherapp",
+ "Attribution",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
+ ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ],
+ )
+ edition = ModelState(
+ "thirdapp",
+ "Edition",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ],
+ )
+ custom_user = ModelState(
+ "thirdapp",
+ "CustomUser",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("username", models.CharField(max_length=255)),
+ ],
+ bases=(AbstractBaseUser,),
+ )
+ custom_user_no_inherit = ModelState(
+ "thirdapp",
+ "CustomUser",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("username", models.CharField(max_length=255)),
+ ],
+ )
+ aardvark = ModelState(
+ "thirdapp", "Aardvark", [("id", models.AutoField(primary_key=True))]
+ )
+ aardvark_testapp = ModelState(
+ "testapp", "Aardvark", [("id", models.AutoField(primary_key=True))]
+ )
+ aardvark_based_on_author = ModelState(
+ "testapp", "Aardvark", [], bases=("testapp.Author",)
+ )
+ aardvark_pk_fk_author = ModelState(
+ "testapp",
+ "Aardvark",
+ [
+ (
+ "id",
+ models.OneToOneField(
+ "testapp.Author", models.CASCADE, primary_key=True
+ ),
+ ),
+ ],
)
- author_dates_of_birth_auto_now = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("date_of_birth", models.DateField(auto_now=True)),
- ("date_time_of_birth", models.DateTimeField(auto_now=True)),
- ("time_of_birth", models.TimeField(auto_now=True)),
- ])
- author_dates_of_birth_auto_now_add = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("date_of_birth", models.DateField(auto_now_add=True)),
- ("date_time_of_birth", models.DateTimeField(auto_now_add=True)),
- ("time_of_birth", models.TimeField(auto_now_add=True)),
- ])
- author_name_deconstructible_1 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=DeconstructibleObject())),
- ])
- author_name_deconstructible_2 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=DeconstructibleObject())),
- ])
- author_name_deconstructible_3 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=models.IntegerField())),
- ])
- author_name_deconstructible_4 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=models.IntegerField())),
- ])
- author_name_deconstructible_list_1 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=[DeconstructibleObject(), 123])),
- ])
- author_name_deconstructible_list_2 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=[DeconstructibleObject(), 123])),
- ])
- author_name_deconstructible_list_3 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=[DeconstructibleObject(), 999])),
- ])
- author_name_deconstructible_tuple_1 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=(DeconstructibleObject(), 123))),
- ])
- author_name_deconstructible_tuple_2 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=(DeconstructibleObject(), 123))),
- ])
- author_name_deconstructible_tuple_3 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=(DeconstructibleObject(), 999))),
- ])
- author_name_deconstructible_dict_1 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default={
- 'item': DeconstructibleObject(), 'otheritem': 123
- })),
- ])
- author_name_deconstructible_dict_2 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default={
- 'item': DeconstructibleObject(), 'otheritem': 123
- })),
- ])
- author_name_deconstructible_dict_3 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default={
- 'item': DeconstructibleObject(), 'otheritem': 999
- })),
- ])
- author_name_nested_deconstructible_1 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=DeconstructibleObject(
- DeconstructibleObject(1),
- (DeconstructibleObject('t1'), DeconstructibleObject('t2'),),
- a=DeconstructibleObject('A'),
- b=DeconstructibleObject(B=DeconstructibleObject('c')),
- ))),
- ])
- author_name_nested_deconstructible_2 = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=DeconstructibleObject(
- DeconstructibleObject(1),
- (DeconstructibleObject('t1'), DeconstructibleObject('t2'),),
- a=DeconstructibleObject('A'),
- b=DeconstructibleObject(B=DeconstructibleObject('c')),
- ))),
- ])
- author_name_nested_deconstructible_changed_arg = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=DeconstructibleObject(
- DeconstructibleObject(1),
- (DeconstructibleObject('t1'), DeconstructibleObject('t2-changed'),),
- a=DeconstructibleObject('A'),
- b=DeconstructibleObject(B=DeconstructibleObject('c')),
- ))),
- ])
- author_name_nested_deconstructible_extra_arg = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=DeconstructibleObject(
- DeconstructibleObject(1),
- (DeconstructibleObject('t1'), DeconstructibleObject('t2'),),
- None,
- a=DeconstructibleObject('A'),
- b=DeconstructibleObject(B=DeconstructibleObject('c')),
- ))),
- ])
- author_name_nested_deconstructible_changed_kwarg = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=DeconstructibleObject(
- DeconstructibleObject(1),
- (DeconstructibleObject('t1'), DeconstructibleObject('t2'),),
- a=DeconstructibleObject('A'),
- b=DeconstructibleObject(B=DeconstructibleObject('c-changed')),
- ))),
- ])
- author_name_nested_deconstructible_extra_kwarg = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200, default=DeconstructibleObject(
- DeconstructibleObject(1),
- (DeconstructibleObject('t1'), DeconstructibleObject('t2'),),
- a=DeconstructibleObject('A'),
- b=DeconstructibleObject(B=DeconstructibleObject('c')),
- c=None,
- ))),
- ])
- author_custom_pk = ModelState("testapp", "Author", [("pk_field", models.IntegerField(primary_key=True))])
- author_with_biography_non_blank = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField()),
- ("biography", models.TextField()),
- ])
- author_with_biography_blank = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(blank=True)),
- ("biography", models.TextField(blank=True)),
- ])
- author_with_book = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
- ])
- author_with_book_order_wrt = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
- ], options={"order_with_respect_to": "book"})
- author_renamed_with_book = ModelState("testapp", "Writer", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
- ])
- author_with_publisher_string = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ("publisher_name", models.CharField(max_length=200)),
- ])
- author_with_publisher = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
- ])
- author_with_user = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ("user", models.ForeignKey("auth.User", models.CASCADE)),
- ])
- author_with_custom_user = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ("user", models.ForeignKey("thirdapp.CustomUser", models.CASCADE)),
- ])
- author_proxy = ModelState("testapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author",))
- author_proxy_options = ModelState("testapp", "AuthorProxy", [], {
- "proxy": True,
- "verbose_name": "Super Author",
- }, ("testapp.author",))
- author_proxy_notproxy = ModelState("testapp", "AuthorProxy", [], {}, ("testapp.author",))
- author_proxy_third = ModelState("thirdapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author",))
- author_proxy_third_notproxy = ModelState("thirdapp", "AuthorProxy", [], {}, ("testapp.author",))
- author_proxy_proxy = ModelState("testapp", "AAuthorProxyProxy", [], {"proxy": True}, ("testapp.authorproxy",))
- author_unmanaged = ModelState("testapp", "AuthorUnmanaged", [], {"managed": False}, ("testapp.author",))
- author_unmanaged_managed = ModelState("testapp", "AuthorUnmanaged", [], {}, ("testapp.author",))
- author_unmanaged_default_pk = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True))])
- author_unmanaged_custom_pk = ModelState("testapp", "Author", [
- ("pk_field", models.IntegerField(primary_key=True)),
- ])
- author_with_m2m = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("publishers", models.ManyToManyField("testapp.Publisher")),
- ])
- author_with_m2m_blank = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("publishers", models.ManyToManyField("testapp.Publisher", blank=True)),
- ])
- author_with_m2m_through = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("publishers", models.ManyToManyField("testapp.Publisher", through="testapp.Contract")),
- ])
- author_with_renamed_m2m_through = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("publishers", models.ManyToManyField("testapp.Publisher", through="testapp.Deal")),
- ])
- author_with_former_m2m = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("publishers", models.CharField(max_length=100)),
- ])
- author_with_options = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ], {
- "permissions": [('can_hire', 'Can hire')],
- "verbose_name": "Authi",
- })
- author_with_db_table_options = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ], {"db_table": "author_one"})
- author_with_new_db_table_options = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ], {"db_table": "author_two"})
- author_renamed_with_db_table_options = ModelState("testapp", "NewAuthor", [
- ("id", models.AutoField(primary_key=True)),
- ], {"db_table": "author_one"})
- author_renamed_with_new_db_table_options = ModelState("testapp", "NewAuthor", [
- ("id", models.AutoField(primary_key=True)),
- ], {"db_table": "author_three"})
- contract = ModelState("testapp", "Contract", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
- ])
- contract_renamed = ModelState("testapp", "Deal", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
- ])
- publisher = ModelState("testapp", "Publisher", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=100)),
- ])
- publisher_with_author = ModelState("testapp", "Publisher", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("name", models.CharField(max_length=100)),
- ])
- publisher_with_aardvark_author = ModelState("testapp", "Publisher", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Aardvark", models.CASCADE)),
- ("name", models.CharField(max_length=100)),
- ])
- publisher_with_book = ModelState("testapp", "Publisher", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("otherapp.Book", models.CASCADE)),
- ("name", models.CharField(max_length=100)),
- ])
- other_pony = ModelState("otherapp", "Pony", [
- ("id", models.AutoField(primary_key=True)),
- ])
- other_pony_food = ModelState("otherapp", "Pony", [
- ("id", models.AutoField(primary_key=True)),
- ], managers=[
- ('food_qs', FoodQuerySet.as_manager()),
- ('food_mgr', FoodManager('a', 'b')),
- ('food_mgr_kwargs', FoodManager('x', 'y', 3, 4)),
- ])
- other_stable = ModelState("otherapp", "Stable", [("id", models.AutoField(primary_key=True))])
- third_thing = ModelState("thirdapp", "Thing", [("id", models.AutoField(primary_key=True))])
- book = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ])
- book_proxy_fk = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("thirdapp.AuthorProxy", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ])
- book_proxy_proxy_fk = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.AAuthorProxyProxy", models.CASCADE)),
- ])
- book_migrations_fk = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.UnmigratedModel", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ])
- book_with_no_author_fk = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.IntegerField()),
- ("title", models.CharField(max_length=200)),
- ])
- book_with_no_author = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("title", models.CharField(max_length=200)),
- ])
- book_with_author_renamed = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Writer", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ])
- book_with_field_and_author_renamed = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("writer", models.ForeignKey("testapp.Writer", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ])
- book_with_multiple_authors = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("authors", models.ManyToManyField("testapp.Author")),
- ("title", models.CharField(max_length=200)),
- ])
- book_with_multiple_authors_through_attribution = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("authors", models.ManyToManyField("testapp.Author", through="otherapp.Attribution")),
- ("title", models.CharField(max_length=200)),
- ])
- book_indexes = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ], {
- "indexes": [models.Index(fields=["author", "title"], name="book_title_author_idx")],
- })
- book_unordered_indexes = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ], {
- "indexes": [models.Index(fields=["title", "author"], name="book_author_title_idx")],
- })
- book_foo_together = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ], {
- "index_together": {("author", "title")},
- "unique_together": {("author", "title")},
- })
- book_foo_together_2 = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ], {
- "index_together": {("title", "author")},
- "unique_together": {("title", "author")},
- })
- book_foo_together_3 = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("newfield", models.IntegerField()),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ], {
- "index_together": {("title", "newfield")},
- "unique_together": {("title", "newfield")},
- })
- book_foo_together_4 = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("newfield2", models.IntegerField()),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ], {
- "index_together": {("title", "newfield2")},
- "unique_together": {("title", "newfield2")},
- })
- attribution = ModelState("otherapp", "Attribution", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
- ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
- ])
- edition = ModelState("thirdapp", "Edition", [
- ("id", models.AutoField(primary_key=True)),
- ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
- ])
- custom_user = ModelState("thirdapp", "CustomUser", [
- ("id", models.AutoField(primary_key=True)),
- ("username", models.CharField(max_length=255)),
- ], bases=(AbstractBaseUser,))
- custom_user_no_inherit = ModelState("thirdapp", "CustomUser", [
- ("id", models.AutoField(primary_key=True)),
- ("username", models.CharField(max_length=255)),
- ])
- aardvark = ModelState("thirdapp", "Aardvark", [("id", models.AutoField(primary_key=True))])
- aardvark_testapp = ModelState("testapp", "Aardvark", [("id", models.AutoField(primary_key=True))])
- aardvark_based_on_author = ModelState("testapp", "Aardvark", [], bases=("testapp.Author",))
- aardvark_pk_fk_author = ModelState("testapp", "Aardvark", [
- ("id", models.OneToOneField("testapp.Author", models.CASCADE, primary_key=True)),
- ])
knight = ModelState("eggs", "Knight", [("id", models.AutoField(primary_key=True))])
- rabbit = ModelState("eggs", "Rabbit", [
- ("id", models.AutoField(primary_key=True)),
- ("knight", models.ForeignKey("eggs.Knight", models.CASCADE)),
- ("parent", models.ForeignKey("eggs.Rabbit", models.CASCADE)),
- ], {
- "unique_together": {("parent", "knight")},
- "indexes": [models.Index(fields=["parent", "knight"], name='rabbit_circular_fk_index')],
- })
+ rabbit = ModelState(
+ "eggs",
+ "Rabbit",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("knight", models.ForeignKey("eggs.Knight", models.CASCADE)),
+ ("parent", models.ForeignKey("eggs.Rabbit", models.CASCADE)),
+ ],
+ {
+ "unique_together": {("parent", "knight")},
+ "indexes": [
+ models.Index(
+ fields=["parent", "knight"], name="rabbit_circular_fk_index"
+ )
+ ],
+ },
+ )
def repr_changes(self, changes, include_dependencies=False):
output = ""
@@ -481,100 +961,154 @@ class AutodetectorTests(TestCase):
def assertNumberMigrations(self, changes, app_label, number):
if len(changes.get(app_label, [])) != number:
- self.fail("Incorrect number of migrations (%s) for %s (expected %s)\n%s" % (
- len(changes.get(app_label, [])),
- app_label,
- number,
- self.repr_changes(changes),
- ))
+ self.fail(
+ "Incorrect number of migrations (%s) for %s (expected %s)\n%s"
+ % (
+ len(changes.get(app_label, [])),
+ app_label,
+ number,
+ self.repr_changes(changes),
+ )
+ )
def assertMigrationDependencies(self, changes, app_label, position, dependencies):
if not changes.get(app_label):
- self.fail("No migrations found for %s\n%s" % (app_label, self.repr_changes(changes)))
+ self.fail(
+ "No migrations found for %s\n%s"
+ % (app_label, self.repr_changes(changes))
+ )
if len(changes[app_label]) < position + 1:
- self.fail("No migration at index %s for %s\n%s" % (position, app_label, self.repr_changes(changes)))
+ self.fail(
+ "No migration at index %s for %s\n%s"
+ % (position, app_label, self.repr_changes(changes))
+ )
migration = changes[app_label][position]
if set(migration.dependencies) != set(dependencies):
- self.fail("Migration dependencies mismatch for %s.%s (expected %s):\n%s" % (
- app_label,
- migration.name,
- dependencies,
- self.repr_changes(changes, include_dependencies=True),
- ))
+ self.fail(
+ "Migration dependencies mismatch for %s.%s (expected %s):\n%s"
+ % (
+ app_label,
+ migration.name,
+ dependencies,
+ self.repr_changes(changes, include_dependencies=True),
+ )
+ )
def assertOperationTypes(self, changes, app_label, position, types):
if not changes.get(app_label):
- self.fail("No migrations found for %s\n%s" % (app_label, self.repr_changes(changes)))
+ self.fail(
+ "No migrations found for %s\n%s"
+ % (app_label, self.repr_changes(changes))
+ )
if len(changes[app_label]) < position + 1:
- self.fail("No migration at index %s for %s\n%s" % (position, app_label, self.repr_changes(changes)))
+ self.fail(
+ "No migration at index %s for %s\n%s"
+ % (position, app_label, self.repr_changes(changes))
+ )
migration = changes[app_label][position]
- real_types = [operation.__class__.__name__ for operation in migration.operations]
+ real_types = [
+ operation.__class__.__name__ for operation in migration.operations
+ ]
if types != real_types:
- self.fail("Operation type mismatch for %s.%s (expected %s):\n%s" % (
- app_label,
- migration.name,
- types,
- self.repr_changes(changes),
- ))
+ self.fail(
+ "Operation type mismatch for %s.%s (expected %s):\n%s"
+ % (
+ app_label,
+ migration.name,
+ types,
+ self.repr_changes(changes),
+ )
+ )
- def assertOperationAttributes(self, changes, app_label, position, operation_position, **attrs):
+ def assertOperationAttributes(
+ self, changes, app_label, position, operation_position, **attrs
+ ):
if not changes.get(app_label):
- self.fail("No migrations found for %s\n%s" % (app_label, self.repr_changes(changes)))
+ self.fail(
+ "No migrations found for %s\n%s"
+ % (app_label, self.repr_changes(changes))
+ )
if len(changes[app_label]) < position + 1:
- self.fail("No migration at index %s for %s\n%s" % (position, app_label, self.repr_changes(changes)))
+ self.fail(
+ "No migration at index %s for %s\n%s"
+ % (position, app_label, self.repr_changes(changes))
+ )
migration = changes[app_label][position]
if len(changes[app_label]) < position + 1:
- self.fail("No operation at index %s for %s.%s\n%s" % (
- operation_position,
- app_label,
- migration.name,
- self.repr_changes(changes),
- ))
- operation = migration.operations[operation_position]
- for attr, value in attrs.items():
- if getattr(operation, attr, None) != value:
- self.fail("Attribute mismatch for %s.%s op #%s, %s (expected %r, got %r):\n%s" % (
+ self.fail(
+ "No operation at index %s for %s.%s\n%s"
+ % (
+ operation_position,
app_label,
migration.name,
- operation_position,
- attr,
- value,
- getattr(operation, attr, None),
self.repr_changes(changes),
- ))
+ )
+ )
+ operation = migration.operations[operation_position]
+ for attr, value in attrs.items():
+ if getattr(operation, attr, None) != value:
+ self.fail(
+ "Attribute mismatch for %s.%s op #%s, %s (expected %r, got %r):\n%s"
+ % (
+ app_label,
+ migration.name,
+ operation_position,
+ attr,
+ value,
+ getattr(operation, attr, None),
+ self.repr_changes(changes),
+ )
+ )
- def assertOperationFieldAttributes(self, changes, app_label, position, operation_position, **attrs):
+ def assertOperationFieldAttributes(
+ self, changes, app_label, position, operation_position, **attrs
+ ):
if not changes.get(app_label):
- self.fail("No migrations found for %s\n%s" % (app_label, self.repr_changes(changes)))
+ self.fail(
+ "No migrations found for %s\n%s"
+ % (app_label, self.repr_changes(changes))
+ )
if len(changes[app_label]) < position + 1:
- self.fail("No migration at index %s for %s\n%s" % (position, app_label, self.repr_changes(changes)))
+ self.fail(
+ "No migration at index %s for %s\n%s"
+ % (position, app_label, self.repr_changes(changes))
+ )
migration = changes[app_label][position]
if len(changes[app_label]) < position + 1:
- self.fail("No operation at index %s for %s.%s\n%s" % (
- operation_position,
- app_label,
- migration.name,
- self.repr_changes(changes),
- ))
+ self.fail(
+ "No operation at index %s for %s.%s\n%s"
+ % (
+ operation_position,
+ app_label,
+ migration.name,
+ self.repr_changes(changes),
+ )
+ )
operation = migration.operations[operation_position]
- if not hasattr(operation, 'field'):
- self.fail("No field attribute for %s.%s op #%s." % (
- app_label,
- migration.name,
- operation_position,
- ))
- field = operation.field
- for attr, value in attrs.items():
- if getattr(field, attr, None) != value:
- self.fail("Field attribute mismatch for %s.%s op #%s, field.%s (expected %r, got %r):\n%s" % (
+ if not hasattr(operation, "field"):
+ self.fail(
+ "No field attribute for %s.%s op #%s."
+ % (
app_label,
migration.name,
operation_position,
- attr,
- value,
- getattr(field, attr, None),
- self.repr_changes(changes),
- ))
+ )
+ )
+ field = operation.field
+ for attr, value in attrs.items():
+ if getattr(field, attr, None) != value:
+ self.fail(
+ "Field attribute mismatch for %s.%s op #%s, field.%s (expected %r, got %r):\n%s"
+ % (
+ app_label,
+ migration.name,
+ operation_position,
+ attr,
+ value,
+ getattr(field, attr, None),
+ self.repr_changes(changes),
+ )
+ )
def make_project_state(self, model_states):
"Shortcut to make ProjectStates from lists of predefined models"
@@ -601,42 +1135,65 @@ class AutodetectorTests(TestCase):
graph.add_node(("testapp", "0001_initial"), None)
graph.add_node(("testapp", "0002_foobar"), None)
graph.add_node(("otherapp", "0001_initial"), None)
- graph.add_dependency("testapp.0002_foobar", ("testapp", "0002_foobar"), ("testapp", "0001_initial"))
- graph.add_dependency("testapp.0002_foobar", ("testapp", "0002_foobar"), ("otherapp", "0001_initial"))
+ graph.add_dependency(
+ "testapp.0002_foobar",
+ ("testapp", "0002_foobar"),
+ ("testapp", "0001_initial"),
+ )
+ graph.add_dependency(
+ "testapp.0002_foobar",
+ ("testapp", "0002_foobar"),
+ ("otherapp", "0001_initial"),
+ )
# Use project state to make a new migration change set
before = self.make_project_state([self.publisher, self.other_pony])
- after = self.make_project_state([
- self.author_empty, self.publisher, self.other_pony, self.other_stable,
- ])
+ after = self.make_project_state(
+ [
+ self.author_empty,
+ self.publisher,
+ self.other_pony,
+ self.other_stable,
+ ]
+ )
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
# Run through arrange_for_graph
changes = autodetector.arrange_for_graph(changes, graph)
# Make sure there's a new name, deps match, etc.
self.assertEqual(changes["testapp"][0].name, "0003_author")
- self.assertEqual(changes["testapp"][0].dependencies, [("testapp", "0002_foobar")])
- self.assertEqual(changes["otherapp"][0].name, '0002_stable')
- self.assertEqual(changes["otherapp"][0].dependencies, [("otherapp", "0001_initial")])
+ self.assertEqual(
+ changes["testapp"][0].dependencies, [("testapp", "0002_foobar")]
+ )
+ self.assertEqual(changes["otherapp"][0].name, "0002_stable")
+ self.assertEqual(
+ changes["otherapp"][0].dependencies, [("otherapp", "0001_initial")]
+ )
def test_arrange_for_graph_with_multiple_initial(self):
# Make a fake graph.
graph = MigrationGraph()
# Use project state to make a new migration change set.
before = self.make_project_state([])
- after = self.make_project_state([self.author_with_book, self.book, self.attribution])
- autodetector = MigrationAutodetector(before, after, MigrationQuestioner({'ask_initial': True}))
+ after = self.make_project_state(
+ [self.author_with_book, self.book, self.attribution]
+ )
+ autodetector = MigrationAutodetector(
+ before, after, MigrationQuestioner({"ask_initial": True})
+ )
changes = autodetector._detect_changes()
changes = autodetector.arrange_for_graph(changes, graph)
- self.assertEqual(changes['otherapp'][0].name, '0001_initial')
- self.assertEqual(changes['otherapp'][0].dependencies, [])
- self.assertEqual(changes['otherapp'][1].name, '0002_initial')
+ self.assertEqual(changes["otherapp"][0].name, "0001_initial")
+ self.assertEqual(changes["otherapp"][0].dependencies, [])
+ self.assertEqual(changes["otherapp"][1].name, "0002_initial")
self.assertCountEqual(
- changes['otherapp'][1].dependencies,
- [('testapp', '0001_initial'), ('otherapp', '0001_initial')],
+ changes["otherapp"][1].dependencies,
+ [("testapp", "0001_initial"), ("otherapp", "0001_initial")],
+ )
+ self.assertEqual(changes["testapp"][0].name, "0001_initial")
+ self.assertEqual(
+ changes["testapp"][0].dependencies, [("otherapp", "0001_initial")]
)
- self.assertEqual(changes['testapp'][0].name, '0001_initial')
- self.assertEqual(changes['testapp'][0].dependencies, [('otherapp', '0001_initial')])
def test_trim_apps(self):
"""
@@ -644,8 +1201,12 @@ class AutodetectorTests(TestCase):
"""
# Use project state to make a new migration change set
before = self.make_project_state([])
- after = self.make_project_state([self.author_empty, self.other_pony, self.other_stable, self.third_thing])
- autodetector = MigrationAutodetector(before, after, MigrationQuestioner({"ask_initial": True}))
+ after = self.make_project_state(
+ [self.author_empty, self.other_pony, self.other_stable, self.third_thing]
+ )
+ autodetector = MigrationAutodetector(
+ before, after, MigrationQuestioner({"ask_initial": True})
+ )
changes = autodetector._detect_changes()
# Run through arrange_for_graph
graph = MigrationGraph()
@@ -664,78 +1225,114 @@ class AutodetectorTests(TestCase):
graph.add_node(("testapp", "0001_initial"), None)
graph.add_node(("testapp", "0002_foobar"), None)
graph.add_node(("otherapp", "0001_initial"), None)
- graph.add_dependency("testapp.0002_foobar", ("testapp", "0002_foobar"), ("testapp", "0001_initial"))
+ graph.add_dependency(
+ "testapp.0002_foobar",
+ ("testapp", "0002_foobar"),
+ ("testapp", "0001_initial"),
+ )
# Use project state to make a new migration change set
before = self.make_project_state([])
- after = self.make_project_state([self.author_empty, self.other_pony, self.other_stable])
+ after = self.make_project_state(
+ [self.author_empty, self.other_pony, self.other_stable]
+ )
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
# Run through arrange_for_graph
- migration_name = 'custom_name'
+ migration_name = "custom_name"
changes = autodetector.arrange_for_graph(changes, graph, migration_name)
# Make sure there's a new name, deps match, etc.
self.assertEqual(changes["testapp"][0].name, "0003_%s" % migration_name)
- self.assertEqual(changes["testapp"][0].dependencies, [("testapp", "0002_foobar")])
+ self.assertEqual(
+ changes["testapp"][0].dependencies, [("testapp", "0002_foobar")]
+ )
self.assertEqual(changes["otherapp"][0].name, "0002_%s" % migration_name)
- self.assertEqual(changes["otherapp"][0].dependencies, [("otherapp", "0001_initial")])
+ self.assertEqual(
+ changes["otherapp"][0].dependencies, [("otherapp", "0001_initial")]
+ )
def test_new_model(self):
"""Tests autodetection of new models."""
changes = self.get_changes([], [self.other_pony_food])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Pony")
- self.assertEqual([name for name, mgr in changes['otherapp'][0].operations[0].managers],
- ['food_qs', 'food_mgr', 'food_mgr_kwargs'])
+ self.assertEqual(
+ [name for name, mgr in changes["otherapp"][0].operations[0].managers],
+ ["food_qs", "food_mgr", "food_mgr_kwargs"],
+ )
def test_old_model(self):
"""Tests deletion of old models."""
changes = self.get_changes([self.author_empty], [])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["DeleteModel"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
def test_add_field(self):
"""Tests autodetection of new fields."""
changes = self.get_changes([self.author_empty], [self.author_name])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AddField"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="name")
- @mock.patch('django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition',
- side_effect=AssertionError("Should not have prompted for not null addition"))
- def test_add_date_fields_with_auto_now_not_asking_for_default(self, mocked_ask_method):
- changes = self.get_changes([self.author_empty], [self.author_dates_of_birth_auto_now])
+ @mock.patch(
+ "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition",
+ side_effect=AssertionError("Should not have prompted for not null addition"),
+ )
+ def test_add_date_fields_with_auto_now_not_asking_for_default(
+ self, mocked_ask_method
+ ):
+ changes = self.get_changes(
+ [self.author_empty], [self.author_dates_of_birth_auto_now]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField", "AddField", "AddField"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["AddField", "AddField", "AddField"]
+ )
self.assertOperationFieldAttributes(changes, "testapp", 0, 0, auto_now=True)
self.assertOperationFieldAttributes(changes, "testapp", 0, 1, auto_now=True)
self.assertOperationFieldAttributes(changes, "testapp", 0, 2, auto_now=True)
- @mock.patch('django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition',
- side_effect=AssertionError("Should not have prompted for not null addition"))
- def test_add_date_fields_with_auto_now_add_not_asking_for_null_addition(self, mocked_ask_method):
- changes = self.get_changes([self.author_empty], [self.author_dates_of_birth_auto_now_add])
+ @mock.patch(
+ "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition",
+ side_effect=AssertionError("Should not have prompted for not null addition"),
+ )
+ def test_add_date_fields_with_auto_now_add_not_asking_for_null_addition(
+ self, mocked_ask_method
+ ):
+ changes = self.get_changes(
+ [self.author_empty], [self.author_dates_of_birth_auto_now_add]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField", "AddField", "AddField"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["AddField", "AddField", "AddField"]
+ )
self.assertOperationFieldAttributes(changes, "testapp", 0, 0, auto_now_add=True)
self.assertOperationFieldAttributes(changes, "testapp", 0, 1, auto_now_add=True)
self.assertOperationFieldAttributes(changes, "testapp", 0, 2, auto_now_add=True)
- @mock.patch('django.db.migrations.questioner.MigrationQuestioner.ask_auto_now_add_addition')
- def test_add_date_fields_with_auto_now_add_asking_for_default(self, mocked_ask_method):
- changes = self.get_changes([self.author_empty], [self.author_dates_of_birth_auto_now_add])
+ @mock.patch(
+ "django.db.migrations.questioner.MigrationQuestioner.ask_auto_now_add_addition"
+ )
+ def test_add_date_fields_with_auto_now_add_asking_for_default(
+ self, mocked_ask_method
+ ):
+ changes = self.get_changes(
+ [self.author_empty], [self.author_dates_of_birth_auto_now_add]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField", "AddField", "AddField"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["AddField", "AddField", "AddField"]
+ )
self.assertOperationFieldAttributes(changes, "testapp", 0, 0, auto_now_add=True)
self.assertOperationFieldAttributes(changes, "testapp", 0, 1, auto_now_add=True)
self.assertOperationFieldAttributes(changes, "testapp", 0, 2, auto_now_add=True)
@@ -745,83 +1342,136 @@ class AutodetectorTests(TestCase):
"""Tests autodetection of removed fields."""
changes = self.get_changes([self.author_name], [self.author_empty])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["RemoveField"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RemoveField"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="name")
def test_alter_field(self):
"""Tests autodetection of new fields."""
changes = self.get_changes([self.author_name], [self.author_name_longer])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=True)
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="name", preserve_default=True
+ )
def test_supports_functools_partial(self):
def _content_file_name(instance, filename, key, **kwargs):
- return '{}/{}'.format(instance, filename)
+ return "{}/{}".format(instance, filename)
def content_file_name(key, **kwargs):
return functools.partial(_content_file_name, key, **kwargs)
# An unchanged partial reference.
- before = [ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("file", models.FileField(max_length=200, upload_to=content_file_name('file'))),
- ])]
- after = [ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("file", models.FileField(max_length=200, upload_to=content_file_name('file'))),
- ])]
+ before = [
+ ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "file",
+ models.FileField(
+ max_length=200, upload_to=content_file_name("file")
+ ),
+ ),
+ ],
+ )
+ ]
+ after = [
+ ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "file",
+ models.FileField(
+ max_length=200, upload_to=content_file_name("file")
+ ),
+ ),
+ ],
+ )
+ ]
changes = self.get_changes(before, after)
- self.assertNumberMigrations(changes, 'testapp', 0)
+ self.assertNumberMigrations(changes, "testapp", 0)
# A changed partial reference.
- args_changed = [ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("file", models.FileField(max_length=200, upload_to=content_file_name('other-file'))),
- ])]
+ args_changed = [
+ ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "file",
+ models.FileField(
+ max_length=200, upload_to=content_file_name("other-file")
+ ),
+ ),
+ ],
+ )
+ ]
changes = self.get_changes(before, args_changed)
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['AlterField'])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
# Can't use assertOperationFieldAttributes because we need the
# deconstructed version, i.e., the exploded func/args/keywords rather
# than the partial: we don't care if it's not the same instance of the
# partial, only if it's the same source function, args, and keywords.
- value = changes['testapp'][0].operations[0].field.upload_to
+ value = changes["testapp"][0].operations[0].field.upload_to
self.assertEqual(
- (_content_file_name, ('other-file',), {}),
- (value.func, value.args, value.keywords)
+ (_content_file_name, ("other-file",), {}),
+ (value.func, value.args, value.keywords),
)
- kwargs_changed = [ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("file", models.FileField(max_length=200, upload_to=content_file_name('file', spam='eggs'))),
- ])]
+ kwargs_changed = [
+ ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "file",
+ models.FileField(
+ max_length=200,
+ upload_to=content_file_name("file", spam="eggs"),
+ ),
+ ),
+ ],
+ )
+ ]
changes = self.get_changes(before, kwargs_changed)
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['AlterField'])
- value = changes['testapp'][0].operations[0].field.upload_to
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
+ value = changes["testapp"][0].operations[0].field.upload_to
self.assertEqual(
- (_content_file_name, ('file',), {'spam': 'eggs'}),
- (value.func, value.args, value.keywords)
+ (_content_file_name, ("file",), {"spam": "eggs"}),
+ (value.func, value.args, value.keywords),
)
- @mock.patch('django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration',
- side_effect=AssertionError("Should not have prompted for not null addition"))
+ @mock.patch(
+ "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration",
+ side_effect=AssertionError("Should not have prompted for not null addition"),
+ )
def test_alter_field_to_not_null_with_default(self, mocked_ask_method):
"""
#23609 - Tests autodetection of nullable to non-nullable alterations.
"""
changes = self.get_changes([self.author_name_null], [self.author_name_default])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=True)
- self.assertOperationFieldAttributes(changes, "testapp", 0, 0, default='Ada Lovelace')
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="name", preserve_default=True
+ )
+ self.assertOperationFieldAttributes(
+ changes, "testapp", 0, 0, default="Ada Lovelace"
+ )
@mock.patch(
- 'django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration',
+ "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration",
return_value=models.NOT_PROVIDED,
)
def test_alter_field_to_not_null_without_default(self, mocked_ask_method):
@@ -831,14 +1481,18 @@ class AutodetectorTests(TestCase):
changes = self.get_changes([self.author_name_null], [self.author_name])
self.assertEqual(mocked_ask_method.call_count, 1)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=True)
- self.assertOperationFieldAttributes(changes, "testapp", 0, 0, default=models.NOT_PROVIDED)
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="name", preserve_default=True
+ )
+ self.assertOperationFieldAttributes(
+ changes, "testapp", 0, 0, default=models.NOT_PROVIDED
+ )
@mock.patch(
- 'django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration',
- return_value='Some Name',
+ "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration",
+ return_value="Some Name",
)
def test_alter_field_to_not_null_oneoff_default(self, mocked_ask_method):
"""
@@ -847,140 +1501,269 @@ class AutodetectorTests(TestCase):
changes = self.get_changes([self.author_name_null], [self.author_name])
self.assertEqual(mocked_ask_method.call_count, 1)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=False)
- self.assertOperationFieldAttributes(changes, "testapp", 0, 0, default="Some Name")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="name", preserve_default=False
+ )
+ self.assertOperationFieldAttributes(
+ changes, "testapp", 0, 0, default="Some Name"
+ )
def test_rename_field(self):
"""Tests autodetection of renamed fields."""
changes = self.get_changes(
- [self.author_name], [self.author_name_renamed], MigrationQuestioner({"ask_rename": True})
+ [self.author_name],
+ [self.author_name_renamed],
+ MigrationQuestioner({"ask_rename": True}),
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["RenameField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name="name", new_name="names")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RenameField"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, old_name="name", new_name="names"
+ )
def test_rename_field_foreign_key_to_field(self):
before = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ('field', models.IntegerField(unique=True)),
- ]),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('foo', models.ForeignKey('app.Foo', models.CASCADE, to_field='field')),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("field", models.IntegerField(unique=True)),
+ ],
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "foo",
+ models.ForeignKey("app.Foo", models.CASCADE, to_field="field"),
+ ),
+ ],
+ ),
]
after = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ('renamed_field', models.IntegerField(unique=True)),
- ]),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('foo', models.ForeignKey('app.Foo', models.CASCADE, to_field='renamed_field')),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("renamed_field", models.IntegerField(unique=True)),
+ ],
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "foo",
+ models.ForeignKey(
+ "app.Foo", models.CASCADE, to_field="renamed_field"
+ ),
+ ),
+ ],
+ ),
]
- changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename': True}))
+ changes = self.get_changes(
+ before, after, MigrationQuestioner({"ask_rename": True})
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['RenameField'])
- self.assertOperationAttributes(changes, 'app', 0, 0, old_name='field', new_name='renamed_field')
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["RenameField"])
+ self.assertOperationAttributes(
+ changes, "app", 0, 0, old_name="field", new_name="renamed_field"
+ )
def test_rename_foreign_object_fields(self):
- fields = ('first', 'second')
- renamed_fields = ('first_renamed', 'second_renamed')
+ fields = ("first", "second")
+ renamed_fields = ("first_renamed", "second_renamed")
before = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ('first', models.IntegerField()),
- ('second', models.IntegerField()),
- ], options={'unique_together': {fields}}),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('first', models.IntegerField()),
- ('second', models.IntegerField()),
- ('foo', models.ForeignObject(
- 'app.Foo', models.CASCADE, from_fields=fields, to_fields=fields,
- )),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("first", models.IntegerField()),
+ ("second", models.IntegerField()),
+ ],
+ options={"unique_together": {fields}},
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("first", models.IntegerField()),
+ ("second", models.IntegerField()),
+ (
+ "foo",
+ models.ForeignObject(
+ "app.Foo",
+ models.CASCADE,
+ from_fields=fields,
+ to_fields=fields,
+ ),
+ ),
+ ],
+ ),
]
# Case 1: to_fields renames.
after = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ('first_renamed', models.IntegerField()),
- ('second_renamed', models.IntegerField()),
- ], options={'unique_together': {renamed_fields}}),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('first', models.IntegerField()),
- ('second', models.IntegerField()),
- ('foo', models.ForeignObject(
- 'app.Foo', models.CASCADE, from_fields=fields, to_fields=renamed_fields,
- )),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("first_renamed", models.IntegerField()),
+ ("second_renamed", models.IntegerField()),
+ ],
+ options={"unique_together": {renamed_fields}},
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("first", models.IntegerField()),
+ ("second", models.IntegerField()),
+ (
+ "foo",
+ models.ForeignObject(
+ "app.Foo",
+ models.CASCADE,
+ from_fields=fields,
+ to_fields=renamed_fields,
+ ),
+ ),
+ ],
+ ),
]
- changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename': True}))
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['RenameField', 'RenameField', 'AlterUniqueTogether'])
+ changes = self.get_changes(
+ before, after, MigrationQuestioner({"ask_rename": True})
+ )
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(
+ changes, "app", 0, ["RenameField", "RenameField", "AlterUniqueTogether"]
+ )
self.assertOperationAttributes(
- changes, 'app', 0, 0, model_name='foo', old_name='first', new_name='first_renamed',
+ changes,
+ "app",
+ 0,
+ 0,
+ model_name="foo",
+ old_name="first",
+ new_name="first_renamed",
)
self.assertOperationAttributes(
- changes, 'app', 0, 1, model_name='foo', old_name='second', new_name='second_renamed',
+ changes,
+ "app",
+ 0,
+ 1,
+ model_name="foo",
+ old_name="second",
+ new_name="second_renamed",
)
# Case 2: from_fields renames.
after = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ('first', models.IntegerField()),
- ('second', models.IntegerField()),
- ], options={'unique_together': {fields}}),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('first_renamed', models.IntegerField()),
- ('second_renamed', models.IntegerField()),
- ('foo', models.ForeignObject(
- 'app.Foo', models.CASCADE, from_fields=renamed_fields, to_fields=fields,
- )),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("first", models.IntegerField()),
+ ("second", models.IntegerField()),
+ ],
+ options={"unique_together": {fields}},
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("first_renamed", models.IntegerField()),
+ ("second_renamed", models.IntegerField()),
+ (
+ "foo",
+ models.ForeignObject(
+ "app.Foo",
+ models.CASCADE,
+ from_fields=renamed_fields,
+ to_fields=fields,
+ ),
+ ),
+ ],
+ ),
]
- changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename': True}))
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['RenameField', 'RenameField'])
+ changes = self.get_changes(
+ before, after, MigrationQuestioner({"ask_rename": True})
+ )
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["RenameField", "RenameField"])
self.assertOperationAttributes(
- changes, 'app', 0, 0, model_name='bar', old_name='first', new_name='first_renamed',
+ changes,
+ "app",
+ 0,
+ 0,
+ model_name="bar",
+ old_name="first",
+ new_name="first_renamed",
)
self.assertOperationAttributes(
- changes, 'app', 0, 1, model_name='bar', old_name='second', new_name='second_renamed',
+ changes,
+ "app",
+ 0,
+ 1,
+ model_name="bar",
+ old_name="second",
+ new_name="second_renamed",
)
def test_rename_referenced_primary_key(self):
before = [
- ModelState('app', 'Foo', [
- ('id', models.CharField(primary_key=True, serialize=False)),
- ]),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('foo', models.ForeignKey('app.Foo', models.CASCADE)),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.CharField(primary_key=True, serialize=False)),
+ ],
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("foo", models.ForeignKey("app.Foo", models.CASCADE)),
+ ],
+ ),
]
after = [
- ModelState('app', 'Foo', [
- ('renamed_id', models.CharField(primary_key=True, serialize=False))
- ]),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('foo', models.ForeignKey('app.Foo', models.CASCADE)),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [("renamed_id", models.CharField(primary_key=True, serialize=False))],
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("foo", models.ForeignKey("app.Foo", models.CASCADE)),
+ ],
+ ),
]
- changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename': True}))
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['RenameField'])
- self.assertOperationAttributes(changes, 'app', 0, 0, old_name='id', new_name='renamed_id')
+ changes = self.get_changes(
+ before, after, MigrationQuestioner({"ask_rename": True})
+ )
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["RenameField"])
+ self.assertOperationAttributes(
+ changes, "app", 0, 0, old_name="id", new_name="renamed_id"
+ )
def test_rename_field_preserved_db_column(self):
"""
@@ -988,85 +1771,161 @@ class AutodetectorTests(TestCase):
old field's column is added.
"""
before = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ('field', models.IntegerField()),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("field", models.IntegerField()),
+ ],
+ ),
]
after = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ('renamed_field', models.IntegerField(db_column='field')),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("renamed_field", models.IntegerField(db_column="field")),
+ ],
+ ),
]
- changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename': True}))
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['AlterField', 'RenameField'])
+ changes = self.get_changes(
+ before, after, MigrationQuestioner({"ask_rename": True})
+ )
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["AlterField", "RenameField"])
self.assertOperationAttributes(
- changes, 'app', 0, 0, model_name='foo', name='field',
+ changes,
+ "app",
+ 0,
+ 0,
+ model_name="foo",
+ name="field",
+ )
+ self.assertEqual(
+ changes["app"][0].operations[0].field.deconstruct(),
+ (
+ "field",
+ "django.db.models.IntegerField",
+ [],
+ {"db_column": "field"},
+ ),
)
- self.assertEqual(changes['app'][0].operations[0].field.deconstruct(), (
- 'field', 'django.db.models.IntegerField', [], {'db_column': 'field'},
- ))
self.assertOperationAttributes(
- changes, 'app', 0, 1, model_name='foo', old_name='field',
- new_name='renamed_field',
+ changes,
+ "app",
+ 0,
+ 1,
+ model_name="foo",
+ old_name="field",
+ new_name="renamed_field",
)
def test_rename_related_field_preserved_db_column(self):
before = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ]),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('foo', models.ForeignKey('app.Foo', models.CASCADE)),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("foo", models.ForeignKey("app.Foo", models.CASCADE)),
+ ],
+ ),
]
after = [
- ModelState('app', 'Foo', [
- ('id', models.AutoField(primary_key=True)),
- ]),
- ModelState('app', 'Bar', [
- ('id', models.AutoField(primary_key=True)),
- ('renamed_foo', models.ForeignKey('app.Foo', models.CASCADE, db_column='foo_id')),
- ]),
+ ModelState(
+ "app",
+ "Foo",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ ModelState(
+ "app",
+ "Bar",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "renamed_foo",
+ models.ForeignKey(
+ "app.Foo", models.CASCADE, db_column="foo_id"
+ ),
+ ),
+ ],
+ ),
]
- changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename': True}))
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['AlterField', 'RenameField'])
+ changes = self.get_changes(
+ before, after, MigrationQuestioner({"ask_rename": True})
+ )
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["AlterField", "RenameField"])
self.assertOperationAttributes(
- changes, 'app', 0, 0, model_name='bar', name='foo',
+ changes,
+ "app",
+ 0,
+ 0,
+ model_name="bar",
+ name="foo",
+ )
+ self.assertEqual(
+ changes["app"][0].operations[0].field.deconstruct(),
+ (
+ "foo",
+ "django.db.models.ForeignKey",
+ [],
+ {"to": "app.foo", "on_delete": models.CASCADE, "db_column": "foo_id"},
+ ),
)
- self.assertEqual(changes['app'][0].operations[0].field.deconstruct(), (
- 'foo',
- 'django.db.models.ForeignKey',
- [],
- {'to': 'app.foo', 'on_delete': models.CASCADE, 'db_column': 'foo_id'},
- ))
self.assertOperationAttributes(
- changes, 'app', 0, 1, model_name='bar', old_name='foo',
- new_name='renamed_foo',
+ changes,
+ "app",
+ 0,
+ 1,
+ model_name="bar",
+ old_name="foo",
+ new_name="renamed_foo",
)
def test_rename_field_with_renamed_model(self):
changes = self.get_changes(
[self.author_name],
[
- ModelState('testapp', 'RenamedAuthor', [
- ('id', models.AutoField(primary_key=True)),
- ('renamed_name', models.CharField(max_length=200)),
- ]),
+ ModelState(
+ "testapp",
+ "RenamedAuthor",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("renamed_name", models.CharField(max_length=200)),
+ ],
+ ),
],
- MigrationQuestioner({'ask_rename_model': True, 'ask_rename': True}),
+ MigrationQuestioner({"ask_rename_model": True, "ask_rename": True}),
)
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['RenameModel', 'RenameField'])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RenameModel", "RenameField"])
self.assertOperationAttributes(
- changes, 'testapp', 0, 0, old_name='Author', new_name='RenamedAuthor',
+ changes,
+ "testapp",
+ 0,
+ 0,
+ old_name="Author",
+ new_name="RenamedAuthor",
)
self.assertOperationAttributes(
- changes, 'testapp', 0, 1, old_name='name', new_name='renamed_name',
+ changes,
+ "testapp",
+ 0,
+ 1,
+ old_name="name",
+ new_name="renamed_name",
)
def test_rename_model(self):
@@ -1077,41 +1936,51 @@ class AutodetectorTests(TestCase):
MigrationQuestioner({"ask_rename_model": True}),
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["RenameModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name="Author", new_name="Writer")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, old_name="Author", new_name="Writer"
+ )
# Now that RenameModel handles related fields too, there should be
# no AlterField for the related field.
- self.assertNumberMigrations(changes, 'otherapp', 0)
+ self.assertNumberMigrations(changes, "otherapp", 0)
def test_rename_model_case(self):
"""
Model name is case-insensitive. Changing case doesn't lead to any
autodetected operations.
"""
- author_renamed = ModelState('testapp', 'author', [
- ('id', models.AutoField(primary_key=True)),
- ])
+ author_renamed = ModelState(
+ "testapp",
+ "author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
changes = self.get_changes(
[self.author_empty, self.book],
[author_renamed, self.book],
- questioner=MigrationQuestioner({'ask_rename_model': True}),
+ questioner=MigrationQuestioner({"ask_rename_model": True}),
)
- self.assertNumberMigrations(changes, 'testapp', 0)
- self.assertNumberMigrations(changes, 'otherapp', 0)
+ self.assertNumberMigrations(changes, "testapp", 0)
+ self.assertNumberMigrations(changes, "otherapp", 0)
def test_renamed_referenced_m2m_model_case(self):
- publisher_renamed = ModelState('testapp', 'publisher', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=100)),
- ])
+ publisher_renamed = ModelState(
+ "testapp",
+ "publisher",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=100)),
+ ],
+ )
changes = self.get_changes(
[self.publisher, self.author_with_m2m],
[publisher_renamed, self.author_with_m2m],
- questioner=MigrationQuestioner({'ask_rename_model': True}),
+ questioner=MigrationQuestioner({"ask_rename_model": True}),
)
- self.assertNumberMigrations(changes, 'testapp', 0)
- self.assertNumberMigrations(changes, 'otherapp', 0)
+ self.assertNumberMigrations(changes, "testapp", 0)
+ self.assertNumberMigrations(changes, "otherapp", 0)
def test_rename_m2m_through_model(self):
"""
@@ -1120,13 +1989,19 @@ class AutodetectorTests(TestCase):
"""
changes = self.get_changes(
[self.author_with_m2m_through, self.publisher, self.contract],
- [self.author_with_renamed_m2m_through, self.publisher, self.contract_renamed],
- MigrationQuestioner({'ask_rename_model': True})
+ [
+ self.author_with_renamed_m2m_through,
+ self.publisher,
+ self.contract_renamed,
+ ],
+ MigrationQuestioner({"ask_rename_model": True}),
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['RenameModel'])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name='Contract', new_name='Deal')
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, old_name="Contract", new_name="Deal"
+ )
def test_rename_model_with_renamed_rel_field(self):
"""
@@ -1139,14 +2014,18 @@ class AutodetectorTests(TestCase):
MigrationQuestioner({"ask_rename": True, "ask_rename_model": True}),
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["RenameModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name="Author", new_name="Writer")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, old_name="Author", new_name="Writer"
+ )
# Right number/type of migrations for related field rename?
# Alter is already taken care of.
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ["RenameField"])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, old_name="author", new_name="writer")
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["RenameField"])
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 0, old_name="author", new_name="writer"
+ )
def test_rename_model_with_fks_in_different_position(self):
"""
@@ -1154,29 +2033,49 @@ class AutodetectorTests(TestCase):
the RenameModel detection.
"""
before = [
- ModelState("testapp", "EntityA", [
- ("id", models.AutoField(primary_key=True)),
- ]),
- ModelState("testapp", "EntityB", [
- ("id", models.AutoField(primary_key=True)),
- ("some_label", models.CharField(max_length=255)),
- ("entity_a", models.ForeignKey("testapp.EntityA", models.CASCADE)),
- ]),
+ ModelState(
+ "testapp",
+ "EntityA",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ ModelState(
+ "testapp",
+ "EntityB",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("some_label", models.CharField(max_length=255)),
+ ("entity_a", models.ForeignKey("testapp.EntityA", models.CASCADE)),
+ ],
+ ),
]
after = [
- ModelState("testapp", "EntityA", [
- ("id", models.AutoField(primary_key=True)),
- ]),
- ModelState("testapp", "RenamedEntityB", [
- ("id", models.AutoField(primary_key=True)),
- ("entity_a", models.ForeignKey("testapp.EntityA", models.CASCADE)),
- ("some_label", models.CharField(max_length=255)),
- ]),
+ ModelState(
+ "testapp",
+ "EntityA",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ ModelState(
+ "testapp",
+ "RenamedEntityB",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("entity_a", models.ForeignKey("testapp.EntityA", models.CASCADE)),
+ ("some_label", models.CharField(max_length=255)),
+ ],
+ ),
]
- changes = self.get_changes(before, after, MigrationQuestioner({"ask_rename_model": True}))
+ changes = self.get_changes(
+ before, after, MigrationQuestioner({"ask_rename_model": True})
+ )
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, old_name="EntityB", new_name="RenamedEntityB")
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, old_name="EntityB", new_name="RenamedEntityB"
+ )
def test_rename_model_reverse_relation_dependencies(self):
"""
@@ -1186,28 +2085,53 @@ class AutodetectorTests(TestCase):
dependency on that other migration.
"""
before = [
- ModelState('testapp', 'EntityA', [
- ('id', models.AutoField(primary_key=True)),
- ]),
- ModelState('otherapp', 'EntityB', [
- ('id', models.AutoField(primary_key=True)),
- ('entity_a', models.ForeignKey('testapp.EntityA', models.CASCADE)),
- ]),
+ ModelState(
+ "testapp",
+ "EntityA",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ ModelState(
+ "otherapp",
+ "EntityB",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("entity_a", models.ForeignKey("testapp.EntityA", models.CASCADE)),
+ ],
+ ),
]
after = [
- ModelState('testapp', 'RenamedEntityA', [
- ('id', models.AutoField(primary_key=True)),
- ]),
- ModelState('otherapp', 'EntityB', [
- ('id', models.AutoField(primary_key=True)),
- ('entity_a', models.ForeignKey('testapp.RenamedEntityA', models.CASCADE)),
- ]),
+ ModelState(
+ "testapp",
+ "RenamedEntityA",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ ModelState(
+ "otherapp",
+ "EntityB",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "entity_a",
+ models.ForeignKey("testapp.RenamedEntityA", models.CASCADE),
+ ),
+ ],
+ ),
]
- changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename_model': True}))
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertMigrationDependencies(changes, 'testapp', 0, [('otherapp', '__first__')])
- self.assertOperationTypes(changes, 'testapp', 0, ['RenameModel'])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name='EntityA', new_name='RenamedEntityA')
+ changes = self.get_changes(
+ before, after, MigrationQuestioner({"ask_rename_model": True})
+ )
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertMigrationDependencies(
+ changes, "testapp", 0, [("otherapp", "__first__")]
+ )
+ self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, old_name="EntityA", new_name="RenamedEntityA"
+ )
def test_fk_dependency(self):
"""Having a ForeignKey automatically adds a dependency."""
@@ -1216,41 +2140,51 @@ class AutodetectorTests(TestCase):
# thirdapp (edition) depends on otherapp (book)
changes = self.get_changes([], [self.author_name, self.book, self.edition])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
- self.assertMigrationDependencies(changes, 'testapp', 0, [])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
+ self.assertMigrationDependencies(changes, "testapp", 0, [])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="Book")
- self.assertMigrationDependencies(changes, 'otherapp', 0, [("testapp", "auto_1")])
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Book")
+ self.assertMigrationDependencies(
+ changes, "otherapp", 0, [("testapp", "auto_1")]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'thirdapp', 1)
- self.assertOperationTypes(changes, 'thirdapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'thirdapp', 0, 0, name="Edition")
- self.assertMigrationDependencies(changes, 'thirdapp', 0, [("otherapp", "auto_1")])
+ self.assertNumberMigrations(changes, "thirdapp", 1)
+ self.assertOperationTypes(changes, "thirdapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "thirdapp", 0, 0, name="Edition")
+ self.assertMigrationDependencies(
+ changes, "thirdapp", 0, [("otherapp", "auto_1")]
+ )
def test_proxy_fk_dependency(self):
"""FK dependencies still work on proxy models."""
# Note that testapp (author) has no dependencies,
# otherapp (book) depends on testapp (authorproxy)
- changes = self.get_changes([], [self.author_empty, self.author_proxy_third, self.book_proxy_fk])
+ changes = self.get_changes(
+ [], [self.author_empty, self.author_proxy_third, self.book_proxy_fk]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
- self.assertMigrationDependencies(changes, 'testapp', 0, [])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
+ self.assertMigrationDependencies(changes, "testapp", 0, [])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="Book")
- self.assertMigrationDependencies(changes, 'otherapp', 0, [("thirdapp", "auto_1")])
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Book")
+ self.assertMigrationDependencies(
+ changes, "otherapp", 0, [("thirdapp", "auto_1")]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'thirdapp', 1)
- self.assertOperationTypes(changes, 'thirdapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'thirdapp', 0, 0, name="AuthorProxy")
- self.assertMigrationDependencies(changes, 'thirdapp', 0, [("testapp", "auto_1")])
+ self.assertNumberMigrations(changes, "thirdapp", 1)
+ self.assertOperationTypes(changes, "thirdapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "thirdapp", 0, 0, name="AuthorProxy")
+ self.assertMigrationDependencies(
+ changes, "thirdapp", 0, [("testapp", "auto_1")]
+ )
def test_same_app_no_fk_dependency(self):
"""
@@ -1259,47 +2193,57 @@ class AutodetectorTests(TestCase):
"""
changes = self.get_changes([], [self.author_with_publisher, self.publisher])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
self.assertOperationAttributes(changes, "testapp", 0, 1, name="Author")
- self.assertMigrationDependencies(changes, 'testapp', 0, [])
+ self.assertMigrationDependencies(changes, "testapp", 0, [])
def test_circular_fk_dependency(self):
"""
Having a circular ForeignKey dependency automatically
resolves the situation into 2 migrations on one side and 1 on the other.
"""
- changes = self.get_changes([], [self.author_with_book, self.book, self.publisher_with_book])
+ changes = self.get_changes(
+ [], [self.author_with_book, self.book, self.publisher_with_book]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
self.assertOperationAttributes(changes, "testapp", 0, 1, name="Author")
- self.assertMigrationDependencies(changes, 'testapp', 0, [("otherapp", "auto_1")])
+ self.assertMigrationDependencies(
+ changes, "testapp", 0, [("otherapp", "auto_1")]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 2)
- self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
- self.assertOperationTypes(changes, 'otherapp', 1, ["AddField"])
- self.assertMigrationDependencies(changes, 'otherapp', 0, [])
- self.assertMigrationDependencies(changes, 'otherapp', 1, [("otherapp", "auto_1"), ("testapp", "auto_1")])
+ self.assertNumberMigrations(changes, "otherapp", 2)
+ self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
+ self.assertOperationTypes(changes, "otherapp", 1, ["AddField"])
+ self.assertMigrationDependencies(changes, "otherapp", 0, [])
+ self.assertMigrationDependencies(
+ changes, "otherapp", 1, [("otherapp", "auto_1"), ("testapp", "auto_1")]
+ )
# both split migrations should be `initial`
- self.assertTrue(changes['otherapp'][0].initial)
- self.assertTrue(changes['otherapp'][1].initial)
+ self.assertTrue(changes["otherapp"][0].initial)
+ self.assertTrue(changes["otherapp"][1].initial)
def test_same_app_circular_fk_dependency(self):
"""
A migration with a FK between two models of the same app does
not have a dependency to itself.
"""
- changes = self.get_changes([], [self.author_with_publisher, self.publisher_with_author])
+ changes = self.get_changes(
+ [], [self.author_with_publisher, self.publisher_with_author]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel", "AddField"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["CreateModel", "CreateModel", "AddField"]
+ )
self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
self.assertOperationAttributes(changes, "testapp", 0, 2, name="publisher")
- self.assertMigrationDependencies(changes, 'testapp', 0, [])
+ self.assertMigrationDependencies(changes, "testapp", 0, [])
def test_same_app_circular_fk_dependency_with_unique_together_and_indexes(self):
"""
@@ -1309,43 +2253,60 @@ class AutodetectorTests(TestCase):
"""
changes = self.get_changes([], [self.knight, self.rabbit])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'eggs', 1)
+ self.assertNumberMigrations(changes, "eggs", 1)
self.assertOperationTypes(
- changes, 'eggs', 0, ["CreateModel", "CreateModel", "AddIndex", "AlterUniqueTogether"]
+ changes,
+ "eggs",
+ 0,
+ ["CreateModel", "CreateModel", "AddIndex", "AlterUniqueTogether"],
)
- self.assertNotIn("unique_together", changes['eggs'][0].operations[0].options)
- self.assertNotIn("unique_together", changes['eggs'][0].operations[1].options)
- self.assertMigrationDependencies(changes, 'eggs', 0, [])
+ self.assertNotIn("unique_together", changes["eggs"][0].operations[0].options)
+ self.assertNotIn("unique_together", changes["eggs"][0].operations[1].options)
+ self.assertMigrationDependencies(changes, "eggs", 0, [])
def test_alter_db_table_add(self):
"""Tests detection for adding db_table in model's options."""
- changes = self.get_changes([self.author_empty], [self.author_with_db_table_options])
+ changes = self.get_changes(
+ [self.author_empty], [self.author_with_db_table_options]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterModelTable"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", table="author_one")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterModelTable"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="author", table="author_one"
+ )
def test_alter_db_table_change(self):
"""Tests detection for changing db_table in model's options'."""
- changes = self.get_changes([self.author_with_db_table_options], [self.author_with_new_db_table_options])
+ changes = self.get_changes(
+ [self.author_with_db_table_options], [self.author_with_new_db_table_options]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterModelTable"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", table="author_two")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterModelTable"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="author", table="author_two"
+ )
def test_alter_db_table_remove(self):
"""Tests detection for removing db_table in model's options."""
- changes = self.get_changes([self.author_with_db_table_options], [self.author_empty])
+ changes = self.get_changes(
+ [self.author_with_db_table_options], [self.author_empty]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterModelTable"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", table=None)
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterModelTable"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="author", table=None
+ )
def test_alter_db_table_no_changes(self):
"""
Alter_db_table doesn't generate a migration if no changes have been made.
"""
- changes = self.get_changes([self.author_with_db_table_options], [self.author_with_db_table_options])
+ changes = self.get_changes(
+ [self.author_with_db_table_options], [self.author_with_db_table_options]
+ )
# Right number of migrations?
self.assertEqual(len(changes), 0)
@@ -1360,9 +2321,11 @@ class AutodetectorTests(TestCase):
MigrationQuestioner({"ask_rename_model": True}),
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["RenameModel"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, old_name="Author", new_name="NewAuthor")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, old_name="Author", new_name="NewAuthor"
+ )
def test_alter_db_table_with_model_change(self):
"""
@@ -1375,23 +2338,41 @@ class AutodetectorTests(TestCase):
MigrationQuestioner({"ask_rename_model": True}),
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["RenameModel", "AlterModelTable"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, old_name="Author", new_name="NewAuthor")
- self.assertOperationAttributes(changes, "testapp", 0, 1, name="newauthor", table="author_three")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["RenameModel", "AlterModelTable"]
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, old_name="Author", new_name="NewAuthor"
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 1, name="newauthor", table="author_three"
+ )
def test_identical_regex_doesnt_alter(self):
from_state = ModelState(
- "testapp", "model", [("id", models.AutoField(primary_key=True, validators=[
- RegexValidator(
- re.compile('^[-a-zA-Z0-9_]+\\Z'),
- 'Enter a valid “slug” consisting of letters, numbers, underscores or hyphens.',
- 'invalid'
+ "testapp",
+ "model",
+ [
+ (
+ "id",
+ models.AutoField(
+ primary_key=True,
+ validators=[
+ RegexValidator(
+ re.compile("^[-a-zA-Z0-9_]+\\Z"),
+ "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens.",
+ "invalid",
+ )
+ ],
+ ),
)
- ]))]
+ ],
)
to_state = ModelState(
- "testapp", "model", [("id", models.AutoField(primary_key=True, validators=[validate_slug]))]
+ "testapp",
+ "model",
+ [("id", models.AutoField(primary_key=True, validators=[validate_slug]))],
)
changes = self.get_changes([from_state], [to_state])
# Right number/type of migrations?
@@ -1399,16 +2380,28 @@ class AutodetectorTests(TestCase):
def test_different_regex_does_alter(self):
from_state = ModelState(
- "testapp", "model", [("id", models.AutoField(primary_key=True, validators=[
- RegexValidator(
- re.compile('^[a-z]+\\Z', 32),
- 'Enter a valid “slug” consisting of letters, numbers, underscores or hyphens.',
- 'invalid'
+ "testapp",
+ "model",
+ [
+ (
+ "id",
+ models.AutoField(
+ primary_key=True,
+ validators=[
+ RegexValidator(
+ re.compile("^[a-z]+\\Z", 32),
+ "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens.",
+ "invalid",
+ )
+ ],
+ ),
)
- ]))]
+ ],
)
to_state = ModelState(
- "testapp", "model", [("id", models.AutoField(primary_key=True, validators=[validate_slug]))]
+ "testapp",
+ "model",
+ [("id", models.AutoField(primary_key=True, validators=[validate_slug]))],
)
changes = self.get_changes([from_state], [to_state])
self.assertNumberMigrations(changes, "testapp", 1)
@@ -1420,38 +2413,60 @@ class AutodetectorTests(TestCase):
"""
# Explicitly testing for not specified, since this is the case after
# a CreateModel operation w/o any definition on the original model
- model_state_not_specified = ModelState("a", "model", [("id", models.AutoField(primary_key=True))])
+ model_state_not_specified = ModelState(
+ "a", "model", [("id", models.AutoField(primary_key=True))]
+ )
# Explicitly testing for None, since this was the issue in #23452 after
# an AlterFooTogether operation with e.g. () as value
- model_state_none = ModelState("a", "model", [
- ("id", models.AutoField(primary_key=True))
- ], {
- "index_together": None,
- "unique_together": None,
- })
+ model_state_none = ModelState(
+ "a",
+ "model",
+ [("id", models.AutoField(primary_key=True))],
+ {
+ "index_together": None,
+ "unique_together": None,
+ },
+ )
# Explicitly testing for the empty set, since we now always have sets.
# During removal (('col1', 'col2'),) --> () this becomes set([])
- model_state_empty = ModelState("a", "model", [
- ("id", models.AutoField(primary_key=True))
- ], {
- "index_together": set(),
- "unique_together": set(),
- })
+ model_state_empty = ModelState(
+ "a",
+ "model",
+ [("id", models.AutoField(primary_key=True))],
+ {
+ "index_together": set(),
+ "unique_together": set(),
+ },
+ )
def test(from_state, to_state, msg):
changes = self.get_changes([from_state], [to_state])
if changes:
- ops = ', '.join(o.__class__.__name__ for o in changes['a'][0].operations)
- self.fail('Created operation(s) %s from %s' % (ops, msg))
+ ops = ", ".join(
+ o.__class__.__name__ for o in changes["a"][0].operations
+ )
+ self.fail("Created operation(s) %s from %s" % (ops, msg))
tests = (
- (model_state_not_specified, model_state_not_specified, '"not specified" to "not specified"'),
+ (
+ model_state_not_specified,
+ model_state_not_specified,
+ '"not specified" to "not specified"',
+ ),
(model_state_not_specified, model_state_none, '"not specified" to "None"'),
- (model_state_not_specified, model_state_empty, '"not specified" to "empty"'),
+ (
+ model_state_not_specified,
+ model_state_empty,
+ '"not specified" to "empty"',
+ ),
(model_state_none, model_state_not_specified, '"None" to "not specified"'),
(model_state_none, model_state_none, '"None" to "None"'),
(model_state_none, model_state_empty, '"None" to "empty"'),
- (model_state_empty, model_state_not_specified, '"empty" to "not specified"'),
+ (
+ model_state_empty,
+ model_state_not_specified,
+ '"empty" to "not specified"',
+ ),
(model_state_empty, model_state_none, '"empty" to "None"'),
(model_state_empty, model_state_empty, '"empty" to "empty"'),
)
@@ -1461,114 +2476,202 @@ class AutodetectorTests(TestCase):
def test_create_model_with_indexes(self):
"""Test creation of new model with indexes already defined."""
- author = ModelState('otherapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ], {'indexes': [models.Index(fields=['name'], name='create_model_with_indexes_idx')]})
+ author = ModelState(
+ "otherapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ],
+ {
+ "indexes": [
+ models.Index(fields=["name"], name="create_model_with_indexes_idx")
+ ]
+ },
+ )
changes = self.get_changes([], [author])
- added_index = models.Index(fields=['name'], name='create_model_with_indexes_idx')
+ added_index = models.Index(
+ fields=["name"], name="create_model_with_indexes_idx"
+ )
# Right number of migrations?
- self.assertEqual(len(changes['otherapp']), 1)
+ self.assertEqual(len(changes["otherapp"]), 1)
# Right number of actions?
- migration = changes['otherapp'][0]
+ migration = changes["otherapp"][0]
self.assertEqual(len(migration.operations), 2)
# Right actions order?
- self.assertOperationTypes(changes, 'otherapp', 0, ['CreateModel', 'AddIndex'])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name='Author')
- self.assertOperationAttributes(changes, 'otherapp', 0, 1, model_name='author', index=added_index)
+ self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel", "AddIndex"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Author")
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 1, model_name="author", index=added_index
+ )
def test_add_indexes(self):
"""Test change detection of new indexes."""
- changes = self.get_changes([self.author_empty, self.book], [self.author_empty, self.book_indexes])
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ['AddIndex'])
- added_index = models.Index(fields=['author', 'title'], name='book_title_author_idx')
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, model_name='book', index=added_index)
+ changes = self.get_changes(
+ [self.author_empty, self.book], [self.author_empty, self.book_indexes]
+ )
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["AddIndex"])
+ added_index = models.Index(
+ fields=["author", "title"], name="book_title_author_idx"
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 0, model_name="book", index=added_index
+ )
def test_remove_indexes(self):
"""Test change detection of removed indexes."""
- changes = self.get_changes([self.author_empty, self.book_indexes], [self.author_empty, self.book])
+ changes = self.get_changes(
+ [self.author_empty, self.book_indexes], [self.author_empty, self.book]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ['RemoveIndex'])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, model_name='book', name='book_title_author_idx')
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["RemoveIndex"])
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 0, model_name="book", name="book_title_author_idx"
+ )
def test_order_fields_indexes(self):
"""Test change detection of reordering of fields in indexes."""
changes = self.get_changes(
- [self.author_empty, self.book_indexes], [self.author_empty, self.book_unordered_indexes]
+ [self.author_empty, self.book_indexes],
+ [self.author_empty, self.book_unordered_indexes],
+ )
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["RemoveIndex", "AddIndex"])
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 0, model_name="book", name="book_title_author_idx"
+ )
+ added_index = models.Index(
+ fields=["title", "author"], name="book_author_title_idx"
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 1, model_name="book", index=added_index
)
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ['RemoveIndex', 'AddIndex'])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, model_name='book', name='book_title_author_idx')
- added_index = models.Index(fields=['title', 'author'], name='book_author_title_idx')
- self.assertOperationAttributes(changes, 'otherapp', 0, 1, model_name='book', index=added_index)
def test_create_model_with_check_constraint(self):
"""Test creation of new model with constraints already defined."""
- author = ModelState('otherapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ], {'constraints': [models.CheckConstraint(check=models.Q(name__contains='Bob'), name='name_contains_bob')]})
+ author = ModelState(
+ "otherapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ],
+ {
+ "constraints": [
+ models.CheckConstraint(
+ check=models.Q(name__contains="Bob"), name="name_contains_bob"
+ )
+ ]
+ },
+ )
changes = self.get_changes([], [author])
- added_constraint = models.CheckConstraint(check=models.Q(name__contains='Bob'), name='name_contains_bob')
+ added_constraint = models.CheckConstraint(
+ check=models.Q(name__contains="Bob"), name="name_contains_bob"
+ )
# Right number of migrations?
- self.assertEqual(len(changes['otherapp']), 1)
+ self.assertEqual(len(changes["otherapp"]), 1)
# Right number of actions?
- migration = changes['otherapp'][0]
+ migration = changes["otherapp"][0]
self.assertEqual(len(migration.operations), 2)
# Right actions order?
- self.assertOperationTypes(changes, 'otherapp', 0, ['CreateModel', 'AddConstraint'])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name='Author')
- self.assertOperationAttributes(changes, 'otherapp', 0, 1, model_name='author', constraint=added_constraint)
+ self.assertOperationTypes(
+ changes, "otherapp", 0, ["CreateModel", "AddConstraint"]
+ )
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Author")
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 1, model_name="author", constraint=added_constraint
+ )
def test_add_constraints(self):
"""Test change detection of new constraints."""
- changes = self.get_changes([self.author_name], [self.author_name_check_constraint])
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['AddConstraint'])
- added_constraint = models.CheckConstraint(check=models.Q(name__contains='Bob'), name='name_contains_bob')
- self.assertOperationAttributes(changes, 'testapp', 0, 0, model_name='author', constraint=added_constraint)
+ changes = self.get_changes(
+ [self.author_name], [self.author_name_check_constraint]
+ )
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AddConstraint"])
+ added_constraint = models.CheckConstraint(
+ check=models.Q(name__contains="Bob"), name="name_contains_bob"
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, model_name="author", constraint=added_constraint
+ )
def test_remove_constraints(self):
"""Test change detection of removed constraints."""
- changes = self.get_changes([self.author_name_check_constraint], [self.author_name])
+ changes = self.get_changes(
+ [self.author_name_check_constraint], [self.author_name]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['RemoveConstraint'])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, model_name='author', name='name_contains_bob')
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RemoveConstraint"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, model_name="author", name="name_contains_bob"
+ )
def test_add_foo_together(self):
"""Tests index/unique_together detection."""
- changes = self.get_changes([self.author_empty, self.book], [self.author_empty, self.book_foo_together])
+ changes = self.get_changes(
+ [self.author_empty, self.book], [self.author_empty, self.book_foo_together]
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"])
- self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together={("author", "title")})
- self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", index_together={("author", "title")})
+ self.assertOperationTypes(
+ changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"]
+ )
+ self.assertOperationAttributes(
+ changes,
+ "otherapp",
+ 0,
+ 0,
+ name="book",
+ unique_together={("author", "title")},
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 1, name="book", index_together={("author", "title")}
+ )
def test_remove_foo_together(self):
"""Tests index/unique_together detection."""
- changes = self.get_changes([self.author_empty, self.book_foo_together], [self.author_empty, self.book])
+ changes = self.get_changes(
+ [self.author_empty, self.book_foo_together], [self.author_empty, self.book]
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"])
- self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together=set())
- self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", index_together=set())
+ self.assertOperationTypes(
+ changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"]
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 0, name="book", unique_together=set()
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 1, name="book", index_together=set()
+ )
def test_foo_together_remove_fk(self):
"""Tests unique_together and field removal detection & ordering"""
changes = self.get_changes(
- [self.author_empty, self.book_foo_together], [self.author_empty, self.book_with_no_author]
+ [self.author_empty, self.book_foo_together],
+ [self.author_empty, self.book_with_no_author],
)
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, "otherapp", 0, [
- "AlterUniqueTogether", "AlterIndexTogether", "RemoveField"
- ])
- self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together=set())
- self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", index_together=set())
- self.assertOperationAttributes(changes, "otherapp", 0, 2, model_name="book", name="author")
+ self.assertOperationTypes(
+ changes,
+ "otherapp",
+ 0,
+ ["AlterUniqueTogether", "AlterIndexTogether", "RemoveField"],
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 0, name="book", unique_together=set()
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 1, name="book", index_together=set()
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 2, model_name="book", name="author"
+ )
def test_foo_together_no_changes(self):
"""
@@ -1576,7 +2679,8 @@ class AutodetectorTests(TestCase):
changes have been made.
"""
changes = self.get_changes(
- [self.author_empty, self.book_foo_together], [self.author_empty, self.book_foo_together]
+ [self.author_empty, self.book_foo_together],
+ [self.author_empty, self.book_foo_together],
)
# Right number of migrations?
self.assertEqual(len(changes), 0)
@@ -1586,57 +2690,106 @@ class AutodetectorTests(TestCase):
index/unique_together also triggers on ordering changes.
"""
changes = self.get_changes(
- [self.author_empty, self.book_foo_together], [self.author_empty, self.book_foo_together_2]
+ [self.author_empty, self.book_foo_together],
+ [self.author_empty, self.book_foo_together_2],
)
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, 'otherapp', 0, [
- 'AlterUniqueTogether',
- 'AlterIndexTogether',
- ])
+ self.assertOperationTypes(
+ changes,
+ "otherapp",
+ 0,
+ [
+ "AlterUniqueTogether",
+ "AlterIndexTogether",
+ ],
+ )
self.assertOperationAttributes(
- changes, 'otherapp', 0, 0, name='book',
- unique_together={('title', 'author')},
+ changes,
+ "otherapp",
+ 0,
+ 0,
+ name="book",
+ unique_together={("title", "author")},
)
self.assertOperationAttributes(
- changes, 'otherapp', 0, 1, name='book',
- index_together={('title', 'author')},
+ changes,
+ "otherapp",
+ 0,
+ 1,
+ name="book",
+ index_together={("title", "author")},
)
def test_add_field_and_foo_together(self):
"""
Added fields will be created before using them in index/unique_together.
"""
- changes = self.get_changes([self.author_empty, self.book], [self.author_empty, self.book_foo_together_3])
+ changes = self.get_changes(
+ [self.author_empty, self.book],
+ [self.author_empty, self.book_foo_together_3],
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, "otherapp", 0, ["AddField", "AlterUniqueTogether", "AlterIndexTogether"])
- self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", unique_together={("title", "newfield")})
- self.assertOperationAttributes(changes, "otherapp", 0, 2, name="book", index_together={("title", "newfield")})
+ self.assertOperationTypes(
+ changes,
+ "otherapp",
+ 0,
+ ["AddField", "AlterUniqueTogether", "AlterIndexTogether"],
+ )
+ self.assertOperationAttributes(
+ changes,
+ "otherapp",
+ 0,
+ 1,
+ name="book",
+ unique_together={("title", "newfield")},
+ )
+ self.assertOperationAttributes(
+ changes,
+ "otherapp",
+ 0,
+ 2,
+ name="book",
+ index_together={("title", "newfield")},
+ )
def test_create_model_and_unique_together(self):
- author = ModelState("otherapp", "Author", [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=200)),
- ])
- book_with_author = ModelState("otherapp", "Book", [
- ("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("otherapp.Author", models.CASCADE)),
- ("title", models.CharField(max_length=200)),
- ], {
- "index_together": {("title", "author")},
- "unique_together": {("title", "author")},
- })
- changes = self.get_changes([self.book_with_no_author], [author, book_with_author])
+ author = ModelState(
+ "otherapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ],
+ )
+ book_with_author = ModelState(
+ "otherapp",
+ "Book",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("author", models.ForeignKey("otherapp.Author", models.CASCADE)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ {
+ "index_together": {("title", "author")},
+ "unique_together": {("title", "author")},
+ },
+ )
+ changes = self.get_changes(
+ [self.book_with_no_author], [author, book_with_author]
+ )
# Right number of migrations?
- self.assertEqual(len(changes['otherapp']), 1)
+ self.assertEqual(len(changes["otherapp"]), 1)
# Right number of actions?
- migration = changes['otherapp'][0]
+ migration = changes["otherapp"][0]
self.assertEqual(len(migration.operations), 4)
# Right actions order?
self.assertOperationTypes(
- changes, 'otherapp', 0,
- ['CreateModel', 'AddField', 'AlterUniqueTogether', 'AlterIndexTogether']
+ changes,
+ "otherapp",
+ 0,
+ ["CreateModel", "AddField", "AlterUniqueTogether", "AlterIndexTogether"],
)
def test_remove_field_and_foo_together(self):
@@ -1644,95 +2797,173 @@ class AutodetectorTests(TestCase):
Removed fields will be removed after updating index/unique_together.
"""
changes = self.get_changes(
- [self.author_empty, self.book_foo_together_3], [self.author_empty, self.book_foo_together]
+ [self.author_empty, self.book_foo_together_3],
+ [self.author_empty, self.book_foo_together],
)
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, 'otherapp', 0, [
- 'AlterUniqueTogether',
- 'AlterIndexTogether',
- 'RemoveField',
- ])
+ self.assertOperationTypes(
+ changes,
+ "otherapp",
+ 0,
+ [
+ "AlterUniqueTogether",
+ "AlterIndexTogether",
+ "RemoveField",
+ ],
+ )
self.assertOperationAttributes(
- changes, 'otherapp', 0, 0, name='book',
- unique_together={('author', 'title')},
+ changes,
+ "otherapp",
+ 0,
+ 0,
+ name="book",
+ unique_together={("author", "title")},
)
self.assertOperationAttributes(
- changes, 'otherapp', 0, 1, name='book',
- index_together={('author', 'title')},
+ changes,
+ "otherapp",
+ 0,
+ 1,
+ name="book",
+ index_together={("author", "title")},
)
self.assertOperationAttributes(
- changes, 'otherapp', 0, 2, model_name='book', name='newfield',
+ changes,
+ "otherapp",
+ 0,
+ 2,
+ model_name="book",
+ name="newfield",
)
def test_alter_field_and_foo_together(self):
"""Fields are altered after deleting some index/unique_together."""
- initial_author = ModelState('testapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ('age', models.IntegerField(db_index=True)),
- ], {
- 'unique_together': {('name',)},
- })
- author_reversed_constraints = ModelState('testapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200, unique=True)),
- ('age', models.IntegerField()),
- ], {
- 'index_together': {('age',)},
- })
+ initial_author = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("age", models.IntegerField(db_index=True)),
+ ],
+ {
+ "unique_together": {("name",)},
+ },
+ )
+ author_reversed_constraints = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200, unique=True)),
+ ("age", models.IntegerField()),
+ ],
+ {
+ "index_together": {("age",)},
+ },
+ )
changes = self.get_changes([initial_author], [author_reversed_constraints])
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, [
- 'AlterUniqueTogether',
- 'AlterField',
- 'AlterField',
- 'AlterIndexTogether',
- ])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes,
+ "testapp",
+ 0,
+ [
+ "AlterUniqueTogether",
+ "AlterField",
+ "AlterField",
+ "AlterIndexTogether",
+ ],
+ )
self.assertOperationAttributes(
- changes, 'testapp', 0, 0, name='author', unique_together=set(),
+ changes,
+ "testapp",
+ 0,
+ 0,
+ name="author",
+ unique_together=set(),
)
self.assertOperationAttributes(
- changes, 'testapp', 0, 1, model_name='author', name='age',
+ changes,
+ "testapp",
+ 0,
+ 1,
+ model_name="author",
+ name="age",
)
self.assertOperationAttributes(
- changes, 'testapp', 0, 2, model_name='author', name='name',
+ changes,
+ "testapp",
+ 0,
+ 2,
+ model_name="author",
+ name="name",
)
self.assertOperationAttributes(
- changes, 'testapp', 0, 3, name='author', index_together={('age',)},
+ changes,
+ "testapp",
+ 0,
+ 3,
+ name="author",
+ index_together={("age",)},
)
def test_partly_alter_foo_together(self):
- initial_author = ModelState('testapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ('age', models.IntegerField()),
- ], {
- 'unique_together': {('name',), ('age',)},
- 'index_together': {('name',)},
- })
- author_reversed_constraints = ModelState('testapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ('age', models.IntegerField()),
- ], {
- 'unique_together': {('age',)},
- 'index_together': {('name',), ('age',)},
- })
+ initial_author = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("age", models.IntegerField()),
+ ],
+ {
+ "unique_together": {("name",), ("age",)},
+ "index_together": {("name",)},
+ },
+ )
+ author_reversed_constraints = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("age", models.IntegerField()),
+ ],
+ {
+ "unique_together": {("age",)},
+ "index_together": {("name",), ("age",)},
+ },
+ )
changes = self.get_changes([initial_author], [author_reversed_constraints])
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, [
- 'AlterUniqueTogether',
- 'AlterIndexTogether',
- ])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes,
+ "testapp",
+ 0,
+ [
+ "AlterUniqueTogether",
+ "AlterIndexTogether",
+ ],
+ )
self.assertOperationAttributes(
- changes, 'testapp', 0, 0, name='author', unique_together={('age',)},
+ changes,
+ "testapp",
+ 0,
+ 0,
+ name="author",
+ unique_together={("age",)},
)
self.assertOperationAttributes(
- changes, 'testapp', 0, 1, name='author',
- index_together={('name',), ('age',)},
+ changes,
+ "testapp",
+ 0,
+ 1,
+ name="author",
+ index_together={("name",), ("age",)},
)
def test_rename_field_and_foo_together(self):
@@ -1744,62 +2975,89 @@ class AutodetectorTests(TestCase):
)
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, 'otherapp', 0, [
- 'RenameField',
- 'AlterUniqueTogether',
- 'AlterIndexTogether',
- ])
+ self.assertOperationTypes(
+ changes,
+ "otherapp",
+ 0,
+ [
+ "RenameField",
+ "AlterUniqueTogether",
+ "AlterIndexTogether",
+ ],
+ )
self.assertOperationAttributes(
- changes, 'otherapp', 0, 1, name='book',
- unique_together={('title', 'newfield2')},
+ changes,
+ "otherapp",
+ 0,
+ 1,
+ name="book",
+ unique_together={("title", "newfield2")},
)
self.assertOperationAttributes(
- changes, 'otherapp', 0, 2, name='book',
- index_together={('title', 'newfield2')},
+ changes,
+ "otherapp",
+ 0,
+ 2,
+ name="book",
+ index_together={("title", "newfield2")},
)
def test_proxy(self):
"""The autodetector correctly deals with proxy models."""
# First, we test adding a proxy model
- changes = self.get_changes([self.author_empty], [self.author_empty, self.author_proxy])
+ changes = self.get_changes(
+ [self.author_empty], [self.author_empty, self.author_proxy]
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
self.assertOperationAttributes(
- changes, "testapp", 0, 0, name="AuthorProxy", options={"proxy": True, "indexes": [], "constraints": []}
+ changes,
+ "testapp",
+ 0,
+ 0,
+ name="AuthorProxy",
+ options={"proxy": True, "indexes": [], "constraints": []},
)
# Now, we test turning a proxy model into a non-proxy model
# It should delete the proxy then make the real one
changes = self.get_changes(
- [self.author_empty, self.author_proxy], [self.author_empty, self.author_proxy_notproxy]
+ [self.author_empty, self.author_proxy],
+ [self.author_empty, self.author_proxy_notproxy],
)
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel", "CreateModel"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="AuthorProxy")
- self.assertOperationAttributes(changes, "testapp", 0, 1, name="AuthorProxy", options={})
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 1, name="AuthorProxy", options={}
+ )
def test_proxy_non_model_parent(self):
class Mixin:
pass
author_proxy_non_model_parent = ModelState(
- 'testapp',
- 'AuthorProxy',
+ "testapp",
+ "AuthorProxy",
[],
- {'proxy': True},
- (Mixin, 'testapp.author'),
+ {"proxy": True},
+ (Mixin, "testapp.author"),
)
changes = self.get_changes(
[self.author_empty],
[self.author_empty, author_proxy_non_model_parent],
)
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['CreateModel'])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
self.assertOperationAttributes(
- changes, 'testapp', 0, 0, name='AuthorProxy',
- options={'proxy': True, 'indexes': [], 'constraints': []},
- bases=(Mixin, 'testapp.author'),
+ changes,
+ "testapp",
+ 0,
+ 0,
+ name="AuthorProxy",
+ options={"proxy": True, "indexes": [], "constraints": []},
+ bases=(Mixin, "testapp.author"),
)
def test_proxy_custom_pk(self):
@@ -1808,18 +3066,22 @@ class AutodetectorTests(TestCase):
models.
"""
# First, we test the default pk field name
- changes = self.get_changes([], [self.author_empty, self.author_proxy_third, self.book_proxy_fk])
+ changes = self.get_changes(
+ [], [self.author_empty, self.author_proxy_third, self.book_proxy_fk]
+ )
# The model the FK is pointing from and to.
self.assertEqual(
- changes['otherapp'][0].operations[0].fields[2][1].remote_field.model,
- 'thirdapp.AuthorProxy',
+ changes["otherapp"][0].operations[0].fields[2][1].remote_field.model,
+ "thirdapp.AuthorProxy",
)
# Now, we test the custom pk field name
- changes = self.get_changes([], [self.author_custom_pk, self.author_proxy_third, self.book_proxy_fk])
+ changes = self.get_changes(
+ [], [self.author_custom_pk, self.author_proxy_third, self.book_proxy_fk]
+ )
# The model the FK is pointing from and to.
self.assertEqual(
- changes['otherapp'][0].operations[0].fields[2][1].remote_field.model,
- 'thirdapp.AuthorProxy',
+ changes["otherapp"][0].operations[0].fields[2][1].remote_field.model,
+ "thirdapp.AuthorProxy",
)
def test_proxy_to_mti_with_fk_to_proxy(self):
@@ -1828,12 +3090,12 @@ class AutodetectorTests(TestCase):
[self.author_empty, self.author_proxy_third, self.book_proxy_fk],
)
changes = self.get_changes([], to_state)
- fk_field = changes['otherapp'][0].operations[0].fields[2][1]
+ fk_field = changes["otherapp"][0].operations[0].fields[2][1]
self.assertEqual(
to_state.get_concrete_model_key(fk_field.remote_field.model),
- ('testapp', 'author'),
+ ("testapp", "author"),
)
- self.assertEqual(fk_field.remote_field.model, 'thirdapp.AuthorProxy')
+ self.assertEqual(fk_field.remote_field.model, "thirdapp.AuthorProxy")
# Change AuthorProxy to use MTI.
from_state = to_state.clone()
@@ -1842,98 +3104,120 @@ class AutodetectorTests(TestCase):
)
changes = self.get_changes(from_state, to_state)
# Right number/type of migrations for the AuthorProxy model?
- self.assertNumberMigrations(changes, 'thirdapp', 1)
- self.assertOperationTypes(changes, 'thirdapp', 0, ['DeleteModel', 'CreateModel'])
+ self.assertNumberMigrations(changes, "thirdapp", 1)
+ self.assertOperationTypes(
+ changes, "thirdapp", 0, ["DeleteModel", "CreateModel"]
+ )
# Right number/type of migrations for the Book model with a FK to
# AuthorProxy?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ['AlterField'])
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterField"])
# otherapp should depend on thirdapp.
- self.assertMigrationDependencies(changes, 'otherapp', 0, [('thirdapp', 'auto_1')])
+ self.assertMigrationDependencies(
+ changes, "otherapp", 0, [("thirdapp", "auto_1")]
+ )
# Now, test the pk table and field name.
- fk_field = changes['otherapp'][0].operations[0].field
+ fk_field = changes["otherapp"][0].operations[0].field
self.assertEqual(
to_state.get_concrete_model_key(fk_field.remote_field.model),
- ('thirdapp', 'authorproxy'),
+ ("thirdapp", "authorproxy"),
)
- self.assertEqual(fk_field.remote_field.model, 'thirdapp.AuthorProxy')
+ self.assertEqual(fk_field.remote_field.model, "thirdapp.AuthorProxy")
def test_proxy_to_mti_with_fk_to_proxy_proxy(self):
# First, test the pk table and field name.
- to_state = self.make_project_state([
- self.author_empty,
- self.author_proxy,
- self.author_proxy_proxy,
- self.book_proxy_proxy_fk,
- ])
+ to_state = self.make_project_state(
+ [
+ self.author_empty,
+ self.author_proxy,
+ self.author_proxy_proxy,
+ self.book_proxy_proxy_fk,
+ ]
+ )
changes = self.get_changes([], to_state)
- fk_field = changes['otherapp'][0].operations[0].fields[1][1]
+ fk_field = changes["otherapp"][0].operations[0].fields[1][1]
self.assertEqual(
to_state.get_concrete_model_key(fk_field.remote_field.model),
- ('testapp', 'author'),
+ ("testapp", "author"),
)
- self.assertEqual(fk_field.remote_field.model, 'testapp.AAuthorProxyProxy')
+ self.assertEqual(fk_field.remote_field.model, "testapp.AAuthorProxyProxy")
# Change AuthorProxy to use MTI. FK still points to AAuthorProxyProxy,
# a proxy of AuthorProxy.
from_state = to_state.clone()
- to_state = self.make_project_state([
- self.author_empty,
- self.author_proxy_notproxy,
- self.author_proxy_proxy,
- self.book_proxy_proxy_fk,
- ])
+ to_state = self.make_project_state(
+ [
+ self.author_empty,
+ self.author_proxy_notproxy,
+ self.author_proxy_proxy,
+ self.book_proxy_proxy_fk,
+ ]
+ )
changes = self.get_changes(from_state, to_state)
# Right number/type of migrations for the AuthorProxy model?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['DeleteModel', 'CreateModel'])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel", "CreateModel"])
# Right number/type of migrations for the Book model with a FK to
# AAuthorProxyProxy?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ['AlterField'])
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterField"])
# otherapp should depend on testapp.
- self.assertMigrationDependencies(changes, 'otherapp', 0, [('testapp', 'auto_1')])
+ self.assertMigrationDependencies(
+ changes, "otherapp", 0, [("testapp", "auto_1")]
+ )
# Now, test the pk table and field name.
- fk_field = changes['otherapp'][0].operations[0].field
+ fk_field = changes["otherapp"][0].operations[0].field
self.assertEqual(
to_state.get_concrete_model_key(fk_field.remote_field.model),
- ('testapp', 'authorproxy'),
+ ("testapp", "authorproxy"),
)
- self.assertEqual(fk_field.remote_field.model, 'testapp.AAuthorProxyProxy')
+ self.assertEqual(fk_field.remote_field.model, "testapp.AAuthorProxyProxy")
def test_unmanaged_create(self):
"""The autodetector correctly deals with managed models."""
# First, we test adding an unmanaged model
- changes = self.get_changes([self.author_empty], [self.author_empty, self.author_unmanaged])
+ changes = self.get_changes(
+ [self.author_empty], [self.author_empty, self.author_unmanaged]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="AuthorUnmanaged", options={"managed": False})
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="AuthorUnmanaged", options={"managed": False}
+ )
def test_unmanaged_delete(self):
- changes = self.get_changes([self.author_empty, self.author_unmanaged], [self.author_empty])
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['DeleteModel'])
+ changes = self.get_changes(
+ [self.author_empty, self.author_unmanaged], [self.author_empty]
+ )
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel"])
def test_unmanaged_to_managed(self):
# Now, we test turning an unmanaged model into a managed model
changes = self.get_changes(
- [self.author_empty, self.author_unmanaged], [self.author_empty, self.author_unmanaged_managed]
+ [self.author_empty, self.author_unmanaged],
+ [self.author_empty, self.author_unmanaged_managed],
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterModelOptions"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="authorunmanaged", options={})
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="authorunmanaged", options={}
+ )
def test_managed_to_unmanaged(self):
# Now, we turn managed to unmanaged.
changes = self.get_changes(
- [self.author_empty, self.author_unmanaged_managed], [self.author_empty, self.author_unmanaged]
+ [self.author_empty, self.author_unmanaged_managed],
+ [self.author_empty, self.author_unmanaged],
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="authorunmanaged", options={"managed": False})
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="authorunmanaged", options={"managed": False}
+ )
def test_unmanaged_custom_pk(self):
"""
@@ -1943,74 +3227,97 @@ class AutodetectorTests(TestCase):
# First, we test the default pk field name
changes = self.get_changes([], [self.author_unmanaged_default_pk, self.book])
# The model the FK on the book model points to.
- fk_field = changes['otherapp'][0].operations[0].fields[2][1]
- self.assertEqual(fk_field.remote_field.model, 'testapp.Author')
+ fk_field = changes["otherapp"][0].operations[0].fields[2][1]
+ self.assertEqual(fk_field.remote_field.model, "testapp.Author")
# Now, we test the custom pk field name
changes = self.get_changes([], [self.author_unmanaged_custom_pk, self.book])
# The model the FK on the book model points to.
- fk_field = changes['otherapp'][0].operations[0].fields[2][1]
- self.assertEqual(fk_field.remote_field.model, 'testapp.Author')
+ fk_field = changes["otherapp"][0].operations[0].fields[2][1]
+ self.assertEqual(fk_field.remote_field.model, "testapp.Author")
@override_settings(AUTH_USER_MODEL="thirdapp.CustomUser")
def test_swappable(self):
with isolate_lru_cache(apps.get_swappable_settings_name):
- changes = self.get_changes([self.custom_user], [self.custom_user, self.author_with_custom_user])
+ changes = self.get_changes(
+ [self.custom_user], [self.custom_user, self.author_with_custom_user]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
- self.assertMigrationDependencies(changes, 'testapp', 0, [("__setting__", "AUTH_USER_MODEL")])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
+ self.assertMigrationDependencies(
+ changes, "testapp", 0, [("__setting__", "AUTH_USER_MODEL")]
+ )
def test_swappable_lowercase(self):
- model_state = ModelState('testapp', 'Document', [
- ('id', models.AutoField(primary_key=True)),
- ('owner', models.ForeignKey(
- settings.AUTH_USER_MODEL.lower(), models.CASCADE,
- )),
- ])
+ model_state = ModelState(
+ "testapp",
+ "Document",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "owner",
+ models.ForeignKey(
+ settings.AUTH_USER_MODEL.lower(),
+ models.CASCADE,
+ ),
+ ),
+ ],
+ )
with isolate_lru_cache(apps.get_swappable_settings_name):
changes = self.get_changes([], [model_state])
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['CreateModel'])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name='Document')
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Document")
self.assertMigrationDependencies(
- changes, 'testapp', 0, [('__setting__', 'AUTH_USER_MODEL')],
+ changes,
+ "testapp",
+ 0,
+ [("__setting__", "AUTH_USER_MODEL")],
)
def test_swappable_changed(self):
with isolate_lru_cache(apps.get_swappable_settings_name):
before = self.make_project_state([self.custom_user, self.author_with_user])
with override_settings(AUTH_USER_MODEL="thirdapp.CustomUser"):
- after = self.make_project_state([self.custom_user, self.author_with_custom_user])
+ after = self.make_project_state(
+ [self.custom_user, self.author_with_custom_user]
+ )
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, model_name="author", name='user')
- fk_field = changes['testapp'][0].operations[0].field
- self.assertEqual(fk_field.remote_field.model, 'thirdapp.CustomUser')
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, model_name="author", name="user"
+ )
+ fk_field = changes["testapp"][0].operations[0].field
+ self.assertEqual(fk_field.remote_field.model, "thirdapp.CustomUser")
def test_add_field_with_default(self):
"""#22030 - Adding a field with a default should work."""
changes = self.get_changes([self.author_empty], [self.author_name_default])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="name")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AddField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="name")
def test_custom_deconstructible(self):
"""
Two instances which deconstruct to the same value aren't considered a
change.
"""
- changes = self.get_changes([self.author_name_deconstructible_1], [self.author_name_deconstructible_2])
+ changes = self.get_changes(
+ [self.author_name_deconstructible_1], [self.author_name_deconstructible_2]
+ )
# Right number of migrations?
self.assertEqual(len(changes), 0)
def test_deconstruct_field_kwarg(self):
"""Field instances are handled correctly by nested deconstruction."""
- changes = self.get_changes([self.author_name_deconstructible_3], [self.author_name_deconstructible_4])
+ changes = self.get_changes(
+ [self.author_name_deconstructible_3], [self.author_name_deconstructible_4]
+ )
self.assertEqual(changes, {})
def test_deconstructible_list(self):
@@ -2019,13 +3326,15 @@ class AutodetectorTests(TestCase):
# should be considered equal for the purpose of detecting state changes
# (even if the original items are unequal).
changes = self.get_changes(
- [self.author_name_deconstructible_list_1], [self.author_name_deconstructible_list_2]
+ [self.author_name_deconstructible_list_1],
+ [self.author_name_deconstructible_list_2],
)
self.assertEqual(changes, {})
# Legitimate differences within the deconstructed lists should be reported
# as a change
changes = self.get_changes(
- [self.author_name_deconstructible_list_1], [self.author_name_deconstructible_list_3]
+ [self.author_name_deconstructible_list_1],
+ [self.author_name_deconstructible_list_3],
)
self.assertEqual(len(changes), 1)
@@ -2035,13 +3344,15 @@ class AutodetectorTests(TestCase):
# should be considered equal for the purpose of detecting state changes
# (even if the original items are unequal).
changes = self.get_changes(
- [self.author_name_deconstructible_tuple_1], [self.author_name_deconstructible_tuple_2]
+ [self.author_name_deconstructible_tuple_1],
+ [self.author_name_deconstructible_tuple_2],
)
self.assertEqual(changes, {})
# Legitimate differences within the deconstructed tuples should be reported
# as a change
changes = self.get_changes(
- [self.author_name_deconstructible_tuple_1], [self.author_name_deconstructible_tuple_3]
+ [self.author_name_deconstructible_tuple_1],
+ [self.author_name_deconstructible_tuple_3],
)
self.assertEqual(len(changes), 1)
@@ -2051,13 +3362,15 @@ class AutodetectorTests(TestCase):
# those dicts should be considered equal for the purpose of detecting
# state changes (even if the original values are unequal).
changes = self.get_changes(
- [self.author_name_deconstructible_dict_1], [self.author_name_deconstructible_dict_2]
+ [self.author_name_deconstructible_dict_1],
+ [self.author_name_deconstructible_dict_2],
)
self.assertEqual(changes, {})
# Legitimate differences within the deconstructed dicts should be reported
# as a change
changes = self.get_changes(
- [self.author_name_deconstructible_dict_1], [self.author_name_deconstructible_dict_3]
+ [self.author_name_deconstructible_dict_1],
+ [self.author_name_deconstructible_dict_3],
)
self.assertEqual(len(changes), 1)
@@ -2070,29 +3383,34 @@ class AutodetectorTests(TestCase):
# deconstructed values - whether or not the items themselves are different
# instances - then the object as a whole is regarded as unchanged.
changes = self.get_changes(
- [self.author_name_nested_deconstructible_1], [self.author_name_nested_deconstructible_2]
+ [self.author_name_nested_deconstructible_1],
+ [self.author_name_nested_deconstructible_2],
)
self.assertEqual(changes, {})
# Differences that exist solely within the args list of a deconstructed object
# should be reported as changes
changes = self.get_changes(
- [self.author_name_nested_deconstructible_1], [self.author_name_nested_deconstructible_changed_arg]
+ [self.author_name_nested_deconstructible_1],
+ [self.author_name_nested_deconstructible_changed_arg],
)
self.assertEqual(len(changes), 1)
# Additional args should also be reported as a change
changes = self.get_changes(
- [self.author_name_nested_deconstructible_1], [self.author_name_nested_deconstructible_extra_arg]
+ [self.author_name_nested_deconstructible_1],
+ [self.author_name_nested_deconstructible_extra_arg],
)
self.assertEqual(len(changes), 1)
# Differences that exist solely within the kwargs dict of a deconstructed object
# should be reported as changes
changes = self.get_changes(
- [self.author_name_nested_deconstructible_1], [self.author_name_nested_deconstructible_changed_kwarg]
+ [self.author_name_nested_deconstructible_1],
+ [self.author_name_nested_deconstructible_changed_kwarg],
)
self.assertEqual(len(changes), 1)
# Additional kwargs should also be reported as a change
changes = self.get_changes(
- [self.author_name_nested_deconstructible_1], [self.author_name_nested_deconstructible_extra_kwarg]
+ [self.author_name_nested_deconstructible_1],
+ [self.author_name_nested_deconstructible_extra_kwarg],
)
self.assertEqual(len(changes), 1)
@@ -2106,30 +3424,38 @@ class AutodetectorTests(TestCase):
"Author",
[
("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(
- max_length=200,
- # IntegerField intentionally not instantiated.
- default=models.IntegerField,
- ))
+ (
+ "name",
+ models.CharField(
+ max_length=200,
+ # IntegerField intentionally not instantiated.
+ default=models.IntegerField,
+ ),
+ ),
],
)
changes = self.get_changes([], [author])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
def test_replace_string_with_foreignkey(self):
"""
#22300 - Adding an FK in the same "spot" as a deleted CharField should
work.
"""
- changes = self.get_changes([self.author_with_publisher_string], [self.author_with_publisher, self.publisher])
+ changes = self.get_changes(
+ [self.author_with_publisher_string],
+ [self.author_with_publisher, self.publisher],
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "RemoveField", "AddField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Publisher")
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="publisher_name")
- self.assertOperationAttributes(changes, 'testapp', 0, 2, name="publisher")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["CreateModel", "RemoveField", "AddField"]
+ )
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="publisher_name")
+ self.assertOperationAttributes(changes, "testapp", 0, 2, name="publisher")
def test_foreign_key_removed_before_target_model(self):
"""
@@ -2140,45 +3466,62 @@ class AutodetectorTests(TestCase):
[self.author_with_publisher, self.publisher], [self.author_name]
) # removes both the model and FK
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["RemoveField", "DeleteModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="publisher")
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="Publisher")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["RemoveField", "DeleteModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="publisher")
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
- @mock.patch('django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition',
- side_effect=AssertionError("Should not have prompted for not null addition"))
+ @mock.patch(
+ "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition",
+ side_effect=AssertionError("Should not have prompted for not null addition"),
+ )
def test_add_many_to_many(self, mocked_ask_method):
"""#22435 - Adding a ManyToManyField should not prompt for a default."""
- changes = self.get_changes([self.author_empty, self.publisher], [self.author_with_m2m, self.publisher])
+ changes = self.get_changes(
+ [self.author_empty, self.publisher], [self.author_with_m2m, self.publisher]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="publishers")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AddField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="publishers")
def test_alter_many_to_many(self):
changes = self.get_changes(
- [self.author_with_m2m, self.publisher], [self.author_with_m2m_blank, self.publisher]
+ [self.author_with_m2m, self.publisher],
+ [self.author_with_m2m_blank, self.publisher],
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="publishers")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="publishers")
def test_create_with_through_model(self):
"""
Adding a m2m with a through model and the models that use it should be
ordered correctly.
"""
- changes = self.get_changes([], [self.author_with_m2m_through, self.publisher, self.contract])
+ changes = self.get_changes(
+ [], [self.author_with_m2m_through, self.publisher, self.contract]
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- self.assertOperationTypes(changes, "testapp", 0, [
- 'CreateModel', 'CreateModel', 'CreateModel', 'AddField',
- ])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name='Author')
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name='Publisher')
- self.assertOperationAttributes(changes, 'testapp', 0, 2, name='Contract')
- self.assertOperationAttributes(changes, 'testapp', 0, 3, model_name='author', name='publishers')
+ self.assertOperationTypes(
+ changes,
+ "testapp",
+ 0,
+ [
+ "CreateModel",
+ "CreateModel",
+ "CreateModel",
+ "AddField",
+ ],
+ )
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
+ self.assertOperationAttributes(changes, "testapp", 0, 2, name="Contract")
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 3, model_name="author", name="publishers"
+ )
def test_many_to_many_removed_before_through_model(self):
"""
@@ -2186,15 +3529,23 @@ class AutodetectorTests(TestCase):
must remove the field before the model to maintain consistency.
"""
changes = self.get_changes(
- [self.book_with_multiple_authors_through_attribution, self.author_name, self.attribution],
+ [
+ self.book_with_multiple_authors_through_attribution,
+ self.author_name,
+ self.attribution,
+ ],
[self.book_with_no_author, self.author_name],
)
# Remove both the through model and ManyToMany
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ['RemoveField', 'DeleteModel'])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name='authors', model_name='book')
- self.assertOperationAttributes(changes, 'otherapp', 0, 1, name='Attribution')
+ self.assertOperationTypes(
+ changes, "otherapp", 0, ["RemoveField", "DeleteModel"]
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 0, name="authors", model_name="book"
+ )
+ self.assertOperationAttributes(changes, "otherapp", 0, 1, name="Attribution")
def test_many_to_many_removed_before_through_model_2(self):
"""
@@ -2203,16 +3554,24 @@ class AutodetectorTests(TestCase):
consistency.
"""
changes = self.get_changes(
- [self.book_with_multiple_authors_through_attribution, self.author_name, self.attribution],
+ [
+ self.book_with_multiple_authors_through_attribution,
+ self.author_name,
+ self.attribution,
+ ],
[self.author_name],
)
# Remove both the through model and ManyToMany
# Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ['RemoveField', 'DeleteModel', 'DeleteModel'])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name='authors', model_name='book')
- self.assertOperationAttributes(changes, 'otherapp', 0, 1, name='Attribution')
- self.assertOperationAttributes(changes, 'otherapp', 0, 2, name='Book')
+ self.assertOperationTypes(
+ changes, "otherapp", 0, ["RemoveField", "DeleteModel", "DeleteModel"]
+ )
+ self.assertOperationAttributes(
+ changes, "otherapp", 0, 0, name="authors", model_name="book"
+ )
+ self.assertOperationAttributes(changes, "otherapp", 0, 1, name="Attribution")
+ self.assertOperationAttributes(changes, "otherapp", 0, 2, name="Book")
def test_m2m_w_through_multistep_remove(self):
"""
@@ -2221,14 +3580,24 @@ class AutodetectorTests(TestCase):
pass through an inconsistent state. The autodetector should produce two
migrations to avoid this issue.
"""
- changes = self.get_changes([self.author_with_m2m_through, self.publisher, self.contract], [self.publisher])
+ changes = self.get_changes(
+ [self.author_with_m2m_through, self.publisher, self.contract],
+ [self.publisher],
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- self.assertOperationTypes(changes, "testapp", 0, [
- "RemoveField", "RemoveField", "DeleteModel", "DeleteModel"
- ])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", model_name='contract')
- self.assertOperationAttributes(changes, "testapp", 0, 1, name="publisher", model_name='contract')
+ self.assertOperationTypes(
+ changes,
+ "testapp",
+ 0,
+ ["RemoveField", "RemoveField", "DeleteModel", "DeleteModel"],
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="author", model_name="contract"
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 1, name="publisher", model_name="contract"
+ )
self.assertOperationAttributes(changes, "testapp", 0, 2, name="Author")
self.assertOperationAttributes(changes, "testapp", 0, 3, name="Contract")
@@ -2237,38 +3606,60 @@ class AutodetectorTests(TestCase):
#23938 - Changing a concrete field into a ManyToManyField
first removes the concrete field and then adds the m2m field.
"""
- changes = self.get_changes([self.author_with_former_m2m], [self.author_with_m2m, self.publisher])
+ changes = self.get_changes(
+ [self.author_with_former_m2m], [self.author_with_m2m, self.publisher]
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "RemoveField", "AddField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name='Publisher')
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="publishers", model_name='author')
- self.assertOperationAttributes(changes, 'testapp', 0, 2, name="publishers", model_name='author')
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["CreateModel", "RemoveField", "AddField"]
+ )
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 1, name="publishers", model_name="author"
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 2, name="publishers", model_name="author"
+ )
def test_many_to_many_changed_to_concrete_field(self):
"""
#23938 - Changing a ManyToManyField into a concrete field
first removes the m2m field and then adds the concrete field.
"""
- changes = self.get_changes([self.author_with_m2m, self.publisher], [self.author_with_former_m2m])
+ changes = self.get_changes(
+ [self.author_with_m2m, self.publisher], [self.author_with_former_m2m]
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- self.assertOperationTypes(changes, "testapp", 0, ["RemoveField", "AddField", "DeleteModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="publishers", model_name='author')
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="publishers", model_name='author')
- self.assertOperationAttributes(changes, 'testapp', 0, 2, name='Publisher')
- self.assertOperationFieldAttributes(changes, 'testapp', 0, 1, max_length=100)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["RemoveField", "AddField", "DeleteModel"]
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="publishers", model_name="author"
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 1, name="publishers", model_name="author"
+ )
+ self.assertOperationAttributes(changes, "testapp", 0, 2, name="Publisher")
+ self.assertOperationFieldAttributes(changes, "testapp", 0, 1, max_length=100)
def test_non_circular_foreignkey_dependency_removal(self):
"""
If two models with a ForeignKey from one to the other are removed at the
same time, the autodetector should remove them in the correct order.
"""
- changes = self.get_changes([self.author_with_publisher, self.publisher_with_author], [])
+ changes = self.get_changes(
+ [self.author_with_publisher, self.publisher_with_author], []
+ )
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- self.assertOperationTypes(changes, "testapp", 0, ["RemoveField", "DeleteModel", "DeleteModel"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", model_name='publisher')
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["RemoveField", "DeleteModel", "DeleteModel"]
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="author", model_name="publisher"
+ )
self.assertOperationAttributes(changes, "testapp", 0, 1, name="Author")
self.assertOperationAttributes(changes, "testapp", 0, 2, name="Publisher")
@@ -2278,61 +3669,96 @@ class AutodetectorTests(TestCase):
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, options={
- "permissions": [('can_hire', 'Can hire')],
- "verbose_name": "Authi",
- })
+ self.assertOperationAttributes(
+ changes,
+ "testapp",
+ 0,
+ 0,
+ options={
+ "permissions": [("can_hire", "Can hire")],
+ "verbose_name": "Authi",
+ },
+ )
# Changing them back to empty should also make a change
changes = self.get_changes([self.author_with_options], [self.author_empty])
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", options={})
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="author", options={}
+ )
def test_alter_model_options_proxy(self):
"""Changing a proxy model's options should also make a change."""
changes = self.get_changes(
- [self.author_proxy, self.author_empty], [self.author_proxy_options, self.author_empty]
+ [self.author_proxy, self.author_empty],
+ [self.author_proxy_options, self.author_empty],
)
# Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="authorproxy", options={
- "verbose_name": "Super Author"
- })
+ self.assertOperationAttributes(
+ changes,
+ "testapp",
+ 0,
+ 0,
+ name="authorproxy",
+ options={"verbose_name": "Super Author"},
+ )
def test_set_alter_order_with_respect_to(self):
"""Setting order_with_respect_to adds a field."""
- changes = self.get_changes([self.book, self.author_with_book], [self.book, self.author_with_book_order_wrt])
+ changes = self.get_changes(
+ [self.book, self.author_with_book],
+ [self.book, self.author_with_book_order_wrt],
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterOrderWithRespectTo"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="author", order_with_respect_to="book")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AlterOrderWithRespectTo"])
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="author", order_with_respect_to="book"
+ )
def test_add_alter_order_with_respect_to(self):
"""
Setting order_with_respect_to when adding the FK too does
things in the right order.
"""
- changes = self.get_changes([self.author_name], [self.book, self.author_with_book_order_wrt])
+ changes = self.get_changes(
+ [self.author_name], [self.book, self.author_with_book_order_wrt]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField", "AlterOrderWithRespectTo"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, model_name="author", name="book")
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="author", order_with_respect_to="book")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["AddField", "AlterOrderWithRespectTo"]
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, model_name="author", name="book"
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 1, name="author", order_with_respect_to="book"
+ )
def test_remove_alter_order_with_respect_to(self):
"""
Removing order_with_respect_to when removing the FK too does
things in the right order.
"""
- changes = self.get_changes([self.book, self.author_with_book_order_wrt], [self.author_name])
+ changes = self.get_changes(
+ [self.book, self.author_with_book_order_wrt], [self.author_name]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AlterOrderWithRespectTo", "RemoveField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="author", order_with_respect_to=None)
- self.assertOperationAttributes(changes, 'testapp', 0, 1, model_name="author", name="book")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["AlterOrderWithRespectTo", "RemoveField"]
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 0, name="author", order_with_respect_to=None
+ )
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 1, model_name="author", name="book"
+ )
def test_add_model_order_with_respect_to(self):
"""
@@ -2341,121 +3767,167 @@ class AutodetectorTests(TestCase):
"""
changes = self.get_changes([], [self.book, self.author_with_book_order_wrt])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
self.assertOperationAttributes(
- changes, 'testapp', 0, 0, name="Author", options={'order_with_respect_to': 'book'}
+ changes,
+ "testapp",
+ 0,
+ 0,
+ name="Author",
+ options={"order_with_respect_to": "book"},
+ )
+ self.assertNotIn(
+ "_order",
+ [name for name, field in changes["testapp"][0].operations[0].fields],
)
- self.assertNotIn("_order", [name for name, field in changes['testapp'][0].operations[0].fields])
def test_add_model_order_with_respect_to_index_foo_together(self):
- changes = self.get_changes([], [
- self.book,
- ModelState('testapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ('book', models.ForeignKey('otherapp.Book', models.CASCADE)),
- ], options={
- 'order_with_respect_to': 'book',
- 'index_together': {('name', '_order')},
- 'unique_together': {('id', '_order')},
- }),
- ])
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['CreateModel'])
+ changes = self.get_changes(
+ [],
+ [
+ self.book,
+ ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ],
+ options={
+ "order_with_respect_to": "book",
+ "index_together": {("name", "_order")},
+ "unique_together": {("id", "_order")},
+ },
+ ),
+ ],
+ )
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
self.assertOperationAttributes(
changes,
- 'testapp',
+ "testapp",
0,
0,
- name='Author',
+ name="Author",
options={
- 'order_with_respect_to': 'book',
- 'index_together': {('name', '_order')},
- 'unique_together': {('id', '_order')},
+ "order_with_respect_to": "book",
+ "index_together": {("name", "_order")},
+ "unique_together": {("id", "_order")},
},
)
def test_add_model_order_with_respect_to_index_constraint(self):
tests = [
(
- 'AddIndex',
- {'indexes': [
- models.Index(fields=['_order'], name='book_order_idx'),
- ]},
+ "AddIndex",
+ {
+ "indexes": [
+ models.Index(fields=["_order"], name="book_order_idx"),
+ ]
+ },
),
(
- 'AddConstraint',
- {'constraints': [
- models.CheckConstraint(
- check=models.Q(_order__gt=1),
- name='book_order_gt_1',
- ),
- ]},
+ "AddConstraint",
+ {
+ "constraints": [
+ models.CheckConstraint(
+ check=models.Q(_order__gt=1),
+ name="book_order_gt_1",
+ ),
+ ]
+ },
),
]
for operation, extra_option in tests:
with self.subTest(operation=operation):
- after = ModelState('testapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ('book', models.ForeignKey('otherapp.Book', models.CASCADE)),
- ], options={
- 'order_with_respect_to': 'book',
- **extra_option,
- })
+ after = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ],
+ options={
+ "order_with_respect_to": "book",
+ **extra_option,
+ },
+ )
changes = self.get_changes([], [self.book, after])
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, [
- 'CreateModel', operation,
- ])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes,
+ "testapp",
+ 0,
+ [
+ "CreateModel",
+ operation,
+ ],
+ )
self.assertOperationAttributes(
changes,
- 'testapp',
+ "testapp",
0,
0,
- name='Author',
- options={'order_with_respect_to': 'book'},
+ name="Author",
+ options={"order_with_respect_to": "book"},
)
def test_set_alter_order_with_respect_to_index_constraint_foo_together(self):
tests = [
(
- 'AddIndex',
- {'indexes': [
- models.Index(fields=['_order'], name='book_order_idx'),
- ]},
+ "AddIndex",
+ {
+ "indexes": [
+ models.Index(fields=["_order"], name="book_order_idx"),
+ ]
+ },
),
(
- 'AddConstraint',
- {'constraints': [
- models.CheckConstraint(
- check=models.Q(_order__gt=1),
- name='book_order_gt_1',
- ),
- ]},
+ "AddConstraint",
+ {
+ "constraints": [
+ models.CheckConstraint(
+ check=models.Q(_order__gt=1),
+ name="book_order_gt_1",
+ ),
+ ]
+ },
),
- ('AlterIndexTogether', {'index_together': {('name', '_order')}}),
- ('AlterUniqueTogether', {'unique_together': {('id', '_order')}}),
+ ("AlterIndexTogether", {"index_together": {("name", "_order")}}),
+ ("AlterUniqueTogether", {"unique_together": {("id", "_order")}}),
]
for operation, extra_option in tests:
with self.subTest(operation=operation):
- after = ModelState('testapp', 'Author', [
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=200)),
- ('book', models.ForeignKey('otherapp.Book', models.CASCADE)),
- ], options={
- 'order_with_respect_to': 'book',
- **extra_option,
- })
+ after = ModelState(
+ "testapp",
+ "Author",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=200)),
+ ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
+ ],
+ options={
+ "order_with_respect_to": "book",
+ **extra_option,
+ },
+ )
changes = self.get_changes(
[self.book, self.author_with_book],
[self.book, after],
)
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, [
- 'AlterOrderWithRespectTo', operation,
- ])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes,
+ "testapp",
+ 0,
+ [
+ "AlterOrderWithRespectTo",
+ operation,
+ ],
+ )
def test_alter_model_managers(self):
"""
@@ -2463,41 +3935,62 @@ class AutodetectorTests(TestCase):
"""
changes = self.get_changes([self.other_pony], [self.other_pony_food])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ["AlterModelManagers"])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="pony")
- self.assertEqual([name for name, mgr in changes['otherapp'][0].operations[0].managers],
- ['food_qs', 'food_mgr', 'food_mgr_kwargs'])
- self.assertEqual(changes['otherapp'][0].operations[0].managers[1][1].args, ('a', 'b', 1, 2))
- self.assertEqual(changes['otherapp'][0].operations[0].managers[2][1].args, ('x', 'y', 3, 4))
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterModelManagers"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="pony")
+ self.assertEqual(
+ [name for name, mgr in changes["otherapp"][0].operations[0].managers],
+ ["food_qs", "food_mgr", "food_mgr_kwargs"],
+ )
+ self.assertEqual(
+ changes["otherapp"][0].operations[0].managers[1][1].args, ("a", "b", 1, 2)
+ )
+ self.assertEqual(
+ changes["otherapp"][0].operations[0].managers[2][1].args, ("x", "y", 3, 4)
+ )
def test_swappable_first_inheritance(self):
"""Swappable models get their CreateModel first."""
changes = self.get_changes([], [self.custom_user, self.aardvark])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'thirdapp', 1)
- self.assertOperationTypes(changes, 'thirdapp', 0, ["CreateModel", "CreateModel"])
- self.assertOperationAttributes(changes, 'thirdapp', 0, 0, name="CustomUser")
- self.assertOperationAttributes(changes, 'thirdapp', 0, 1, name="Aardvark")
+ self.assertNumberMigrations(changes, "thirdapp", 1)
+ self.assertOperationTypes(
+ changes, "thirdapp", 0, ["CreateModel", "CreateModel"]
+ )
+ self.assertOperationAttributes(changes, "thirdapp", 0, 0, name="CustomUser")
+ self.assertOperationAttributes(changes, "thirdapp", 0, 1, name="Aardvark")
def test_default_related_name_option(self):
- model_state = ModelState('app', 'model', [
- ('id', models.AutoField(primary_key=True)),
- ], options={'default_related_name': 'related_name'})
+ model_state = ModelState(
+ "app",
+ "model",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ options={"default_related_name": "related_name"},
+ )
changes = self.get_changes([], [model_state])
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['CreateModel'])
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["CreateModel"])
self.assertOperationAttributes(
- changes, 'app', 0, 0, name='model',
- options={'default_related_name': 'related_name'},
+ changes,
+ "app",
+ 0,
+ 0,
+ name="model",
+ options={"default_related_name": "related_name"},
+ )
+ altered_model_state = ModelState(
+ "app",
+ "Model",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
)
- altered_model_state = ModelState('app', 'Model', [
- ('id', models.AutoField(primary_key=True)),
- ])
changes = self.get_changes([model_state], [altered_model_state])
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['AlterModelOptions'])
- self.assertOperationAttributes(changes, 'app', 0, 0, name='model', options={})
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["AlterModelOptions"])
+ self.assertOperationAttributes(changes, "app", 0, 0, name="model", options={})
@override_settings(AUTH_USER_MODEL="thirdapp.CustomUser")
def test_swappable_first_setting(self):
@@ -2505,39 +3998,64 @@ class AutodetectorTests(TestCase):
with isolate_lru_cache(apps.get_swappable_settings_name):
changes = self.get_changes([], [self.custom_user_no_inherit, self.aardvark])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'thirdapp', 1)
- self.assertOperationTypes(changes, 'thirdapp', 0, ["CreateModel", "CreateModel"])
- self.assertOperationAttributes(changes, 'thirdapp', 0, 0, name="CustomUser")
- self.assertOperationAttributes(changes, 'thirdapp', 0, 1, name="Aardvark")
+ self.assertNumberMigrations(changes, "thirdapp", 1)
+ self.assertOperationTypes(
+ changes, "thirdapp", 0, ["CreateModel", "CreateModel"]
+ )
+ self.assertOperationAttributes(changes, "thirdapp", 0, 0, name="CustomUser")
+ self.assertOperationAttributes(changes, "thirdapp", 0, 1, name="Aardvark")
def test_bases_first(self):
"""Bases of other models come first."""
- changes = self.get_changes([], [self.aardvark_based_on_author, self.author_name])
+ changes = self.get_changes(
+ [], [self.aardvark_based_on_author, self.author_name]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="Aardvark")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="Aardvark")
def test_bases_first_mixed_case_app_label(self):
- app_label = 'MiXedCaseApp'
- changes = self.get_changes([], [
- ModelState(app_label, 'owner', [
- ('id', models.AutoField(primary_key=True)),
- ]),
- ModelState(app_label, 'place', [
- ('id', models.AutoField(primary_key=True)),
- ('owner', models.ForeignKey('MiXedCaseApp.owner', models.CASCADE)),
- ]),
- ModelState(app_label, 'restaurant', [], bases=('MiXedCaseApp.place',)),
- ])
+ app_label = "MiXedCaseApp"
+ changes = self.get_changes(
+ [],
+ [
+ ModelState(
+ app_label,
+ "owner",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ ModelState(
+ app_label,
+ "place",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "owner",
+ models.ForeignKey("MiXedCaseApp.owner", models.CASCADE),
+ ),
+ ],
+ ),
+ ModelState(app_label, "restaurant", [], bases=("MiXedCaseApp.place",)),
+ ],
+ )
self.assertNumberMigrations(changes, app_label, 1)
- self.assertOperationTypes(changes, app_label, 0, [
- 'CreateModel', 'CreateModel', 'CreateModel',
- ])
- self.assertOperationAttributes(changes, app_label, 0, 0, name='owner')
- self.assertOperationAttributes(changes, app_label, 0, 1, name='place')
- self.assertOperationAttributes(changes, app_label, 0, 2, name='restaurant')
+ self.assertOperationTypes(
+ changes,
+ app_label,
+ 0,
+ [
+ "CreateModel",
+ "CreateModel",
+ "CreateModel",
+ ],
+ )
+ self.assertOperationAttributes(changes, app_label, 0, 0, name="owner")
+ self.assertOperationAttributes(changes, app_label, 0, 1, name="place")
+ self.assertOperationAttributes(changes, app_label, 0, 2, name="restaurant")
def test_multiple_bases(self):
"""#23956 - Inheriting models doesn't move *_ptr fields into AddField operations."""
@@ -2549,9 +4067,12 @@ class AutodetectorTests(TestCase):
changes = self.get_changes([], [A, B, C, D, E])
# Right number/type of migrations?
self.assertNumberMigrations(changes, "app", 1)
- self.assertOperationTypes(changes, "app", 0, [
- "CreateModel", "CreateModel", "CreateModel", "CreateModel", "CreateModel"
- ])
+ self.assertOperationTypes(
+ changes,
+ "app",
+ 0,
+ ["CreateModel", "CreateModel", "CreateModel", "CreateModel", "CreateModel"],
+ )
self.assertOperationAttributes(changes, "app", 0, 0, name="A")
self.assertOperationAttributes(changes, "app", 0, 1, name="B")
self.assertOperationAttributes(changes, "app", 0, 2, name="C")
@@ -2560,13 +4081,19 @@ class AutodetectorTests(TestCase):
def test_proxy_bases_first(self):
"""Bases of proxies come first."""
- changes = self.get_changes([], [self.author_empty, self.author_proxy, self.author_proxy_proxy])
+ changes = self.get_changes(
+ [], [self.author_empty, self.author_proxy, self.author_proxy_proxy]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel", "CreateModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="AuthorProxy")
- self.assertOperationAttributes(changes, 'testapp', 0, 2, name="AAuthorProxyProxy")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["CreateModel", "CreateModel", "CreateModel"]
+ )
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="AuthorProxy")
+ self.assertOperationAttributes(
+ changes, "testapp", 0, 2, name="AAuthorProxyProxy"
+ )
def test_pk_fk_included(self):
"""
@@ -2574,10 +4101,10 @@ class AutodetectorTests(TestCase):
"""
changes = self.get_changes([], [self.aardvark_pk_fk_author, self.author_name])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="Aardvark")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="Aardvark")
def test_first_dependency(self):
"""
@@ -2587,14 +4114,16 @@ class AutodetectorTests(TestCase):
loader = MigrationLoader(connection)
before = self.make_project_state([])
after = self.make_project_state([self.book_migrations_fk])
- after.real_apps = {'migrations'}
+ after.real_apps = {"migrations"}
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes(graph=loader.graph)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="Book")
- self.assertMigrationDependencies(changes, 'otherapp', 0, [("migrations", "__first__")])
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Book")
+ self.assertMigrationDependencies(
+ changes, "otherapp", 0, [("migrations", "__first__")]
+ )
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_last_dependency(self):
@@ -2606,14 +4135,16 @@ class AutodetectorTests(TestCase):
loader = MigrationLoader(connection)
before = self.make_project_state([])
after = self.make_project_state([self.book_migrations_fk])
- after.real_apps = {'migrations'}
+ after.real_apps = {"migrations"}
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes(graph=loader.graph)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
- self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="Book")
- self.assertMigrationDependencies(changes, 'otherapp', 0, [("migrations", "0002_second")])
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Book")
+ self.assertMigrationDependencies(
+ changes, "otherapp", 0, [("migrations", "0002_second")]
+ )
def test_alter_fk_before_model_deletion(self):
"""
@@ -2622,61 +4153,85 @@ class AutodetectorTests(TestCase):
"""
changes = self.get_changes(
[self.author_name, self.publisher_with_author],
- [self.aardvark_testapp, self.publisher_with_aardvark_author]
+ [self.aardvark_testapp, self.publisher_with_aardvark_author],
)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "AlterField", "DeleteModel"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Aardvark")
- self.assertOperationAttributes(changes, 'testapp', 0, 1, name="author")
- self.assertOperationAttributes(changes, 'testapp', 0, 2, name="Author")
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(
+ changes, "testapp", 0, ["CreateModel", "AlterField", "DeleteModel"]
+ )
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Aardvark")
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="author")
+ self.assertOperationAttributes(changes, "testapp", 0, 2, name="Author")
def test_fk_dependency_other_app(self):
"""
#23100 - ForeignKeys correctly depend on other apps' models.
"""
- changes = self.get_changes([self.author_name, self.book], [self.author_with_book, self.book])
+ changes = self.get_changes(
+ [self.author_name, self.book], [self.author_with_book, self.book]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name="book")
- self.assertMigrationDependencies(changes, 'testapp', 0, [("otherapp", "__first__")])
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AddField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="book")
+ self.assertMigrationDependencies(
+ changes, "testapp", 0, [("otherapp", "__first__")]
+ )
def test_alter_field_to_fk_dependency_other_app(self):
changes = self.get_changes(
[self.author_empty, self.book_with_no_author_fk],
[self.author_empty, self.book],
)
- self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertOperationTypes(changes, 'otherapp', 0, ['AlterField'])
- self.assertMigrationDependencies(changes, 'otherapp', 0, [('testapp', '__first__')])
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterField"])
+ self.assertMigrationDependencies(
+ changes, "otherapp", 0, [("testapp", "__first__")]
+ )
def test_circular_dependency_mixed_addcreate(self):
"""
#23315 - The dependency resolver knows to put all CreateModel
before AddField and not become unsolvable.
"""
- address = ModelState("a", "Address", [
- ("id", models.AutoField(primary_key=True)),
- ("country", models.ForeignKey("b.DeliveryCountry", models.CASCADE)),
- ])
- person = ModelState("a", "Person", [
- ("id", models.AutoField(primary_key=True)),
- ])
- apackage = ModelState("b", "APackage", [
- ("id", models.AutoField(primary_key=True)),
- ("person", models.ForeignKey("a.Person", models.CASCADE)),
- ])
- country = ModelState("b", "DeliveryCountry", [
- ("id", models.AutoField(primary_key=True)),
- ])
+ address = ModelState(
+ "a",
+ "Address",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("country", models.ForeignKey("b.DeliveryCountry", models.CASCADE)),
+ ],
+ )
+ person = ModelState(
+ "a",
+ "Person",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
+ apackage = ModelState(
+ "b",
+ "APackage",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("person", models.ForeignKey("a.Person", models.CASCADE)),
+ ],
+ )
+ country = ModelState(
+ "b",
+ "DeliveryCountry",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
changes = self.get_changes([], [address, person, apackage, country])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'a', 2)
- self.assertNumberMigrations(changes, 'b', 1)
- self.assertOperationTypes(changes, 'a', 0, ["CreateModel", "CreateModel"])
- self.assertOperationTypes(changes, 'a', 1, ["AddField"])
- self.assertOperationTypes(changes, 'b', 0, ["CreateModel", "CreateModel"])
+ self.assertNumberMigrations(changes, "a", 2)
+ self.assertNumberMigrations(changes, "b", 1)
+ self.assertOperationTypes(changes, "a", 0, ["CreateModel", "CreateModel"])
+ self.assertOperationTypes(changes, "a", 1, ["AddField"])
+ self.assertOperationTypes(changes, "b", 0, ["CreateModel", "CreateModel"])
@override_settings(AUTH_USER_MODEL="a.Tenant")
def test_circular_dependency_swappable(self):
@@ -2685,27 +4240,42 @@ class AutodetectorTests(TestCase):
swappable models.
"""
with isolate_lru_cache(apps.get_swappable_settings_name):
- tenant = ModelState("a", "Tenant", [
- ("id", models.AutoField(primary_key=True)),
- ("primary_address", models.ForeignKey("b.Address", models.CASCADE))],
- bases=(AbstractBaseUser,)
+ tenant = ModelState(
+ "a",
+ "Tenant",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("primary_address", models.ForeignKey("b.Address", models.CASCADE)),
+ ],
+ bases=(AbstractBaseUser,),
+ )
+ address = ModelState(
+ "b",
+ "Address",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "tenant",
+ models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE),
+ ),
+ ],
)
- address = ModelState("b", "Address", [
- ("id", models.AutoField(primary_key=True)),
- ("tenant", models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE)),
- ])
changes = self.get_changes([], [address, tenant])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'a', 2)
- self.assertOperationTypes(changes, 'a', 0, ["CreateModel"])
- self.assertOperationTypes(changes, 'a', 1, ["AddField"])
- self.assertMigrationDependencies(changes, 'a', 0, [])
- self.assertMigrationDependencies(changes, 'a', 1, [('a', 'auto_1'), ('b', 'auto_1')])
+ self.assertNumberMigrations(changes, "a", 2)
+ self.assertOperationTypes(changes, "a", 0, ["CreateModel"])
+ self.assertOperationTypes(changes, "a", 1, ["AddField"])
+ self.assertMigrationDependencies(changes, "a", 0, [])
+ self.assertMigrationDependencies(
+ changes, "a", 1, [("a", "auto_1"), ("b", "auto_1")]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'b', 1)
- self.assertOperationTypes(changes, 'b', 0, ["CreateModel"])
- self.assertMigrationDependencies(changes, 'b', 0, [('__setting__', 'AUTH_USER_MODEL')])
+ self.assertNumberMigrations(changes, "b", 1)
+ self.assertOperationTypes(changes, "b", 0, ["CreateModel"])
+ self.assertMigrationDependencies(
+ changes, "b", 0, [("__setting__", "AUTH_USER_MODEL")]
+ )
@override_settings(AUTH_USER_MODEL="b.Tenant")
def test_circular_dependency_swappable2(self):
@@ -2715,26 +4285,39 @@ class AutodetectorTests(TestCase):
model.
"""
with isolate_lru_cache(apps.get_swappable_settings_name):
- address = ModelState("a", "Address", [
- ("id", models.AutoField(primary_key=True)),
- ("tenant", models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE)),
- ])
- tenant = ModelState("b", "Tenant", [
- ("id", models.AutoField(primary_key=True)),
- ("primary_address", models.ForeignKey("a.Address", models.CASCADE))],
- bases=(AbstractBaseUser,)
+ address = ModelState(
+ "a",
+ "Address",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "tenant",
+ models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE),
+ ),
+ ],
+ )
+ tenant = ModelState(
+ "b",
+ "Tenant",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("primary_address", models.ForeignKey("a.Address", models.CASCADE)),
+ ],
+ bases=(AbstractBaseUser,),
)
changes = self.get_changes([], [address, tenant])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'a', 2)
- self.assertOperationTypes(changes, 'a', 0, ["CreateModel"])
- self.assertOperationTypes(changes, 'a', 1, ["AddField"])
- self.assertMigrationDependencies(changes, 'a', 0, [])
- self.assertMigrationDependencies(changes, 'a', 1, [('__setting__', 'AUTH_USER_MODEL'), ('a', 'auto_1')])
+ self.assertNumberMigrations(changes, "a", 2)
+ self.assertOperationTypes(changes, "a", 0, ["CreateModel"])
+ self.assertOperationTypes(changes, "a", 1, ["AddField"])
+ self.assertMigrationDependencies(changes, "a", 0, [])
+ self.assertMigrationDependencies(
+ changes, "a", 1, [("__setting__", "AUTH_USER_MODEL"), ("a", "auto_1")]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'b', 1)
- self.assertOperationTypes(changes, 'b', 0, ["CreateModel"])
- self.assertMigrationDependencies(changes, 'b', 0, [('a', 'auto_1')])
+ self.assertNumberMigrations(changes, "b", 1)
+ self.assertOperationTypes(changes, "b", 0, ["CreateModel"])
+ self.assertMigrationDependencies(changes, "b", 0, [("a", "auto_1")])
@override_settings(AUTH_USER_MODEL="a.Person")
def test_circular_dependency_swappable_self(self):
@@ -2743,63 +4326,90 @@ class AutodetectorTests(TestCase):
swappable models.
"""
with isolate_lru_cache(apps.get_swappable_settings_name):
- person = ModelState("a", "Person", [
- ("id", models.AutoField(primary_key=True)),
- ("parent1", models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, related_name='children'))
- ])
+ person = ModelState(
+ "a",
+ "Person",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "parent1",
+ models.ForeignKey(
+ settings.AUTH_USER_MODEL,
+ models.CASCADE,
+ related_name="children",
+ ),
+ ),
+ ],
+ )
changes = self.get_changes([], [person])
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'a', 1)
- self.assertOperationTypes(changes, 'a', 0, ["CreateModel"])
- self.assertMigrationDependencies(changes, 'a', 0, [])
+ self.assertNumberMigrations(changes, "a", 1)
+ self.assertOperationTypes(changes, "a", 0, ["CreateModel"])
+ self.assertMigrationDependencies(changes, "a", 0, [])
- @override_settings(AUTH_USER_MODEL='a.User')
+ @override_settings(AUTH_USER_MODEL="a.User")
def test_swappable_circular_multi_mti(self):
with isolate_lru_cache(apps.get_swappable_settings_name):
- parent = ModelState('a', 'Parent', [
- ('user', models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE))
- ])
- child = ModelState('a', 'Child', [], bases=('a.Parent',))
- user = ModelState('a', 'User', [], bases=(AbstractBaseUser, 'a.Child'))
+ parent = ModelState(
+ "a",
+ "Parent",
+ [("user", models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE))],
+ )
+ child = ModelState("a", "Child", [], bases=("a.Parent",))
+ user = ModelState("a", "User", [], bases=(AbstractBaseUser, "a.Child"))
changes = self.get_changes([], [parent, child, user])
- self.assertNumberMigrations(changes, 'a', 1)
- self.assertOperationTypes(changes, 'a', 0, ['CreateModel', 'CreateModel', 'CreateModel', 'AddField'])
+ self.assertNumberMigrations(changes, "a", 1)
+ self.assertOperationTypes(
+ changes, "a", 0, ["CreateModel", "CreateModel", "CreateModel", "AddField"]
+ )
- @mock.patch('django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition',
- side_effect=AssertionError("Should not have prompted for not null addition"))
+ @mock.patch(
+ "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition",
+ side_effect=AssertionError("Should not have prompted for not null addition"),
+ )
def test_add_blank_textfield_and_charfield(self, mocked_ask_method):
"""
#23405 - Adding a NOT NULL and blank `CharField` or `TextField`
without default should not prompt for a default.
"""
- changes = self.get_changes([self.author_empty], [self.author_with_biography_blank])
+ changes = self.get_changes(
+ [self.author_empty], [self.author_with_biography_blank]
+ )
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField", "AddField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0)
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AddField", "AddField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0)
- @mock.patch('django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition')
+ @mock.patch(
+ "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition"
+ )
def test_add_non_blank_textfield_and_charfield(self, mocked_ask_method):
"""
#23405 - Adding a NOT NULL and non-blank `CharField` or `TextField`
without default should prompt for a default.
"""
- changes = self.get_changes([self.author_empty], [self.author_with_biography_non_blank])
+ changes = self.get_changes(
+ [self.author_empty], [self.author_with_biography_non_blank]
+ )
self.assertEqual(mocked_ask_method.call_count, 2)
# Right number/type of migrations?
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ["AddField", "AddField"])
- self.assertOperationAttributes(changes, 'testapp', 0, 0)
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["AddField", "AddField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0)
def test_mti_inheritance_model_removal(self):
- Animal = ModelState('app', 'Animal', [
- ("id", models.AutoField(primary_key=True)),
- ])
- Dog = ModelState('app', 'Dog', [], bases=('app.Animal',))
+ Animal = ModelState(
+ "app",
+ "Animal",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
+ Dog = ModelState("app", "Dog", [], bases=("app.Animal",))
changes = self.get_changes([Animal, Dog], [Animal])
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['DeleteModel'])
- self.assertOperationAttributes(changes, 'app', 0, 0, name='Dog')
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["DeleteModel"])
+ self.assertOperationAttributes(changes, "app", 0, 0, name="Dog")
def test_add_model_with_field_removed_from_base_model(self):
"""
@@ -2807,37 +4417,52 @@ class AutodetectorTests(TestCase):
that has a field with the same name.
"""
before = [
- ModelState('app', 'readable', [
- ('id', models.AutoField(primary_key=True)),
- ('title', models.CharField(max_length=200)),
- ]),
+ ModelState(
+ "app",
+ "readable",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("title", models.CharField(max_length=200)),
+ ],
+ ),
]
after = [
- ModelState('app', 'readable', [
- ('id', models.AutoField(primary_key=True)),
- ]),
- ModelState('app', 'book', [
- ('title', models.CharField(max_length=200)),
- ], bases=('app.readable',)),
+ ModelState(
+ "app",
+ "readable",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ ModelState(
+ "app",
+ "book",
+ [
+ ("title", models.CharField(max_length=200)),
+ ],
+ bases=("app.readable",),
+ ),
]
changes = self.get_changes(before, after)
- self.assertNumberMigrations(changes, 'app', 1)
- self.assertOperationTypes(changes, 'app', 0, ['RemoveField', 'CreateModel'])
- self.assertOperationAttributes(changes, 'app', 0, 0, name='title', model_name='readable')
- self.assertOperationAttributes(changes, 'app', 0, 1, name='book')
+ self.assertNumberMigrations(changes, "app", 1)
+ self.assertOperationTypes(changes, "app", 0, ["RemoveField", "CreateModel"])
+ self.assertOperationAttributes(
+ changes, "app", 0, 0, name="title", model_name="readable"
+ )
+ self.assertOperationAttributes(changes, "app", 0, 1, name="book")
def test_parse_number(self):
tests = [
- ('no_number', None),
- ('0001_initial', 1),
- ('0002_model3', 2),
- ('0002_auto_20380101_1112', 2),
- ('0002_squashed_0003', 3),
- ('0002_model2_squashed_0003_other4', 3),
- ('0002_squashed_0003_squashed_0004', 4),
- ('0002_model2_squashed_0003_other4_squashed_0005_other6', 5),
- ('0002_custom_name_20380101_1112_squashed_0003_model', 3),
- ('2_squashed_4', 4),
+ ("no_number", None),
+ ("0001_initial", 1),
+ ("0002_model3", 2),
+ ("0002_auto_20380101_1112", 2),
+ ("0002_squashed_0003", 3),
+ ("0002_model2_squashed_0003_other4", 3),
+ ("0002_squashed_0003_squashed_0004", 4),
+ ("0002_model2_squashed_0003_other4_squashed_0005_other6", 5),
+ ("0002_custom_name_20380101_1112_squashed_0003_model", 3),
+ ("2_squashed_4", 4),
]
for migration_name, expected_number in tests:
with self.subTest(migration_name=migration_name):
@@ -2849,24 +4474,28 @@ class AutodetectorTests(TestCase):
def test_add_custom_fk_with_hardcoded_to(self):
class HardcodedForeignKey(models.ForeignKey):
def __init__(self, *args, **kwargs):
- kwargs['to'] = 'testapp.Author'
+ kwargs["to"] = "testapp.Author"
super().__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
- del kwargs['to']
+ del kwargs["to"]
return name, path, args, kwargs
- book_hardcoded_fk_to = ModelState('testapp', 'Book', [
- ('author', HardcodedForeignKey(on_delete=models.CASCADE)),
- ])
+ book_hardcoded_fk_to = ModelState(
+ "testapp",
+ "Book",
+ [
+ ("author", HardcodedForeignKey(on_delete=models.CASCADE)),
+ ],
+ )
changes = self.get_changes(
[self.author_empty],
[self.author_empty, book_hardcoded_fk_to],
)
- self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertOperationTypes(changes, 'testapp', 0, ['CreateModel'])
- self.assertOperationAttributes(changes, 'testapp', 0, 0, name='Book')
+ self.assertNumberMigrations(changes, "testapp", 1)
+ self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Book")
class MigrationSuggestNameTests(SimpleTestCase):
@@ -2874,111 +4503,111 @@ class MigrationSuggestNameTests(SimpleTestCase):
class Migration(migrations.Migration):
operations = []
- migration = Migration('some_migration', 'test_app')
- self.assertIs(migration.suggest_name().startswith('auto_'), True)
+ migration = Migration("some_migration", "test_app")
+ self.assertIs(migration.suggest_name().startswith("auto_"), True)
def test_no_operations_initial(self):
class Migration(migrations.Migration):
initial = True
operations = []
- migration = Migration('some_migration', 'test_app')
- self.assertEqual(migration.suggest_name(), 'initial')
+ migration = Migration("some_migration", "test_app")
+ self.assertEqual(migration.suggest_name(), "initial")
def test_single_operation(self):
class Migration(migrations.Migration):
- operations = [migrations.CreateModel('Person', fields=[])]
+ operations = [migrations.CreateModel("Person", fields=[])]
- migration = Migration('0001_initial', 'test_app')
- self.assertEqual(migration.suggest_name(), 'person')
+ migration = Migration("0001_initial", "test_app")
+ self.assertEqual(migration.suggest_name(), "person")
class Migration(migrations.Migration):
- operations = [migrations.DeleteModel('Person')]
+ operations = [migrations.DeleteModel("Person")]
- migration = Migration('0002_initial', 'test_app')
- self.assertEqual(migration.suggest_name(), 'delete_person')
+ migration = Migration("0002_initial", "test_app")
+ self.assertEqual(migration.suggest_name(), "delete_person")
def test_single_operation_long_name(self):
class Migration(migrations.Migration):
- operations = [migrations.CreateModel('A' * 53, fields=[])]
+ operations = [migrations.CreateModel("A" * 53, fields=[])]
- migration = Migration('some_migration', 'test_app')
- self.assertEqual(migration.suggest_name(), 'a' * 53)
+ migration = Migration("some_migration", "test_app")
+ self.assertEqual(migration.suggest_name(), "a" * 53)
def test_two_operations(self):
class Migration(migrations.Migration):
operations = [
- migrations.CreateModel('Person', fields=[]),
- migrations.DeleteModel('Animal'),
+ migrations.CreateModel("Person", fields=[]),
+ migrations.DeleteModel("Animal"),
]
- migration = Migration('some_migration', 'test_app')
- self.assertEqual(migration.suggest_name(), 'person_delete_animal')
+ migration = Migration("some_migration", "test_app")
+ self.assertEqual(migration.suggest_name(), "person_delete_animal")
def test_two_create_models(self):
class Migration(migrations.Migration):
operations = [
- migrations.CreateModel('Person', fields=[]),
- migrations.CreateModel('Animal', fields=[]),
+ migrations.CreateModel("Person", fields=[]),
+ migrations.CreateModel("Animal", fields=[]),
]
- migration = Migration('0001_initial', 'test_app')
- self.assertEqual(migration.suggest_name(), 'person_animal')
+ migration = Migration("0001_initial", "test_app")
+ self.assertEqual(migration.suggest_name(), "person_animal")
def test_two_create_models_with_initial_true(self):
class Migration(migrations.Migration):
initial = True
operations = [
- migrations.CreateModel('Person', fields=[]),
- migrations.CreateModel('Animal', fields=[]),
+ migrations.CreateModel("Person", fields=[]),
+ migrations.CreateModel("Animal", fields=[]),
]
- migration = Migration('0001_initial', 'test_app')
- self.assertEqual(migration.suggest_name(), 'initial')
+ migration = Migration("0001_initial", "test_app")
+ self.assertEqual(migration.suggest_name(), "initial")
def test_many_operations_suffix(self):
class Migration(migrations.Migration):
operations = [
- migrations.CreateModel('Person1', fields=[]),
- migrations.CreateModel('Person2', fields=[]),
- migrations.CreateModel('Person3', fields=[]),
- migrations.DeleteModel('Person4'),
- migrations.DeleteModel('Person5'),
+ migrations.CreateModel("Person1", fields=[]),
+ migrations.CreateModel("Person2", fields=[]),
+ migrations.CreateModel("Person3", fields=[]),
+ migrations.DeleteModel("Person4"),
+ migrations.DeleteModel("Person5"),
]
- migration = Migration('some_migration', 'test_app')
+ migration = Migration("some_migration", "test_app")
self.assertEqual(
migration.suggest_name(),
- 'person1_person2_person3_delete_person4_and_more',
+ "person1_person2_person3_delete_person4_and_more",
)
def test_operation_with_no_suggested_name(self):
class Migration(migrations.Migration):
operations = [
- migrations.CreateModel('Person', fields=[]),
- migrations.RunSQL('SELECT 1 FROM person;'),
+ migrations.CreateModel("Person", fields=[]),
+ migrations.RunSQL("SELECT 1 FROM person;"),
]
- migration = Migration('some_migration', 'test_app')
- self.assertIs(migration.suggest_name().startswith('auto_'), True)
+ migration = Migration("some_migration", "test_app")
+ self.assertIs(migration.suggest_name().startswith("auto_"), True)
def test_none_name(self):
class Migration(migrations.Migration):
- operations = [migrations.RunSQL('SELECT 1 FROM person;')]
+ operations = [migrations.RunSQL("SELECT 1 FROM person;")]
- migration = Migration('0001_initial', 'test_app')
+ migration = Migration("0001_initial", "test_app")
suggest_name = migration.suggest_name()
- self.assertIs(suggest_name.startswith('auto_'), True)
+ self.assertIs(suggest_name.startswith("auto_"), True)
def test_none_name_with_initial_true(self):
class Migration(migrations.Migration):
initial = True
- operations = [migrations.RunSQL('SELECT 1 FROM person;')]
+ operations = [migrations.RunSQL("SELECT 1 FROM person;")]
- migration = Migration('0001_initial', 'test_app')
- self.assertEqual(migration.suggest_name(), 'initial')
+ migration = Migration("0001_initial", "test_app")
+ self.assertEqual(migration.suggest_name(), "initial")
def test_auto(self):
- migration = migrations.Migration('0001_initial', 'test_app')
+ migration = migrations.Migration("0001_initial", "test_app")
suggest_name = migration.suggest_name()
- self.assertIs(suggest_name.startswith('auto_'), True)
+ self.assertIs(suggest_name.startswith("auto_"), True)
diff --git a/tests/migrations/test_base.py b/tests/migrations/test_base.py
index 6f8081a462..955bfa99d0 100644
--- a/tests/migrations/test_base.py
+++ b/tests/migrations/test_base.py
@@ -20,52 +20,66 @@ class MigrationTestBase(TransactionTestCase):
"""
available_apps = ["migrations"]
- databases = {'default', 'other'}
+ databases = {"default", "other"}
def tearDown(self):
# Reset applied-migrations state.
for db in self.databases:
recorder = MigrationRecorder(connections[db])
- recorder.migration_qs.filter(app='migrations').delete()
+ recorder.migration_qs.filter(app="migrations").delete()
- def get_table_description(self, table, using='default'):
+ def get_table_description(self, table, using="default"):
with connections[using].cursor() as cursor:
return connections[using].introspection.get_table_description(cursor, table)
- def assertTableExists(self, table, using='default'):
+ def assertTableExists(self, table, using="default"):
with connections[using].cursor() as cursor:
self.assertIn(table, connections[using].introspection.table_names(cursor))
- def assertTableNotExists(self, table, using='default'):
+ def assertTableNotExists(self, table, using="default"):
with connections[using].cursor() as cursor:
- self.assertNotIn(table, connections[using].introspection.table_names(cursor))
+ self.assertNotIn(
+ table, connections[using].introspection.table_names(cursor)
+ )
- def assertColumnExists(self, table, column, using='default'):
- self.assertIn(column, [c.name for c in self.get_table_description(table, using=using)])
+ def assertColumnExists(self, table, column, using="default"):
+ self.assertIn(
+ column, [c.name for c in self.get_table_description(table, using=using)]
+ )
- def assertColumnNotExists(self, table, column, using='default'):
- self.assertNotIn(column, [c.name for c in self.get_table_description(table, using=using)])
+ def assertColumnNotExists(self, table, column, using="default"):
+ self.assertNotIn(
+ column, [c.name for c in self.get_table_description(table, using=using)]
+ )
def _get_column_allows_null(self, table, column, using):
- return [c.null_ok for c in self.get_table_description(table, using=using) if c.name == column][0]
+ return [
+ c.null_ok
+ for c in self.get_table_description(table, using=using)
+ if c.name == column
+ ][0]
- def assertColumnNull(self, table, column, using='default'):
+ def assertColumnNull(self, table, column, using="default"):
self.assertTrue(self._get_column_allows_null(table, column, using))
- def assertColumnNotNull(self, table, column, using='default'):
+ def assertColumnNotNull(self, table, column, using="default"):
self.assertFalse(self._get_column_allows_null(table, column, using))
- def assertIndexExists(self, table, columns, value=True, using='default', index_type=None):
+ def assertIndexExists(
+ self, table, columns, value=True, using="default", index_type=None
+ ):
with connections[using].cursor() as cursor:
self.assertEqual(
value,
any(
c["index"]
- for c in connections[using].introspection.get_constraints(cursor, table).values()
+ for c in connections[using]
+ .introspection.get_constraints(cursor, table)
+ .values()
if (
- c['columns'] == list(columns) and
- (index_type is None or c['type'] == index_type) and
- not c['unique']
+ c["columns"] == list(columns)
+ and (index_type is None or c["type"] == index_type)
+ and not c["unique"]
)
),
)
@@ -73,47 +87,53 @@ class MigrationTestBase(TransactionTestCase):
def assertIndexNotExists(self, table, columns):
return self.assertIndexExists(table, columns, False)
- def assertIndexNameExists(self, table, index, using='default'):
+ def assertIndexNameExists(self, table, index, using="default"):
with connections[using].cursor() as cursor:
self.assertIn(
index,
connection.introspection.get_constraints(cursor, table),
)
- def assertIndexNameNotExists(self, table, index, using='default'):
+ def assertIndexNameNotExists(self, table, index, using="default"):
with connections[using].cursor() as cursor:
self.assertNotIn(
index,
connection.introspection.get_constraints(cursor, table),
)
- def assertConstraintExists(self, table, name, value=True, using='default'):
+ def assertConstraintExists(self, table, name, value=True, using="default"):
with connections[using].cursor() as cursor:
- constraints = connections[using].introspection.get_constraints(cursor, table).items()
+ constraints = (
+ connections[using].introspection.get_constraints(cursor, table).items()
+ )
self.assertEqual(
value,
- any(c['check'] for n, c in constraints if n == name),
+ any(c["check"] for n, c in constraints if n == name),
)
def assertConstraintNotExists(self, table, name):
return self.assertConstraintExists(table, name, False)
- def assertUniqueConstraintExists(self, table, columns, value=True, using='default'):
+ def assertUniqueConstraintExists(self, table, columns, value=True, using="default"):
with connections[using].cursor() as cursor:
- constraints = connections[using].introspection.get_constraints(cursor, table).values()
+ constraints = (
+ connections[using].introspection.get_constraints(cursor, table).values()
+ )
self.assertEqual(
value,
- any(c['unique'] for c in constraints if c['columns'] == list(columns)),
+ any(c["unique"] for c in constraints if c["columns"] == list(columns)),
)
- def assertFKExists(self, table, columns, to, value=True, using='default'):
+ def assertFKExists(self, table, columns, to, value=True, using="default"):
with connections[using].cursor() as cursor:
self.assertEqual(
value,
any(
c["foreign_key"] == to
- for c in connections[using].introspection.get_constraints(cursor, table).values()
- if c['columns'] == list(columns)
+ for c in connections[using]
+ .introspection.get_constraints(cursor, table)
+ .values()
+ if c["columns"] == list(columns)
),
)
@@ -121,7 +141,7 @@ class MigrationTestBase(TransactionTestCase):
return self.assertFKExists(table, columns, to, False)
@contextmanager
- def temporary_migration_module(self, app_label='migrations', module=None):
+ def temporary_migration_module(self, app_label="migrations", module=None):
"""
Allows testing management commands in a temporary migrations module.
@@ -140,12 +160,12 @@ class MigrationTestBase(TransactionTestCase):
"""
with tempfile.TemporaryDirectory() as temp_dir:
target_dir = tempfile.mkdtemp(dir=temp_dir)
- with open(os.path.join(target_dir, '__init__.py'), 'w'):
+ with open(os.path.join(target_dir, "__init__.py"), "w"):
pass
- target_migrations_dir = os.path.join(target_dir, 'migrations')
+ target_migrations_dir = os.path.join(target_dir, "migrations")
if module is None:
- module = apps.get_app_config(app_label).name + '.migrations'
+ module = apps.get_app_config(app_label).name + ".migrations"
try:
source_migrations_dir = module_dir(import_module(module))
@@ -155,7 +175,7 @@ class MigrationTestBase(TransactionTestCase):
shutil.copytree(source_migrations_dir, target_migrations_dir)
with extend_sys_path(temp_dir):
- new_module = os.path.basename(target_dir) + '.migrations'
+ new_module = os.path.basename(target_dir) + ".migrations"
with self.settings(MIGRATION_MODULES={app_label: new_module}):
yield target_migrations_dir
@@ -173,22 +193,28 @@ class OperationTestBase(MigrationTestBase):
super().tearDown()
def cleanup_test_tables(self):
- table_names = frozenset(connection.introspection.table_names()) - self._initial_table_names
+ table_names = (
+ frozenset(connection.introspection.table_names())
+ - self._initial_table_names
+ )
with connection.schema_editor() as editor:
with connection.constraint_checks_disabled():
for table_name in table_names:
- editor.execute(editor.sql_delete_table % {
- 'table': editor.quote_name(table_name),
- })
+ editor.execute(
+ editor.sql_delete_table
+ % {
+ "table": editor.quote_name(table_name),
+ }
+ )
def apply_operations(self, app_label, project_state, operations, atomic=True):
- migration = Migration('name', app_label)
+ migration = Migration("name", app_label)
migration.operations = operations
with connection.schema_editor(atomic=atomic) as editor:
return migration.apply(project_state, editor)
def unapply_operations(self, app_label, project_state, operations, atomic=True):
- migration = Migration('name', app_label)
+ migration = Migration("name", app_label)
migration.operations = operations
with connection.schema_editor(atomic=atomic) as editor:
return migration.unapply(project_state, editor)
@@ -204,106 +230,142 @@ class OperationTestBase(MigrationTestBase):
return project_state, new_state
def set_up_test_model(
- self, app_label, second_model=False, third_model=False, index=False,
- multicol_index=False, related_model=False, mti_model=False,
- proxy_model=False, manager_model=False, unique_together=False,
- options=False, db_table=None, index_together=False, constraints=None,
+ self,
+ app_label,
+ second_model=False,
+ third_model=False,
+ index=False,
+ multicol_index=False,
+ related_model=False,
+ mti_model=False,
+ proxy_model=False,
+ manager_model=False,
+ unique_together=False,
+ options=False,
+ db_table=None,
+ index_together=False,
+ constraints=None,
indexes=None,
):
"""Creates a test model state and database table."""
# Make the "current" state.
model_options = {
- 'swappable': 'TEST_SWAP_MODEL',
- 'index_together': [['weight', 'pink']] if index_together else [],
- 'unique_together': [['pink', 'weight']] if unique_together else [],
+ "swappable": "TEST_SWAP_MODEL",
+ "index_together": [["weight", "pink"]] if index_together else [],
+ "unique_together": [["pink", "weight"]] if unique_together else [],
}
if options:
- model_options['permissions'] = [('can_groom', 'Can groom')]
+ model_options["permissions"] = [("can_groom", "Can groom")]
if db_table:
- model_options['db_table'] = db_table
- operations = [migrations.CreateModel(
- 'Pony',
- [
- ('id', models.AutoField(primary_key=True)),
- ('pink', models.IntegerField(default=3)),
- ('weight', models.FloatField()),
- ],
- options=model_options,
- )]
+ model_options["db_table"] = db_table
+ operations = [
+ migrations.CreateModel(
+ "Pony",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("pink", models.IntegerField(default=3)),
+ ("weight", models.FloatField()),
+ ],
+ options=model_options,
+ )
+ ]
if index:
- operations.append(migrations.AddIndex(
- 'Pony',
- models.Index(fields=['pink'], name='pony_pink_idx'),
- ))
+ operations.append(
+ migrations.AddIndex(
+ "Pony",
+ models.Index(fields=["pink"], name="pony_pink_idx"),
+ )
+ )
if multicol_index:
- operations.append(migrations.AddIndex(
- 'Pony',
- models.Index(fields=['pink', 'weight'], name='pony_test_idx'),
- ))
+ operations.append(
+ migrations.AddIndex(
+ "Pony",
+ models.Index(fields=["pink", "weight"], name="pony_test_idx"),
+ )
+ )
if indexes:
for index in indexes:
- operations.append(migrations.AddIndex('Pony', index))
+ operations.append(migrations.AddIndex("Pony", index))
if constraints:
for constraint in constraints:
- operations.append(migrations.AddConstraint('Pony', constraint))
+ operations.append(migrations.AddConstraint("Pony", constraint))
if second_model:
- operations.append(migrations.CreateModel(
- 'Stable',
- [
- ('id', models.AutoField(primary_key=True)),
- ]
- ))
+ operations.append(
+ migrations.CreateModel(
+ "Stable",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
+ )
if third_model:
- operations.append(migrations.CreateModel(
- 'Van',
- [
- ('id', models.AutoField(primary_key=True)),
- ]
- ))
+ operations.append(
+ migrations.CreateModel(
+ "Van",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ )
+ )
if related_model:
- operations.append(migrations.CreateModel(
- 'Rider',
- [
- ('id', models.AutoField(primary_key=True)),
- ('pony', models.ForeignKey('Pony', models.CASCADE)),
- ('friend', models.ForeignKey('self', models.CASCADE, null=True))
- ],
- ))
+ operations.append(
+ migrations.CreateModel(
+ "Rider",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("pony", models.ForeignKey("Pony", models.CASCADE)),
+ (
+ "friend",
+ models.ForeignKey("self", models.CASCADE, null=True),
+ ),
+ ],
+ )
+ )
if mti_model:
- operations.append(migrations.CreateModel(
- 'ShetlandPony',
- fields=[
- ('pony_ptr', models.OneToOneField(
- 'Pony',
- models.CASCADE,
- auto_created=True,
- parent_link=True,
- primary_key=True,
- to_field='id',
- serialize=False,
- )),
- ('cuteness', models.IntegerField(default=1)),
- ],
- bases=['%s.Pony' % app_label],
- ))
+ operations.append(
+ migrations.CreateModel(
+ "ShetlandPony",
+ fields=[
+ (
+ "pony_ptr",
+ models.OneToOneField(
+ "Pony",
+ models.CASCADE,
+ auto_created=True,
+ parent_link=True,
+ primary_key=True,
+ to_field="id",
+ serialize=False,
+ ),
+ ),
+ ("cuteness", models.IntegerField(default=1)),
+ ],
+ bases=["%s.Pony" % app_label],
+ )
+ )
if proxy_model:
- operations.append(migrations.CreateModel(
- 'ProxyPony',
- fields=[],
- options={'proxy': True},
- bases=['%s.Pony' % app_label],
- ))
+ operations.append(
+ migrations.CreateModel(
+ "ProxyPony",
+ fields=[],
+ options={"proxy": True},
+ bases=["%s.Pony" % app_label],
+ )
+ )
if manager_model:
from .models import FoodManager, FoodQuerySet
- operations.append(migrations.CreateModel(
- 'Food',
- fields=[
- ('id', models.AutoField(primary_key=True)),
- ],
- managers=[
- ('food_qs', FoodQuerySet.as_manager()),
- ('food_mgr', FoodManager('a', 'b')),
- ('food_mgr_kwargs', FoodManager('x', 'y', 3, 4)),
- ]
- ))
+
+ operations.append(
+ migrations.CreateModel(
+ "Food",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ managers=[
+ ("food_qs", FoodQuerySet.as_manager()),
+ ("food_mgr", FoodManager("a", "b")),
+ ("food_mgr_kwargs", FoodManager("x", "y", 3, 4)),
+ ],
+ )
+ )
return self.apply_operations(app_label, ProjectState(), operations)
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 0c62db8ae6..099690aa30 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -8,8 +8,12 @@ from unittest import mock
from django.apps import apps
from django.core.management import CommandError, call_command
from django.db import (
- ConnectionHandler, DatabaseError, OperationalError, connection,
- connections, models,
+ ConnectionHandler,
+ DatabaseError,
+ OperationalError,
+ connection,
+ connections,
+ models,
)
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.backends.utils import truncate_name
@@ -29,7 +33,8 @@ class MigrateTests(MigrationTestBase):
"""
Tests running the migrate command.
"""
- databases = {'default', 'other'}
+
+ databases = {"default", "other"}
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_migrate(self):
@@ -42,12 +47,18 @@ class MigrateTests(MigrationTestBase):
self.assertTableNotExists("migrations_book")
# Run the migrations to 0001 only
stdout = io.StringIO()
- call_command('migrate', 'migrations', '0001', verbosity=2, stdout=stdout, no_color=True)
+ call_command(
+ "migrate", "migrations", "0001", verbosity=2, stdout=stdout, no_color=True
+ )
stdout = stdout.getvalue()
- self.assertIn('Target specific migration: 0001_initial, from migrations', stdout)
- self.assertIn('Applying migrations.0001_initial... OK', stdout)
- self.assertIn('Running pre-migrate handlers for application migrations', stdout)
- self.assertIn('Running post-migrate handlers for application migrations', stdout)
+ self.assertIn(
+ "Target specific migration: 0001_initial, from migrations", stdout
+ )
+ self.assertIn("Applying migrations.0001_initial... OK", stdout)
+ self.assertIn("Running pre-migrate handlers for application migrations", stdout)
+ self.assertIn(
+ "Running post-migrate handlers for application migrations", stdout
+ )
# The correct tables exist
self.assertTableExists("migrations_author")
self.assertTableExists("migrations_tribble")
@@ -60,49 +71,66 @@ class MigrateTests(MigrationTestBase):
self.assertTableExists("migrations_book")
# Unmigrate everything
stdout = io.StringIO()
- call_command('migrate', 'migrations', 'zero', verbosity=2, stdout=stdout, no_color=True)
+ call_command(
+ "migrate", "migrations", "zero", verbosity=2, stdout=stdout, no_color=True
+ )
stdout = stdout.getvalue()
- self.assertIn('Unapply all migrations: migrations', stdout)
- self.assertIn('Unapplying migrations.0002_second... OK', stdout)
- self.assertIn('Running pre-migrate handlers for application migrations', stdout)
- self.assertIn('Running post-migrate handlers for application migrations', stdout)
+ self.assertIn("Unapply all migrations: migrations", stdout)
+ self.assertIn("Unapplying migrations.0002_second... OK", stdout)
+ self.assertIn("Running pre-migrate handlers for application migrations", stdout)
+ self.assertIn(
+ "Running post-migrate handlers for application migrations", stdout
+ )
# Tables are gone
self.assertTableNotExists("migrations_author")
self.assertTableNotExists("migrations_tribble")
self.assertTableNotExists("migrations_book")
- @override_settings(INSTALLED_APPS=[
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'migrations.migrations_test_apps.migrated_app',
- ])
+ @override_settings(
+ INSTALLED_APPS=[
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ "migrations.migrations_test_apps.migrated_app",
+ ]
+ )
def test_migrate_with_system_checks(self):
out = io.StringIO()
- call_command('migrate', skip_checks=False, no_color=True, stdout=out)
- self.assertIn('Apply all migrations: migrated_app', out.getvalue())
+ call_command("migrate", skip_checks=False, no_color=True, stdout=out)
+ self.assertIn("Apply all migrations: migrated_app", out.getvalue())
- @override_settings(INSTALLED_APPS=['migrations', 'migrations.migrations_test_apps.unmigrated_app_syncdb'])
+ @override_settings(
+ INSTALLED_APPS=[
+ "migrations",
+ "migrations.migrations_test_apps.unmigrated_app_syncdb",
+ ]
+ )
def test_app_without_migrations(self):
msg = "App 'unmigrated_app_syncdb' does not have migrations."
with self.assertRaisesMessage(CommandError, msg):
- call_command('migrate', app_label='unmigrated_app_syncdb')
+ call_command("migrate", app_label="unmigrated_app_syncdb")
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_clashing_prefix'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_clashing_prefix"}
+ )
def test_ambiguous_prefix(self):
msg = (
"More than one migration matches 'a' in app 'migrations'. Please "
"be more specific."
)
with self.assertRaisesMessage(CommandError, msg):
- call_command('migrate', app_label='migrations', migration_name='a')
+ call_command("migrate", app_label="migrations", migration_name="a")
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
+ @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_unknown_prefix(self):
msg = "Cannot find a migration matching 'nonexistent' from app 'migrations'."
with self.assertRaisesMessage(CommandError, msg):
- call_command('migrate', app_label='migrations', migration_name='nonexistent')
+ call_command(
+ "migrate", app_label="migrations", migration_name="nonexistent"
+ )
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_initial_false"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_initial_false"}
+ )
def test_migrate_initial_false(self):
"""
`Migration.initial = False` skips fake-initial detection.
@@ -116,7 +144,9 @@ class MigrateTests(MigrationTestBase):
call_command("migrate", "migrations", "zero", fake=True, verbosity=0)
# Make sure fake-initial detection does not run
with self.assertRaises(DatabaseError):
- call_command("migrate", "migrations", "0001", fake_initial=True, verbosity=0)
+ call_command(
+ "migrate", "migrations", "0001", fake_initial=True, verbosity=0
+ )
call_command("migrate", "migrations", "0001", fake=True, verbosity=0)
# Real rollback
@@ -128,7 +158,7 @@ class MigrateTests(MigrationTestBase):
@override_settings(
MIGRATION_MODULES={"migrations": "migrations.test_migrations"},
- DATABASE_ROUTERS=['migrations.routers.TestRouter'],
+ DATABASE_ROUTERS=["migrations.routers.TestRouter"],
)
def test_migrate_fake_initial(self):
"""
@@ -152,7 +182,9 @@ class MigrateTests(MigrationTestBase):
# Fake a roll-back
call_command("migrate", "migrations", "zero", fake=True, verbosity=0)
- call_command("migrate", "migrations", "zero", fake=True, verbosity=0, database="other")
+ call_command(
+ "migrate", "migrations", "zero", fake=True, verbosity=0, database="other"
+ )
# Make sure the tables still exist
self.assertTableExists("migrations_author")
self.assertTableExists("migrations_tribble", using="other")
@@ -161,97 +193,138 @@ class MigrateTests(MigrationTestBase):
call_command("migrate", "migrations", "0001", verbosity=0)
# Run initial migration with an explicit --fake-initial
out = io.StringIO()
- with mock.patch('django.core.management.color.supports_color', lambda *args: False):
- call_command("migrate", "migrations", "0001", fake_initial=True, stdout=out, verbosity=1)
- call_command("migrate", "migrations", "0001", fake_initial=True, verbosity=0, database="other")
- self.assertIn(
- "migrations.0001_initial... faked",
- out.getvalue().lower()
- )
+ with mock.patch(
+ "django.core.management.color.supports_color", lambda *args: False
+ ):
+ call_command(
+ "migrate",
+ "migrations",
+ "0001",
+ fake_initial=True,
+ stdout=out,
+ verbosity=1,
+ )
+ call_command(
+ "migrate",
+ "migrations",
+ "0001",
+ fake_initial=True,
+ verbosity=0,
+ database="other",
+ )
+ self.assertIn("migrations.0001_initial... faked", out.getvalue().lower())
try:
# Run migrations all the way.
- call_command('migrate', verbosity=0)
- call_command('migrate', verbosity=0, database="other")
- self.assertTableExists('migrations_author')
- self.assertTableNotExists('migrations_tribble')
- self.assertTableExists('migrations_book')
- self.assertTableNotExists('migrations_author', using='other')
- self.assertTableNotExists('migrations_tribble', using='other')
- self.assertTableNotExists('migrations_book', using='other')
+ call_command("migrate", verbosity=0)
+ call_command("migrate", verbosity=0, database="other")
+ self.assertTableExists("migrations_author")
+ self.assertTableNotExists("migrations_tribble")
+ self.assertTableExists("migrations_book")
+ self.assertTableNotExists("migrations_author", using="other")
+ self.assertTableNotExists("migrations_tribble", using="other")
+ self.assertTableNotExists("migrations_book", using="other")
# Fake a roll-back.
- call_command('migrate', 'migrations', 'zero', fake=True, verbosity=0)
- call_command('migrate', 'migrations', 'zero', fake=True, verbosity=0, database='other')
- self.assertTableExists('migrations_author')
- self.assertTableNotExists('migrations_tribble')
- self.assertTableExists('migrations_book')
+ call_command("migrate", "migrations", "zero", fake=True, verbosity=0)
+ call_command(
+ "migrate",
+ "migrations",
+ "zero",
+ fake=True,
+ verbosity=0,
+ database="other",
+ )
+ self.assertTableExists("migrations_author")
+ self.assertTableNotExists("migrations_tribble")
+ self.assertTableExists("migrations_book")
# Run initial migration.
with self.assertRaises(DatabaseError):
- call_command('migrate', 'migrations', verbosity=0)
+ call_command("migrate", "migrations", verbosity=0)
# Run initial migration with an explicit --fake-initial.
with self.assertRaises(DatabaseError):
# Fails because "migrations_tribble" does not exist but needs
# to in order to make --fake-initial work.
- call_command('migrate', 'migrations', fake_initial=True, verbosity=0)
+ call_command("migrate", "migrations", fake_initial=True, verbosity=0)
# Fake an apply.
- call_command('migrate', 'migrations', fake=True, verbosity=0)
- call_command('migrate', 'migrations', fake=True, verbosity=0, database='other')
+ call_command("migrate", "migrations", fake=True, verbosity=0)
+ call_command(
+ "migrate", "migrations", fake=True, verbosity=0, database="other"
+ )
finally:
# Unmigrate everything.
- call_command('migrate', 'migrations', 'zero', verbosity=0)
- call_command('migrate', 'migrations', 'zero', verbosity=0, database='other')
+ call_command("migrate", "migrations", "zero", verbosity=0)
+ call_command("migrate", "migrations", "zero", verbosity=0, database="other")
# Make sure it's all gone
for db in self.databases:
self.assertTableNotExists("migrations_author", using=db)
self.assertTableNotExists("migrations_tribble", using=db)
self.assertTableNotExists("migrations_book", using=db)
- @skipUnlessDBFeature('ignores_table_name_case')
+ @skipUnlessDBFeature("ignores_table_name_case")
def test_migrate_fake_initial_case_insensitive(self):
- with override_settings(MIGRATION_MODULES={
- 'migrations': 'migrations.test_fake_initial_case_insensitive.initial',
- }):
- call_command('migrate', 'migrations', '0001', verbosity=0)
- call_command('migrate', 'migrations', 'zero', fake=True, verbosity=0)
+ with override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_fake_initial_case_insensitive.initial",
+ }
+ ):
+ call_command("migrate", "migrations", "0001", verbosity=0)
+ call_command("migrate", "migrations", "zero", fake=True, verbosity=0)
- with override_settings(MIGRATION_MODULES={
- 'migrations': 'migrations.test_fake_initial_case_insensitive.fake_initial',
- }):
+ with override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_fake_initial_case_insensitive.fake_initial",
+ }
+ ):
out = io.StringIO()
call_command(
- 'migrate',
- 'migrations',
- '0001',
+ "migrate",
+ "migrations",
+ "0001",
fake_initial=True,
stdout=out,
verbosity=1,
no_color=True,
)
self.assertIn(
- 'migrations.0001_initial... faked',
+ "migrations.0001_initial... faked",
out.getvalue().lower(),
)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_fake_split_initial"})
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations_fake_split_initial"
+ }
+ )
def test_migrate_fake_split_initial(self):
"""
Split initial migrations can be faked with --fake-initial.
"""
try:
- call_command('migrate', 'migrations', '0002', verbosity=0)
- call_command('migrate', 'migrations', 'zero', fake=True, verbosity=0)
+ call_command("migrate", "migrations", "0002", verbosity=0)
+ call_command("migrate", "migrations", "zero", fake=True, verbosity=0)
out = io.StringIO()
- with mock.patch('django.core.management.color.supports_color', lambda *args: False):
- call_command('migrate', 'migrations', '0002', fake_initial=True, stdout=out, verbosity=1)
+ with mock.patch(
+ "django.core.management.color.supports_color", lambda *args: False
+ ):
+ call_command(
+ "migrate",
+ "migrations",
+ "0002",
+ fake_initial=True,
+ stdout=out,
+ verbosity=1,
+ )
value = out.getvalue().lower()
- self.assertIn('migrations.0001_initial... faked', value)
- self.assertIn('migrations.0002_second... faked', value)
+ self.assertIn("migrations.0001_initial... faked", value)
+ self.assertIn("migrations.0002_second... faked", value)
finally:
# Fake an apply.
- call_command('migrate', 'migrations', fake=True, verbosity=0)
+ call_command("migrate", "migrations", fake=True, verbosity=0)
# Unmigrate everything.
- call_command('migrate', 'migrations', 'zero', verbosity=0)
+ call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_conflict"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_conflict"}
+ )
def test_migrate_conflict_exit(self):
"""
migrate exits if it detects a conflict.
@@ -265,36 +338,40 @@ class MigrateTests(MigrationTestBase):
with self.assertRaisesMessage(CommandError, msg):
call_command("migrate", "migrations")
- @override_settings(MIGRATION_MODULES={
- 'migrations': 'migrations.test_migrations',
- })
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations",
+ }
+ )
def test_migrate_check(self):
with self.assertRaises(SystemExit):
- call_command('migrate', 'migrations', '0001', check_unapplied=True)
- self.assertTableNotExists('migrations_author')
- self.assertTableNotExists('migrations_tribble')
- self.assertTableNotExists('migrations_book')
+ call_command("migrate", "migrations", "0001", check_unapplied=True)
+ self.assertTableNotExists("migrations_author")
+ self.assertTableNotExists("migrations_tribble")
+ self.assertTableNotExists("migrations_book")
- @override_settings(MIGRATION_MODULES={
- 'migrations': 'migrations.test_migrations_plan',
- })
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations_plan",
+ }
+ )
def test_migrate_check_plan(self):
out = io.StringIO()
with self.assertRaises(SystemExit):
call_command(
- 'migrate',
- 'migrations',
- '0001',
+ "migrate",
+ "migrations",
+ "0001",
check_unapplied=True,
plan=True,
stdout=out,
no_color=True,
)
self.assertEqual(
- 'Planned operations:\n'
- 'migrations.0001_initial\n'
- ' Create model Salamander\n'
- ' Raw Python operation -> Grow salamander tail.\n',
+ "Planned operations:\n"
+ "migrations.0001_initial\n"
+ " Create model Salamander\n"
+ " Raw Python operation -> Grow salamander tail.\n",
out.getvalue(),
)
@@ -305,333 +382,387 @@ class MigrateTests(MigrationTestBase):
applied.
"""
out = io.StringIO()
- with mock.patch('django.core.management.color.supports_color', lambda *args: True):
- call_command("showmigrations", format='list', stdout=out, verbosity=0, no_color=False)
+ with mock.patch(
+ "django.core.management.color.supports_color", lambda *args: True
+ ):
+ call_command(
+ "showmigrations", format="list", stdout=out, verbosity=0, no_color=False
+ )
self.assertEqual(
- '\x1b[1mmigrations\n\x1b[0m [ ] 0001_initial\n [ ] 0002_second\n',
- out.getvalue().lower()
+ "\x1b[1mmigrations\n\x1b[0m [ ] 0001_initial\n [ ] 0002_second\n",
+ out.getvalue().lower(),
)
call_command("migrate", "migrations", "0001", verbosity=0)
out = io.StringIO()
# Giving the explicit app_label tests for selective `show_list` in the command
- call_command("showmigrations", "migrations", format='list', stdout=out, verbosity=0, no_color=True)
+ call_command(
+ "showmigrations",
+ "migrations",
+ format="list",
+ stdout=out,
+ verbosity=0,
+ no_color=True,
+ )
self.assertEqual(
- 'migrations\n [x] 0001_initial\n [ ] 0002_second\n',
- out.getvalue().lower()
+ "migrations\n [x] 0001_initial\n [ ] 0002_second\n", out.getvalue().lower()
)
out = io.StringIO()
# Applied datetimes are displayed at verbosity 2+.
- call_command('showmigrations', 'migrations', stdout=out, verbosity=2, no_color=True)
- migration1 = MigrationRecorder(connection).migration_qs.get(app='migrations', name='0001_initial')
+ call_command(
+ "showmigrations", "migrations", stdout=out, verbosity=2, no_color=True
+ )
+ migration1 = MigrationRecorder(connection).migration_qs.get(
+ app="migrations", name="0001_initial"
+ )
self.assertEqual(
- 'migrations\n'
- ' [x] 0001_initial (applied at %s)\n'
- ' [ ] 0002_second\n' % migration1.applied.strftime('%Y-%m-%d %H:%M:%S'),
- out.getvalue().lower()
+ "migrations\n"
+ " [x] 0001_initial (applied at %s)\n"
+ " [ ] 0002_second\n" % migration1.applied.strftime("%Y-%m-%d %H:%M:%S"),
+ out.getvalue().lower(),
)
# Cleanup by unmigrating everything
call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_showmigrations_list_squashed(self):
out = io.StringIO()
- call_command('showmigrations', format='list', stdout=out, verbosity=2, no_color=True)
+ call_command(
+ "showmigrations", format="list", stdout=out, verbosity=2, no_color=True
+ )
self.assertEqual(
- 'migrations\n [ ] 0001_squashed_0002 (2 squashed migrations)\n',
+ "migrations\n [ ] 0001_squashed_0002 (2 squashed migrations)\n",
out.getvalue().lower(),
)
out = io.StringIO()
call_command(
- 'migrate',
- 'migrations',
- '0001_squashed_0002',
+ "migrate",
+ "migrations",
+ "0001_squashed_0002",
stdout=out,
verbosity=2,
no_color=True,
)
try:
self.assertIn(
- 'operations to perform:\n'
- ' target specific migration: 0001_squashed_0002, from migrations\n'
- 'running pre-migrate handlers for application migrations\n'
- 'running migrations:\n'
- ' applying migrations.0001_squashed_0002... ok (',
+ "operations to perform:\n"
+ " target specific migration: 0001_squashed_0002, from migrations\n"
+ "running pre-migrate handlers for application migrations\n"
+ "running migrations:\n"
+ " applying migrations.0001_squashed_0002... ok (",
out.getvalue().lower(),
)
out = io.StringIO()
- call_command('showmigrations', format='list', stdout=out, verbosity=2, no_color=True)
+ call_command(
+ "showmigrations", format="list", stdout=out, verbosity=2, no_color=True
+ )
self.assertEqual(
- 'migrations\n [x] 0001_squashed_0002 (2 squashed migrations)\n',
+ "migrations\n [x] 0001_squashed_0002 (2 squashed migrations)\n",
out.getvalue().lower(),
)
finally:
# Unmigrate everything.
- call_command('migrate', 'migrations', 'zero', verbosity=0)
+ call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_run_before"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_run_before"}
+ )
def test_showmigrations_plan(self):
"""
Tests --plan output of showmigrations command
"""
out = io.StringIO()
- call_command("showmigrations", format='plan', stdout=out)
+ call_command("showmigrations", format="plan", stdout=out)
self.assertEqual(
"[ ] migrations.0001_initial\n"
"[ ] migrations.0003_third\n"
"[ ] migrations.0002_second\n",
- out.getvalue().lower()
+ out.getvalue().lower(),
)
out = io.StringIO()
- call_command("showmigrations", format='plan', stdout=out, verbosity=2)
+ call_command("showmigrations", format="plan", stdout=out, verbosity=2)
self.assertEqual(
"[ ] migrations.0001_initial\n"
"[ ] migrations.0003_third ... (migrations.0001_initial)\n"
"[ ] migrations.0002_second ... (migrations.0001_initial, migrations.0003_third)\n",
- out.getvalue().lower()
+ out.getvalue().lower(),
)
call_command("migrate", "migrations", "0003", verbosity=0)
out = io.StringIO()
- call_command("showmigrations", format='plan', stdout=out)
+ call_command("showmigrations", format="plan", stdout=out)
self.assertEqual(
"[x] migrations.0001_initial\n"
"[x] migrations.0003_third\n"
"[ ] migrations.0002_second\n",
- out.getvalue().lower()
+ out.getvalue().lower(),
)
out = io.StringIO()
- call_command("showmigrations", format='plan', stdout=out, verbosity=2)
+ call_command("showmigrations", format="plan", stdout=out, verbosity=2)
self.assertEqual(
"[x] migrations.0001_initial\n"
"[x] migrations.0003_third ... (migrations.0001_initial)\n"
"[ ] migrations.0002_second ... (migrations.0001_initial, migrations.0003_third)\n",
- out.getvalue().lower()
+ out.getvalue().lower(),
)
# Cleanup by unmigrating everything
call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_plan'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_plan"}
+ )
def test_migrate_plan(self):
"""Tests migrate --plan output."""
out = io.StringIO()
# Show the plan up to the third migration.
- call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True)
+ call_command(
+ "migrate", "migrations", "0003", plan=True, stdout=out, no_color=True
+ )
self.assertEqual(
- 'Planned operations:\n'
- 'migrations.0001_initial\n'
- ' Create model Salamander\n'
- ' Raw Python operation -> Grow salamander tail.\n'
- 'migrations.0002_second\n'
- ' Create model Book\n'
+ "Planned operations:\n"
+ "migrations.0001_initial\n"
+ " Create model Salamander\n"
+ " Raw Python operation -> Grow salamander tail.\n"
+ "migrations.0002_second\n"
+ " Create model Book\n"
" Raw SQL operation -> ['SELECT * FROM migrations_book']\n"
- 'migrations.0003_third\n'
- ' Create model Author\n'
+ "migrations.0003_third\n"
+ " Create model Author\n"
" Raw SQL operation -> ['SELECT * FROM migrations_author']\n",
- out.getvalue()
+ out.getvalue(),
)
try:
# Migrate to the third migration.
- call_command('migrate', 'migrations', '0003', verbosity=0)
+ call_command("migrate", "migrations", "0003", verbosity=0)
out = io.StringIO()
# Show the plan for when there is nothing to apply.
- call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True)
+ call_command(
+ "migrate", "migrations", "0003", plan=True, stdout=out, no_color=True
+ )
self.assertEqual(
- 'Planned operations:\n No planned migration operations.\n',
- out.getvalue()
+ "Planned operations:\n No planned migration operations.\n",
+ out.getvalue(),
)
out = io.StringIO()
# Show the plan for reverse migration back to 0001.
- call_command('migrate', 'migrations', '0001', plan=True, stdout=out, no_color=True)
+ call_command(
+ "migrate", "migrations", "0001", plan=True, stdout=out, no_color=True
+ )
self.assertEqual(
- 'Planned operations:\n'
- 'migrations.0003_third\n'
- ' Undo Create model Author\n'
+ "Planned operations:\n"
+ "migrations.0003_third\n"
+ " Undo Create model Author\n"
" Raw SQL operation -> ['SELECT * FROM migrations_book']\n"
- 'migrations.0002_second\n'
- ' Undo Create model Book\n'
+ "migrations.0002_second\n"
+ " Undo Create model Book\n"
" Raw SQL operation -> ['SELECT * FROM migrations_salamand…\n",
- out.getvalue()
+ out.getvalue(),
)
out = io.StringIO()
# Show the migration plan to fourth, with truncated details.
- call_command('migrate', 'migrations', '0004', plan=True, stdout=out, no_color=True)
+ call_command(
+ "migrate", "migrations", "0004", plan=True, stdout=out, no_color=True
+ )
self.assertEqual(
- 'Planned operations:\n'
- 'migrations.0004_fourth\n'
- ' Raw SQL operation -> SELECT * FROM migrations_author WHE…\n',
- out.getvalue()
+ "Planned operations:\n"
+ "migrations.0004_fourth\n"
+ " Raw SQL operation -> SELECT * FROM migrations_author WHE…\n",
+ out.getvalue(),
)
# Show the plan when an operation is irreversible.
# Migrate to the fourth migration.
- call_command('migrate', 'migrations', '0004', verbosity=0)
+ call_command("migrate", "migrations", "0004", verbosity=0)
out = io.StringIO()
- call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True)
+ call_command(
+ "migrate", "migrations", "0003", plan=True, stdout=out, no_color=True
+ )
self.assertEqual(
- 'Planned operations:\n'
- 'migrations.0004_fourth\n'
- ' Raw SQL operation -> IRREVERSIBLE\n',
- out.getvalue()
+ "Planned operations:\n"
+ "migrations.0004_fourth\n"
+ " Raw SQL operation -> IRREVERSIBLE\n",
+ out.getvalue(),
)
out = io.StringIO()
- call_command('migrate', 'migrations', '0005', plan=True, stdout=out, no_color=True)
+ call_command(
+ "migrate", "migrations", "0005", plan=True, stdout=out, no_color=True
+ )
# Operation is marked as irreversible only in the revert plan.
self.assertEqual(
- 'Planned operations:\n'
- 'migrations.0005_fifth\n'
- ' Raw Python operation\n'
- ' Raw Python operation\n'
- ' Raw Python operation -> Feed salamander.\n',
- out.getvalue()
+ "Planned operations:\n"
+ "migrations.0005_fifth\n"
+ " Raw Python operation\n"
+ " Raw Python operation\n"
+ " Raw Python operation -> Feed salamander.\n",
+ out.getvalue(),
)
- call_command('migrate', 'migrations', '0005', verbosity=0)
+ call_command("migrate", "migrations", "0005", verbosity=0)
out = io.StringIO()
- call_command('migrate', 'migrations', '0004', plan=True, stdout=out, no_color=True)
+ call_command(
+ "migrate", "migrations", "0004", plan=True, stdout=out, no_color=True
+ )
self.assertEqual(
- 'Planned operations:\n'
- 'migrations.0005_fifth\n'
- ' Raw Python operation -> IRREVERSIBLE\n'
- ' Raw Python operation -> IRREVERSIBLE\n'
- ' Raw Python operation\n',
- out.getvalue()
+ "Planned operations:\n"
+ "migrations.0005_fifth\n"
+ " Raw Python operation -> IRREVERSIBLE\n"
+ " Raw Python operation -> IRREVERSIBLE\n"
+ " Raw Python operation\n",
+ out.getvalue(),
)
finally:
# Cleanup by unmigrating everything: fake the irreversible, then
# migrate all to zero.
- call_command('migrate', 'migrations', '0003', fake=True, verbosity=0)
- call_command('migrate', 'migrations', 'zero', verbosity=0)
+ call_command("migrate", "migrations", "0003", fake=True, verbosity=0)
+ call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_empty'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_empty"}
+ )
def test_showmigrations_no_migrations(self):
out = io.StringIO()
- call_command('showmigrations', stdout=out, no_color=True)
- self.assertEqual('migrations\n (no migrations)\n', out.getvalue().lower())
+ call_command("showmigrations", stdout=out, no_color=True)
+ self.assertEqual("migrations\n (no migrations)\n", out.getvalue().lower())
- @override_settings(INSTALLED_APPS=['migrations.migrations_test_apps.unmigrated_app'])
+ @override_settings(
+ INSTALLED_APPS=["migrations.migrations_test_apps.unmigrated_app"]
+ )
def test_showmigrations_unmigrated_app(self):
out = io.StringIO()
- call_command('showmigrations', 'unmigrated_app', stdout=out, no_color=True)
+ call_command("showmigrations", "unmigrated_app", stdout=out, no_color=True)
try:
- self.assertEqual('unmigrated_app\n (no migrations)\n', out.getvalue().lower())
+ self.assertEqual(
+ "unmigrated_app\n (no migrations)\n", out.getvalue().lower()
+ )
finally:
# unmigrated_app.SillyModel has a foreign key to
# 'migrations.Tribble', but that model is only defined in a
# migration, so the global app registry never sees it and the
# reference is left dangling. Remove it to avoid problems in
# subsequent tests.
- apps._pending_operations.pop(('migrations', 'tribble'), None)
+ apps._pending_operations.pop(("migrations", "tribble"), None)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_empty"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_empty"}
+ )
def test_showmigrations_plan_no_migrations(self):
"""
Tests --plan output of showmigrations command without migrations
"""
out = io.StringIO()
- call_command('showmigrations', format='plan', stdout=out, no_color=True)
- self.assertEqual('(no migrations)\n', out.getvalue().lower())
+ call_command("showmigrations", format="plan", stdout=out, no_color=True)
+ self.assertEqual("(no migrations)\n", out.getvalue().lower())
out = io.StringIO()
- call_command('showmigrations', format='plan', stdout=out, verbosity=2, no_color=True)
- self.assertEqual('(no migrations)\n', out.getvalue().lower())
+ call_command(
+ "showmigrations", format="plan", stdout=out, verbosity=2, no_color=True
+ )
+ self.assertEqual("(no migrations)\n", out.getvalue().lower())
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed_complex"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed_complex"}
+ )
def test_showmigrations_plan_squashed(self):
"""
Tests --plan output of showmigrations command with squashed migrations.
"""
out = io.StringIO()
- call_command("showmigrations", format='plan', stdout=out)
+ call_command("showmigrations", format="plan", stdout=out)
self.assertEqual(
"[ ] migrations.1_auto\n"
"[ ] migrations.2_auto\n"
"[ ] migrations.3_squashed_5\n"
"[ ] migrations.6_auto\n"
"[ ] migrations.7_auto\n",
- out.getvalue().lower()
+ out.getvalue().lower(),
)
out = io.StringIO()
- call_command("showmigrations", format='plan', stdout=out, verbosity=2)
+ call_command("showmigrations", format="plan", stdout=out, verbosity=2)
self.assertEqual(
"[ ] migrations.1_auto\n"
"[ ] migrations.2_auto ... (migrations.1_auto)\n"
"[ ] migrations.3_squashed_5 ... (migrations.2_auto)\n"
"[ ] migrations.6_auto ... (migrations.3_squashed_5)\n"
"[ ] migrations.7_auto ... (migrations.6_auto)\n",
- out.getvalue().lower()
+ out.getvalue().lower(),
)
call_command("migrate", "migrations", "3_squashed_5", verbosity=0)
out = io.StringIO()
- call_command("showmigrations", format='plan', stdout=out)
+ call_command("showmigrations", format="plan", stdout=out)
self.assertEqual(
"[x] migrations.1_auto\n"
"[x] migrations.2_auto\n"
"[x] migrations.3_squashed_5\n"
"[ ] migrations.6_auto\n"
"[ ] migrations.7_auto\n",
- out.getvalue().lower()
+ out.getvalue().lower(),
)
out = io.StringIO()
- call_command("showmigrations", format='plan', stdout=out, verbosity=2)
+ call_command("showmigrations", format="plan", stdout=out, verbosity=2)
self.assertEqual(
"[x] migrations.1_auto\n"
"[x] migrations.2_auto ... (migrations.1_auto)\n"
"[x] migrations.3_squashed_5 ... (migrations.2_auto)\n"
"[ ] migrations.6_auto ... (migrations.3_squashed_5)\n"
"[ ] migrations.7_auto ... (migrations.6_auto)\n",
- out.getvalue().lower()
+ out.getvalue().lower(),
)
- @override_settings(INSTALLED_APPS=[
- 'migrations.migrations_test_apps.mutate_state_b',
- 'migrations.migrations_test_apps.alter_fk.author_app',
- 'migrations.migrations_test_apps.alter_fk.book_app',
- ])
+ @override_settings(
+ INSTALLED_APPS=[
+ "migrations.migrations_test_apps.mutate_state_b",
+ "migrations.migrations_test_apps.alter_fk.author_app",
+ "migrations.migrations_test_apps.alter_fk.book_app",
+ ]
+ )
def test_showmigrations_plan_single_app_label(self):
"""
`showmigrations --plan app_label` output with a single app_label.
"""
# Single app with no dependencies on other apps.
out = io.StringIO()
- call_command('showmigrations', 'mutate_state_b', format='plan', stdout=out)
+ call_command("showmigrations", "mutate_state_b", format="plan", stdout=out)
self.assertEqual(
- '[ ] mutate_state_b.0001_initial\n[ ] mutate_state_b.0002_add_field\n',
- out.getvalue()
+ "[ ] mutate_state_b.0001_initial\n[ ] mutate_state_b.0002_add_field\n",
+ out.getvalue(),
)
# Single app with dependencies.
out = io.StringIO()
- call_command('showmigrations', 'author_app', format='plan', stdout=out)
+ call_command("showmigrations", "author_app", format="plan", stdout=out)
self.assertEqual(
- '[ ] author_app.0001_initial\n'
- '[ ] book_app.0001_initial\n'
- '[ ] author_app.0002_alter_id\n',
- out.getvalue()
+ "[ ] author_app.0001_initial\n"
+ "[ ] book_app.0001_initial\n"
+ "[ ] author_app.0002_alter_id\n",
+ out.getvalue(),
)
# Some migrations already applied.
- call_command('migrate', 'author_app', '0001', verbosity=0)
+ call_command("migrate", "author_app", "0001", verbosity=0)
out = io.StringIO()
- call_command('showmigrations', 'author_app', format='plan', stdout=out)
+ call_command("showmigrations", "author_app", format="plan", stdout=out)
self.assertEqual(
- '[X] author_app.0001_initial\n'
- '[ ] book_app.0001_initial\n'
- '[ ] author_app.0002_alter_id\n',
- out.getvalue()
+ "[X] author_app.0001_initial\n"
+ "[ ] book_app.0001_initial\n"
+ "[ ] author_app.0002_alter_id\n",
+ out.getvalue(),
)
# Cleanup by unmigrating author_app.
- call_command('migrate', 'author_app', 'zero', verbosity=0)
+ call_command("migrate", "author_app", "zero", verbosity=0)
- @override_settings(INSTALLED_APPS=[
- 'migrations.migrations_test_apps.mutate_state_b',
- 'migrations.migrations_test_apps.alter_fk.author_app',
- 'migrations.migrations_test_apps.alter_fk.book_app',
- ])
+ @override_settings(
+ INSTALLED_APPS=[
+ "migrations.migrations_test_apps.mutate_state_b",
+ "migrations.migrations_test_apps.alter_fk.author_app",
+ "migrations.migrations_test_apps.alter_fk.book_app",
+ ]
+ )
def test_showmigrations_plan_multiple_app_labels(self):
"""
`showmigrations --plan app_label` output with multiple app_labels.
@@ -639,41 +770,49 @@ class MigrateTests(MigrationTestBase):
# Multiple apps: author_app depends on book_app; mutate_state_b doesn't
# depend on other apps.
out = io.StringIO()
- call_command('showmigrations', 'mutate_state_b', 'author_app', format='plan', stdout=out)
+ call_command(
+ "showmigrations", "mutate_state_b", "author_app", format="plan", stdout=out
+ )
self.assertEqual(
- '[ ] author_app.0001_initial\n'
- '[ ] book_app.0001_initial\n'
- '[ ] author_app.0002_alter_id\n'
- '[ ] mutate_state_b.0001_initial\n'
- '[ ] mutate_state_b.0002_add_field\n',
- out.getvalue()
+ "[ ] author_app.0001_initial\n"
+ "[ ] book_app.0001_initial\n"
+ "[ ] author_app.0002_alter_id\n"
+ "[ ] mutate_state_b.0001_initial\n"
+ "[ ] mutate_state_b.0002_add_field\n",
+ out.getvalue(),
)
# Multiple apps: args order shouldn't matter (the same result is
# expected as above).
out = io.StringIO()
- call_command('showmigrations', 'author_app', 'mutate_state_b', format='plan', stdout=out)
+ call_command(
+ "showmigrations", "author_app", "mutate_state_b", format="plan", stdout=out
+ )
self.assertEqual(
- '[ ] author_app.0001_initial\n'
- '[ ] book_app.0001_initial\n'
- '[ ] author_app.0002_alter_id\n'
- '[ ] mutate_state_b.0001_initial\n'
- '[ ] mutate_state_b.0002_add_field\n',
- out.getvalue()
+ "[ ] author_app.0001_initial\n"
+ "[ ] book_app.0001_initial\n"
+ "[ ] author_app.0002_alter_id\n"
+ "[ ] mutate_state_b.0001_initial\n"
+ "[ ] mutate_state_b.0002_add_field\n",
+ out.getvalue(),
)
- @override_settings(INSTALLED_APPS=['migrations.migrations_test_apps.unmigrated_app'])
+ @override_settings(
+ INSTALLED_APPS=["migrations.migrations_test_apps.unmigrated_app"]
+ )
def test_showmigrations_plan_app_label_no_migrations(self):
out = io.StringIO()
- call_command('showmigrations', 'unmigrated_app', format='plan', stdout=out, no_color=True)
+ call_command(
+ "showmigrations", "unmigrated_app", format="plan", stdout=out, no_color=True
+ )
try:
- self.assertEqual('(no migrations)\n', out.getvalue())
+ self.assertEqual("(no migrations)\n", out.getvalue())
finally:
# unmigrated_app.SillyModel has a foreign key to
# 'migrations.Tribble', but that model is only defined in a
# migration, so the global app registry never sees it and the
# reference is left dangling. Remove it to avoid problems in
# subsequent tests.
- apps._pending_operations.pop(('migrations', 'tribble'), None)
+ apps._pending_operations.pop(("migrations", "tribble"), None)
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_sqlmigrate_forwards(self):
@@ -685,34 +824,39 @@ class MigrateTests(MigrationTestBase):
output = out.getvalue().lower()
index_tx_start = output.find(connection.ops.start_transaction_sql().lower())
- index_op_desc_author = output.find('-- create model author')
- index_create_table = output.find('create table')
- index_op_desc_tribble = output.find('-- create model tribble')
- index_op_desc_unique_together = output.find('-- alter unique_together')
+ index_op_desc_author = output.find("-- create model author")
+ index_create_table = output.find("create table")
+ index_op_desc_tribble = output.find("-- create model tribble")
+ index_op_desc_unique_together = output.find("-- alter unique_together")
index_tx_end = output.find(connection.ops.end_transaction_sql().lower())
if connection.features.can_rollback_ddl:
self.assertGreater(index_tx_start, -1, "Transaction start not found")
self.assertGreater(
- index_tx_end, index_op_desc_unique_together,
- "Transaction end not found or found before operation description (unique_together)"
+ index_tx_end,
+ index_op_desc_unique_together,
+ "Transaction end not found or found before operation description (unique_together)",
)
self.assertGreater(
- index_op_desc_author, index_tx_start,
- "Operation description (author) not found or found before transaction start"
+ index_op_desc_author,
+ index_tx_start,
+ "Operation description (author) not found or found before transaction start",
)
self.assertGreater(
- index_create_table, index_op_desc_author,
- "CREATE TABLE not found or found before operation description (author)"
+ index_create_table,
+ index_op_desc_author,
+ "CREATE TABLE not found or found before operation description (author)",
)
self.assertGreater(
- index_op_desc_tribble, index_create_table,
- "Operation description (tribble) not found or found before CREATE TABLE (author)"
+ index_op_desc_tribble,
+ index_create_table,
+ "Operation description (tribble) not found or found before CREATE TABLE (author)",
)
self.assertGreater(
- index_op_desc_unique_together, index_op_desc_tribble,
- "Operation description (unique_together) not found or found before operation description (tribble)"
+ index_op_desc_unique_together,
+ index_op_desc_tribble,
+ "Operation description (unique_together) not found or found before operation description (tribble)",
)
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
@@ -728,40 +872,47 @@ class MigrateTests(MigrationTestBase):
output = out.getvalue().lower()
index_tx_start = output.find(connection.ops.start_transaction_sql().lower())
- index_op_desc_unique_together = output.find('-- alter unique_together')
- index_op_desc_tribble = output.find('-- create model tribble')
- index_op_desc_author = output.find('-- create model author')
- index_drop_table = output.rfind('drop table')
+ index_op_desc_unique_together = output.find("-- alter unique_together")
+ index_op_desc_tribble = output.find("-- create model tribble")
+ index_op_desc_author = output.find("-- create model author")
+ index_drop_table = output.rfind("drop table")
index_tx_end = output.find(connection.ops.end_transaction_sql().lower())
if connection.features.can_rollback_ddl:
self.assertGreater(index_tx_start, -1, "Transaction start not found")
self.assertGreater(
- index_tx_end, index_op_desc_unique_together,
- "Transaction end not found or found before DROP TABLE"
+ index_tx_end,
+ index_op_desc_unique_together,
+ "Transaction end not found or found before DROP TABLE",
)
self.assertGreater(
- index_op_desc_unique_together, index_tx_start,
- "Operation description (unique_together) not found or found before transaction start"
+ index_op_desc_unique_together,
+ index_tx_start,
+ "Operation description (unique_together) not found or found before transaction start",
)
self.assertGreater(
- index_op_desc_tribble, index_op_desc_unique_together,
- "Operation description (tribble) not found or found before operation description (unique_together)"
+ index_op_desc_tribble,
+ index_op_desc_unique_together,
+ "Operation description (tribble) not found or found before operation description (unique_together)",
)
self.assertGreater(
- index_op_desc_author, index_op_desc_tribble,
- "Operation description (author) not found or found before operation description (tribble)"
+ index_op_desc_author,
+ index_op_desc_tribble,
+ "Operation description (author) not found or found before operation description (tribble)",
)
self.assertGreater(
- index_drop_table, index_op_desc_author,
- "DROP TABLE not found or found before operation description (author)"
+ index_drop_table,
+ index_op_desc_author,
+ "DROP TABLE not found or found before operation description (author)",
)
# Cleanup by unmigrating everything
call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_non_atomic"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_non_atomic"}
+ )
def test_sqlmigrate_for_non_atomic_migration(self):
"""
Transaction wrappers aren't shown for non-atomic migrations.
@@ -774,15 +925,15 @@ class MigrateTests(MigrationTestBase):
self.assertNotIn(connection.ops.start_transaction_sql().lower(), queries)
self.assertNotIn(connection.ops.end_transaction_sql().lower(), queries)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
+ @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_sqlmigrate_for_non_transactional_databases(self):
"""
Transaction wrappers aren't shown for databases that don't support
transactional DDL.
"""
out = io.StringIO()
- with mock.patch.object(connection.features, 'can_rollback_ddl', False):
- call_command('sqlmigrate', 'migrations', '0001', stdout=out)
+ with mock.patch.object(connection.features, "can_rollback_ddl", False):
+ call_command("sqlmigrate", "migrations", "0001", stdout=out)
output = out.getvalue().lower()
queries = [q.strip() for q in output.splitlines()]
start_transaction_sql = connection.ops.start_transaction_sql()
@@ -790,37 +941,45 @@ class MigrateTests(MigrationTestBase):
self.assertNotIn(start_transaction_sql.lower(), queries)
self.assertNotIn(connection.ops.end_transaction_sql().lower(), queries)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_sqlmigrate_ambiguous_prefix_squashed_migrations(self):
msg = (
"More than one migration matches '0001' in app 'migrations'. "
"Please be more specific."
)
with self.assertRaisesMessage(CommandError, msg):
- call_command('sqlmigrate', 'migrations', '0001')
+ call_command("sqlmigrate", "migrations", "0001")
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_sqlmigrate_squashed_migration(self):
out = io.StringIO()
- call_command('sqlmigrate', 'migrations', '0001_squashed_0002', stdout=out)
+ call_command("sqlmigrate", "migrations", "0001_squashed_0002", stdout=out)
output = out.getvalue().lower()
- self.assertIn('-- create model author', output)
- self.assertIn('-- create model book', output)
- self.assertNotIn('-- create model tribble', output)
+ self.assertIn("-- create model author", output)
+ self.assertIn("-- create model book", output)
+ self.assertNotIn("-- create model tribble", output)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_sqlmigrate_replaced_migration(self):
out = io.StringIO()
- call_command('sqlmigrate', 'migrations', '0001_initial', stdout=out)
+ call_command("sqlmigrate", "migrations", "0001_initial", stdout=out)
output = out.getvalue().lower()
- self.assertIn('-- create model author', output)
- self.assertIn('-- create model tribble', output)
+ self.assertIn("-- create model author", output)
+ self.assertIn("-- create model tribble", output)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_no_operations'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_no_operations"}
+ )
def test_migrations_no_operations(self):
err = io.StringIO()
- call_command('sqlmigrate', 'migrations', '0001_initial', stderr=err)
- self.assertEqual(err.getvalue(), 'No operations found.\n')
+ call_command("sqlmigrate", "migrations", "0001_initial", stderr=err)
+ self.assertEqual(err.getvalue(), "No operations found.\n")
@override_settings(
INSTALLED_APPS=[
@@ -841,58 +1000,76 @@ class MigrateTests(MigrationTestBase):
"B" was not included in the ProjectState that is used to detect
soft-applied migrations (#22823).
"""
- call_command('migrate', 'migrated_unapplied_app', verbosity=0)
+ call_command("migrate", "migrated_unapplied_app", verbosity=0)
# unmigrated_app.SillyModel has a foreign key to 'migrations.Tribble',
# but that model is only defined in a migration, so the global app
# registry never sees it and the reference is left dangling. Remove it
# to avoid problems in subsequent tests.
- apps._pending_operations.pop(('migrations', 'tribble'), None)
+ apps._pending_operations.pop(("migrations", "tribble"), None)
- @override_settings(INSTALLED_APPS=['migrations.migrations_test_apps.unmigrated_app_syncdb'])
+ @override_settings(
+ INSTALLED_APPS=["migrations.migrations_test_apps.unmigrated_app_syncdb"]
+ )
def test_migrate_syncdb_deferred_sql_executed_with_schemaeditor(self):
"""
For an app without migrations, editor.execute() is used for executing
the syncdb deferred SQL.
"""
stdout = io.StringIO()
- with mock.patch.object(BaseDatabaseSchemaEditor, 'execute') as execute:
- call_command('migrate', run_syncdb=True, verbosity=1, stdout=stdout, no_color=True)
- create_table_count = len([call for call in execute.mock_calls if 'CREATE TABLE' in str(call)])
+ with mock.patch.object(BaseDatabaseSchemaEditor, "execute") as execute:
+ call_command(
+ "migrate", run_syncdb=True, verbosity=1, stdout=stdout, no_color=True
+ )
+ create_table_count = len(
+ [call for call in execute.mock_calls if "CREATE TABLE" in str(call)]
+ )
self.assertEqual(create_table_count, 2)
# There's at least one deferred SQL for creating the foreign key
# index.
self.assertGreater(len(execute.mock_calls), 2)
stdout = stdout.getvalue()
- self.assertIn('Synchronize unmigrated apps: unmigrated_app_syncdb', stdout)
- self.assertIn('Creating tables...', stdout)
- table_name = truncate_name('unmigrated_app_syncdb_classroom', connection.ops.max_name_length())
- self.assertIn('Creating table %s' % table_name, stdout)
+ self.assertIn("Synchronize unmigrated apps: unmigrated_app_syncdb", stdout)
+ self.assertIn("Creating tables...", stdout)
+ table_name = truncate_name(
+ "unmigrated_app_syncdb_classroom", connection.ops.max_name_length()
+ )
+ self.assertIn("Creating table %s" % table_name, stdout)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
+ @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_migrate_syncdb_app_with_migrations(self):
msg = "Can't use run_syncdb with app 'migrations' as it has migrations."
with self.assertRaisesMessage(CommandError, msg):
- call_command('migrate', 'migrations', run_syncdb=True, verbosity=0)
+ call_command("migrate", "migrations", run_syncdb=True, verbosity=0)
- @override_settings(INSTALLED_APPS=[
- 'migrations.migrations_test_apps.unmigrated_app_syncdb',
- 'migrations.migrations_test_apps.unmigrated_app_simple',
- ])
+ @override_settings(
+ INSTALLED_APPS=[
+ "migrations.migrations_test_apps.unmigrated_app_syncdb",
+ "migrations.migrations_test_apps.unmigrated_app_simple",
+ ]
+ )
def test_migrate_syncdb_app_label(self):
"""
Running migrate --run-syncdb with an app_label only creates tables for
the specified app.
"""
stdout = io.StringIO()
- with mock.patch.object(BaseDatabaseSchemaEditor, 'execute') as execute:
- call_command('migrate', 'unmigrated_app_syncdb', run_syncdb=True, stdout=stdout)
- create_table_count = len([call for call in execute.mock_calls if 'CREATE TABLE' in str(call)])
+ with mock.patch.object(BaseDatabaseSchemaEditor, "execute") as execute:
+ call_command(
+ "migrate", "unmigrated_app_syncdb", run_syncdb=True, stdout=stdout
+ )
+ create_table_count = len(
+ [call for call in execute.mock_calls if "CREATE TABLE" in str(call)]
+ )
self.assertEqual(create_table_count, 2)
self.assertGreater(len(execute.mock_calls), 2)
- self.assertIn('Synchronize unmigrated app: unmigrated_app_syncdb', stdout.getvalue())
+ self.assertIn(
+ "Synchronize unmigrated app: unmigrated_app_syncdb", stdout.getvalue()
+ )
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_migrate_record_replaced(self):
"""
Running a single squashed migration should record all of the original
@@ -903,8 +1080,8 @@ class MigrateTests(MigrationTestBase):
call_command("migrate", "migrations", verbosity=0)
call_command("showmigrations", "migrations", stdout=out, no_color=True)
self.assertEqual(
- 'migrations\n [x] 0001_squashed_0002 (2 squashed migrations)\n',
- out.getvalue().lower()
+ "migrations\n [x] 0001_squashed_0002 (2 squashed migrations)\n",
+ out.getvalue().lower(),
)
applied_migrations = recorder.applied_migrations()
self.assertIn(("migrations", "0001_initial"), applied_migrations)
@@ -913,7 +1090,9 @@ class MigrateTests(MigrationTestBase):
# Rollback changes
call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_migrate_record_squashed(self):
"""
Running migrate for a squashed migration should record as run
@@ -923,7 +1102,7 @@ class MigrateTests(MigrationTestBase):
recorder.record_applied("migrations", "0001_initial")
recorder.record_applied("migrations", "0002_second")
out = io.StringIO()
- call_command('showmigrations', 'migrations', stdout=out, no_color=True)
+ call_command("showmigrations", "migrations", stdout=out, no_color=True)
self.assertEqual(
"migrations\n"
" [-] 0001_squashed_0002 (2 squashed migrations) "
@@ -935,12 +1114,11 @@ class MigrateTests(MigrationTestBase):
call_command("migrate", "migrations", verbosity=0)
call_command("showmigrations", "migrations", stdout=out, no_color=True)
self.assertEqual(
- 'migrations\n [x] 0001_squashed_0002 (2 squashed migrations)\n',
- out.getvalue().lower()
+ "migrations\n [x] 0001_squashed_0002 (2 squashed migrations)\n",
+ out.getvalue().lower(),
)
self.assertIn(
- ("migrations", "0001_squashed_0002"),
- recorder.applied_migrations()
+ ("migrations", "0001_squashed_0002"), recorder.applied_migrations()
)
# No changes were actually applied so there is nothing to rollback
@@ -949,43 +1127,45 @@ class MigrateTests(MigrationTestBase):
Migrating to a squashed migration specified by name should succeed
even if it is partially applied.
"""
- with self.temporary_migration_module(module='migrations.test_migrations'):
+ with self.temporary_migration_module(module="migrations.test_migrations"):
recorder = MigrationRecorder(connection)
try:
- call_command('migrate', 'migrations', '0001_initial', verbosity=0)
+ call_command("migrate", "migrations", "0001_initial", verbosity=0)
call_command(
- 'squashmigrations',
- 'migrations',
- '0002',
+ "squashmigrations",
+ "migrations",
+ "0002",
interactive=False,
verbosity=0,
)
call_command(
- 'migrate',
- 'migrations',
- '0001_squashed_0002_second',
+ "migrate",
+ "migrations",
+ "0001_squashed_0002_second",
verbosity=0,
)
applied_migrations = recorder.applied_migrations()
- self.assertIn(('migrations', '0002_second'), applied_migrations)
+ self.assertIn(("migrations", "0002_second"), applied_migrations)
finally:
# Unmigrate everything.
- call_command('migrate', 'migrations', 'zero', verbosity=0)
+ call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_migrate_backward_to_squashed_migration(self):
try:
- call_command('migrate', 'migrations', '0001_squashed_0002', verbosity=0)
- self.assertTableExists('migrations_author')
- self.assertTableExists('migrations_book')
- call_command('migrate', 'migrations', '0001_initial', verbosity=0)
- self.assertTableExists('migrations_author')
- self.assertTableNotExists('migrations_book')
+ call_command("migrate", "migrations", "0001_squashed_0002", verbosity=0)
+ self.assertTableExists("migrations_author")
+ self.assertTableExists("migrations_book")
+ call_command("migrate", "migrations", "0001_initial", verbosity=0)
+ self.assertTableExists("migrations_author")
+ self.assertTableNotExists("migrations_book")
finally:
# Unmigrate everything.
- call_command('migrate', 'migrations', 'zero', verbosity=0)
+ call_command("migrate", "migrations", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
+ @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_migrate_inconsistent_history(self):
"""
Running migrate with some migrations applied before their dependencies
@@ -999,23 +1179,25 @@ class MigrateTests(MigrationTestBase):
applied_migrations = recorder.applied_migrations()
self.assertNotIn(("migrations", "0001_initial"), applied_migrations)
- @override_settings(INSTALLED_APPS=[
- 'migrations.migrations_test_apps.migrated_unapplied_app',
- 'migrations.migrations_test_apps.migrated_app',
- ])
+ @override_settings(
+ INSTALLED_APPS=[
+ "migrations.migrations_test_apps.migrated_unapplied_app",
+ "migrations.migrations_test_apps.migrated_app",
+ ]
+ )
def test_migrate_not_reflected_changes(self):
class NewModel1(models.Model):
- class Meta():
- app_label = 'migrated_app'
+ class Meta:
+ app_label = "migrated_app"
class NewModel2(models.Model):
- class Meta():
- app_label = 'migrated_unapplied_app'
+ class Meta:
+ app_label = "migrated_unapplied_app"
out = io.StringIO()
try:
- call_command('migrate', verbosity=0)
- call_command('migrate', stdout=out, no_color=True)
+ call_command("migrate", verbosity=0)
+ call_command("migrate", stdout=out, no_color=True)
self.assertEqual(
"operations to perform:\n"
" apply all migrations: migrated_app, migrated_unapplied_app\n"
@@ -1030,12 +1212,14 @@ class MigrateTests(MigrationTestBase):
)
finally:
# Unmigrate everything.
- call_command('migrate', 'migrated_app', 'zero', verbosity=0)
- call_command('migrate', 'migrated_unapplied_app', 'zero', verbosity=0)
+ call_command("migrate", "migrated_app", "zero", verbosity=0)
+ call_command("migrate", "migrated_unapplied_app", "zero", verbosity=0)
- @override_settings(MIGRATION_MODULES={
- 'migrations': 'migrations.test_migrations_squashed_no_replaces',
- })
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations_squashed_no_replaces",
+ }
+ )
def test_migrate_prune(self):
"""
With prune=True, references to migration files deleted from the
@@ -1043,44 +1227,50 @@ class MigrateTests(MigrationTestBase):
django_migrations table.
"""
recorder = MigrationRecorder(connection)
- recorder.record_applied('migrations', '0001_initial')
- recorder.record_applied('migrations', '0002_second')
- recorder.record_applied('migrations', '0001_squashed_0002')
+ recorder.record_applied("migrations", "0001_initial")
+ recorder.record_applied("migrations", "0002_second")
+ recorder.record_applied("migrations", "0001_squashed_0002")
out = io.StringIO()
try:
- call_command('migrate', 'migrations', prune=True, stdout=out, no_color=True)
+ call_command("migrate", "migrations", prune=True, stdout=out, no_color=True)
self.assertEqual(
out.getvalue(),
- 'Pruning migrations:\n'
- ' Pruning migrations.0001_initial OK\n'
- ' Pruning migrations.0002_second OK\n',
+ "Pruning migrations:\n"
+ " Pruning migrations.0001_initial OK\n"
+ " Pruning migrations.0002_second OK\n",
)
applied_migrations = [
migration
for migration in recorder.applied_migrations()
- if migration[0] == 'migrations'
+ if migration[0] == "migrations"
]
- self.assertEqual(applied_migrations, [('migrations', '0001_squashed_0002')])
+ self.assertEqual(applied_migrations, [("migrations", "0001_squashed_0002")])
finally:
- recorder.record_unapplied('migrations', '0001_initial')
- recorder.record_unapplied('migrations', '0001_second')
- recorder.record_unapplied('migrations', '0001_squashed_0002')
+ recorder.record_unapplied("migrations", "0001_initial")
+ recorder.record_unapplied("migrations", "0001_second")
+ recorder.record_unapplied("migrations", "0001_squashed_0002")
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_prune_deleted_squashed_migrations_in_replaces(self):
out = io.StringIO()
with self.temporary_migration_module(
- module='migrations.test_migrations_squashed'
+ module="migrations.test_migrations_squashed"
) as migration_dir:
try:
- call_command('migrate', 'migrations', verbosity=0)
+ call_command("migrate", "migrations", verbosity=0)
# Delete the replaced migrations.
- os.remove(os.path.join(migration_dir, '0001_initial.py'))
- os.remove(os.path.join(migration_dir, '0002_second.py'))
+ os.remove(os.path.join(migration_dir, "0001_initial.py"))
+ os.remove(os.path.join(migration_dir, "0002_second.py"))
# --prune cannot be used before removing the "replaces"
# attribute.
call_command(
- 'migrate', 'migrations', prune=True, stdout=out, no_color=True,
+ "migrate",
+ "migrations",
+ prune=True,
+ stdout=out,
+ no_color=True,
)
self.assertEqual(
out.getvalue(),
@@ -1091,32 +1281,37 @@ class MigrateTests(MigrationTestBase):
" migrations.0001_squashed_0002\n"
" Re-run 'manage.py migrate' if they are not marked as "
"applied, and remove 'replaces' attributes in their "
- "Migration classes.\n"
+ "Migration classes.\n",
)
finally:
# Unmigrate everything.
- call_command('migrate', 'migrations', 'zero', verbosity=0)
+ call_command("migrate", "migrations", "zero", verbosity=0)
@override_settings(
- MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'}
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
)
def test_prune_no_migrations_to_prune(self):
out = io.StringIO()
- call_command('migrate', 'migrations', prune=True, stdout=out, no_color=True)
+ call_command("migrate", "migrations", prune=True, stdout=out, no_color=True)
self.assertEqual(
out.getvalue(),
- 'Pruning migrations:\n No migrations to prune.\n',
+ "Pruning migrations:\n No migrations to prune.\n",
)
out = io.StringIO()
call_command(
- 'migrate', 'migrations', prune=True, stdout=out, no_color=True, verbosity=0,
+ "migrate",
+ "migrations",
+ prune=True,
+ stdout=out,
+ no_color=True,
+ verbosity=0,
)
- self.assertEqual(out.getvalue(), '')
+ self.assertEqual(out.getvalue(), "")
def test_prune_no_app_label(self):
- msg = 'Migrations can be pruned only when an app is specified.'
+ msg = "Migrations can be pruned only when an app is specified."
with self.assertRaisesMessage(CommandError, msg):
- call_command('migrate', prune=True)
+ call_command("migrate", prune=True)
class MakeMigrationsTests(MigrationTestBase):
@@ -1126,17 +1321,17 @@ class MakeMigrationsTests(MigrationTestBase):
def setUp(self):
super().setUp()
- self._old_models = apps.app_configs['migrations'].models.copy()
+ self._old_models = apps.app_configs["migrations"].models.copy()
def tearDown(self):
- apps.app_configs['migrations'].models = self._old_models
- apps.all_models['migrations'] = self._old_models
+ apps.app_configs["migrations"].models = self._old_models
+ apps.all_models["migrations"] = self._old_models
apps.clear_cache()
super().tearDown()
def test_files_content(self):
self.assertTableNotExists("migrations_unicodemodel")
- apps.register_model('migrations', UnicodeModel)
+ apps.register_model("migrations", UnicodeModel)
with self.temporary_migration_module() as migration_dir:
call_command("makemigrations", "migrations", verbosity=0)
@@ -1146,65 +1341,71 @@ class MakeMigrationsTests(MigrationTestBase):
with open(init_file) as fp:
content = fp.read()
- self.assertEqual(content, '')
+ self.assertEqual(content, "")
# Check for existing 0001_initial.py file in migration folder
initial_file = os.path.join(migration_dir, "0001_initial.py")
self.assertTrue(os.path.exists(initial_file))
- with open(initial_file, encoding='utf-8') as fp:
+ with open(initial_file, encoding="utf-8") as fp:
content = fp.read()
- self.assertIn('migrations.CreateModel', content)
- self.assertIn('initial = True', content)
+ self.assertIn("migrations.CreateModel", content)
+ self.assertIn("initial = True", content)
- self.assertIn('úñí©óðé µóðéø', content) # Meta.verbose_name
- self.assertIn('úñí©óðé µóðéøß', content) # Meta.verbose_name_plural
- self.assertIn('ÚÑÍ¢ÓÐÉ', content) # title.verbose_name
- self.assertIn('“Ðjáñgó”', content) # title.default
+ self.assertIn("úñí©óðé µóðéø", content) # Meta.verbose_name
+ self.assertIn("úñí©óðé µóðéøß", content) # Meta.verbose_name_plural
+ self.assertIn("ÚÑÍ¢ÓÐÉ", content) # title.verbose_name
+ self.assertIn("“Ðjáñgó”", content) # title.default
def test_makemigrations_order(self):
"""
makemigrations should recognize number-only migrations (0001.py).
"""
- module = 'migrations.test_migrations_order'
+ module = "migrations.test_migrations_order"
with self.temporary_migration_module(module=module) as migration_dir:
- if hasattr(importlib, 'invalidate_caches'):
+ if hasattr(importlib, "invalidate_caches"):
# importlib caches os.listdir() on some platforms like macOS
# (#23850).
importlib.invalidate_caches()
- call_command('makemigrations', 'migrations', '--empty', '-n', 'a', '-v', '0')
- self.assertTrue(os.path.exists(os.path.join(migration_dir, '0002_a.py')))
+ call_command(
+ "makemigrations", "migrations", "--empty", "-n", "a", "-v", "0"
+ )
+ self.assertTrue(os.path.exists(os.path.join(migration_dir, "0002_a.py")))
def test_makemigrations_empty_connections(self):
- empty_connections = ConnectionHandler({'default': {}})
- with mock.patch('django.core.management.commands.makemigrations.connections', new=empty_connections):
+ empty_connections = ConnectionHandler({"default": {}})
+ with mock.patch(
+ "django.core.management.commands.makemigrations.connections",
+ new=empty_connections,
+ ):
# with no apps
out = io.StringIO()
- call_command('makemigrations', stdout=out)
- self.assertIn('No changes detected', out.getvalue())
+ call_command("makemigrations", stdout=out)
+ self.assertIn("No changes detected", out.getvalue())
# with an app
with self.temporary_migration_module() as migration_dir:
- call_command('makemigrations', 'migrations', verbosity=0)
- init_file = os.path.join(migration_dir, '__init__.py')
+ call_command("makemigrations", "migrations", verbosity=0)
+ init_file = os.path.join(migration_dir, "__init__.py")
self.assertTrue(os.path.exists(init_file))
- @override_settings(INSTALLED_APPS=['migrations', 'migrations2'])
+ @override_settings(INSTALLED_APPS=["migrations", "migrations2"])
def test_makemigrations_consistency_checks_respect_routers(self):
"""
The history consistency checks in makemigrations respect
settings.DATABASE_ROUTERS.
"""
+
def patched_has_table(migration_recorder):
- if migration_recorder.connection is connections['other']:
- raise Exception('Other connection')
+ if migration_recorder.connection is connections["other"]:
+ raise Exception("Other connection")
else:
return mock.DEFAULT
- self.assertTableNotExists('migrations_unicodemodel')
- apps.register_model('migrations', UnicodeModel)
+ self.assertTableNotExists("migrations_unicodemodel")
+ apps.register_model("migrations", UnicodeModel)
with mock.patch.object(
- MigrationRecorder, 'has_table',
- autospec=True, side_effect=patched_has_table) as has_table:
+ MigrationRecorder, "has_table", autospec=True, side_effect=patched_has_table
+ ) as has_table:
with self.temporary_migration_module() as migration_dir:
call_command("makemigrations", "migrations", verbosity=0)
initial_file = os.path.join(migration_dir, "0001_initial.py")
@@ -1213,23 +1414,29 @@ class MakeMigrationsTests(MigrationTestBase):
# Router says not to migrate 'other' so consistency shouldn't
# be checked.
- with self.settings(DATABASE_ROUTERS=['migrations.routers.TestRouter']):
- call_command('makemigrations', 'migrations', verbosity=0)
+ with self.settings(DATABASE_ROUTERS=["migrations.routers.TestRouter"]):
+ call_command("makemigrations", "migrations", verbosity=0)
self.assertEqual(has_table.call_count, 2) # 'default' again
# With a router that doesn't prohibit migrating 'other',
# consistency is checked.
- with self.settings(DATABASE_ROUTERS=['migrations.routers.DefaultOtherRouter']):
- with self.assertRaisesMessage(Exception, 'Other connection'):
- call_command('makemigrations', 'migrations', verbosity=0)
+ with self.settings(
+ DATABASE_ROUTERS=["migrations.routers.DefaultOtherRouter"]
+ ):
+ with self.assertRaisesMessage(Exception, "Other connection"):
+ call_command("makemigrations", "migrations", verbosity=0)
self.assertEqual(has_table.call_count, 4) # 'default' and 'other'
# With a router that doesn't allow migrating on any database,
# no consistency checks are made.
- with self.settings(DATABASE_ROUTERS=['migrations.routers.TestRouter']):
- with mock.patch.object(TestRouter, 'allow_migrate', return_value=False) as allow_migrate:
- call_command('makemigrations', 'migrations', verbosity=0)
- allow_migrate.assert_any_call('other', 'migrations', model_name='UnicodeModel')
+ with self.settings(DATABASE_ROUTERS=["migrations.routers.TestRouter"]):
+ with mock.patch.object(
+ TestRouter, "allow_migrate", return_value=False
+ ) as allow_migrate:
+ call_command("makemigrations", "migrations", verbosity=0)
+ allow_migrate.assert_any_call(
+ "other", "migrations", model_name="UnicodeModel"
+ )
# allow_migrate() is called with the correct arguments.
self.assertGreater(len(allow_migrate.mock_calls), 0)
called_aliases = set()
@@ -1238,16 +1445,16 @@ class MakeMigrationsTests(MigrationTestBase):
connection_alias, app_name = call_args
called_aliases.add(connection_alias)
# Raises an error if invalid app_name/model_name occurs.
- apps.get_app_config(app_name).get_model(call_kwargs['model_name'])
+ apps.get_app_config(app_name).get_model(call_kwargs["model_name"])
self.assertEqual(called_aliases, set(connections))
self.assertEqual(has_table.call_count, 4)
def test_failing_migration(self):
# If a migration fails to serialize, it shouldn't generate an empty file. #21280
- apps.register_model('migrations', UnserializableModel)
+ apps.register_model("migrations", UnserializableModel)
with self.temporary_migration_module() as migration_dir:
- with self.assertRaisesMessage(ValueError, 'Cannot serialize'):
+ with self.assertRaisesMessage(ValueError, "Cannot serialize"):
call_command("makemigrations", "migrations", verbosity=0)
initial_file = os.path.join(migration_dir, "0001_initial.py")
@@ -1257,7 +1464,9 @@ class MakeMigrationsTests(MigrationTestBase):
"""
makemigrations exits if it detects a conflict.
"""
- with self.temporary_migration_module(module="migrations.test_migrations_conflict"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_conflict"
+ ):
with self.assertRaises(CommandError) as context:
call_command("makemigrations")
self.assertEqual(
@@ -1265,7 +1474,7 @@ class MakeMigrationsTests(MigrationTestBase):
"Conflicting migrations detected; multiple leaf nodes in the "
"migration graph: (0002_conflicting_second, 0002_second in "
"migrations).\n"
- "To fix them run 'python manage.py makemigrations --merge'"
+ "To fix them run 'python manage.py makemigrations --merge'",
)
def test_makemigrations_merge_no_conflict(self):
@@ -1281,7 +1490,7 @@ class MakeMigrationsTests(MigrationTestBase):
"""
makemigrations exits if no app is specified with 'empty' mode.
"""
- msg = 'You must supply at least one app label when using --empty.'
+ msg = "You must supply at least one app label when using --empty."
with self.assertRaisesMessage(CommandError, msg):
call_command("makemigrations", empty=True)
@@ -1296,13 +1505,13 @@ class MakeMigrationsTests(MigrationTestBase):
initial_file = os.path.join(migration_dir, "0001_initial.py")
self.assertTrue(os.path.exists(initial_file))
- with open(initial_file, encoding='utf-8') as fp:
+ with open(initial_file, encoding="utf-8") as fp:
content = fp.read()
# Remove all whitespace to check for empty dependencies and operations
- content = content.replace(' ', '')
- self.assertIn('dependencies=[\n]', content)
- self.assertIn('operations=[\n]', content)
+ content = content.replace(" ", "")
+ self.assertIn("dependencies=[\n]", content)
+ self.assertIn("operations=[\n]", content)
@override_settings(MIGRATION_MODULES={"migrations": None})
def test_makemigrations_disabled_migrations_for_app(self):
@@ -1330,7 +1539,9 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations exits when there are no changes to an app.
"""
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_no_changes"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_changes"
+ ):
call_command("makemigrations", "migrations", stdout=out)
self.assertIn("No changes detected in app 'migrations'", out.getvalue())
@@ -1347,9 +1558,11 @@ class MakeMigrationsTests(MigrationTestBase):
def test_makemigrations_no_init(self):
"""Migration directories without an __init__.py file are allowed."""
out = io.StringIO()
- with self.temporary_migration_module(module='migrations.test_migrations_no_init'):
- call_command('makemigrations', stdout=out)
- self.assertIn('0001_initial.py', out.getvalue())
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_init"
+ ):
+ call_command("makemigrations", stdout=out)
+ self.assertIn("0001_initial.py", out.getvalue())
def test_makemigrations_migrations_announce(self):
"""
@@ -1365,7 +1578,9 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations fails to merge migrations with no common ancestor.
"""
with self.assertRaises(ValueError) as context:
- with self.temporary_migration_module(module="migrations.test_migrations_no_ancestor"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_ancestor"
+ ):
call_command("makemigrations", "migrations", merge=True)
exception_message = str(context.exception)
self.assertIn("Could not find common ancestor of", exception_message)
@@ -1377,18 +1592,20 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations enters and exits interactive mode properly.
"""
# Monkeypatch interactive questioner to auto reject
- with mock.patch('builtins.input', mock.Mock(return_value='N')):
- with self.temporary_migration_module(module="migrations.test_migrations_conflict") as migration_dir:
+ with mock.patch("builtins.input", mock.Mock(return_value="N")):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_conflict"
+ ) as migration_dir:
with captured_stdout():
call_command(
- 'makemigrations',
- 'migrations',
- name='merge',
+ "makemigrations",
+ "migrations",
+ name="merge",
merge=True,
interactive=True,
verbosity=0,
)
- merge_file = os.path.join(migration_dir, '0003_merge.py')
+ merge_file = os.path.join(migration_dir, "0003_merge.py")
self.assertFalse(os.path.exists(merge_file))
def test_makemigrations_interactive_accept(self):
@@ -1396,37 +1613,58 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations enters interactive mode and merges properly.
"""
# Monkeypatch interactive questioner to auto accept
- with mock.patch('builtins.input', mock.Mock(return_value='y')):
+ with mock.patch("builtins.input", mock.Mock(return_value="y")):
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_conflict") as migration_dir:
- call_command("makemigrations", "migrations", name="merge", merge=True, interactive=True, stdout=out)
- merge_file = os.path.join(migration_dir, '0003_merge.py')
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_conflict"
+ ) as migration_dir:
+ call_command(
+ "makemigrations",
+ "migrations",
+ name="merge",
+ merge=True,
+ interactive=True,
+ stdout=out,
+ )
+ merge_file = os.path.join(migration_dir, "0003_merge.py")
self.assertTrue(os.path.exists(merge_file))
self.assertIn("Created new merge migration", out.getvalue())
def test_makemigrations_default_merge_name(self):
out = io.StringIO()
with self.temporary_migration_module(
- module='migrations.test_migrations_conflict'
+ module="migrations.test_migrations_conflict"
) as migration_dir:
- call_command('makemigrations', 'migrations', merge=True, interactive=False, stdout=out)
+ call_command(
+ "makemigrations",
+ "migrations",
+ merge=True,
+ interactive=False,
+ stdout=out,
+ )
merge_file = os.path.join(
migration_dir,
- '0003_merge_0002_conflicting_second_0002_second.py',
+ "0003_merge_0002_conflicting_second_0002_second.py",
)
self.assertIs(os.path.exists(merge_file), True)
- self.assertIn('Created new merge migration %s' % merge_file, out.getvalue())
+ self.assertIn("Created new merge migration %s" % merge_file, out.getvalue())
- @mock.patch('django.db.migrations.utils.datetime')
+ @mock.patch("django.db.migrations.utils.datetime")
def test_makemigrations_auto_merge_name(self, mock_datetime):
mock_datetime.datetime.now.return_value = datetime.datetime(2016, 1, 2, 3, 4)
- with mock.patch('builtins.input', mock.Mock(return_value='y')):
+ with mock.patch("builtins.input", mock.Mock(return_value="y")):
out = io.StringIO()
with self.temporary_migration_module(
- module='migrations.test_migrations_conflict_long_name'
+ module="migrations.test_migrations_conflict_long_name"
) as migration_dir:
- call_command("makemigrations", "migrations", merge=True, interactive=True, stdout=out)
- merge_file = os.path.join(migration_dir, '0003_merge_20160102_0304.py')
+ call_command(
+ "makemigrations",
+ "migrations",
+ merge=True,
+ interactive=True,
+ stdout=out,
+ )
+ merge_file = os.path.join(migration_dir, "0003_merge_20160102_0304.py")
self.assertTrue(os.path.exists(merge_file))
self.assertIn("Created new merge migration", out.getvalue())
@@ -1435,6 +1673,7 @@ class MakeMigrationsTests(MigrationTestBase):
Non-interactive makemigrations fails when a default is missing on a
new not-null field.
"""
+
class SillyModel(models.Model):
silly_field = models.BooleanField(default=False)
silly_int = models.IntegerField()
@@ -1443,9 +1682,11 @@ class MakeMigrationsTests(MigrationTestBase):
app_label = "migrations"
with self.assertRaises(SystemExit):
- with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_default"
+ ):
with captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=False)
+ call_command("makemigrations", "migrations", interactive=False)
self.assertIn(
"Field 'silly_int' on model 'sillymodel' not migrated: it is "
"impossible to add a non-nullable field without specifying a "
@@ -1458,11 +1699,12 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations messages when adding a NOT NULL field in interactive
mode.
"""
+
class Author(models.Model):
silly_field = models.BooleanField(null=False)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
input_msg = (
"It is impossible to add a non-nullable field 'silly_field' to "
@@ -1473,23 +1715,23 @@ class MakeMigrationsTests(MigrationTestBase):
"rows with a null value for this column)\n"
" 2) Quit and manually define a default value in models.py."
)
- with self.temporary_migration_module(module='migrations.test_migrations'):
+ with self.temporary_migration_module(module="migrations.test_migrations"):
# 2 - quit.
- with mock.patch('builtins.input', return_value='2'):
+ with mock.patch("builtins.input", return_value="2"):
with captured_stdout() as out, self.assertRaises(SystemExit):
- call_command('makemigrations', 'migrations', interactive=True)
+ call_command("makemigrations", "migrations", interactive=True)
self.assertIn(input_msg, out.getvalue())
# 1 - provide a default.
- with mock.patch('builtins.input', return_value='1'):
+ with mock.patch("builtins.input", return_value="1"):
with captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=True)
+ call_command("makemigrations", "migrations", interactive=True)
output = out.getvalue()
self.assertIn(input_msg, output)
- self.assertIn('Please enter the default value as valid Python.', output)
+ self.assertIn("Please enter the default value as valid Python.", output)
self.assertIn(
- 'The datetime and django.utils.timezone modules are '
- 'available, so it is possible to provide e.g. timezone.now as '
- 'a value',
+ "The datetime and django.utils.timezone modules are "
+ "available, so it is possible to provide e.g. timezone.now as "
+ "a value",
output,
)
self.assertIn("Type 'exit' to exit this prompt", output)
@@ -1499,6 +1741,7 @@ class MakeMigrationsTests(MigrationTestBase):
Non-interactive makemigrations fails when a default is missing on a
field changed to not-null.
"""
+
class Author(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
@@ -1509,7 +1752,7 @@ class MakeMigrationsTests(MigrationTestBase):
with self.temporary_migration_module(module="migrations.test_migrations"):
with captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=False)
+ call_command("makemigrations", "migrations", interactive=False)
self.assertIn("Alter field slug on author", out.getvalue())
self.assertIn(
"Field 'slug' on model 'author' given a default of NOT PROVIDED "
@@ -1522,11 +1765,12 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations messages when changing a NULL field to NOT NULL in
interactive mode.
"""
+
class Author(models.Model):
slug = models.SlugField(null=False)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
input_msg = (
"It is impossible to change a nullable field 'slug' on author to "
@@ -1540,29 +1784,32 @@ class MakeMigrationsTests(MigrationTestBase):
"RunSQL operation.\n"
" 3) Quit and manually define a default value in models.py."
)
- with self.temporary_migration_module(module='migrations.test_migrations'):
+ with self.temporary_migration_module(module="migrations.test_migrations"):
# No message appears if --dry-run.
with captured_stdout() as out:
call_command(
- 'makemigrations', 'migrations', interactive=True, dry_run=True,
+ "makemigrations",
+ "migrations",
+ interactive=True,
+ dry_run=True,
)
self.assertNotIn(input_msg, out.getvalue())
# 3 - quit.
- with mock.patch('builtins.input', return_value='3'):
+ with mock.patch("builtins.input", return_value="3"):
with captured_stdout() as out, self.assertRaises(SystemExit):
- call_command('makemigrations', 'migrations', interactive=True)
+ call_command("makemigrations", "migrations", interactive=True)
self.assertIn(input_msg, out.getvalue())
# 1 - provide a default.
- with mock.patch('builtins.input', return_value='1'):
+ with mock.patch("builtins.input", return_value="1"):
with captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=True)
+ call_command("makemigrations", "migrations", interactive=True)
output = out.getvalue()
self.assertIn(input_msg, output)
- self.assertIn('Please enter the default value as valid Python.', output)
+ self.assertIn("Please enter the default value as valid Python.", output)
self.assertIn(
- 'The datetime and django.utils.timezone modules are '
- 'available, so it is possible to provide e.g. timezone.now as '
- 'a value',
+ "The datetime and django.utils.timezone modules are "
+ "available, so it is possible to provide e.g. timezone.now as "
+ "a value",
output,
)
self.assertIn("Type 'exit' to exit this prompt", output)
@@ -1572,6 +1819,7 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations adds and removes a possible model rename in
non-interactive mode.
"""
+
class RenamedModel(models.Model):
silly_field = models.BooleanField(default=False)
@@ -1579,7 +1827,9 @@ class MakeMigrationsTests(MigrationTestBase):
app_label = "migrations"
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_default"
+ ):
call_command("makemigrations", "migrations", interactive=False, stdout=out)
self.assertIn("Delete model SillyModel", out.getvalue())
self.assertIn("Create model RenamedModel", out.getvalue())
@@ -1589,6 +1839,7 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations adds and removes a possible field rename in
non-interactive mode.
"""
+
class SillyModel(models.Model):
silly_rename = models.BooleanField(default=False)
@@ -1596,41 +1847,43 @@ class MakeMigrationsTests(MigrationTestBase):
app_label = "migrations"
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_default"
+ ):
call_command("makemigrations", "migrations", interactive=False, stdout=out)
self.assertIn("Remove field silly_field from sillymodel", out.getvalue())
self.assertIn("Add field silly_rename to sillymodel", out.getvalue())
- @mock.patch('builtins.input', return_value='Y')
+ @mock.patch("builtins.input", return_value="Y")
def test_makemigrations_model_rename_interactive(self, mock_input):
class RenamedModel(models.Model):
silly_field = models.BooleanField(default=False)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
with self.temporary_migration_module(
- module='migrations.test_migrations_no_default',
+ module="migrations.test_migrations_no_default",
):
with captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=True)
- self.assertIn('Rename model SillyModel to RenamedModel', out.getvalue())
+ call_command("makemigrations", "migrations", interactive=True)
+ self.assertIn("Rename model SillyModel to RenamedModel", out.getvalue())
- @mock.patch('builtins.input', return_value='Y')
+ @mock.patch("builtins.input", return_value="Y")
def test_makemigrations_field_rename_interactive(self, mock_input):
class SillyModel(models.Model):
silly_rename = models.BooleanField(default=False)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
with self.temporary_migration_module(
- module='migrations.test_migrations_no_default',
+ module="migrations.test_migrations_no_default",
):
with captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=True)
+ call_command("makemigrations", "migrations", interactive=True)
self.assertIn(
- 'Rename field silly_field on sillymodel to silly_rename',
+ "Rename field silly_field on sillymodel to silly_rename",
out.getvalue(),
)
@@ -1639,9 +1892,18 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations properly merges the conflicting migrations with --noinput.
"""
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_conflict") as migration_dir:
- call_command("makemigrations", "migrations", name="merge", merge=True, interactive=False, stdout=out)
- merge_file = os.path.join(migration_dir, '0003_merge.py')
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_conflict"
+ ) as migration_dir:
+ call_command(
+ "makemigrations",
+ "migrations",
+ name="merge",
+ merge=True,
+ interactive=False,
+ stdout=out,
+ )
+ merge_file = os.path.join(migration_dir, "0003_merge.py")
self.assertTrue(os.path.exists(merge_file))
output = out.getvalue()
self.assertIn("Merging migrations", output)
@@ -1655,12 +1917,19 @@ class MakeMigrationsTests(MigrationTestBase):
conflicts (#24427).
"""
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_conflict") as migration_dir:
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_conflict"
+ ) as migration_dir:
call_command(
- "makemigrations", "migrations", name="merge", dry_run=True,
- merge=True, interactive=False, stdout=out,
+ "makemigrations",
+ "migrations",
+ name="merge",
+ dry_run=True,
+ merge=True,
+ interactive=False,
+ stdout=out,
)
- merge_file = os.path.join(migration_dir, '0003_merge.py')
+ merge_file = os.path.join(migration_dir, "0003_merge.py")
self.assertFalse(os.path.exists(merge_file))
output = out.getvalue()
self.assertIn("Merging migrations", output)
@@ -1674,12 +1943,20 @@ class MakeMigrationsTests(MigrationTestBase):
stdout with `verbosity == 3` (#24427).
"""
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_conflict") as migration_dir:
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_conflict"
+ ) as migration_dir:
call_command(
- "makemigrations", "migrations", name="merge", dry_run=True,
- merge=True, interactive=False, stdout=out, verbosity=3,
+ "makemigrations",
+ "migrations",
+ name="merge",
+ dry_run=True,
+ merge=True,
+ interactive=False,
+ stdout=out,
+ verbosity=3,
)
- merge_file = os.path.join(migration_dir, '0003_merge.py')
+ merge_file = os.path.join(migration_dir, "0003_merge.py")
self.assertFalse(os.path.exists(merge_file))
output = out.getvalue()
self.assertIn("Merging migrations", output)
@@ -1700,6 +1977,7 @@ class MakeMigrationsTests(MigrationTestBase):
"""
`makemigrations --dry-run` should not ask for defaults.
"""
+
class SillyModel(models.Model):
silly_field = models.BooleanField(default=False)
silly_date = models.DateField() # Added field without a default
@@ -1709,7 +1987,9 @@ class MakeMigrationsTests(MigrationTestBase):
app_label = "migrations"
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_default"
+ ):
call_command("makemigrations", "migrations", dry_run=True, stdout=out)
# Output the expected changes directly, without asking for defaults
self.assertIn("Add field silly_date to sillymodel", out.getvalue())
@@ -1719,6 +1999,7 @@ class MakeMigrationsTests(MigrationTestBase):
Allow `makemigrations --dry-run` to output the migrations file to
stdout (with verbosity == 3).
"""
+
class SillyModel(models.Model):
silly_field = models.BooleanField(default=False)
silly_char = models.CharField(default="")
@@ -1727,8 +2008,12 @@ class MakeMigrationsTests(MigrationTestBase):
app_label = "migrations"
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
- call_command("makemigrations", "migrations", dry_run=True, stdout=out, verbosity=3)
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_default"
+ ):
+ call_command(
+ "makemigrations", "migrations", dry_run=True, stdout=out, verbosity=3
+ )
# Normal --dry-run output
self.assertIn("- Add field silly_char to sillymodel", out.getvalue())
@@ -1750,38 +2035,38 @@ class MakeMigrationsTests(MigrationTestBase):
out = io.StringIO()
err = io.StringIO()
with self.temporary_migration_module(
- module='migrations.migrations.test_migrations',
+ module="migrations.migrations.test_migrations",
) as migration_dir:
call_command(
- 'makemigrations',
- 'migrations',
+ "makemigrations",
+ "migrations",
scriptable=True,
stdout=out,
stderr=err,
)
- initial_file = os.path.join(migration_dir, '0001_initial.py')
- self.assertEqual(out.getvalue(), f'{initial_file}\n')
- self.assertIn(' - Create model ModelWithCustomBase\n', err.getvalue())
+ initial_file = os.path.join(migration_dir, "0001_initial.py")
+ self.assertEqual(out.getvalue(), f"{initial_file}\n")
+ self.assertIn(" - Create model ModelWithCustomBase\n", err.getvalue())
- @mock.patch('builtins.input', return_value='Y')
+ @mock.patch("builtins.input", return_value="Y")
def test_makemigrations_scriptable_merge(self, mock_input):
out = io.StringIO()
err = io.StringIO()
with self.temporary_migration_module(
- module='migrations.test_migrations_conflict',
+ module="migrations.test_migrations_conflict",
) as migration_dir:
call_command(
- 'makemigrations',
- 'migrations',
+ "makemigrations",
+ "migrations",
merge=True,
- name='merge',
+ name="merge",
scriptable=True,
stdout=out,
stderr=err,
)
- merge_file = os.path.join(migration_dir, '0003_merge.py')
- self.assertEqual(out.getvalue(), f'{merge_file}\n')
- self.assertIn(f'Created new merge migration {merge_file}', err.getvalue())
+ merge_file = os.path.join(migration_dir, "0003_merge.py")
+ self.assertEqual(out.getvalue(), f"{merge_file}\n")
+ self.assertIn(f"Created new merge migration {merge_file}", err.getvalue())
def test_makemigrations_migrations_modules_path_not_exist(self):
"""
@@ -1789,6 +2074,7 @@ class MakeMigrationsTests(MigrationTestBase):
for migration files using MIGRATION_MODULES if the custom path
doesn't already exist.
"""
+
class SillyModel(models.Model):
silly_field = models.BooleanField(default=False)
@@ -1807,15 +2093,15 @@ class MakeMigrationsTests(MigrationTestBase):
# Command output indicates the migration is created.
self.assertIn(" - Create model SillyModel", out.getvalue())
- @override_settings(MIGRATION_MODULES={'migrations': 'some.nonexistent.path'})
+ @override_settings(MIGRATION_MODULES={"migrations": "some.nonexistent.path"})
def test_makemigrations_migrations_modules_nonexistent_toplevel_package(self):
msg = (
- 'Could not locate an appropriate location to create migrations '
- 'package some.nonexistent.path. Make sure the toplevel package '
- 'exists and can be imported.'
+ "Could not locate an appropriate location to create migrations "
+ "package some.nonexistent.path. Make sure the toplevel package "
+ "exists and can be imported."
)
with self.assertRaisesMessage(ValueError, msg):
- call_command('makemigrations', 'migrations', empty=True, verbosity=0)
+ call_command("makemigrations", "migrations", empty=True, verbosity=0)
def test_makemigrations_interactive_by_default(self):
"""
@@ -1825,10 +2111,14 @@ class MakeMigrationsTests(MigrationTestBase):
"""
# Monkeypatch interactive questioner to auto reject
out = io.StringIO()
- with mock.patch('builtins.input', mock.Mock(return_value='N')):
- with self.temporary_migration_module(module="migrations.test_migrations_conflict") as migration_dir:
- call_command("makemigrations", "migrations", name="merge", merge=True, stdout=out)
- merge_file = os.path.join(migration_dir, '0003_merge.py')
+ with mock.patch("builtins.input", mock.Mock(return_value="N")):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_conflict"
+ ) as migration_dir:
+ call_command(
+ "makemigrations", "migrations", name="merge", merge=True, stdout=out
+ )
+ merge_file = os.path.join(migration_dir, "0003_merge.py")
# This will fail if interactive is False by default
self.assertFalse(os.path.exists(merge_file))
self.assertNotIn("Created new merge migration", out.getvalue())
@@ -1836,64 +2126,86 @@ class MakeMigrationsTests(MigrationTestBase):
@override_settings(
INSTALLED_APPS=[
"migrations",
- "migrations.migrations_test_apps.unspecified_app_with_conflict"])
+ "migrations.migrations_test_apps.unspecified_app_with_conflict",
+ ]
+ )
def test_makemigrations_unspecified_app_with_conflict_no_merge(self):
"""
makemigrations does not raise a CommandError when an unspecified app
has conflicting migrations.
"""
- with self.temporary_migration_module(module="migrations.test_migrations_no_changes"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_changes"
+ ):
call_command("makemigrations", "migrations", merge=False, verbosity=0)
@override_settings(
INSTALLED_APPS=[
"migrations.migrations_test_apps.migrated_app",
- "migrations.migrations_test_apps.unspecified_app_with_conflict"])
+ "migrations.migrations_test_apps.unspecified_app_with_conflict",
+ ]
+ )
def test_makemigrations_unspecified_app_with_conflict_merge(self):
"""
makemigrations does not create a merge for an unspecified app even if
it has conflicting migrations.
"""
# Monkeypatch interactive questioner to auto accept
- with mock.patch('builtins.input', mock.Mock(return_value='y')):
+ with mock.patch("builtins.input", mock.Mock(return_value="y")):
out = io.StringIO()
- with self.temporary_migration_module(app_label="migrated_app") as migration_dir:
- call_command("makemigrations", "migrated_app", name="merge", merge=True, interactive=True, stdout=out)
- merge_file = os.path.join(migration_dir, '0003_merge.py')
+ with self.temporary_migration_module(
+ app_label="migrated_app"
+ ) as migration_dir:
+ call_command(
+ "makemigrations",
+ "migrated_app",
+ name="merge",
+ merge=True,
+ interactive=True,
+ stdout=out,
+ )
+ merge_file = os.path.join(migration_dir, "0003_merge.py")
self.assertFalse(os.path.exists(merge_file))
self.assertIn("No conflicts detected to merge.", out.getvalue())
@override_settings(
INSTALLED_APPS=[
"migrations.migrations_test_apps.migrated_app",
- "migrations.migrations_test_apps.conflicting_app_with_dependencies"])
+ "migrations.migrations_test_apps.conflicting_app_with_dependencies",
+ ]
+ )
def test_makemigrations_merge_dont_output_dependency_operations(self):
"""
makemigrations --merge does not output any operations from apps that
don't belong to a given app.
"""
# Monkeypatch interactive questioner to auto accept
- with mock.patch('builtins.input', mock.Mock(return_value='N')):
+ with mock.patch("builtins.input", mock.Mock(return_value="N")):
out = io.StringIO()
- with mock.patch('django.core.management.color.supports_color', lambda *args: False):
+ with mock.patch(
+ "django.core.management.color.supports_color", lambda *args: False
+ ):
call_command(
- "makemigrations", "conflicting_app_with_dependencies",
- merge=True, interactive=True, stdout=out
+ "makemigrations",
+ "conflicting_app_with_dependencies",
+ merge=True,
+ interactive=True,
+ stdout=out,
)
self.assertEqual(
out.getvalue().lower(),
- 'merging conflicting_app_with_dependencies\n'
- ' branch 0002_conflicting_second\n'
- ' - create model something\n'
- ' branch 0002_second\n'
- ' - delete model tribble\n'
- ' - remove field silly_field from author\n'
- ' - add field rating to author\n'
- ' - create model book\n'
- '\n'
- 'merging will only work if the operations printed above do not conflict\n'
- 'with each other (working on different fields or models)\n'
- 'should these migration branches be merged? [y/n] '
+ "merging conflicting_app_with_dependencies\n"
+ " branch 0002_conflicting_second\n"
+ " - create model something\n"
+ " branch 0002_second\n"
+ " - delete model tribble\n"
+ " - remove field silly_field from author\n"
+ " - add field rating to author\n"
+ " - create model book\n"
+ "\n"
+ "merging will only work if the operations printed above do not conflict\n"
+ "with each other (working on different fields or models)\n"
+ "should these migration branches be merged? [y/n] ",
)
def test_makemigrations_with_custom_name(self):
@@ -1903,11 +2215,21 @@ class MakeMigrationsTests(MigrationTestBase):
with self.temporary_migration_module() as migration_dir:
def cmd(migration_count, migration_name, *args):
- call_command("makemigrations", "migrations", "--verbosity", "0", "--name", migration_name, *args)
- migration_file = os.path.join(migration_dir, "%s_%s.py" % (migration_count, migration_name))
+ call_command(
+ "makemigrations",
+ "migrations",
+ "--verbosity",
+ "0",
+ "--name",
+ migration_name,
+ *args,
+ )
+ migration_file = os.path.join(
+ migration_dir, "%s_%s.py" % (migration_count, migration_name)
+ )
# Check for existing migration file in migration folder
self.assertTrue(os.path.exists(migration_file))
- with open(migration_file, encoding='utf-8') as fp:
+ with open(migration_file, encoding="utf-8") as fp:
content = fp.read()
content = content.replace(" ", "")
return content
@@ -1919,19 +2241,24 @@ class MakeMigrationsTests(MigrationTestBase):
# importlib caches os.listdir() on some platforms like macOS
# (#23850).
- if hasattr(importlib, 'invalidate_caches'):
+ if hasattr(importlib, "invalidate_caches"):
importlib.invalidate_caches()
# generate an empty migration
migration_name_0002 = "my_custom_migration"
content = cmd("0002", migration_name_0002, "--empty")
- self.assertIn("dependencies=[\n('migrations','0001_%s'),\n]" % migration_name_0001, content)
+ self.assertIn(
+ "dependencies=[\n('migrations','0001_%s'),\n]" % migration_name_0001,
+ content,
+ )
self.assertIn("operations=[\n]", content)
def test_makemigrations_with_invalid_custom_name(self):
- msg = 'The migration name must be a valid Python identifier.'
+ msg = "The migration name must be a valid Python identifier."
with self.assertRaisesMessage(CommandError, msg):
- call_command('makemigrations', 'migrations', '--name', 'invalid name', '--empty')
+ call_command(
+ "makemigrations", "migrations", "--name", "invalid name", "--empty"
+ )
def test_makemigrations_check(self):
"""
@@ -1942,7 +2269,9 @@ class MakeMigrationsTests(MigrationTestBase):
with self.assertRaises(SystemExit):
call_command("makemigrations", "--check", "migrations", verbosity=0)
- with self.temporary_migration_module(module="migrations.test_migrations_no_changes"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_changes"
+ ):
call_command("makemigrations", "--check", "migrations", verbosity=0)
def test_makemigrations_migration_path_output(self):
@@ -1952,10 +2281,12 @@ class MakeMigrationsTests(MigrationTestBase):
should be shown.
"""
out = io.StringIO()
- apps.register_model('migrations', UnicodeModel)
+ apps.register_model("migrations", UnicodeModel)
with self.temporary_migration_module() as migration_dir:
call_command("makemigrations", "migrations", stdout=out)
- self.assertIn(os.path.join(migration_dir, '0001_initial.py'), out.getvalue())
+ self.assertIn(
+ os.path.join(migration_dir, "0001_initial.py"), out.getvalue()
+ )
def test_makemigrations_migration_path_output_valueerror(self):
"""
@@ -1966,9 +2297,9 @@ class MakeMigrationsTests(MigrationTestBase):
"""
out = io.StringIO()
with self.temporary_migration_module() as migration_dir:
- with mock.patch('os.path.relpath', side_effect=ValueError):
- call_command('makemigrations', 'migrations', stdout=out)
- self.assertIn(os.path.join(migration_dir, '0001_initial.py'), out.getvalue())
+ with mock.patch("os.path.relpath", side_effect=ValueError):
+ call_command("makemigrations", "migrations", stdout=out)
+ self.assertIn(os.path.join(migration_dir, "0001_initial.py"), out.getvalue())
def test_makemigrations_inconsistent_history(self):
"""
@@ -1976,7 +2307,7 @@ class MakeMigrationsTests(MigrationTestBase):
there are some migrations applied before their dependencies.
"""
recorder = MigrationRecorder(connection)
- recorder.record_applied('migrations', '0002_second')
+ recorder.record_applied("migrations", "0002_second")
msg = "Migration migrations.0002_second is applied before its dependency migrations.0001_initial"
with self.temporary_migration_module(module="migrations.test_migrations"):
with self.assertRaisesMessage(InconsistentMigrationHistory, msg):
@@ -1988,27 +2319,31 @@ class MakeMigrationsTests(MigrationTestBase):
"for database connection 'default': could not connect to server"
)
with mock.patch(
- 'django.db.migrations.loader.MigrationLoader.check_consistent_history',
- side_effect=OperationalError('could not connect to server'),
+ "django.db.migrations.loader.MigrationLoader.check_consistent_history",
+ side_effect=OperationalError("could not connect to server"),
):
with self.temporary_migration_module():
with self.assertWarns(RuntimeWarning) as cm:
- call_command('makemigrations', verbosity=0)
+ call_command("makemigrations", verbosity=0)
self.assertEqual(str(cm.warning), msg)
- @mock.patch('builtins.input', return_value='1')
- @mock.patch('django.db.migrations.questioner.sys.stdin', mock.MagicMock(encoding=sys.getdefaultencoding()))
+ @mock.patch("builtins.input", return_value="1")
+ @mock.patch(
+ "django.db.migrations.questioner.sys.stdin",
+ mock.MagicMock(encoding=sys.getdefaultencoding()),
+ )
def test_makemigrations_auto_now_add_interactive(self, *args):
"""
makemigrations prompts the user when adding auto_now_add to an existing
model.
"""
+
class Entry(models.Model):
title = models.CharField(max_length=255)
creation_date = models.DateTimeField(auto_now_add=True)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
input_msg = (
"It is impossible to add the field 'creation_date' with "
@@ -2021,11 +2356,13 @@ class MakeMigrationsTests(MigrationTestBase):
)
# Monkeypatch interactive questioner to auto accept
prompt_stdout = io.StringIO()
- with self.temporary_migration_module(module='migrations.test_auto_now_add'):
- call_command('makemigrations', 'migrations', interactive=True, stdout=prompt_stdout)
+ with self.temporary_migration_module(module="migrations.test_auto_now_add"):
+ call_command(
+ "makemigrations", "migrations", interactive=True, stdout=prompt_stdout
+ )
prompt_output = prompt_stdout.getvalue()
self.assertIn(input_msg, prompt_output)
- self.assertIn('Please enter the default value as valid Python.', prompt_output)
+ self.assertIn("Please enter the default value as valid Python.", prompt_output)
self.assertIn(
"Accept the default 'timezone.now' by pressing 'Enter' or provide "
"another value.",
@@ -2034,33 +2371,34 @@ class MakeMigrationsTests(MigrationTestBase):
self.assertIn("Type 'exit' to exit this prompt", prompt_output)
self.assertIn("Add field creation_date to entry", prompt_output)
- @mock.patch('builtins.input', return_value='2')
+ @mock.patch("builtins.input", return_value="2")
def test_makemigrations_auto_now_add_interactive_quit(self, mock_input):
class Author(models.Model):
publishing_date = models.DateField(auto_now_add=True)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
- with self.temporary_migration_module(module='migrations.test_migrations'):
+ with self.temporary_migration_module(module="migrations.test_migrations"):
with captured_stdout():
with self.assertRaises(SystemExit):
- call_command('makemigrations', 'migrations', interactive=True)
+ call_command("makemigrations", "migrations", interactive=True)
def test_makemigrations_non_interactive_auto_now_add_addition(self):
"""
Non-interactive makemigrations fails when a default is missing on a
new field when auto_now_add=True.
"""
+
class Entry(models.Model):
creation_date = models.DateTimeField(auto_now_add=True)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
- with self.temporary_migration_module(module='migrations.test_auto_now_add'):
+ with self.temporary_migration_module(module="migrations.test_auto_now_add"):
with self.assertRaises(SystemExit), captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=False)
+ call_command("makemigrations", "migrations", interactive=False)
self.assertIn(
"Field 'creation_date' on model 'entry' not migrated: it is "
"impossible to add a field with 'auto_now_add=True' without "
@@ -2073,66 +2411,69 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations prompts the user when adding a unique field with
a callable default.
"""
+
class Book(models.Model):
created = models.DateTimeField(unique=True, default=timezone.now)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
version = get_docs_version()
input_msg = (
- f'Callable default on unique field book.created will not generate '
- f'unique values upon migrating.\n'
- f'Please choose how to proceed:\n'
- f' 1) Continue making this migration as the first step in writing '
- f'a manual migration to generate unique values described here: '
- f'https://docs.djangoproject.com/en/{version}/howto/'
- f'writing-migrations/#migrations-that-add-unique-fields.\n'
- f' 2) Quit and edit field options in models.py.\n'
+ f"Callable default on unique field book.created will not generate "
+ f"unique values upon migrating.\n"
+ f"Please choose how to proceed:\n"
+ f" 1) Continue making this migration as the first step in writing "
+ f"a manual migration to generate unique values described here: "
+ f"https://docs.djangoproject.com/en/{version}/howto/"
+ f"writing-migrations/#migrations-that-add-unique-fields.\n"
+ f" 2) Quit and edit field options in models.py.\n"
)
- with self.temporary_migration_module(module='migrations.test_migrations'):
+ with self.temporary_migration_module(module="migrations.test_migrations"):
# 2 - quit.
- with mock.patch('builtins.input', return_value='2'):
+ with mock.patch("builtins.input", return_value="2"):
with captured_stdout() as out, self.assertRaises(SystemExit):
- call_command('makemigrations', 'migrations', interactive=True)
+ call_command("makemigrations", "migrations", interactive=True)
out_value = out.getvalue()
self.assertIn(input_msg, out_value)
- self.assertNotIn('Add field created to book', out_value)
+ self.assertNotIn("Add field created to book", out_value)
# 1 - continue.
- with mock.patch('builtins.input', return_value='1'):
+ with mock.patch("builtins.input", return_value="1"):
with captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=True)
+ call_command("makemigrations", "migrations", interactive=True)
out_value = out.getvalue()
self.assertIn(input_msg, out_value)
- self.assertIn('Add field created to book', out_value)
+ self.assertIn("Add field created to book", out_value)
def test_makemigrations_non_interactive_unique_callable_default_addition(self):
class Book(models.Model):
created = models.DateTimeField(unique=True, default=timezone.now)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
- with self.temporary_migration_module(module='migrations.test_migrations'):
+ with self.temporary_migration_module(module="migrations.test_migrations"):
with captured_stdout() as out:
- call_command('makemigrations', 'migrations', interactive=False)
+ call_command("makemigrations", "migrations", interactive=False)
out_value = out.getvalue()
- self.assertIn('Add field created to book', out_value)
+ self.assertIn("Add field created to book", out_value)
@override_settings(
- MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'},
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"},
)
def test_makemigrations_continues_number_sequence_after_squash(self):
- with self.temporary_migration_module(module='migrations.test_migrations_squashed'):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_squashed"
+ ):
with captured_stdout() as out:
call_command(
- 'makemigrations',
- 'migrations',
+ "makemigrations",
+ "migrations",
interactive=False,
empty=True,
)
out_value = out.getvalue()
- self.assertIn('0003_auto', out_value)
+ self.assertIn("0003_auto", out_value)
class SquashMigrationsTests(MigrationTestBase):
@@ -2145,31 +2486,48 @@ class SquashMigrationsTests(MigrationTestBase):
squashmigrations squashes migrations.
"""
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations") as migration_dir:
- call_command('squashmigrations', 'migrations', '0002', interactive=False, stdout=out, no_color=True)
+ with self.temporary_migration_module(
+ module="migrations.test_migrations"
+ ) as migration_dir:
+ call_command(
+ "squashmigrations",
+ "migrations",
+ "0002",
+ interactive=False,
+ stdout=out,
+ no_color=True,
+ )
- squashed_migration_file = os.path.join(migration_dir, "0001_squashed_0002_second.py")
+ squashed_migration_file = os.path.join(
+ migration_dir, "0001_squashed_0002_second.py"
+ )
self.assertTrue(os.path.exists(squashed_migration_file))
self.assertEqual(
out.getvalue(),
- 'Will squash the following migrations:\n'
- ' - 0001_initial\n'
- ' - 0002_second\n'
- 'Optimizing...\n'
- ' Optimized from 8 operations to 2 operations.\n'
- 'Created new squashed migration %s\n'
- ' You should commit this migration but leave the old ones in place;\n'
- ' the new migration will be used for new installs. Once you are sure\n'
- ' all instances of the codebase have applied the migrations you squashed,\n'
- ' you can delete them.\n' % squashed_migration_file
+ "Will squash the following migrations:\n"
+ " - 0001_initial\n"
+ " - 0002_second\n"
+ "Optimizing...\n"
+ " Optimized from 8 operations to 2 operations.\n"
+ "Created new squashed migration %s\n"
+ " You should commit this migration but leave the old ones in place;\n"
+ " the new migration will be used for new installs. Once you are sure\n"
+ " all instances of the codebase have applied the migrations you squashed,\n"
+ " you can delete them.\n" % squashed_migration_file,
)
def test_squashmigrations_initial_attribute(self):
- with self.temporary_migration_module(module="migrations.test_migrations") as migration_dir:
- call_command("squashmigrations", "migrations", "0002", interactive=False, verbosity=0)
+ with self.temporary_migration_module(
+ module="migrations.test_migrations"
+ ) as migration_dir:
+ call_command(
+ "squashmigrations", "migrations", "0002", interactive=False, verbosity=0
+ )
- squashed_migration_file = os.path.join(migration_dir, "0001_squashed_0002_second.py")
- with open(squashed_migration_file, encoding='utf-8') as fp:
+ squashed_migration_file = os.path.join(
+ migration_dir, "0001_squashed_0002_second.py"
+ )
+ with open(squashed_migration_file, encoding="utf-8") as fp:
content = fp.read()
self.assertIn("initial = True", content)
@@ -2179,7 +2537,14 @@ class SquashMigrationsTests(MigrationTestBase):
"""
out = io.StringIO()
with self.temporary_migration_module(module="migrations.test_migrations"):
- call_command("squashmigrations", "migrations", "0002", interactive=False, verbosity=1, stdout=out)
+ call_command(
+ "squashmigrations",
+ "migrations",
+ "0002",
+ interactive=False,
+ verbosity=1,
+ stdout=out,
+ )
self.assertIn("Optimized from 8 operations to 2 operations.", out.getvalue())
def test_ticket_23799_squashmigrations_no_optimize(self):
@@ -2188,8 +2553,15 @@ class SquashMigrationsTests(MigrationTestBase):
"""
out = io.StringIO()
with self.temporary_migration_module(module="migrations.test_migrations"):
- call_command("squashmigrations", "migrations", "0002",
- interactive=False, verbosity=1, no_optimize=True, stdout=out)
+ call_command(
+ "squashmigrations",
+ "migrations",
+ "0002",
+ interactive=False,
+ verbosity=1,
+ no_optimize=True,
+ stdout=out,
+ )
self.assertIn("Skipping optimization", out.getvalue())
def test_squashmigrations_valid_start(self):
@@ -2197,12 +2569,23 @@ class SquashMigrationsTests(MigrationTestBase):
squashmigrations accepts a starting migration.
"""
out = io.StringIO()
- with self.temporary_migration_module(module="migrations.test_migrations_no_changes") as migration_dir:
- call_command("squashmigrations", "migrations", "0002", "0003",
- interactive=False, verbosity=1, stdout=out)
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_changes"
+ ) as migration_dir:
+ call_command(
+ "squashmigrations",
+ "migrations",
+ "0002",
+ "0003",
+ interactive=False,
+ verbosity=1,
+ stdout=out,
+ )
- squashed_migration_file = os.path.join(migration_dir, "0002_second_squashed_0003_third.py")
- with open(squashed_migration_file, encoding='utf-8') as fp:
+ squashed_migration_file = os.path.join(
+ migration_dir, "0002_second_squashed_0003_third.py"
+ )
+ with open(squashed_migration_file, encoding="utf-8") as fp:
content = fp.read()
self.assertIn(" ('migrations', '0001_initial')", content)
self.assertNotIn("initial = True", content)
@@ -2215,79 +2598,110 @@ class SquashMigrationsTests(MigrationTestBase):
"""
squashmigrations doesn't accept a starting migration after the ending migration.
"""
- with self.temporary_migration_module(module="migrations.test_migrations_no_changes"):
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_no_changes"
+ ):
msg = (
"The migration 'migrations.0003_third' cannot be found. Maybe "
"it comes after the migration 'migrations.0002_second'"
)
with self.assertRaisesMessage(CommandError, msg):
- call_command("squashmigrations", "migrations", "0003", "0002", interactive=False, verbosity=0)
+ call_command(
+ "squashmigrations",
+ "migrations",
+ "0003",
+ "0002",
+ interactive=False,
+ verbosity=0,
+ )
def test_squashed_name_with_start_migration_name(self):
"""--squashed-name specifies the new migration's name."""
- squashed_name = 'squashed_name'
- with self.temporary_migration_module(module='migrations.test_migrations') as migration_dir:
+ squashed_name = "squashed_name"
+ with self.temporary_migration_module(
+ module="migrations.test_migrations"
+ ) as migration_dir:
call_command(
- 'squashmigrations', 'migrations', '0001', '0002',
- squashed_name=squashed_name, interactive=False, verbosity=0,
+ "squashmigrations",
+ "migrations",
+ "0001",
+ "0002",
+ squashed_name=squashed_name,
+ interactive=False,
+ verbosity=0,
+ )
+ squashed_migration_file = os.path.join(
+ migration_dir, "0001_%s.py" % squashed_name
)
- squashed_migration_file = os.path.join(migration_dir, '0001_%s.py' % squashed_name)
self.assertTrue(os.path.exists(squashed_migration_file))
def test_squashed_name_without_start_migration_name(self):
"""--squashed-name also works if a start migration is omitted."""
- squashed_name = 'squashed_name'
- with self.temporary_migration_module(module="migrations.test_migrations") as migration_dir:
+ squashed_name = "squashed_name"
+ with self.temporary_migration_module(
+ module="migrations.test_migrations"
+ ) as migration_dir:
call_command(
- 'squashmigrations', 'migrations', '0001',
- squashed_name=squashed_name, interactive=False, verbosity=0,
+ "squashmigrations",
+ "migrations",
+ "0001",
+ squashed_name=squashed_name,
+ interactive=False,
+ verbosity=0,
+ )
+ squashed_migration_file = os.path.join(
+ migration_dir, "0001_%s.py" % squashed_name
)
- squashed_migration_file = os.path.join(migration_dir, '0001_%s.py' % squashed_name)
self.assertTrue(os.path.exists(squashed_migration_file))
def test_squashed_name_exists(self):
- msg = 'Migration 0001_initial already exists. Use a different name.'
- with self.temporary_migration_module(module='migrations.test_migrations'):
+ msg = "Migration 0001_initial already exists. Use a different name."
+ with self.temporary_migration_module(module="migrations.test_migrations"):
with self.assertRaisesMessage(CommandError, msg):
call_command(
- 'squashmigrations', 'migrations', '0001', '0002',
- squashed_name='initial', interactive=False, verbosity=0,
+ "squashmigrations",
+ "migrations",
+ "0001",
+ "0002",
+ squashed_name="initial",
+ interactive=False,
+ verbosity=0,
)
def test_squashmigrations_manual_porting(self):
out = io.StringIO()
with self.temporary_migration_module(
- module='migrations.test_migrations_manual_porting',
+ module="migrations.test_migrations_manual_porting",
) as migration_dir:
call_command(
- 'squashmigrations',
- 'migrations',
- '0002',
+ "squashmigrations",
+ "migrations",
+ "0002",
interactive=False,
stdout=out,
no_color=True,
)
squashed_migration_file = os.path.join(
migration_dir,
- '0001_squashed_0002_second.py',
+ "0001_squashed_0002_second.py",
)
self.assertTrue(os.path.exists(squashed_migration_file))
self.assertEqual(
out.getvalue(),
- f'Will squash the following migrations:\n'
- f' - 0001_initial\n'
- f' - 0002_second\n'
- f'Optimizing...\n'
- f' No optimizations possible.\n'
- f'Created new squashed migration {squashed_migration_file}\n'
- f' You should commit this migration but leave the old ones in place;\n'
- f' the new migration will be used for new installs. Once you are sure\n'
- f' all instances of the codebase have applied the migrations you squashed,\n'
- f' you can delete them.\n'
- f'Manual porting required\n'
- f' Your migrations contained functions that must be manually copied over,\n'
- f' as we could not safely copy their implementation.\n'
- f' See the comment at the top of the squashed migration for details.\n'
+ f"Will squash the following migrations:\n"
+ f" - 0001_initial\n"
+ f" - 0002_second\n"
+ f"Optimizing...\n"
+ f" No optimizations possible.\n"
+ f"Created new squashed migration {squashed_migration_file}\n"
+ f" You should commit this migration but leave the old ones in place;\n"
+ f" the new migration will be used for new installs. Once you are sure\n"
+ f" all instances of the codebase have applied the migrations you squashed,\n"
+ f" you can delete them.\n"
+ f"Manual porting required\n"
+ f" Your migrations contained functions that must be manually copied over,\n"
+ f" as we could not safely copy their implementation.\n"
+ f" See the comment at the top of the squashed migration for details.\n",
)
@@ -2298,6 +2712,7 @@ class AppLabelErrorTests(TestCase):
app. 'django.contrib.auth' must be in INSTALLED_APPS for some of these
tests.
"""
+
nonexistent_app_error = "No installed app with label 'nonexistent_app'."
did_you_mean_auth_error = (
"No installed app with label 'django.contrib.auth'. Did you mean 'auth'?"
@@ -2306,47 +2721,47 @@ class AppLabelErrorTests(TestCase):
def test_makemigrations_nonexistent_app_label(self):
err = io.StringIO()
with self.assertRaises(SystemExit):
- call_command('makemigrations', 'nonexistent_app', stderr=err)
+ call_command("makemigrations", "nonexistent_app", stderr=err)
self.assertIn(self.nonexistent_app_error, err.getvalue())
def test_makemigrations_app_name_specified_as_label(self):
err = io.StringIO()
with self.assertRaises(SystemExit):
- call_command('makemigrations', 'django.contrib.auth', stderr=err)
+ call_command("makemigrations", "django.contrib.auth", stderr=err)
self.assertIn(self.did_you_mean_auth_error, err.getvalue())
def test_migrate_nonexistent_app_label(self):
with self.assertRaisesMessage(CommandError, self.nonexistent_app_error):
- call_command('migrate', 'nonexistent_app')
+ call_command("migrate", "nonexistent_app")
def test_migrate_app_name_specified_as_label(self):
with self.assertRaisesMessage(CommandError, self.did_you_mean_auth_error):
- call_command('migrate', 'django.contrib.auth')
+ call_command("migrate", "django.contrib.auth")
def test_showmigrations_nonexistent_app_label(self):
err = io.StringIO()
with self.assertRaises(SystemExit):
- call_command('showmigrations', 'nonexistent_app', stderr=err)
+ call_command("showmigrations", "nonexistent_app", stderr=err)
self.assertIn(self.nonexistent_app_error, err.getvalue())
def test_showmigrations_app_name_specified_as_label(self):
err = io.StringIO()
with self.assertRaises(SystemExit):
- call_command('showmigrations', 'django.contrib.auth', stderr=err)
+ call_command("showmigrations", "django.contrib.auth", stderr=err)
self.assertIn(self.did_you_mean_auth_error, err.getvalue())
def test_sqlmigrate_nonexistent_app_label(self):
with self.assertRaisesMessage(CommandError, self.nonexistent_app_error):
- call_command('sqlmigrate', 'nonexistent_app', '0002')
+ call_command("sqlmigrate", "nonexistent_app", "0002")
def test_sqlmigrate_app_name_specified_as_label(self):
with self.assertRaisesMessage(CommandError, self.did_you_mean_auth_error):
- call_command('sqlmigrate', 'django.contrib.auth', '0002')
+ call_command("sqlmigrate", "django.contrib.auth", "0002")
def test_squashmigrations_nonexistent_app_label(self):
with self.assertRaisesMessage(CommandError, self.nonexistent_app_error):
- call_command('squashmigrations', 'nonexistent_app', '0002')
+ call_command("squashmigrations", "nonexistent_app", "0002")
def test_squashmigrations_app_name_specified_as_label(self):
with self.assertRaisesMessage(CommandError, self.did_you_mean_auth_error):
- call_command('squashmigrations', 'django.contrib.auth', '0002')
+ call_command("squashmigrations", "django.contrib.auth", "0002")
diff --git a/tests/migrations/test_deprecated_fields.py b/tests/migrations/test_deprecated_fields.py
index 2e9808e20b..63975514f6 100644
--- a/tests/migrations/test_deprecated_fields.py
+++ b/tests/migrations/test_deprecated_fields.py
@@ -8,7 +8,10 @@ class Tests(MigrationTestBase):
"""
Deprecated model fields should still be usable in historic migrations.
"""
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.deprecated_field_migrations"})
+
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.deprecated_field_migrations"}
+ )
def test_migrate(self):
# Make sure no tables are created
self.assertTableNotExists("migrations_ipaddressfield")
diff --git a/tests/migrations/test_exceptions.py b/tests/migrations/test_exceptions.py
index 3d839471f9..64d2109d5a 100644
--- a/tests/migrations/test_exceptions.py
+++ b/tests/migrations/test_exceptions.py
@@ -4,9 +4,8 @@ from django.test import SimpleTestCase
class ExceptionTests(SimpleTestCase):
def test_node_not_found_error_repr(self):
- node = ('some_app_label', 'some_migration_label')
- error_repr = repr(NodeNotFoundError('some message', node))
+ node = ("some_app_label", "some_migration_label")
+ error_repr = repr(NodeNotFoundError("some message", node))
self.assertEqual(
- error_repr,
- "NodeNotFoundError(('some_app_label', 'some_migration_label'))"
+ error_repr, "NodeNotFoundError(('some_app_label', 'some_migration_label'))"
)
diff --git a/tests/migrations/test_executor.py b/tests/migrations/test_executor.py
index cab6ac6cb5..6232b44b98 100644
--- a/tests/migrations/test_executor.py
+++ b/tests/migrations/test_executor.py
@@ -8,14 +8,17 @@ from django.db.migrations.graph import MigrationGraph
from django.db.migrations.recorder import MigrationRecorder
from django.db.migrations.state import ProjectState
from django.test import (
- SimpleTestCase, modify_settings, override_settings, skipUnlessDBFeature,
+ SimpleTestCase,
+ modify_settings,
+ override_settings,
+ skipUnlessDBFeature,
)
from django.test.utils import isolate_lru_cache
from .test_base import MigrationTestBase
-@modify_settings(INSTALLED_APPS={'append': 'migrations2'})
+@modify_settings(INSTALLED_APPS={"append": "migrations2"})
class ExecutorTests(MigrationTestBase):
"""
Tests the migration executor (full end-to-end running).
@@ -24,7 +27,12 @@ class ExecutorTests(MigrationTestBase):
test failures first, as they may be propagating into here.
"""
- available_apps = ["migrations", "migrations2", "django.contrib.auth", "django.contrib.contenttypes"]
+ available_apps = [
+ "migrations",
+ "migrations2",
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ ]
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_run(self):
@@ -65,21 +73,28 @@ class ExecutorTests(MigrationTestBase):
self.assertTableNotExists("migrations_author")
self.assertTableNotExists("migrations_book")
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_run_with_squashed(self):
"""
Tests running a squashed migration from zero (should ignore what it replaces)
"""
executor = MigrationExecutor(connection)
# Check our leaf node is the squashed one
- leaves = [key for key in executor.loader.graph.leaf_nodes() if key[0] == "migrations"]
+ leaves = [
+ key for key in executor.loader.graph.leaf_nodes() if key[0] == "migrations"
+ ]
self.assertEqual(leaves, [("migrations", "0001_squashed_0002")])
# Check the plan
plan = executor.migration_plan([("migrations", "0001_squashed_0002")])
self.assertEqual(
plan,
[
- (executor.loader.graph.nodes["migrations", "0001_squashed_0002"], False),
+ (
+ executor.loader.graph.nodes["migrations", "0001_squashed_0002"],
+ False,
+ ),
],
)
# Were the tables there before?
@@ -106,29 +121,31 @@ class ExecutorTests(MigrationTestBase):
self.assertTableNotExists("migrations_book")
@override_settings(
- MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'},
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"},
)
def test_migrate_backward_to_squashed_migration(self):
executor = MigrationExecutor(connection)
try:
- self.assertTableNotExists('migrations_author')
- self.assertTableNotExists('migrations_book')
- executor.migrate([('migrations', '0001_squashed_0002')])
- self.assertTableExists('migrations_author')
- self.assertTableExists('migrations_book')
+ self.assertTableNotExists("migrations_author")
+ self.assertTableNotExists("migrations_book")
+ executor.migrate([("migrations", "0001_squashed_0002")])
+ self.assertTableExists("migrations_author")
+ self.assertTableExists("migrations_book")
executor.loader.build_graph()
# Migrate backward to a squashed migration.
- executor.migrate([('migrations', '0001_initial')])
- self.assertTableExists('migrations_author')
- self.assertTableNotExists('migrations_book')
+ executor.migrate([("migrations", "0001_initial")])
+ self.assertTableExists("migrations_author")
+ self.assertTableNotExists("migrations_book")
finally:
# Unmigrate everything.
executor = MigrationExecutor(connection)
- executor.migrate([('migrations', None)])
- self.assertTableNotExists('migrations_author')
- self.assertTableNotExists('migrations_book')
+ executor.migrate([("migrations", None)])
+ self.assertTableNotExists("migrations_author")
+ self.assertTableNotExists("migrations_book")
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_non_atomic"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_non_atomic"}
+ )
def test_non_atomic_migration(self):
"""
Applying a non-atomic migration works as expected.
@@ -137,12 +154,16 @@ class ExecutorTests(MigrationTestBase):
with self.assertRaisesMessage(RuntimeError, "Abort migration"):
executor.migrate([("migrations", "0001_initial")])
self.assertTableExists("migrations_publisher")
- migrations_apps = executor.loader.project_state(("migrations", "0001_initial")).apps
+ migrations_apps = executor.loader.project_state(
+ ("migrations", "0001_initial")
+ ).apps
Publisher = migrations_apps.get_model("migrations", "Publisher")
self.assertTrue(Publisher.objects.exists())
self.assertTableNotExists("migrations_book")
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_atomic_operation"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_atomic_operation"}
+ )
def test_atomic_operation_in_non_atomic_migration(self):
"""
An atomic operation is properly rolled back inside a non-atomic
@@ -151,7 +172,9 @@ class ExecutorTests(MigrationTestBase):
executor = MigrationExecutor(connection)
with self.assertRaisesMessage(RuntimeError, "Abort migration"):
executor.migrate([("migrations", "0001_initial")])
- migrations_apps = executor.loader.project_state(("migrations", "0001_initial")).apps
+ migrations_apps = executor.loader.project_state(
+ ("migrations", "0001_initial")
+ ).apps
Editor = migrations_apps.get_model("migrations", "Editor")
self.assertFalse(Editor.objects.exists())
# Record previous migration as successful.
@@ -163,10 +186,12 @@ class ExecutorTests(MigrationTestBase):
executor.migrate([("migrations", None)])
self.assertFalse(Editor.objects.exists())
- @override_settings(MIGRATION_MODULES={
- "migrations": "migrations.test_migrations",
- "migrations2": "migrations2.test_migrations_2",
- })
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations",
+ "migrations2": "migrations2.test_migrations_2",
+ }
+ )
def test_empty_plan(self):
"""
Re-planning a full migration of a fully-migrated set doesn't
@@ -179,10 +204,12 @@ class ExecutorTests(MigrationTestBase):
"""
# Make the initial plan, check it
executor = MigrationExecutor(connection)
- plan = executor.migration_plan([
- ("migrations", "0002_second"),
- ("migrations2", "0001_initial"),
- ])
+ plan = executor.migration_plan(
+ [
+ ("migrations", "0002_second"),
+ ("migrations2", "0001_initial"),
+ ]
+ )
self.assertEqual(
plan,
[
@@ -192,35 +219,40 @@ class ExecutorTests(MigrationTestBase):
],
)
# Fake-apply all migrations
- executor.migrate([
- ("migrations", "0002_second"),
- ("migrations2", "0001_initial")
- ], fake=True)
+ executor.migrate(
+ [("migrations", "0002_second"), ("migrations2", "0001_initial")], fake=True
+ )
# Rebuild the graph to reflect the new DB state
executor.loader.build_graph()
# Now plan a second time and make sure it's empty
- plan = executor.migration_plan([
- ("migrations", "0002_second"),
- ("migrations2", "0001_initial"),
- ])
+ plan = executor.migration_plan(
+ [
+ ("migrations", "0002_second"),
+ ("migrations2", "0001_initial"),
+ ]
+ )
self.assertEqual(plan, [])
# The resulting state should include applied migrations.
- state = executor.migrate([
- ("migrations", "0002_second"),
- ("migrations2", "0001_initial"),
- ])
- self.assertIn(('migrations', 'book'), state.models)
- self.assertIn(('migrations', 'author'), state.models)
- self.assertIn(('migrations2', 'otherauthor'), state.models)
+ state = executor.migrate(
+ [
+ ("migrations", "0002_second"),
+ ("migrations2", "0001_initial"),
+ ]
+ )
+ self.assertIn(("migrations", "book"), state.models)
+ self.assertIn(("migrations", "author"), state.models)
+ self.assertIn(("migrations2", "otherauthor"), state.models)
# Erase all the fake records
executor.recorder.record_unapplied("migrations2", "0001_initial")
executor.recorder.record_unapplied("migrations", "0002_second")
executor.recorder.record_unapplied("migrations", "0001_initial")
- @override_settings(MIGRATION_MODULES={
- "migrations": "migrations.test_migrations",
- "migrations2": "migrations2.test_migrations_2_no_deps",
- })
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations",
+ "migrations2": "migrations2.test_migrations_2_no_deps",
+ }
+ )
def test_mixed_plan_not_supported(self):
"""
Although the MigrationExecutor interfaces allows for mixed migration
@@ -240,19 +272,25 @@ class ExecutorTests(MigrationTestBase):
executor.migrate(None, plan)
# Rebuild the graph to reflect the new DB state
executor.loader.build_graph()
- self.assertIn(('migrations', '0001_initial'), executor.loader.applied_migrations)
- self.assertIn(('migrations', '0002_second'), executor.loader.applied_migrations)
- self.assertNotIn(('migrations2', '0001_initial'), executor.loader.applied_migrations)
+ self.assertIn(
+ ("migrations", "0001_initial"), executor.loader.applied_migrations
+ )
+ self.assertIn(("migrations", "0002_second"), executor.loader.applied_migrations)
+ self.assertNotIn(
+ ("migrations2", "0001_initial"), executor.loader.applied_migrations
+ )
# Generate mixed plan
- plan = executor.migration_plan([
- ("migrations", None),
- ("migrations2", "0001_initial"),
- ])
+ plan = executor.migration_plan(
+ [
+ ("migrations", None),
+ ("migrations2", "0001_initial"),
+ ]
+ )
msg = (
- 'Migration plans with both forwards and backwards migrations are '
- 'not supported. Please split your migration process into separate '
- 'plans of only forwards OR backwards migrations.'
+ "Migration plans with both forwards and backwards migrations are "
+ "not supported. Please split your migration process into separate "
+ "plans of only forwards OR backwards migrations."
)
with self.assertRaisesMessage(InvalidMigrationPlan, msg) as cm:
executor.migrate(None, plan)
@@ -266,10 +304,12 @@ class ExecutorTests(MigrationTestBase):
)
# Rebuild the graph to reflect the new DB state
executor.loader.build_graph()
- executor.migrate([
- ("migrations", None),
- ("migrations2", None),
- ])
+ executor.migrate(
+ [
+ ("migrations", None),
+ ("migrations2", None),
+ ]
+ )
# Are the tables gone?
self.assertTableNotExists("migrations_author")
self.assertTableNotExists("migrations_book")
@@ -284,6 +324,7 @@ class ExecutorTests(MigrationTestBase):
def fake_storer(phase, migration=None, fake=None):
state["faked"] = fake
+
executor = MigrationExecutor(connection, progress_callback=fake_storer)
# Were the tables there before?
self.assertTableNotExists("migrations_author")
@@ -347,37 +388,37 @@ class ExecutorTests(MigrationTestBase):
"""
with isolate_lru_cache(global_apps.get_swappable_settings_name):
executor = MigrationExecutor(connection)
- self.assertTableNotExists('migrations_author')
- self.assertTableNotExists('migrations_tribble')
+ self.assertTableNotExists("migrations_author")
+ self.assertTableNotExists("migrations_tribble")
# Migrate forwards
- executor.migrate([('migrations', '0001_initial')])
- self.assertTableExists('migrations_author')
- self.assertTableExists('migrations_tribble')
+ executor.migrate([("migrations", "0001_initial")])
+ self.assertTableExists("migrations_author")
+ self.assertTableExists("migrations_tribble")
# The soft-application detection works.
# Change table_names to not return auth_user during this as it
# wouldn't be there in a normal run, and ensure migrations.Author
# exists in the global app registry temporarily.
old_table_names = connection.introspection.table_names
connection.introspection.table_names = lambda c: [
- x for x in old_table_names(c) if x != 'auth_user'
+ x for x in old_table_names(c) if x != "auth_user"
]
migrations_apps = executor.loader.project_state(
- ('migrations', '0001_initial'),
+ ("migrations", "0001_initial"),
).apps
- global_apps.get_app_config('migrations').models['author'] = (
- migrations_apps.get_model('migrations', 'author')
- )
+ global_apps.get_app_config("migrations").models[
+ "author"
+ ] = migrations_apps.get_model("migrations", "author")
try:
- migration = executor.loader.get_migration('auth', '0001_initial')
+ migration = executor.loader.get_migration("auth", "0001_initial")
self.assertIs(executor.detect_soft_applied(None, migration)[0], True)
finally:
connection.introspection.table_names = old_table_names
- del global_apps.get_app_config('migrations').models['author']
+ del global_apps.get_app_config("migrations").models["author"]
# Migrate back to clean up the database.
executor.loader.build_graph()
- executor.migrate([('migrations', None)])
- self.assertTableNotExists('migrations_author')
- self.assertTableNotExists('migrations_tribble')
+ executor.migrate([("migrations", None)])
+ self.assertTableNotExists("migrations_author")
+ self.assertTableNotExists("migrations_tribble")
@override_settings(
MIGRATION_MODULES={
@@ -442,7 +483,7 @@ class ExecutorTests(MigrationTestBase):
INSTALLED_APPS=[
"migrations.migrations_test_apps.lookuperror_a",
"migrations.migrations_test_apps.lookuperror_b",
- "migrations.migrations_test_apps.lookuperror_c"
+ "migrations.migrations_test_apps.lookuperror_c",
]
)
def test_unrelated_model_lookups_forwards(self):
@@ -463,10 +504,12 @@ class ExecutorTests(MigrationTestBase):
# Migrate forwards -- This led to a lookup LookupErrors because
# lookuperror_b.B2 is already applied
- executor.migrate([
- ("lookuperror_a", "0004_a4"),
- ("lookuperror_c", "0003_c3"),
- ])
+ executor.migrate(
+ [
+ ("lookuperror_a", "0004_a4"),
+ ("lookuperror_c", "0003_c3"),
+ ]
+ )
self.assertTableExists("lookuperror_a_a4")
self.assertTableExists("lookuperror_c_c3")
@@ -474,11 +517,13 @@ class ExecutorTests(MigrationTestBase):
executor.loader.build_graph()
finally:
# Cleanup
- executor.migrate([
- ("lookuperror_a", None),
- ("lookuperror_b", None),
- ("lookuperror_c", None),
- ])
+ executor.migrate(
+ [
+ ("lookuperror_a", None),
+ ("lookuperror_b", None),
+ ("lookuperror_c", None),
+ ]
+ )
self.assertTableNotExists("lookuperror_a_a1")
self.assertTableNotExists("lookuperror_b_b1")
self.assertTableNotExists("lookuperror_c_c1")
@@ -487,7 +532,7 @@ class ExecutorTests(MigrationTestBase):
INSTALLED_APPS=[
"migrations.migrations_test_apps.lookuperror_a",
"migrations.migrations_test_apps.lookuperror_b",
- "migrations.migrations_test_apps.lookuperror_c"
+ "migrations.migrations_test_apps.lookuperror_c",
]
)
def test_unrelated_model_lookups_backwards(self):
@@ -501,11 +546,13 @@ class ExecutorTests(MigrationTestBase):
self.assertTableNotExists("lookuperror_a_a1")
self.assertTableNotExists("lookuperror_b_b1")
self.assertTableNotExists("lookuperror_c_c1")
- executor.migrate([
- ("lookuperror_a", "0004_a4"),
- ("lookuperror_b", "0003_b3"),
- ("lookuperror_c", "0003_c3"),
- ])
+ executor.migrate(
+ [
+ ("lookuperror_a", "0004_a4"),
+ ("lookuperror_b", "0003_b3"),
+ ("lookuperror_c", "0003_c3"),
+ ]
+ )
self.assertTableExists("lookuperror_b_b3")
self.assertTableExists("lookuperror_a_a4")
self.assertTableExists("lookuperror_c_c3")
@@ -520,18 +567,15 @@ class ExecutorTests(MigrationTestBase):
executor.loader.build_graph()
finally:
# Cleanup
- executor.migrate([
- ("lookuperror_b", None),
- ("lookuperror_c", None)
- ])
+ executor.migrate([("lookuperror_b", None), ("lookuperror_c", None)])
self.assertTableNotExists("lookuperror_a_a1")
self.assertTableNotExists("lookuperror_b_b1")
self.assertTableNotExists("lookuperror_c_c1")
@override_settings(
INSTALLED_APPS=[
- 'migrations.migrations_test_apps.mutate_state_a',
- 'migrations.migrations_test_apps.mutate_state_b',
+ "migrations.migrations_test_apps.mutate_state_a",
+ "migrations.migrations_test_apps.mutate_state_b",
]
)
def test_unrelated_applied_migrations_mutate_state(self):
@@ -540,24 +584,32 @@ class ExecutorTests(MigrationTestBase):
state in both directions.
"""
executor = MigrationExecutor(connection)
- executor.migrate([
- ('mutate_state_b', '0002_add_field'),
- ])
+ executor.migrate(
+ [
+ ("mutate_state_b", "0002_add_field"),
+ ]
+ )
# Migrate forward.
executor.loader.build_graph()
- state = executor.migrate([
- ('mutate_state_a', '0001_initial'),
- ])
- self.assertIn('added', state.models['mutate_state_b', 'b'].fields)
+ state = executor.migrate(
+ [
+ ("mutate_state_a", "0001_initial"),
+ ]
+ )
+ self.assertIn("added", state.models["mutate_state_b", "b"].fields)
executor.loader.build_graph()
# Migrate backward.
- state = executor.migrate([
- ('mutate_state_a', None),
- ])
- self.assertIn('added', state.models['mutate_state_b', 'b'].fields)
- executor.migrate([
- ('mutate_state_b', None),
- ])
+ state = executor.migrate(
+ [
+ ("mutate_state_a", None),
+ ]
+ )
+ self.assertIn("added", state.models["mutate_state_b", "b"].fields)
+ executor.migrate(
+ [
+ ("mutate_state_b", None),
+ ]
+ )
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_process_callback(self):
@@ -573,17 +625,21 @@ class ExecutorTests(MigrationTestBase):
# Were the tables there before?
self.assertTableNotExists("migrations_author")
self.assertTableNotExists("migrations_tribble")
- executor.migrate([
- ("migrations", "0001_initial"),
- ("migrations", "0002_second"),
- ])
+ executor.migrate(
+ [
+ ("migrations", "0001_initial"),
+ ("migrations", "0002_second"),
+ ]
+ )
# Rebuild the graph to reflect the new DB state
executor.loader.build_graph()
- executor.migrate([
- ("migrations", None),
- ("migrations", None),
- ])
+ executor.migrate(
+ [
+ ("migrations", None),
+ ("migrations", None),
+ ]
+ )
self.assertTableNotExists("migrations_author")
self.assertTableNotExists("migrations_tribble")
@@ -591,16 +647,16 @@ class ExecutorTests(MigrationTestBase):
expected = [
("render_start",),
("render_success",),
- ("apply_start", migrations['migrations', '0001_initial'], False),
- ("apply_success", migrations['migrations', '0001_initial'], False),
- ("apply_start", migrations['migrations', '0002_second'], False),
- ("apply_success", migrations['migrations', '0002_second'], False),
+ ("apply_start", migrations["migrations", "0001_initial"], False),
+ ("apply_success", migrations["migrations", "0001_initial"], False),
+ ("apply_start", migrations["migrations", "0002_second"], False),
+ ("apply_success", migrations["migrations", "0002_second"], False),
("render_start",),
("render_success",),
- ("unapply_start", migrations['migrations', '0002_second'], False),
- ("unapply_success", migrations['migrations', '0002_second'], False),
- ("unapply_start", migrations['migrations', '0001_initial'], False),
- ("unapply_success", migrations['migrations', '0001_initial'], False),
+ ("unapply_start", migrations["migrations", "0002_second"], False),
+ ("unapply_success", migrations["migrations", "0002_second"], False),
+ ("unapply_start", migrations["migrations", "0001_initial"], False),
+ ("unapply_success", migrations["migrations", "0001_initial"], False),
]
self.assertEqual(call_args_list, expected)
@@ -616,10 +672,12 @@ class ExecutorTests(MigrationTestBase):
self.assertTableNotExists("author_app_author")
self.assertTableNotExists("book_app_book")
# Apply initial migrations
- executor.migrate([
- ("author_app", "0001_initial"),
- ("book_app", "0001_initial"),
- ])
+ executor.migrate(
+ [
+ ("author_app", "0001_initial"),
+ ("book_app", "0001_initial"),
+ ]
+ )
self.assertTableExists("author_app_author")
self.assertTableExists("book_app_book")
# Rebuild the graph to reflect the new DB state
@@ -640,7 +698,9 @@ class ExecutorTests(MigrationTestBase):
self.assertTableNotExists("book_app_book")
executor.migrate([("author_app", None)], fake=True)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_apply_all_replaced_marks_replacement_as_applied(self):
"""
Applying all replaced migrations marks replacement as applied (#24628).
@@ -663,7 +723,9 @@ class ExecutorTests(MigrationTestBase):
recorder.applied_migrations(),
)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_migrate_marks_replacement_applied_even_if_it_did_nothing(self):
"""
A new squash migration will be marked as applied even if all its
@@ -684,59 +746,69 @@ class ExecutorTests(MigrationTestBase):
recorder.applied_migrations(),
)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_migrate_marks_replacement_unapplied(self):
executor = MigrationExecutor(connection)
- executor.migrate([('migrations', '0001_squashed_0002')])
+ executor.migrate([("migrations", "0001_squashed_0002")])
try:
self.assertIn(
- ('migrations', '0001_squashed_0002'),
+ ("migrations", "0001_squashed_0002"),
executor.recorder.applied_migrations(),
)
finally:
executor.loader.build_graph()
- executor.migrate([('migrations', None)])
+ executor.migrate([("migrations", None)])
self.assertNotIn(
- ('migrations', '0001_squashed_0002'),
+ ("migrations", "0001_squashed_0002"),
executor.recorder.applied_migrations(),
)
# When the feature is False, the operation and the record won't be
# performed in a transaction and the test will systematically pass.
- @skipUnlessDBFeature('can_rollback_ddl')
+ @skipUnlessDBFeature("can_rollback_ddl")
def test_migrations_applied_and_recorded_atomically(self):
"""Migrations are applied and recorded atomically."""
+
class Migration(migrations.Migration):
operations = [
- migrations.CreateModel('model', [
- ('id', models.AutoField(primary_key=True)),
- ]),
+ migrations.CreateModel(
+ "model",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
]
executor = MigrationExecutor(connection)
- with mock.patch('django.db.migrations.executor.MigrationExecutor.record_migration') as record_migration:
- record_migration.side_effect = RuntimeError('Recording migration failed.')
- with self.assertRaisesMessage(RuntimeError, 'Recording migration failed.'):
+ with mock.patch(
+ "django.db.migrations.executor.MigrationExecutor.record_migration"
+ ) as record_migration:
+ record_migration.side_effect = RuntimeError("Recording migration failed.")
+ with self.assertRaisesMessage(RuntimeError, "Recording migration failed."):
executor.apply_migration(
ProjectState(),
- Migration('0001_initial', 'record_migration'),
+ Migration("0001_initial", "record_migration"),
)
- executor.migrate([('migrations', '0001_initial')])
+ executor.migrate([("migrations", "0001_initial")])
# The migration isn't recorded as applied since it failed.
migration_recorder = MigrationRecorder(connection)
self.assertIs(
migration_recorder.migration_qs.filter(
- app='record_migration', name='0001_initial',
+ app="record_migration",
+ name="0001_initial",
).exists(),
False,
)
- self.assertTableNotExists('record_migration_model')
+ self.assertTableNotExists("record_migration_model")
def test_migrations_not_applied_on_deferred_sql_failure(self):
"""Migrations are not recorded if deferred SQL application fails."""
+
class DeferredSQL:
def __str__(self):
- raise DatabaseError('Failed to apply deferred SQL')
+ raise DatabaseError("Failed to apply deferred SQL")
class Migration(migrations.Migration):
atomic = False
@@ -745,21 +817,22 @@ class ExecutorTests(MigrationTestBase):
schema_editor.deferred_sql.append(DeferredSQL())
executor = MigrationExecutor(connection)
- with self.assertRaisesMessage(DatabaseError, 'Failed to apply deferred SQL'):
+ with self.assertRaisesMessage(DatabaseError, "Failed to apply deferred SQL"):
executor.apply_migration(
ProjectState(),
- Migration('0001_initial', 'deferred_sql'),
+ Migration("0001_initial", "deferred_sql"),
)
# The migration isn't recorded as applied since it failed.
migration_recorder = MigrationRecorder(connection)
self.assertIs(
migration_recorder.migration_qs.filter(
- app='deferred_sql', name='0001_initial',
+ app="deferred_sql",
+ name="0001_initial",
).exists(),
False,
)
- @mock.patch.object(MigrationRecorder, 'has_table', return_value=False)
+ @mock.patch.object(MigrationRecorder, "has_table", return_value=False)
def test_migrate_skips_schema_creation(self, mocked_has_table):
"""
The django_migrations table is not created if there are no migrations
@@ -780,15 +853,17 @@ class FakeLoader:
class FakeMigration:
"""Really all we need is any object with a debug-useful repr."""
+
def __init__(self, name):
self.name = name
def __repr__(self):
- return 'M<%s>' % self.name
+ return "M<%s>" % self.name
class ExecutorUnitTests(SimpleTestCase):
"""(More) isolated unit tests for executor methods."""
+
def test_minimize_rollbacks(self):
"""
Minimize unnecessary rollbacks in connected apps.
@@ -799,12 +874,12 @@ class ExecutorUnitTests(SimpleTestCase):
to be rolled back since we're not rolling back appA 0001), we migrate
to just before appA-0002.
"""
- a1_impl = FakeMigration('a1')
- a1 = ('a', '1')
- a2_impl = FakeMigration('a2')
- a2 = ('a', '2')
- b1_impl = FakeMigration('b1')
- b1 = ('b', '1')
+ a1_impl = FakeMigration("a1")
+ a1 = ("a", "1")
+ a2_impl = FakeMigration("a2")
+ a2 = ("a", "2")
+ b1_impl = FakeMigration("b1")
+ b1 = ("b", "1")
graph = MigrationGraph()
graph.add_node(a1, a1_impl)
graph.add_node(a2, a2_impl)
@@ -813,11 +888,14 @@ class ExecutorUnitTests(SimpleTestCase):
graph.add_dependency(None, a2, a1)
executor = MigrationExecutor(None)
- executor.loader = FakeLoader(graph, {
- a1: a1_impl,
- b1: b1_impl,
- a2: a2_impl,
- })
+ executor.loader = FakeLoader(
+ graph,
+ {
+ a1: a1_impl,
+ b1: b1_impl,
+ a2: a2_impl,
+ },
+ )
plan = executor.migration_plan({a1})
@@ -832,18 +910,18 @@ class ExecutorUnitTests(SimpleTestCase):
\ \
b: \- 1 <--- 2
"""
- a1_impl = FakeMigration('a1')
- a1 = ('a', '1')
- a2_impl = FakeMigration('a2')
- a2 = ('a', '2')
- a3_impl = FakeMigration('a3')
- a3 = ('a', '3')
- a4_impl = FakeMigration('a4')
- a4 = ('a', '4')
- b1_impl = FakeMigration('b1')
- b1 = ('b', '1')
- b2_impl = FakeMigration('b2')
- b2 = ('b', '2')
+ a1_impl = FakeMigration("a1")
+ a1 = ("a", "1")
+ a2_impl = FakeMigration("a2")
+ a2 = ("a", "2")
+ a3_impl = FakeMigration("a3")
+ a3 = ("a", "3")
+ a4_impl = FakeMigration("a4")
+ a4 = ("a", "4")
+ b1_impl = FakeMigration("b1")
+ b1 = ("b", "1")
+ b2_impl = FakeMigration("b2")
+ b2 = ("b", "2")
graph = MigrationGraph()
graph.add_node(a1, a1_impl)
graph.add_node(a2, a2_impl)
@@ -860,14 +938,17 @@ class ExecutorUnitTests(SimpleTestCase):
graph.add_dependency(None, b2, a2)
executor = MigrationExecutor(None)
- executor.loader = FakeLoader(graph, {
- a1: a1_impl,
- b1: b1_impl,
- a2: a2_impl,
- b2: b2_impl,
- a3: a3_impl,
- a4: a4_impl,
- })
+ executor.loader = FakeLoader(
+ graph,
+ {
+ a1: a1_impl,
+ b1: b1_impl,
+ a2: a2_impl,
+ b2: b2_impl,
+ a3: a3_impl,
+ a4: a4_impl,
+ },
+ )
plan = executor.migration_plan({a1})
@@ -886,14 +967,14 @@ class ExecutorUnitTests(SimpleTestCase):
If a1 is applied already and a2 is not, and we're asked to migrate to
a1, don't apply or unapply b1 or c1, regardless of their current state.
"""
- a1_impl = FakeMigration('a1')
- a1 = ('a', '1')
- a2_impl = FakeMigration('a2')
- a2 = ('a', '2')
- b1_impl = FakeMigration('b1')
- b1 = ('b', '1')
- c1_impl = FakeMigration('c1')
- c1 = ('c', '1')
+ a1_impl = FakeMigration("a1")
+ a1 = ("a", "1")
+ a2_impl = FakeMigration("a2")
+ a2 = ("a", "2")
+ b1_impl = FakeMigration("b1")
+ b1 = ("b", "1")
+ c1_impl = FakeMigration("c1")
+ c1 = ("c", "1")
graph = MigrationGraph()
graph.add_node(a1, a1_impl)
graph.add_node(a2, a2_impl)
@@ -904,10 +985,13 @@ class ExecutorUnitTests(SimpleTestCase):
graph.add_dependency(None, c1, a1)
executor = MigrationExecutor(None)
- executor.loader = FakeLoader(graph, {
- a1: a1_impl,
- b1: b1_impl,
- })
+ executor.loader = FakeLoader(
+ graph,
+ {
+ a1: a1_impl,
+ b1: b1_impl,
+ },
+ )
plan = executor.migration_plan({a1})
diff --git a/tests/migrations/test_fake_initial_case_insensitive/fake_initial/0001_initial.py b/tests/migrations/test_fake_initial_case_insensitive/fake_initial/0001_initial.py
index dc492b3486..6fd6a0d435 100644
--- a/tests/migrations/test_fake_initial_case_insensitive/fake_initial/0001_initial.py
+++ b/tests/migrations/test_fake_initial_case_insensitive/fake_initial/0001_initial.py
@@ -6,23 +6,25 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- 'fakeinitialmodel',
+ "fakeinitialmodel",
[
- ('id', models.AutoField(primary_key=True)),
- ('field', models.CharField(max_length=20)),
+ ("id", models.AutoField(primary_key=True)),
+ ("field", models.CharField(max_length=20)),
],
options={
- 'db_table': 'migrations_mIxEd_cAsE_mOdEl',
+ "db_table": "migrations_mIxEd_cAsE_mOdEl",
},
),
migrations.AddField(
- model_name='fakeinitialmodel',
- name='field_mixed_case',
- field=models.CharField(max_length=20, db_column='fIeLd_mIxEd_cAsE'),
+ model_name="fakeinitialmodel",
+ name="field_mixed_case",
+ field=models.CharField(max_length=20, db_column="fIeLd_mIxEd_cAsE"),
),
migrations.AddField(
- model_name='fakeinitialmodel',
- name='fake_initial_model',
- field=models.ManyToManyField(to='migrations.fakeinitialmodel', db_table='m2m_mIxEd_cAsE'),
+ model_name="fakeinitialmodel",
+ name="fake_initial_model",
+ field=models.ManyToManyField(
+ to="migrations.fakeinitialmodel", db_table="m2m_mIxEd_cAsE"
+ ),
),
]
diff --git a/tests/migrations/test_fake_initial_case_insensitive/initial/0001_initial.py b/tests/migrations/test_fake_initial_case_insensitive/initial/0001_initial.py
index 339d57d21c..e3c1fc8d18 100644
--- a/tests/migrations/test_fake_initial_case_insensitive/initial/0001_initial.py
+++ b/tests/migrations/test_fake_initial_case_insensitive/initial/0001_initial.py
@@ -6,18 +6,23 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- name='fakeinitialmodel',
+ name="fakeinitialmodel",
fields=[
- ('id', models.AutoField(primary_key=True)),
- ('field', models.CharField(max_length=20)),
- ('field_mixed_case', models.CharField(max_length=20, db_column='FiEld_MiXeD_CaSe')),
+ ("id", models.AutoField(primary_key=True)),
+ ("field", models.CharField(max_length=20)),
(
- 'fake_initial_mode',
- models.ManyToManyField('migrations.FakeInitialModel', db_table='m2m_MiXeD_CaSe'),
+ "field_mixed_case",
+ models.CharField(max_length=20, db_column="FiEld_MiXeD_CaSe"),
+ ),
+ (
+ "fake_initial_mode",
+ models.ManyToManyField(
+ "migrations.FakeInitialModel", db_table="m2m_MiXeD_CaSe"
+ ),
),
],
options={
- 'db_table': 'migrations_MiXeD_CaSe_MoDel',
+ "db_table": "migrations_MiXeD_CaSe_MoDel",
},
),
]
diff --git a/tests/migrations/test_graph.py b/tests/migrations/test_graph.py
index 10a5696f57..f62b44180a 100644
--- a/tests/migrations/test_graph.py
+++ b/tests/migrations/test_graph.py
@@ -1,6 +1,4 @@
-from django.db.migrations.exceptions import (
- CircularDependencyError, NodeNotFoundError,
-)
+from django.db.migrations.exceptions import CircularDependencyError, NodeNotFoundError
from django.db.migrations.graph import DummyNode, MigrationGraph, Node
from django.test import SimpleTestCase
@@ -34,7 +32,7 @@ class GraphTests(SimpleTestCase):
# Test root migration case
self.assertEqual(
graph.forwards_plan(("app_a", "0001")),
- [('app_a', '0001')],
+ [("app_a", "0001")],
)
# Test branch B only
self.assertEqual(
@@ -45,23 +43,27 @@ class GraphTests(SimpleTestCase):
self.assertEqual(
graph.forwards_plan(("app_a", "0004")),
[
- ('app_b', '0001'), ('app_b', '0002'), ('app_a', '0001'),
- ('app_a', '0002'), ('app_a', '0003'), ('app_a', '0004'),
+ ("app_b", "0001"),
+ ("app_b", "0002"),
+ ("app_a", "0001"),
+ ("app_a", "0002"),
+ ("app_a", "0003"),
+ ("app_a", "0004"),
],
)
# Test reverse to b:0002
self.assertEqual(
graph.backwards_plan(("app_b", "0002")),
- [('app_a', '0004'), ('app_a', '0003'), ('app_b', '0002')],
+ [("app_a", "0004"), ("app_a", "0003"), ("app_b", "0002")],
)
# Test roots and leaves
self.assertEqual(
graph.root_nodes(),
- [('app_a', '0001'), ('app_b', '0001')],
+ [("app_a", "0001"), ("app_b", "0001")],
)
self.assertEqual(
graph.leaf_nodes(),
- [('app_a', '0004'), ('app_b', '0002')],
+ [("app_a", "0004"), ("app_b", "0002")],
)
def test_complex_graph(self):
@@ -96,33 +98,48 @@ class GraphTests(SimpleTestCase):
# Test branch C only
self.assertEqual(
graph.forwards_plan(("app_c", "0002")),
- [('app_b', '0001'), ('app_c', '0001'), ('app_a', '0001'), ('app_a', '0002'), ('app_c', '0002')],
+ [
+ ("app_b", "0001"),
+ ("app_c", "0001"),
+ ("app_a", "0001"),
+ ("app_a", "0002"),
+ ("app_c", "0002"),
+ ],
)
# Test whole graph
self.assertEqual(
graph.forwards_plan(("app_a", "0004")),
[
- ('app_b', '0001'), ('app_c', '0001'), ('app_a', '0001'),
- ('app_a', '0002'), ('app_c', '0002'), ('app_b', '0002'),
- ('app_a', '0003'), ('app_a', '0004'),
+ ("app_b", "0001"),
+ ("app_c", "0001"),
+ ("app_a", "0001"),
+ ("app_a", "0002"),
+ ("app_c", "0002"),
+ ("app_b", "0002"),
+ ("app_a", "0003"),
+ ("app_a", "0004"),
],
)
# Test reverse to b:0001
self.assertEqual(
graph.backwards_plan(("app_b", "0001")),
[
- ('app_a', '0004'), ('app_c', '0002'), ('app_c', '0001'),
- ('app_a', '0003'), ('app_b', '0002'), ('app_b', '0001'),
+ ("app_a", "0004"),
+ ("app_c", "0002"),
+ ("app_c", "0001"),
+ ("app_a", "0003"),
+ ("app_b", "0002"),
+ ("app_b", "0001"),
],
)
# Test roots and leaves
self.assertEqual(
graph.root_nodes(),
- [('app_a', '0001'), ('app_b', '0001'), ('app_c', '0001')],
+ [("app_a", "0001"), ("app_b", "0001"), ("app_c", "0001")],
)
self.assertEqual(
graph.leaf_nodes(),
- [('app_a', '0004'), ('app_b', '0002'), ('app_c', '0002')],
+ [("app_a", "0004"), ("app_b", "0002"), ("app_c", "0002")],
)
def test_circular_graph(self):
@@ -147,12 +164,12 @@ class GraphTests(SimpleTestCase):
def test_circular_graph_2(self):
graph = MigrationGraph()
- graph.add_node(('A', '0001'), None)
- graph.add_node(('C', '0001'), None)
- graph.add_node(('B', '0001'), None)
- graph.add_dependency('A.0001', ('A', '0001'), ('B', '0001'))
- graph.add_dependency('B.0001', ('B', '0001'), ('A', '0001'))
- graph.add_dependency('C.0001', ('C', '0001'), ('B', '0001'))
+ graph.add_node(("A", "0001"), None)
+ graph.add_node(("C", "0001"), None)
+ graph.add_node(("B", "0001"), None)
+ graph.add_dependency("A.0001", ("A", "0001"), ("B", "0001"))
+ graph.add_dependency("B.0001", ("B", "0001"), ("A", "0001"))
+ graph.add_dependency("C.0001", ("C", "0001"), ("B", "0001"))
with self.assertRaises(CircularDependencyError):
graph.ensure_not_cyclic()
@@ -184,20 +201,18 @@ class GraphTests(SimpleTestCase):
n = 50
graph = MigrationGraph()
for i in range(1, n + 1):
- graph.add_node(('app_a', str(i)), None)
- graph.add_node(('app_b', str(i)), None)
- graph.add_node(('app_c', str(i)), None)
+ graph.add_node(("app_a", str(i)), None)
+ graph.add_node(("app_b", str(i)), None)
+ graph.add_node(("app_c", str(i)), None)
for i in range(1, n):
- graph.add_dependency(None, ('app_b', str(i)), ('app_a', str(i)))
- graph.add_dependency(None, ('app_c', str(i)), ('app_a', str(i)))
- graph.add_dependency(None, ('app_a', str(i + 1)), ('app_b', str(i)))
- graph.add_dependency(None, ('app_a', str(i + 1)), ('app_c', str(i)))
- plan = graph.forwards_plan(('app_a', str(n)))
+ graph.add_dependency(None, ("app_b", str(i)), ("app_a", str(i)))
+ graph.add_dependency(None, ("app_c", str(i)), ("app_a", str(i)))
+ graph.add_dependency(None, ("app_a", str(i + 1)), ("app_b", str(i)))
+ graph.add_dependency(None, ("app_a", str(i + 1)), ("app_c", str(i)))
+ plan = graph.forwards_plan(("app_a", str(n)))
expected = [
- (app, str(i))
- for i in range(1, n)
- for app in ['app_a', 'app_c', 'app_b']
- ] + [('app_a', str(n))]
+ (app, str(i)) for i in range(1, n) for app in ["app_a", "app_c", "app_b"]
+ ] + [("app_a", str(n))]
self.assertEqual(plan, expected)
def test_plan_invalid_node(self):
@@ -243,7 +258,9 @@ class GraphTests(SimpleTestCase):
def test_validate_consistency_missing_parent(self):
graph = MigrationGraph()
graph.add_node(("app_a", "0001"), None)
- graph.add_dependency("app_a.0001", ("app_a", "0001"), ("app_b", "0002"), skip_validation=True)
+ graph.add_dependency(
+ "app_a.0001", ("app_a", "0001"), ("app_b", "0002"), skip_validation=True
+ )
msg = "Migration app_a.0001 dependencies reference nonexistent parent node ('app_b', '0002')"
with self.assertRaisesMessage(NodeNotFoundError, msg):
graph.validate_consistency()
@@ -251,7 +268,9 @@ class GraphTests(SimpleTestCase):
def test_validate_consistency_missing_child(self):
graph = MigrationGraph()
graph.add_node(("app_b", "0002"), None)
- graph.add_dependency("app_b.0002", ("app_a", "0001"), ("app_b", "0002"), skip_validation=True)
+ graph.add_dependency(
+ "app_b.0002", ("app_a", "0001"), ("app_b", "0002"), skip_validation=True
+ )
msg = "Migration app_b.0002 dependencies reference nonexistent child node ('app_a', '0001')"
with self.assertRaisesMessage(NodeNotFoundError, msg):
graph.validate_consistency()
@@ -260,7 +279,9 @@ class GraphTests(SimpleTestCase):
graph = MigrationGraph()
graph.add_node(("app_a", "0001"), None)
graph.add_node(("app_b", "0002"), None)
- graph.add_dependency("app_a.0001", ("app_a", "0001"), ("app_b", "0002"), skip_validation=True)
+ graph.add_dependency(
+ "app_a.0001", ("app_a", "0001"), ("app_b", "0002"), skip_validation=True
+ )
graph.validate_consistency()
def test_validate_consistency_dummy(self):
@@ -271,9 +292,7 @@ class GraphTests(SimpleTestCase):
msg = "app_a.0001 (req'd by app_b.0002) is missing!"
graph = MigrationGraph()
graph.add_dummy_node(
- key=("app_a", "0001"),
- origin="app_b.0002",
- error_message=msg
+ key=("app_a", "0001"), origin="app_b.0002", error_message=msg
)
with self.assertRaisesMessage(NodeNotFoundError, msg):
graph.validate_consistency()
@@ -284,14 +303,24 @@ class GraphTests(SimpleTestCase):
"""
# Add some dummy nodes to be replaced.
graph = MigrationGraph()
- graph.add_dummy_node(key=("app_a", "0001"), origin="app_a.0002", error_message="BAD!")
- graph.add_dummy_node(key=("app_a", "0002"), origin="app_b.0001", error_message="BAD!")
- graph.add_dependency("app_a.0002", ("app_a", "0002"), ("app_a", "0001"), skip_validation=True)
+ graph.add_dummy_node(
+ key=("app_a", "0001"), origin="app_a.0002", error_message="BAD!"
+ )
+ graph.add_dummy_node(
+ key=("app_a", "0002"), origin="app_b.0001", error_message="BAD!"
+ )
+ graph.add_dependency(
+ "app_a.0002", ("app_a", "0002"), ("app_a", "0001"), skip_validation=True
+ )
# Add some normal parent and child nodes to test dependency remapping.
graph.add_node(("app_c", "0001"), None)
graph.add_node(("app_b", "0001"), None)
- graph.add_dependency("app_a.0001", ("app_a", "0001"), ("app_c", "0001"), skip_validation=True)
- graph.add_dependency("app_b.0001", ("app_b", "0001"), ("app_a", "0002"), skip_validation=True)
+ graph.add_dependency(
+ "app_a.0001", ("app_a", "0001"), ("app_c", "0001"), skip_validation=True
+ )
+ graph.add_dependency(
+ "app_b.0001", ("app_b", "0001"), ("app_a", "0002"), skip_validation=True
+ )
# Try replacing before replacement node exists.
msg = (
"Unable to find replacement node ('app_a', '0001_squashed_0002'). It was either"
@@ -300,7 +329,7 @@ class GraphTests(SimpleTestCase):
with self.assertRaisesMessage(NodeNotFoundError, msg):
graph.remove_replaced_nodes(
replacement=("app_a", "0001_squashed_0002"),
- replaced=[("app_a", "0001"), ("app_a", "0002")]
+ replaced=[("app_a", "0001"), ("app_a", "0002")],
)
graph.add_node(("app_a", "0001_squashed_0002"), None)
# Ensure `validate_consistency()` still raises an error at this stage.
@@ -309,7 +338,7 @@ class GraphTests(SimpleTestCase):
# Remove the dummy nodes.
graph.remove_replaced_nodes(
replacement=("app_a", "0001_squashed_0002"),
- replaced=[("app_a", "0001"), ("app_a", "0002")]
+ replaced=[("app_a", "0001"), ("app_a", "0002")],
)
# Ensure graph is now consistent and dependencies have been remapped
graph.validate_consistency()
@@ -339,16 +368,18 @@ class GraphTests(SimpleTestCase):
with self.assertRaisesMessage(NodeNotFoundError, msg):
graph.remove_replacement_node(
replacement=("app_a", "0001_squashed_0002"),
- replaced=[("app_a", "0001"), ("app_a", "0002")]
+ replaced=[("app_a", "0001"), ("app_a", "0002")],
)
graph.add_node(("app_a", "0001_squashed_0002"), None)
# Add a child node to test dependency remapping.
graph.add_node(("app_b", "0001"), None)
- graph.add_dependency("app_b.0001", ("app_b", "0001"), ("app_a", "0001_squashed_0002"))
+ graph.add_dependency(
+ "app_b.0001", ("app_b", "0001"), ("app_a", "0001_squashed_0002")
+ )
# Remove the replacement node.
graph.remove_replacement_node(
replacement=("app_a", "0001_squashed_0002"),
- replaced=[("app_a", "0001"), ("app_a", "0002")]
+ replaced=[("app_a", "0001"), ("app_a", "0002")],
)
# Ensure graph is consistent and child dependency has been remapped
graph.validate_consistency()
@@ -380,10 +411,16 @@ class GraphTests(SimpleTestCase):
graph.add_node(("app_b", "0002"), None)
graph.add_node(("app_c", "0001_squashed_0002"), None)
- graph.add_dependency("app_b.0001", ("app_b", "0001"), ("app_c", "0001_squashed_0002"))
+ graph.add_dependency(
+ "app_b.0001", ("app_b", "0001"), ("app_c", "0001_squashed_0002")
+ )
graph.add_dependency("app_b.0002", ("app_b", "0002"), ("app_a", "0001"))
graph.add_dependency("app_b.0002", ("app_b", "0002"), ("app_b", "0001"))
- graph.add_dependency("app_c.0001_squashed_0002", ("app_c", "0001_squashed_0002"), ("app_b", "0002"))
+ graph.add_dependency(
+ "app_c.0001_squashed_0002",
+ ("app_c", "0001_squashed_0002"),
+ ("app_b", "0002"),
+ )
with self.assertRaises(CircularDependencyError):
graph.ensure_not_cyclic()
@@ -407,13 +444,13 @@ class GraphTests(SimpleTestCase):
class NodeTests(SimpleTestCase):
def test_node_repr(self):
- node = Node(('app_a', '0001'))
+ node = Node(("app_a", "0001"))
self.assertEqual(repr(node), "<Node: ('app_a', '0001')>")
def test_dummynode_repr(self):
node = DummyNode(
- key=('app_a', '0001'),
- origin='app_a.0001',
- error_message='x is missing',
+ key=("app_a", "0001"),
+ origin="app_a.0001",
+ error_message="x is missing",
)
self.assertEqual(repr(node), "<DummyNode: ('app_a', '0001')>")
diff --git a/tests/migrations/test_loader.py b/tests/migrations/test_loader.py
index 03a98506e3..de70c4d981 100644
--- a/tests/migrations/test_loader.py
+++ b/tests/migrations/test_loader.py
@@ -4,7 +4,9 @@ from importlib import import_module
from django.db import connection, connections
from django.db.migrations.exceptions import (
- AmbiguityError, InconsistentMigrationHistory, NodeNotFoundError,
+ AmbiguityError,
+ InconsistentMigrationHistory,
+ NodeNotFoundError,
)
from django.db.migrations.loader import MigrationLoader
from django.db.migrations.recorder import MigrationRecorder
@@ -17,7 +19,8 @@ class RecorderTests(TestCase):
"""
Tests recording migrations as applied or not.
"""
- databases = {'default', 'other'}
+
+ databases = {"default", "other"}
def test_apply(self):
"""
@@ -34,7 +37,7 @@ class RecorderTests(TestCase):
{("myapp", "0432_ponies")},
)
# That should not affect records of another database
- recorder_other = MigrationRecorder(connections['other'])
+ recorder_other = MigrationRecorder(connections["other"])
self.assertEqual(
{(x, y) for (x, y) in recorder_other.applied_migrations() if x == "myapp"},
set(),
@@ -51,6 +54,7 @@ class LoaderTests(TestCase):
Tests the disk and database loader, and running through migrations
in memory.
"""
+
def setUp(self):
self.applied_records = []
@@ -66,7 +70,7 @@ class LoaderTests(TestCase):
self.applied_records.append((recorder, app, name))
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
- @modify_settings(INSTALLED_APPS={'append': 'basic'})
+ @modify_settings(INSTALLED_APPS={"append": "basic"})
def test_load(self):
"""
Makes sure the loader can load the migrations for the test apps,
@@ -87,33 +91,40 @@ class LoaderTests(TestCase):
author_state = project_state.models["migrations", "author"]
self.assertEqual(
- list(author_state.fields),
- ["id", "name", "slug", "age", "rating"]
+ list(author_state.fields), ["id", "name", "slug", "age", "rating"]
)
book_state = project_state.models["migrations", "book"]
- self.assertEqual(list(book_state.fields), ['id', 'author'])
+ self.assertEqual(list(book_state.fields), ["id", "author"])
# Ensure we've included unmigrated apps in there too
self.assertIn("basic", project_state.real_apps)
- @override_settings(MIGRATION_MODULES={
- 'migrations': 'migrations.test_migrations',
- 'migrations2': 'migrations2.test_migrations_2',
- })
- @modify_settings(INSTALLED_APPS={'append': 'migrations2'})
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations",
+ "migrations2": "migrations2.test_migrations_2",
+ }
+ )
+ @modify_settings(INSTALLED_APPS={"append": "migrations2"})
def test_plan_handles_repeated_migrations(self):
"""
_generate_plan() doesn't readd migrations already in the plan (#29180).
"""
migration_loader = MigrationLoader(connection)
- nodes = [('migrations', '0002_second'), ('migrations2', '0001_initial')]
+ nodes = [("migrations", "0002_second"), ("migrations2", "0001_initial")]
self.assertEqual(
migration_loader.graph._generate_plan(nodes, at_end=True),
- [('migrations', '0001_initial'), ('migrations', '0002_second'), ('migrations2', '0001_initial')]
+ [
+ ("migrations", "0001_initial"),
+ ("migrations", "0002_second"),
+ ("migrations2", "0001_initial"),
+ ],
)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_unmigdep"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_unmigdep"}
+ )
def test_load_unmigrated_dependency(self):
"""
Makes sure the loader can load migrations with a dependency on an unmigrated app.
@@ -123,19 +134,23 @@ class LoaderTests(TestCase):
self.assertEqual(
migration_loader.graph.forwards_plan(("migrations", "0001_initial")),
[
- ('contenttypes', '0001_initial'),
- ('auth', '0001_initial'),
+ ("contenttypes", "0001_initial"),
+ ("auth", "0001_initial"),
("migrations", "0001_initial"),
],
)
# Now render it out!
project_state = migration_loader.project_state(("migrations", "0001_initial"))
- self.assertEqual(len([m for a, m in project_state.models if a == "migrations"]), 1)
+ self.assertEqual(
+ len([m for a, m in project_state.models if a == "migrations"]), 1
+ )
book_state = project_state.models["migrations", "book"]
- self.assertEqual(list(book_state.fields), ['id', 'user'])
+ self.assertEqual(list(book_state.fields), ["id", "user"])
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_run_before"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_run_before"}
+ )
def test_run_before(self):
"""
Makes sure the loader uses Migration.run_before.
@@ -151,11 +166,13 @@ class LoaderTests(TestCase):
],
)
- @override_settings(MIGRATION_MODULES={
- "migrations": "migrations.test_migrations_first",
- "migrations2": "migrations2.test_migrations_2_first",
- })
- @modify_settings(INSTALLED_APPS={'append': 'migrations2'})
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations_first",
+ "migrations2": "migrations2.test_migrations_2_first",
+ }
+ )
+ @modify_settings(INSTALLED_APPS={"append": "migrations2"})
def test_first(self):
"""
Makes sure the '__first__' migrations build correctly.
@@ -187,39 +204,47 @@ class LoaderTests(TestCase):
migration_loader.get_migration_by_prefix("migrations", "blarg")
def test_load_import_error(self):
- with override_settings(MIGRATION_MODULES={"migrations": "import_error_package"}):
+ with override_settings(
+ MIGRATION_MODULES={"migrations": "import_error_package"}
+ ):
with self.assertRaises(ImportError):
MigrationLoader(connection)
def test_load_module_file(self):
- with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.file"}):
+ with override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.file"}
+ ):
loader = MigrationLoader(connection)
self.assertIn(
- "migrations", loader.unmigrated_apps,
- "App with migrations module file not in unmigrated apps."
+ "migrations",
+ loader.unmigrated_apps,
+ "App with migrations module file not in unmigrated apps.",
)
def test_load_empty_dir(self):
- with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.namespace"}):
+ with override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.namespace"}
+ ):
loader = MigrationLoader(connection)
self.assertIn(
- "migrations", loader.unmigrated_apps,
- "App missing __init__.py in migrations module not in unmigrated apps."
+ "migrations",
+ loader.unmigrated_apps,
+ "App missing __init__.py in migrations module not in unmigrated apps.",
)
@override_settings(
- INSTALLED_APPS=['migrations.migrations_test_apps.migrated_app'],
+ INSTALLED_APPS=["migrations.migrations_test_apps.migrated_app"],
)
def test_marked_as_migrated(self):
"""
Undefined MIGRATION_MODULES implies default migration module.
"""
migration_loader = MigrationLoader(connection)
- self.assertEqual(migration_loader.migrated_apps, {'migrated_app'})
+ self.assertEqual(migration_loader.migrated_apps, {"migrated_app"})
self.assertEqual(migration_loader.unmigrated_apps, set())
@override_settings(
- INSTALLED_APPS=['migrations.migrations_test_apps.migrated_app'],
+ INSTALLED_APPS=["migrations.migrations_test_apps.migrated_app"],
MIGRATION_MODULES={"migrated_app": None},
)
def test_marked_as_unmigrated(self):
@@ -228,11 +253,11 @@ class LoaderTests(TestCase):
"""
migration_loader = MigrationLoader(connection)
self.assertEqual(migration_loader.migrated_apps, set())
- self.assertEqual(migration_loader.unmigrated_apps, {'migrated_app'})
+ self.assertEqual(migration_loader.unmigrated_apps, {"migrated_app"})
@override_settings(
- INSTALLED_APPS=['migrations.migrations_test_apps.migrated_app'],
- MIGRATION_MODULES={'migrated_app': 'missing-module'},
+ INSTALLED_APPS=["migrations.migrations_test_apps.migrated_app"],
+ MIGRATION_MODULES={"migrated_app": "missing-module"},
)
def test_explicit_missing_module(self):
"""
@@ -240,13 +265,15 @@ class LoaderTests(TestCase):
raised during the importation attempt should be propagated unless
`ignore_no_migrations=True`.
"""
- with self.assertRaisesMessage(ImportError, 'missing-module'):
+ with self.assertRaisesMessage(ImportError, "missing-module"):
migration_loader = MigrationLoader(connection)
migration_loader = MigrationLoader(connection, ignore_no_migrations=True)
self.assertEqual(migration_loader.migrated_apps, set())
- self.assertEqual(migration_loader.unmigrated_apps, {'migrated_app'})
+ self.assertEqual(migration_loader.unmigrated_apps, {"migrated_app"})
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}
+ )
def test_loading_squashed(self):
"Tests loading a squashed migration"
migration_loader = MigrationLoader(connection)
@@ -258,14 +285,16 @@ class LoaderTests(TestCase):
1,
)
# However, fake-apply one migration and it should now use the old two
- self.record_applied(recorder, 'migrations', '0001_initial')
+ self.record_applied(recorder, "migrations", "0001_initial")
migration_loader.build_graph()
self.assertEqual(
len([x for x in migration_loader.graph.nodes if x[0] == "migrations"]),
2,
)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed_complex"})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed_complex"}
+ )
def test_loading_squashed_complex(self):
"Tests loading a complex set of squashed migrations"
@@ -274,7 +303,7 @@ class LoaderTests(TestCase):
self.addCleanup(recorder.flush)
def num_nodes():
- plan = set(loader.graph.forwards_plan(('migrations', '7_auto')))
+ plan = set(loader.graph.forwards_plan(("migrations", "7_auto")))
return len(plan - loader.applied_migrations.keys())
# Empty database: use squashed migration
@@ -282,83 +311,99 @@ class LoaderTests(TestCase):
self.assertEqual(num_nodes(), 5)
# Starting at 1 or 2 should use the squashed migration too
- self.record_applied(recorder, 'migrations', '1_auto')
+ self.record_applied(recorder, "migrations", "1_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 4)
- self.record_applied(recorder, 'migrations', '2_auto')
+ self.record_applied(recorder, "migrations", "2_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 3)
# However, starting at 3 to 5 cannot use the squashed migration
- self.record_applied(recorder, 'migrations', '3_auto')
+ self.record_applied(recorder, "migrations", "3_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 4)
- self.record_applied(recorder, 'migrations', '4_auto')
+ self.record_applied(recorder, "migrations", "4_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 3)
# Starting at 5 to 7 we are past the squashed migrations.
- self.record_applied(recorder, 'migrations', '5_auto')
+ self.record_applied(recorder, "migrations", "5_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 2)
- self.record_applied(recorder, 'migrations', '6_auto')
+ self.record_applied(recorder, "migrations", "6_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 1)
- self.record_applied(recorder, 'migrations', '7_auto')
+ self.record_applied(recorder, "migrations", "7_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 0)
- @override_settings(MIGRATION_MODULES={
- "app1": "migrations.test_migrations_squashed_complex_multi_apps.app1",
- "app2": "migrations.test_migrations_squashed_complex_multi_apps.app2",
- })
- @modify_settings(INSTALLED_APPS={'append': [
- "migrations.test_migrations_squashed_complex_multi_apps.app1",
- "migrations.test_migrations_squashed_complex_multi_apps.app2",
- ]})
+ @override_settings(
+ MIGRATION_MODULES={
+ "app1": "migrations.test_migrations_squashed_complex_multi_apps.app1",
+ "app2": "migrations.test_migrations_squashed_complex_multi_apps.app2",
+ }
+ )
+ @modify_settings(
+ INSTALLED_APPS={
+ "append": [
+ "migrations.test_migrations_squashed_complex_multi_apps.app1",
+ "migrations.test_migrations_squashed_complex_multi_apps.app2",
+ ]
+ }
+ )
def test_loading_squashed_complex_multi_apps(self):
loader = MigrationLoader(connection)
loader.build_graph()
- plan = set(loader.graph.forwards_plan(('app1', '4_auto')))
+ plan = set(loader.graph.forwards_plan(("app1", "4_auto")))
expected_plan = {
- ('app1', '1_auto'),
- ('app2', '1_squashed_2'),
- ('app1', '2_squashed_3'),
- ('app1', '4_auto'),
+ ("app1", "1_auto"),
+ ("app2", "1_squashed_2"),
+ ("app1", "2_squashed_3"),
+ ("app1", "4_auto"),
}
self.assertEqual(plan, expected_plan)
- @override_settings(MIGRATION_MODULES={
- "app1": "migrations.test_migrations_squashed_complex_multi_apps.app1",
- "app2": "migrations.test_migrations_squashed_complex_multi_apps.app2",
- })
- @modify_settings(INSTALLED_APPS={'append': [
- "migrations.test_migrations_squashed_complex_multi_apps.app1",
- "migrations.test_migrations_squashed_complex_multi_apps.app2",
- ]})
+ @override_settings(
+ MIGRATION_MODULES={
+ "app1": "migrations.test_migrations_squashed_complex_multi_apps.app1",
+ "app2": "migrations.test_migrations_squashed_complex_multi_apps.app2",
+ }
+ )
+ @modify_settings(
+ INSTALLED_APPS={
+ "append": [
+ "migrations.test_migrations_squashed_complex_multi_apps.app1",
+ "migrations.test_migrations_squashed_complex_multi_apps.app2",
+ ]
+ }
+ )
def test_loading_squashed_complex_multi_apps_partially_applied(self):
loader = MigrationLoader(connection)
recorder = MigrationRecorder(connection)
- self.record_applied(recorder, 'app1', '1_auto')
- self.record_applied(recorder, 'app1', '2_auto')
+ self.record_applied(recorder, "app1", "1_auto")
+ self.record_applied(recorder, "app1", "2_auto")
loader.build_graph()
- plan = set(loader.graph.forwards_plan(('app1', '4_auto')))
+ plan = set(loader.graph.forwards_plan(("app1", "4_auto")))
plan = plan - loader.applied_migrations.keys()
expected_plan = {
- ('app2', '1_squashed_2'),
- ('app1', '3_auto'),
- ('app1', '4_auto'),
+ ("app2", "1_squashed_2"),
+ ("app1", "3_auto"),
+ ("app1", "4_auto"),
}
self.assertEqual(plan, expected_plan)
- @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed_erroneous"})
+ @override_settings(
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations_squashed_erroneous"
+ }
+ )
def test_loading_squashed_erroneous(self):
"Tests loading a complex but erroneous set of squashed migrations"
@@ -367,7 +412,7 @@ class LoaderTests(TestCase):
self.addCleanup(recorder.flush)
def num_nodes():
- plan = set(loader.graph.forwards_plan(('migrations', '7_auto')))
+ plan = set(loader.graph.forwards_plan(("migrations", "7_auto")))
return len(plan - loader.applied_migrations.keys())
# Empty database: use squashed migration
@@ -375,50 +420,52 @@ class LoaderTests(TestCase):
self.assertEqual(num_nodes(), 5)
# Starting at 1 or 2 should use the squashed migration too
- self.record_applied(recorder, 'migrations', '1_auto')
+ self.record_applied(recorder, "migrations", "1_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 4)
- self.record_applied(recorder, 'migrations', '2_auto')
+ self.record_applied(recorder, "migrations", "2_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 3)
# However, starting at 3 or 4, nonexistent migrations would be needed.
- msg = ("Migration migrations.6_auto depends on nonexistent node ('migrations', '5_auto'). "
- "Django tried to replace migration migrations.5_auto with any of "
- "[migrations.3_squashed_5] but wasn't able to because some of the replaced "
- "migrations are already applied.")
+ msg = (
+ "Migration migrations.6_auto depends on nonexistent node ('migrations', '5_auto'). "
+ "Django tried to replace migration migrations.5_auto with any of "
+ "[migrations.3_squashed_5] but wasn't able to because some of the replaced "
+ "migrations are already applied."
+ )
- self.record_applied(recorder, 'migrations', '3_auto')
+ self.record_applied(recorder, "migrations", "3_auto")
with self.assertRaisesMessage(NodeNotFoundError, msg):
loader.build_graph()
- self.record_applied(recorder, 'migrations', '4_auto')
+ self.record_applied(recorder, "migrations", "4_auto")
with self.assertRaisesMessage(NodeNotFoundError, msg):
loader.build_graph()
# Starting at 5 to 7 we are passed the squashed migrations
- self.record_applied(recorder, 'migrations', '5_auto')
+ self.record_applied(recorder, "migrations", "5_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 2)
- self.record_applied(recorder, 'migrations', '6_auto')
+ self.record_applied(recorder, "migrations", "6_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 1)
- self.record_applied(recorder, 'migrations', '7_auto')
+ self.record_applied(recorder, "migrations", "7_auto")
loader.build_graph()
self.assertEqual(num_nodes(), 0)
@override_settings(
- MIGRATION_MODULES={'migrations': 'migrations.test_migrations'},
- INSTALLED_APPS=['migrations'],
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations"},
+ INSTALLED_APPS=["migrations"],
)
def test_check_consistent_history(self):
loader = MigrationLoader(connection=None)
loader.check_consistent_history(connection)
recorder = MigrationRecorder(connection)
- self.record_applied(recorder, 'migrations', '0002_second')
+ self.record_applied(recorder, "migrations", "0002_second")
msg = (
"Migration migrations.0002_second is applied before its dependency "
"migrations.0001_initial on database 'default'."
@@ -427,8 +474,8 @@ class LoaderTests(TestCase):
loader.check_consistent_history(connection)
@override_settings(
- MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed_extra'},
- INSTALLED_APPS=['migrations'],
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed_extra"},
+ INSTALLED_APPS=["migrations"],
)
def test_check_consistent_history_squashed(self):
"""
@@ -437,20 +484,26 @@ class LoaderTests(TestCase):
"""
loader = MigrationLoader(connection=None)
recorder = MigrationRecorder(connection)
- self.record_applied(recorder, 'migrations', '0001_initial')
- self.record_applied(recorder, 'migrations', '0002_second')
+ self.record_applied(recorder, "migrations", "0001_initial")
+ self.record_applied(recorder, "migrations", "0002_second")
loader.check_consistent_history(connection)
- self.record_applied(recorder, 'migrations', '0003_third')
+ self.record_applied(recorder, "migrations", "0003_third")
loader.check_consistent_history(connection)
- @override_settings(MIGRATION_MODULES={
- "app1": "migrations.test_migrations_squashed_ref_squashed.app1",
- "app2": "migrations.test_migrations_squashed_ref_squashed.app2",
- })
- @modify_settings(INSTALLED_APPS={'append': [
- "migrations.test_migrations_squashed_ref_squashed.app1",
- "migrations.test_migrations_squashed_ref_squashed.app2",
- ]})
+ @override_settings(
+ MIGRATION_MODULES={
+ "app1": "migrations.test_migrations_squashed_ref_squashed.app1",
+ "app2": "migrations.test_migrations_squashed_ref_squashed.app2",
+ }
+ )
+ @modify_settings(
+ INSTALLED_APPS={
+ "append": [
+ "migrations.test_migrations_squashed_ref_squashed.app1",
+ "migrations.test_migrations_squashed_ref_squashed.app2",
+ ]
+ }
+ )
def test_loading_squashed_ref_squashed(self):
"Tests loading a squashed migration with a new migration referencing it"
r"""
@@ -475,13 +528,13 @@ class LoaderTests(TestCase):
# Load with nothing applied: both migrations squashed.
loader.build_graph()
- plan = set(loader.graph.forwards_plan(('app1', '4_auto')))
+ plan = set(loader.graph.forwards_plan(("app1", "4_auto")))
plan = plan - loader.applied_migrations.keys()
expected_plan = {
- ('app1', '1_auto'),
- ('app2', '1_squashed_2'),
- ('app1', '2_squashed_3'),
- ('app1', '4_auto'),
+ ("app1", "1_auto"),
+ ("app2", "1_squashed_2"),
+ ("app1", "2_squashed_3"),
+ ("app1", "4_auto"),
}
self.assertEqual(plan, expected_plan)
@@ -490,72 +543,80 @@ class LoaderTests(TestCase):
loader.build_graph()
msg = "Node ('app1', '3_auto') not a valid node"
with self.assertRaisesMessage(NodeNotFoundError, msg):
- loader.graph.forwards_plan(('app1', '3_auto'))
+ loader.graph.forwards_plan(("app1", "3_auto"))
# Possible if loader.replace_migrations is False.
loader.replace_migrations = False
loader.build_graph()
- plan = set(loader.graph.forwards_plan(('app1', '3_auto')))
+ plan = set(loader.graph.forwards_plan(("app1", "3_auto")))
plan = plan - loader.applied_migrations.keys()
expected_plan = {
- ('app1', '1_auto'),
- ('app2', '1_auto'),
- ('app2', '2_auto'),
- ('app1', '2_auto'),
- ('app1', '3_auto'),
+ ("app1", "1_auto"),
+ ("app2", "1_auto"),
+ ("app2", "2_auto"),
+ ("app1", "2_auto"),
+ ("app1", "3_auto"),
}
self.assertEqual(plan, expected_plan)
loader.replace_migrations = True
# Fake-apply a few from app1: unsquashes migration in app1.
- self.record_applied(recorder, 'app1', '1_auto')
- self.record_applied(recorder, 'app1', '2_auto')
+ self.record_applied(recorder, "app1", "1_auto")
+ self.record_applied(recorder, "app1", "2_auto")
loader.build_graph()
- plan = set(loader.graph.forwards_plan(('app1', '4_auto')))
+ plan = set(loader.graph.forwards_plan(("app1", "4_auto")))
plan = plan - loader.applied_migrations.keys()
expected_plan = {
- ('app2', '1_squashed_2'),
- ('app1', '3_auto'),
- ('app1', '4_auto'),
+ ("app2", "1_squashed_2"),
+ ("app1", "3_auto"),
+ ("app1", "4_auto"),
}
self.assertEqual(plan, expected_plan)
# Fake-apply one from app2: unsquashes migration in app2 too.
- self.record_applied(recorder, 'app2', '1_auto')
+ self.record_applied(recorder, "app2", "1_auto")
loader.build_graph()
- plan = set(loader.graph.forwards_plan(('app1', '4_auto')))
+ plan = set(loader.graph.forwards_plan(("app1", "4_auto")))
plan = plan - loader.applied_migrations.keys()
expected_plan = {
- ('app2', '2_auto'),
- ('app1', '3_auto'),
- ('app1', '4_auto'),
+ ("app2", "2_auto"),
+ ("app1", "3_auto"),
+ ("app1", "4_auto"),
}
self.assertEqual(plan, expected_plan)
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_private'})
+ @override_settings(
+ MIGRATION_MODULES={"migrations": "migrations.test_migrations_private"}
+ )
def test_ignore_files(self):
"""Files prefixed with underscore, tilde, or dot aren't loaded."""
loader = MigrationLoader(connection)
loader.load_disk()
- migrations = [name for app, name in loader.disk_migrations if app == 'migrations']
- self.assertEqual(migrations, ['0001_initial'])
+ migrations = [
+ name for app, name in loader.disk_migrations if app == "migrations"
+ ]
+ self.assertEqual(migrations, ["0001_initial"])
@override_settings(
- MIGRATION_MODULES={'migrations': 'migrations.test_migrations_namespace_package'},
+ MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations_namespace_package"
+ },
)
def test_loading_namespace_package(self):
"""Migration directories without an __init__.py file are ignored."""
loader = MigrationLoader(connection)
loader.load_disk()
- migrations = [name for app, name in loader.disk_migrations if app == 'migrations']
+ migrations = [
+ name for app, name in loader.disk_migrations if app == "migrations"
+ ]
self.assertEqual(migrations, [])
- @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
+ @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_loading_package_without__file__(self):
"""
To support frozen environments, MigrationLoader loads migrations from
regular packages with no __file__ attribute.
"""
- test_module = import_module('migrations.test_migrations')
+ test_module = import_module("migrations.test_migrations")
loader = MigrationLoader(connection)
# __file__ == __spec__.origin or the latter is None and former is
# undefined.
@@ -568,11 +629,9 @@ class LoaderTests(TestCase):
test_module.__spec__.has_location = False
loader.load_disk()
migrations = [
- name
- for app, name in loader.disk_migrations
- if app == 'migrations'
+ name for app, name in loader.disk_migrations if app == "migrations"
]
- self.assertCountEqual(migrations, ['0001_initial', '0002_second'])
+ self.assertCountEqual(migrations, ["0001_initial", "0002_second"])
finally:
test_module.__file__ = module_file
test_module.__spec__.origin = module_origin
@@ -580,30 +639,33 @@ class LoaderTests(TestCase):
class PycLoaderTests(MigrationTestBase):
-
def test_valid(self):
"""
To support frozen environments, MigrationLoader loads .pyc migrations.
"""
- with self.temporary_migration_module(module='migrations.test_migrations') as migration_dir:
+ with self.temporary_migration_module(
+ module="migrations.test_migrations"
+ ) as migration_dir:
# Compile .py files to .pyc files and delete .py files.
compileall.compile_dir(migration_dir, force=True, quiet=1, legacy=True)
for name in os.listdir(migration_dir):
- if name.endswith('.py'):
+ if name.endswith(".py"):
os.remove(os.path.join(migration_dir, name))
loader = MigrationLoader(connection)
- self.assertIn(('migrations', '0001_initial'), loader.disk_migrations)
+ self.assertIn(("migrations", "0001_initial"), loader.disk_migrations)
def test_invalid(self):
"""
MigrationLoader reraises ImportErrors caused by "bad magic number" pyc
files with a more helpful message.
"""
- with self.temporary_migration_module(module='migrations.test_migrations_bad_pyc') as migration_dir:
+ with self.temporary_migration_module(
+ module="migrations.test_migrations_bad_pyc"
+ ) as migration_dir:
# The -tpl suffix is to avoid the pyc exclusion in MANIFEST.in.
os.rename(
- os.path.join(migration_dir, '0001_initial.pyc-tpl'),
- os.path.join(migration_dir, '0001_initial.pyc'),
+ os.path.join(migration_dir, "0001_initial.pyc-tpl"),
+ os.path.join(migration_dir, "0001_initial.pyc"),
)
msg = (
r"Couldn't import '\w+.migrations.0001_initial' as it appears "
diff --git a/tests/migrations/test_migrations/0001_initial.py b/tests/migrations/test_migrations/0001_initial.py
index 259568e8d4..72cf48c7aa 100644
--- a/tests/migrations/test_migrations/0001_initial.py
+++ b/tests/migrations/test_migrations/0001_initial.py
@@ -24,12 +24,12 @@ class Migration(migrations.Migration):
],
),
migrations.AddField(
- model_name='tribble',
- name='bool',
+ model_name="tribble",
+ name="bool",
field=models.BooleanField(default=False),
),
migrations.AlterUniqueTogether(
- name='author',
- unique_together={('name', 'slug')},
+ name="author",
+ unique_together={("name", "slug")},
),
]
diff --git a/tests/migrations/test_migrations/0002_second.py b/tests/migrations/test_migrations/0002_second.py
index 71c300cead..90a1b13b0b 100644
--- a/tests/migrations/test_migrations/0002_second.py
+++ b/tests/migrations/test_migrations/0002_second.py
@@ -8,19 +8,17 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.DeleteModel("Tribble"),
-
migrations.RemoveField("Author", "silly_field"),
-
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_atomic_operation/0001_initial.py b/tests/migrations/test_migrations_atomic_operation/0001_initial.py
index 47ae3df5e9..b3c05c774d 100644
--- a/tests/migrations/test_migrations_atomic_operation/0001_initial.py
+++ b/tests/migrations/test_migrations_atomic_operation/0001_initial.py
@@ -3,9 +3,9 @@ from django.db import migrations, models
def raise_error(apps, schema_editor):
# Test atomic operation in non-atomic migration is wrapped in transaction
- Editor = apps.get_model('migrations', 'Editor')
- Editor.objects.create(name='Test Editor')
- raise RuntimeError('Abort migration')
+ Editor = apps.get_model("migrations", "Editor")
+ Editor.objects.create(name="Test Editor")
+ raise RuntimeError("Abort migration")
class Migration(migrations.Migration):
diff --git a/tests/migrations/test_migrations_backwards_deps_1/0002_second.py b/tests/migrations/test_migrations_backwards_deps_1/0002_second.py
index 6eb831e061..324f3d1b4c 100644
--- a/tests/migrations/test_migrations_backwards_deps_1/0002_second.py
+++ b/tests/migrations/test_migrations_backwards_deps_1/0002_second.py
@@ -2,5 +2,5 @@ from django.db import migrations
class Migration(migrations.Migration):
- dependencies = [('migrations', '0001_initial')]
+ dependencies = [("migrations", "0001_initial")]
operations = []
diff --git a/tests/migrations/test_migrations_clashing_prefix/ab.py b/tests/migrations/test_migrations_clashing_prefix/ab.py
index 54f8924bac..539e347b0c 100644
--- a/tests/migrations/test_migrations_clashing_prefix/ab.py
+++ b/tests/migrations/test_migrations_clashing_prefix/ab.py
@@ -2,4 +2,4 @@ from django.db import migrations
class Migration(migrations.Migration):
- dependencies = [('migrations', 'a')]
+ dependencies = [("migrations", "a")]
diff --git a/tests/migrations/test_migrations_conflict/0001_initial.py b/tests/migrations/test_migrations_conflict/0001_initial.py
index 344bebdfe3..59ad944f67 100644
--- a/tests/migrations/test_migrations_conflict/0001_initial.py
+++ b/tests/migrations/test_migrations_conflict/0001_initial.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -15,13 +14,11 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
migrations.CreateModel(
"Tribble",
[
("id", models.AutoField(primary_key=True)),
("fluffy", models.BooleanField(default=True)),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_conflict/0002_conflicting_second.py b/tests/migrations/test_migrations_conflict/0002_conflicting_second.py
index 15ea1f063a..d542d12dd5 100644
--- a/tests/migrations/test_migrations_conflict/0002_conflicting_second.py
+++ b/tests/migrations/test_migrations_conflict/0002_conflicting_second.py
@@ -6,12 +6,10 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "0001_initial")]
operations = [
-
migrations.CreateModel(
"Something",
[
("id", models.AutoField(primary_key=True)),
],
)
-
]
diff --git a/tests/migrations/test_migrations_conflict/0002_second.py b/tests/migrations/test_migrations_conflict/0002_second.py
index 60a6999ee4..9b4c3264d6 100644
--- a/tests/migrations/test_migrations_conflict/0002_second.py
+++ b/tests/migrations/test_migrations_conflict/0002_second.py
@@ -6,19 +6,17 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "0001_initial")]
operations = [
-
migrations.DeleteModel("Tribble"),
-
migrations.RemoveField("Author", "silly_field"),
-
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_conflict_long_name/0001_initial.py b/tests/migrations/test_migrations_conflict_long_name/0001_initial.py
index e3faa21b3d..8adce29cbd 100644
--- a/tests/migrations/test_migrations_conflict_long_name/0001_initial.py
+++ b/tests/migrations/test_migrations_conflict_long_name/0001_initial.py
@@ -6,9 +6,9 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- 'Author',
+ "Author",
[
- ('id', models.AutoField(primary_key=True)),
+ ("id", models.AutoField(primary_key=True)),
],
),
]
diff --git a/tests/migrations/test_migrations_conflict_long_name/0002_conflicting_second_migration_with_long_name.py b/tests/migrations/test_migrations_conflict_long_name/0002_conflicting_second_migration_with_long_name.py
index 747bd7a675..ddac8d8fe5 100644
--- a/tests/migrations/test_migrations_conflict_long_name/0002_conflicting_second_migration_with_long_name.py
+++ b/tests/migrations/test_migrations_conflict_long_name/0002_conflicting_second_migration_with_long_name.py
@@ -2,13 +2,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [('migrations', '0001_initial')]
+ dependencies = [("migrations", "0001_initial")]
operations = [
migrations.CreateModel(
- 'SomethingElse',
+ "SomethingElse",
[
- ('id', models.AutoField(primary_key=True)),
+ ("id", models.AutoField(primary_key=True)),
],
),
]
diff --git a/tests/migrations/test_migrations_conflict_long_name/0002_second.py b/tests/migrations/test_migrations_conflict_long_name/0002_second.py
index 468dd06938..cc355d3bc0 100644
--- a/tests/migrations/test_migrations_conflict_long_name/0002_second.py
+++ b/tests/migrations/test_migrations_conflict_long_name/0002_second.py
@@ -2,13 +2,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [('migrations', '0001_initial')]
+ dependencies = [("migrations", "0001_initial")]
operations = [
migrations.CreateModel(
- 'Something',
+ "Something",
[
- ('id', models.AutoField(primary_key=True)),
+ ("id", models.AutoField(primary_key=True)),
],
),
]
diff --git a/tests/migrations/test_migrations_custom_user/0001_initial.py b/tests/migrations/test_migrations_custom_user/0001_initial.py
index 250aa9f51b..e562436df7 100644
--- a/tests/migrations/test_migrations_custom_user/0001_initial.py
+++ b/tests/migrations/test_migrations_custom_user/0001_initial.py
@@ -8,7 +8,6 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -16,13 +15,16 @@ class Migration(migrations.Migration):
("name", models.CharField(max_length=255)),
],
),
-
migrations.CreateModel(
"Tribble",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, to_field="id")),
+ (
+ "author",
+ models.ForeignKey(
+ settings.AUTH_USER_MODEL, models.CASCADE, to_field="id"
+ ),
+ ),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_fake_split_initial/0001_initial.py b/tests/migrations/test_migrations_fake_split_initial/0001_initial.py
index ef17e329ce..f96d1b57cd 100644
--- a/tests/migrations/test_migrations_fake_split_initial/0001_initial.py
+++ b/tests/migrations/test_migrations_fake_split_initial/0001_initial.py
@@ -24,7 +24,7 @@ class Migration(migrations.Migration):
],
),
migrations.AlterUniqueTogether(
- name='author',
- unique_together={('name', 'slug')},
+ name="author",
+ unique_together={("name", "slug")},
),
]
diff --git a/tests/migrations/test_migrations_fake_split_initial/0002_second.py b/tests/migrations/test_migrations_fake_split_initial/0002_second.py
index 6e9b28efb4..ba8e9660d1 100644
--- a/tests/migrations/test_migrations_fake_split_initial/0002_second.py
+++ b/tests/migrations/test_migrations_fake_split_initial/0002_second.py
@@ -15,7 +15,10 @@ class Migration(migrations.Migration):
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
),
]
diff --git a/tests/migrations/test_migrations_first/second.py b/tests/migrations/test_migrations_first/second.py
index e4cf995dcc..96550a7b0c 100644
--- a/tests/migrations/test_migrations_first/second.py
+++ b/tests/migrations/test_migrations_first/second.py
@@ -9,19 +9,17 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.DeleteModel("Tribble"),
-
migrations.RemoveField("Author", "silly_field"),
-
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_first/thefirst.py b/tests/migrations/test_migrations_first/thefirst.py
index 344bebdfe3..59ad944f67 100644
--- a/tests/migrations/test_migrations_first/thefirst.py
+++ b/tests/migrations/test_migrations_first/thefirst.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -15,13 +14,11 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
migrations.CreateModel(
"Tribble",
[
("id", models.AutoField(primary_key=True)),
("fluffy", models.BooleanField(default=True)),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_initial_false/0001_not_initial.py b/tests/migrations/test_migrations_initial_false/0001_not_initial.py
index 388c3b61e4..dbf58e4428 100644
--- a/tests/migrations/test_migrations_initial_false/0001_not_initial.py
+++ b/tests/migrations/test_migrations_initial_false/0001_not_initial.py
@@ -24,7 +24,7 @@ class Migration(migrations.Migration):
],
),
migrations.AlterUniqueTogether(
- name='author',
- unique_together={('name', 'slug')},
+ name="author",
+ unique_together={("name", "slug")},
),
]
diff --git a/tests/migrations/test_migrations_manual_porting/0001_initial.py b/tests/migrations/test_migrations_manual_porting/0001_initial.py
index c3e03d6f07..8f827dcdca 100644
--- a/tests/migrations/test_migrations_manual_porting/0001_initial.py
+++ b/tests/migrations/test_migrations_manual_porting/0001_initial.py
@@ -6,10 +6,10 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- 'SomeModel',
+ "SomeModel",
[
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=255)),
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=255)),
],
),
]
diff --git a/tests/migrations/test_migrations_manual_porting/0002_second.py b/tests/migrations/test_migrations_manual_porting/0002_second.py
index 78ab9eebeb..b83c13f84d 100644
--- a/tests/migrations/test_migrations_manual_porting/0002_second.py
+++ b/tests/migrations/test_migrations_manual_porting/0002_second.py
@@ -7,7 +7,7 @@ def forwards(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [
- ('migrations', '0001_initial'),
+ ("migrations", "0001_initial"),
]
operations = [
diff --git a/tests/migrations/test_migrations_no_ancestor/0001_initial.py b/tests/migrations/test_migrations_no_ancestor/0001_initial.py
index 344bebdfe3..59ad944f67 100644
--- a/tests/migrations/test_migrations_no_ancestor/0001_initial.py
+++ b/tests/migrations/test_migrations_no_ancestor/0001_initial.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -15,13 +14,11 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
migrations.CreateModel(
"Tribble",
[
("id", models.AutoField(primary_key=True)),
("fluffy", models.BooleanField(default=True)),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_no_ancestor/0002_conflicting_second.py b/tests/migrations/test_migrations_no_ancestor/0002_conflicting_second.py
index 71625a7116..fe1e0d3686 100644
--- a/tests/migrations/test_migrations_no_ancestor/0002_conflicting_second.py
+++ b/tests/migrations/test_migrations_no_ancestor/0002_conflicting_second.py
@@ -3,23 +3,20 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
-
migrations.DeleteModel("Tribble"),
-
migrations.RemoveField("Author", "silly_field"),
-
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_no_ancestor/0002_second.py b/tests/migrations/test_migrations_no_ancestor/0002_second.py
index 71c300cead..90a1b13b0b 100644
--- a/tests/migrations/test_migrations_no_ancestor/0002_second.py
+++ b/tests/migrations/test_migrations_no_ancestor/0002_second.py
@@ -8,19 +8,17 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.DeleteModel("Tribble"),
-
migrations.RemoveField("Author", "silly_field"),
-
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_no_changes/0001_initial.py b/tests/migrations/test_migrations_no_changes/0001_initial.py
index 344bebdfe3..59ad944f67 100644
--- a/tests/migrations/test_migrations_no_changes/0001_initial.py
+++ b/tests/migrations/test_migrations_no_changes/0001_initial.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -15,13 +14,11 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
migrations.CreateModel(
"Tribble",
[
("id", models.AutoField(primary_key=True)),
("fluffy", models.BooleanField(default=True)),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_no_changes/0002_second.py b/tests/migrations/test_migrations_no_changes/0002_second.py
index 71c300cead..90a1b13b0b 100644
--- a/tests/migrations/test_migrations_no_changes/0002_second.py
+++ b/tests/migrations/test_migrations_no_changes/0002_second.py
@@ -8,19 +8,17 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.DeleteModel("Tribble"),
-
migrations.RemoveField("Author", "silly_field"),
-
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_no_changes/0003_third.py b/tests/migrations/test_migrations_no_changes/0003_third.py
index 89b3bc030c..8802926437 100644
--- a/tests/migrations/test_migrations_no_changes/0003_third.py
+++ b/tests/migrations/test_migrations_no_changes/0003_third.py
@@ -4,30 +4,46 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('migrations', '0002_second'),
+ ("migrations", "0002_second"),
]
operations = [
migrations.CreateModel(
- name='ModelWithCustomBase',
+ name="ModelWithCustomBase",
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ "id",
+ models.AutoField(
+ verbose_name="ID",
+ serialize=False,
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
],
options={},
bases=(models.Model,),
),
migrations.CreateModel(
- name='UnmigratedModel',
+ name="UnmigratedModel",
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ "id",
+ models.AutoField(
+ verbose_name="ID",
+ serialize=False,
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
],
options={},
bases=(models.Model,),
),
migrations.DeleteModel(
- name='Author',
+ name="Author",
),
migrations.DeleteModel(
- name='Book',
+ name="Book",
),
]
diff --git a/tests/migrations/test_migrations_no_default/0001_initial.py b/tests/migrations/test_migrations_no_default/0001_initial.py
index e9176c4958..b247e49271 100644
--- a/tests/migrations/test_migrations_no_default/0001_initial.py
+++ b/tests/migrations/test_migrations_no_default/0001_initial.py
@@ -3,18 +3,24 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='SillyModel',
+ name="SillyModel",
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('silly_field', models.BooleanField(default=False)),
+ (
+ "id",
+ models.AutoField(
+ verbose_name="ID",
+ serialize=False,
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
+ ("silly_field", models.BooleanField(default=False)),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
]
diff --git a/tests/migrations/test_migrations_non_atomic/0001_initial.py b/tests/migrations/test_migrations_non_atomic/0001_initial.py
index f1aa1ae371..c8379e8e07 100644
--- a/tests/migrations/test_migrations_non_atomic/0001_initial.py
+++ b/tests/migrations/test_migrations_non_atomic/0001_initial.py
@@ -3,9 +3,9 @@ from django.db import migrations, models
def raise_error(apps, schema_editor):
# Test operation in non-atomic migration is not wrapped in transaction
- Publisher = apps.get_model('migrations', 'Publisher')
- Publisher.objects.create(name='Test Publisher')
- raise RuntimeError('Abort migration')
+ Publisher = apps.get_model("migrations", "Publisher")
+ Publisher.objects.create(name="Test Publisher")
+ raise RuntimeError("Abort migration")
class Migration(migrations.Migration):
@@ -23,7 +23,12 @@ class Migration(migrations.Migration):
"Book",
[
("title", models.CharField(primary_key=True, max_length=255)),
- ("publisher", models.ForeignKey("migrations.Publisher", models.SET_NULL, null=True)),
+ (
+ "publisher",
+ models.ForeignKey(
+ "migrations.Publisher", models.SET_NULL, null=True
+ ),
+ ),
],
),
]
diff --git a/tests/migrations/test_migrations_order/0001.py b/tests/migrations/test_migrations_order/0001.py
index 2ef88e957d..ee34de77e4 100644
--- a/tests/migrations/test_migrations_order/0001.py
+++ b/tests/migrations/test_migrations_order/0001.py
@@ -5,5 +5,4 @@ class Migration(migrations.Migration):
initial = True
- operations = [
- ]
+ operations = []
diff --git a/tests/migrations/test_migrations_plan/0001_initial.py b/tests/migrations/test_migrations_plan/0001_initial.py
index 0a4001d52a..4e4338c89b 100644
--- a/tests/migrations/test_migrations_plan/0001_initial.py
+++ b/tests/migrations/test_migrations_plan/0001_initial.py
@@ -17,11 +17,11 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- 'Salamander',
+ "Salamander",
[
- ('id', models.AutoField(primary_key=True)),
- ('tail', models.IntegerField(default=0)),
- ('silly_field', models.BooleanField(default=False)),
+ ("id", models.AutoField(primary_key=True)),
+ ("tail", models.IntegerField(default=0)),
+ ("silly_field", models.BooleanField(default=False)),
],
),
migrations.RunPython(grow_tail, shrink_tail),
diff --git a/tests/migrations/test_migrations_plan/0002_second.py b/tests/migrations/test_migrations_plan/0002_second.py
index 2fc9ea6933..12902ceec8 100644
--- a/tests/migrations/test_migrations_plan/0002_second.py
+++ b/tests/migrations/test_migrations_plan/0002_second.py
@@ -4,17 +4,17 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('migrations', '0001_initial'),
+ ("migrations", "0001_initial"),
]
operations = [
-
migrations.CreateModel(
- 'Book',
+ "Book",
[
- ('id', models.AutoField(primary_key=True)),
+ ("id", models.AutoField(primary_key=True)),
],
),
- migrations.RunSQL(['SELECT * FROM migrations_book'], ['SELECT * FROM migrations_salamander'])
-
+ migrations.RunSQL(
+ ["SELECT * FROM migrations_book"], ["SELECT * FROM migrations_salamander"]
+ ),
]
diff --git a/tests/migrations/test_migrations_plan/0003_third.py b/tests/migrations/test_migrations_plan/0003_third.py
index 6d17e217ec..1507fddb4c 100644
--- a/tests/migrations/test_migrations_plan/0003_third.py
+++ b/tests/migrations/test_migrations_plan/0003_third.py
@@ -4,16 +4,17 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ('migrations', '0002_second'),
+ ("migrations", "0002_second"),
]
operations = [
-
migrations.CreateModel(
- 'Author',
+ "Author",
[
- ('id', models.AutoField(primary_key=True)),
+ ("id", models.AutoField(primary_key=True)),
],
),
- migrations.RunSQL(['SELECT * FROM migrations_author'], ['SELECT * FROM migrations_book'])
+ migrations.RunSQL(
+ ["SELECT * FROM migrations_author"], ["SELECT * FROM migrations_book"]
+ ),
]
diff --git a/tests/migrations/test_migrations_plan/0004_fourth.py b/tests/migrations/test_migrations_plan/0004_fourth.py
index d3e1a54b4d..311e56c4b8 100644
--- a/tests/migrations/test_migrations_plan/0004_fourth.py
+++ b/tests/migrations/test_migrations_plan/0004_fourth.py
@@ -7,6 +7,4 @@ class Migration(migrations.Migration):
("migrations", "0003_third"),
]
- operations = [
- migrations.RunSQL('SELECT * FROM migrations_author WHERE id = 1')
- ]
+ operations = [migrations.RunSQL("SELECT * FROM migrations_author WHERE id = 1")]
diff --git a/tests/migrations/test_migrations_plan/0005_fifth.py b/tests/migrations/test_migrations_plan/0005_fifth.py
index 3c569ffded..0fe4a29cdb 100644
--- a/tests/migrations/test_migrations_plan/0005_fifth.py
+++ b/tests/migrations/test_migrations_plan/0005_fifth.py
@@ -12,7 +12,7 @@ def feed(x, y):
class Migration(migrations.Migration):
dependencies = [
- ('migrations', '0004_fourth'),
+ ("migrations", "0004_fourth"),
]
operations = [
diff --git a/tests/migrations/test_migrations_run_before/0001_initial.py b/tests/migrations/test_migrations_run_before/0001_initial.py
index 186c7fbec9..085f3347e8 100644
--- a/tests/migrations/test_migrations_run_before/0001_initial.py
+++ b/tests/migrations/test_migrations_run_before/0001_initial.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"Salamander",
[
@@ -13,5 +12,4 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
]
diff --git a/tests/migrations/test_migrations_run_before/0002_second.py b/tests/migrations/test_migrations_run_before/0002_second.py
index 2be86bb439..9e2784ae6c 100644
--- a/tests/migrations/test_migrations_run_before/0002_second.py
+++ b/tests/migrations/test_migrations_run_before/0002_second.py
@@ -8,13 +8,14 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
)
-
]
diff --git a/tests/migrations/test_migrations_run_before/0003_third.py b/tests/migrations/test_migrations_run_before/0003_third.py
index d24d28ca1c..ea6b2f3877 100644
--- a/tests/migrations/test_migrations_run_before/0003_third.py
+++ b/tests/migrations/test_migrations_run_before/0003_third.py
@@ -15,7 +15,6 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -25,5 +24,4 @@ class Migration(migrations.Migration):
("age", models.IntegerField(default=0)),
],
)
-
]
diff --git a/tests/migrations/test_migrations_squashed/0001_initial.py b/tests/migrations/test_migrations_squashed/0001_initial.py
index 344bebdfe3..59ad944f67 100644
--- a/tests/migrations/test_migrations_squashed/0001_initial.py
+++ b/tests/migrations/test_migrations_squashed/0001_initial.py
@@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -15,13 +14,11 @@ class Migration(migrations.Migration):
("silly_field", models.BooleanField(default=False)),
],
),
-
migrations.CreateModel(
"Tribble",
[
("id", models.AutoField(primary_key=True)),
("fluffy", models.BooleanField(default=True)),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_squashed/0001_squashed_0002.py b/tests/migrations/test_migrations_squashed/0001_squashed_0002.py
index 1ba7f45e41..4ac4530b02 100644
--- a/tests/migrations/test_migrations_squashed/0001_squashed_0002.py
+++ b/tests/migrations/test_migrations_squashed/0001_squashed_0002.py
@@ -9,7 +9,6 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.CreateModel(
"Author",
[
@@ -20,13 +19,14 @@ class Migration(migrations.Migration):
("rating", models.IntegerField(default=0)),
],
),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
),
-
]
diff --git a/tests/migrations/test_migrations_squashed/0002_second.py b/tests/migrations/test_migrations_squashed/0002_second.py
index 60a6999ee4..9b4c3264d6 100644
--- a/tests/migrations/test_migrations_squashed/0002_second.py
+++ b/tests/migrations/test_migrations_squashed/0002_second.py
@@ -6,19 +6,17 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "0001_initial")]
operations = [
-
migrations.DeleteModel("Tribble"),
-
migrations.RemoveField("Author", "silly_field"),
-
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
-
migrations.CreateModel(
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
- )
-
+ ),
]
diff --git a/tests/migrations/test_migrations_squashed_complex/1_auto.py b/tests/migrations/test_migrations_squashed_complex/1_auto.py
index 46fc1242c9..56f45b2a62 100644
--- a/tests/migrations/test_migrations_squashed_complex/1_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/1_auto.py
@@ -3,6 +3,4 @@ from django.db import migrations
class Migration(migrations.Migration):
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex/2_auto.py b/tests/migrations/test_migrations_squashed_complex/2_auto.py
index 1964bf8167..379000e317 100644
--- a/tests/migrations/test_migrations_squashed_complex/2_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/2_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "1_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex/3_auto.py b/tests/migrations/test_migrations_squashed_complex/3_auto.py
index 994ddf3619..e90bf593f9 100644
--- a/tests/migrations/test_migrations_squashed_complex/3_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/3_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex/3_squashed_5.py b/tests/migrations/test_migrations_squashed_complex/3_squashed_5.py
index e8f1eb527e..f750d23b28 100644
--- a/tests/migrations/test_migrations_squashed_complex/3_squashed_5.py
+++ b/tests/migrations/test_migrations_squashed_complex/3_squashed_5.py
@@ -11,6 +11,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex/4_auto.py b/tests/migrations/test_migrations_squashed_complex/4_auto.py
index e7d0f09b55..7bbe7b9614 100644
--- a/tests/migrations/test_migrations_squashed_complex/4_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/4_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "3_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex/5_auto.py b/tests/migrations/test_migrations_squashed_complex/5_auto.py
index e7e25d9a71..df5c2edf32 100644
--- a/tests/migrations/test_migrations_squashed_complex/5_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/5_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "4_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex/6_auto.py b/tests/migrations/test_migrations_squashed_complex/6_auto.py
index 4438bb4196..0ce6bbbb45 100644
--- a/tests/migrations/test_migrations_squashed_complex/6_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/6_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "5_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex/7_auto.py b/tests/migrations/test_migrations_squashed_complex/7_auto.py
index f231edfed1..04d9ea4d55 100644
--- a/tests/migrations/test_migrations_squashed_complex/7_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex/7_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "6_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py
index 46fc1242c9..56f45b2a62 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/1_auto.py
@@ -3,6 +3,4 @@ from django.db import migrations
class Migration(migrations.Migration):
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py
index 83d6e0bedc..7c01a498d2 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py
index 838f68f99f..b9c26b89d3 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/2_squashed_3.py
@@ -10,6 +10,4 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto"), ("app2", "2_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py
index 8abccb5bed..4ea2506733 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/3_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("app1", "2_auto"), ("app2", "2_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py
index 3b44a1d0ab..7752e23ea0 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app1/4_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("app1", "3_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py
index 83d6e0bedc..7c01a498d2 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py
index e12b5754ad..0c182504db 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/1_squashed_2.py
@@ -10,6 +10,4 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py
index 6726beb9d5..b87378ab49 100644
--- a/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py
+++ b/tests/migrations/test_migrations_squashed_complex_multi_apps/app2/2_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("app2", "1_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/1_auto.py b/tests/migrations/test_migrations_squashed_erroneous/1_auto.py
index 46fc1242c9..56f45b2a62 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/1_auto.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/1_auto.py
@@ -3,6 +3,4 @@ from django.db import migrations
class Migration(migrations.Migration):
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/2_auto.py b/tests/migrations/test_migrations_squashed_erroneous/2_auto.py
index 1964bf8167..379000e317 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/2_auto.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/2_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "1_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py b/tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py
index e8f1eb527e..f750d23b28 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/3_squashed_5.py
@@ -11,6 +11,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/6_auto.py b/tests/migrations/test_migrations_squashed_erroneous/6_auto.py
index 4438bb4196..0ce6bbbb45 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/6_auto.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/6_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "5_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_erroneous/7_auto.py b/tests/migrations/test_migrations_squashed_erroneous/7_auto.py
index f231edfed1..04d9ea4d55 100644
--- a/tests/migrations/test_migrations_squashed_erroneous/7_auto.py
+++ b/tests/migrations/test_migrations_squashed_erroneous/7_auto.py
@@ -5,6 +5,4 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "6_auto")]
- operations = [
- migrations.RunPython(migrations.RunPython.noop)
- ]
+ operations = [migrations.RunPython(migrations.RunPython.noop)]
diff --git a/tests/migrations/test_migrations_squashed_no_replaces/0001_squashed_0002.py b/tests/migrations/test_migrations_squashed_no_replaces/0001_squashed_0002.py
index b261b859a1..72eb931d32 100644
--- a/tests/migrations/test_migrations_squashed_no_replaces/0001_squashed_0002.py
+++ b/tests/migrations/test_migrations_squashed_no_replaces/0001_squashed_0002.py
@@ -15,7 +15,10 @@ class Migration(migrations.Migration):
"Book",
[
("id", models.AutoField(primary_key=True)),
- ("author", models.ForeignKey("migrations.Author", models.SET_NULL, null=True)),
+ (
+ "author",
+ models.ForeignKey("migrations.Author", models.SET_NULL, null=True),
+ ),
],
),
]
diff --git a/tests/migrations/test_migrations_unmigdep/0001_initial.py b/tests/migrations/test_migrations_unmigdep/0001_initial.py
index 91b58c3dad..1cb4f8b06e 100644
--- a/tests/migrations/test_migrations_unmigdep/0001_initial.py
+++ b/tests/migrations/test_migrations_unmigdep/0001_initial.py
@@ -8,7 +8,6 @@ class Migration(migrations.Migration):
]
operations = [
-
migrations.CreateModel(
"Book",
[
@@ -16,5 +15,4 @@ class Migration(migrations.Migration):
("user", models.ForeignKey("auth.User", models.SET_NULL, null=True)),
],
)
-
]
diff --git a/tests/migrations/test_multidb.py b/tests/migrations/test_multidb.py
index d8986deb81..7bf5d51454 100644
--- a/tests/migrations/test_multidb.py
+++ b/tests/migrations/test_multidb.py
@@ -9,6 +9,7 @@ class AgnosticRouter:
"""
A router that doesn't have an opinion regarding migrating.
"""
+
def allow_migrate(self, db, app_label, **hints):
return None
@@ -17,6 +18,7 @@ class MigrateNothingRouter:
"""
A router that doesn't allow migrating.
"""
+
def allow_migrate(self, db, app_label, **hints):
return False
@@ -25,6 +27,7 @@ class MigrateEverythingRouter:
"""
A router that always allows migrating.
"""
+
def allow_migrate(self, db, app_label, **hints):
return True
@@ -33,12 +36,13 @@ class MigrateWhenFooRouter:
"""
A router that allows migrating depending on a hint.
"""
+
def allow_migrate(self, db, app_label, **hints):
- return hints.get('foo', False)
+ return hints.get("foo", False)
class MultiDBOperationTests(OperationTestBase):
- databases = {'default', 'other'}
+ databases = {"default", "other"}
def _test_create_model(self, app_label, should_run):
"""
@@ -92,9 +96,13 @@ class MultiDBOperationTests(OperationTestBase):
"""
with override_settings(DATABASE_ROUTERS=[AgnosticRouter(), AgnosticRouter()]):
self._test_create_model("test_mltdb_crmo4", should_run=True)
- with override_settings(DATABASE_ROUTERS=[MigrateNothingRouter(), MigrateEverythingRouter()]):
+ with override_settings(
+ DATABASE_ROUTERS=[MigrateNothingRouter(), MigrateEverythingRouter()]
+ ):
self._test_create_model("test_mltdb_crmo4", should_run=False)
- with override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter(), MigrateNothingRouter()]):
+ with override_settings(
+ DATABASE_ROUTERS=[MigrateEverythingRouter(), MigrateNothingRouter()]
+ ):
self._test_create_model("test_mltdb_crmo4", should_run=True)
def _test_run_sql(self, app_label, should_run, hints=None):
@@ -104,7 +112,9 @@ class MultiDBOperationTests(OperationTestBase):
sql = """
INSERT INTO {0}_pony (pink, weight) VALUES (1, 3.55);
INSERT INTO {0}_pony (pink, weight) VALUES (3, 5.0);
- """.format(app_label)
+ """.format(
+ app_label
+ )
operation = migrations.RunSQL(sql, hints=hints or {})
# Test the state alteration does nothing
@@ -112,7 +122,9 @@ class MultiDBOperationTests(OperationTestBase):
operation.state_forwards(app_label, new_state)
self.assertEqual(new_state, project_state)
# Test the database alteration
- self.assertEqual(project_state.apps.get_model(app_label, "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(app_label, "Pony").objects.count(), 0
+ )
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, project_state, new_state)
Pony = project_state.apps.get_model(app_label, "Pony")
@@ -131,7 +143,7 @@ class MultiDBOperationTests(OperationTestBase):
@override_settings(DATABASE_ROUTERS=[MigrateWhenFooRouter()])
def test_run_sql_migrate_foo_router_with_hints(self):
- self._test_run_sql('test_mltdb_runsql3', should_run=True, hints={'foo': True})
+ self._test_run_sql("test_mltdb_runsql3", should_run=True, hints={"foo": True})
def _test_run_python(self, app_label, should_run, hints=None):
with override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter()]):
@@ -149,7 +161,9 @@ class MultiDBOperationTests(OperationTestBase):
operation.state_forwards(app_label, new_state)
self.assertEqual(new_state, project_state)
# Test the database alteration
- self.assertEqual(project_state.apps.get_model(app_label, "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(app_label, "Pony").objects.count(), 0
+ )
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, project_state, new_state)
Pony = project_state.apps.get_model(app_label, "Pony")
@@ -168,4 +182,6 @@ class MultiDBOperationTests(OperationTestBase):
@override_settings(DATABASE_ROUTERS=[MigrateWhenFooRouter()])
def test_run_python_migrate_foo_router_with_hints(self):
- self._test_run_python('test_mltdb_runpython3', should_run=True, hints={'foo': True})
+ self._test_run_python(
+ "test_mltdb_runpython3", should_run=True, hints={"foo": True}
+ )
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index 7de4dd5d8b..52a798e22d 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -1,7 +1,5 @@
from django.core.exceptions import FieldDoesNotExist
-from django.db import (
- IntegrityError, connection, migrations, models, transaction,
-)
+from django.db import IntegrityError, connection, migrations, models, transaction
from django.db.migrations.migration import Migration
from django.db.migrations.operations.fields import FieldOperation
from django.db.migrations.state import ModelState, ProjectState
@@ -38,7 +36,7 @@ class OperationTests(OperationTestBase):
],
)
self.assertEqual(operation.describe(), "Create model Pony")
- self.assertEqual(operation.migration_name_fragment, 'pony')
+ self.assertEqual(operation.migration_name_fragment, "pony")
# Test the state alteration
project_state = ProjectState()
new_state = project_state.clone()
@@ -60,12 +58,16 @@ class OperationTests(OperationTestBase):
self.assertEqual(definition[1], [])
self.assertEqual(sorted(definition[2]), ["fields", "name"])
# And default manager not in set
- operation = migrations.CreateModel("Foo", fields=[], managers=[("objects", models.Manager())])
+ operation = migrations.CreateModel(
+ "Foo", fields=[], managers=[("objects", models.Manager())]
+ )
definition = operation.deconstruct()
- self.assertNotIn('managers', definition[2])
+ self.assertNotIn("managers", definition[2])
def test_create_model_with_duplicate_field_name(self):
- with self.assertRaisesMessage(ValueError, 'Found duplicate value pink in CreateModel fields argument.'):
+ with self.assertRaisesMessage(
+ ValueError, "Found duplicate value pink in CreateModel fields argument."
+ ):
migrations.CreateModel(
"Pony",
[
@@ -76,55 +78,79 @@ class OperationTests(OperationTestBase):
)
def test_create_model_with_duplicate_base(self):
- message = 'Found duplicate value test_crmo.pony in CreateModel bases argument.'
+ message = "Found duplicate value test_crmo.pony in CreateModel bases argument."
with self.assertRaisesMessage(ValueError, message):
migrations.CreateModel(
"Pony",
fields=[],
- bases=("test_crmo.Pony", "test_crmo.Pony",),
+ bases=(
+ "test_crmo.Pony",
+ "test_crmo.Pony",
+ ),
)
with self.assertRaisesMessage(ValueError, message):
migrations.CreateModel(
"Pony",
fields=[],
- bases=("test_crmo.Pony", "test_crmo.pony",),
+ bases=(
+ "test_crmo.Pony",
+ "test_crmo.pony",
+ ),
)
- message = 'Found duplicate value migrations.unicodemodel in CreateModel bases argument.'
+ message = "Found duplicate value migrations.unicodemodel in CreateModel bases argument."
with self.assertRaisesMessage(ValueError, message):
migrations.CreateModel(
"Pony",
fields=[],
- bases=(UnicodeModel, UnicodeModel,),
+ bases=(
+ UnicodeModel,
+ UnicodeModel,
+ ),
)
with self.assertRaisesMessage(ValueError, message):
migrations.CreateModel(
"Pony",
fields=[],
- bases=(UnicodeModel, 'migrations.unicodemodel',),
+ bases=(
+ UnicodeModel,
+ "migrations.unicodemodel",
+ ),
)
with self.assertRaisesMessage(ValueError, message):
migrations.CreateModel(
"Pony",
fields=[],
- bases=(UnicodeModel, 'migrations.UnicodeModel',),
+ bases=(
+ UnicodeModel,
+ "migrations.UnicodeModel",
+ ),
)
message = "Found duplicate value <class 'django.db.models.base.Model'> in CreateModel bases argument."
with self.assertRaisesMessage(ValueError, message):
migrations.CreateModel(
"Pony",
fields=[],
- bases=(models.Model, models.Model,),
+ bases=(
+ models.Model,
+ models.Model,
+ ),
)
message = "Found duplicate value <class 'migrations.test_operations.Mixin'> in CreateModel bases argument."
with self.assertRaisesMessage(ValueError, message):
migrations.CreateModel(
"Pony",
fields=[],
- bases=(Mixin, Mixin,),
+ bases=(
+ Mixin,
+ Mixin,
+ ),
)
def test_create_model_with_duplicate_manager_name(self):
- with self.assertRaisesMessage(ValueError, 'Found duplicate value objects in CreateModel managers argument.'):
+ with self.assertRaisesMessage(
+ ValueError,
+ "Found duplicate value objects in CreateModel managers argument.",
+ ):
migrations.CreateModel(
"Pony",
fields=[],
@@ -167,13 +193,19 @@ class OperationTests(OperationTestBase):
with connection.schema_editor() as editor:
new_state = project_state.clone()
operation1.state_forwards("test_crmoua", new_state)
- operation1.database_forwards("test_crmoua", editor, project_state, new_state)
+ operation1.database_forwards(
+ "test_crmoua", editor, project_state, new_state
+ )
project_state, new_state = new_state, new_state.clone()
operation2.state_forwards("test_crmoua", new_state)
- operation2.database_forwards("test_crmoua", editor, project_state, new_state)
+ operation2.database_forwards(
+ "test_crmoua", editor, project_state, new_state
+ )
project_state, new_state = new_state, new_state.clone()
operation3.state_forwards("test_crmoua", new_state)
- operation3.database_forwards("test_crmoua", editor, project_state, new_state)
+ operation3.database_forwards(
+ "test_crmoua", editor, project_state, new_state
+ )
self.assertTableExists("test_crmoua_pony")
self.assertTableExists("test_crmoua_rider")
@@ -187,8 +219,8 @@ class OperationTests(OperationTestBase):
"Stable",
[
("id", models.AutoField(primary_key=True)),
- ("ponies", models.ManyToManyField("Pony", related_name="stables"))
- ]
+ ("ponies", models.ManyToManyField("Pony", related_name="stables")),
+ ],
)
# Test the state alteration
new_state = project_state.clone()
@@ -212,7 +244,9 @@ class OperationTests(OperationTestBase):
stable.ponies.all().delete()
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_crmomm", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_crmomm", editor, new_state, project_state
+ )
self.assertTableNotExists("test_crmomm_stable")
self.assertTableNotExists("test_crmomm_stable_ponies")
@@ -225,14 +259,17 @@ class OperationTests(OperationTestBase):
operation = migrations.CreateModel(
"ShetlandPony",
[
- ('pony_ptr', models.OneToOneField(
- 'test_crmoih.Pony',
- models.CASCADE,
- auto_created=True,
- primary_key=True,
- to_field='id',
- serialize=False,
- )),
+ (
+ "pony_ptr",
+ models.OneToOneField(
+ "test_crmoih.Pony",
+ models.CASCADE,
+ auto_created=True,
+ primary_key=True,
+ to_field="id",
+ serialize=False,
+ ),
+ ),
("cuteness", models.IntegerField(default=1)),
],
)
@@ -246,7 +283,9 @@ class OperationTests(OperationTestBase):
self.assertTableExists("test_crmoih_shetlandpony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_crmoih", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_crmoih", editor, new_state, project_state
+ )
self.assertTableNotExists("test_crmoih_shetlandpony")
def test_create_proxy_model(self):
@@ -274,7 +313,9 @@ class OperationTests(OperationTestBase):
self.assertTableExists("test_crprmo_pony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_crprmo", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_crprmo", editor, new_state, project_state
+ )
self.assertTableNotExists("test_crprmo_proxypony")
self.assertTableExists("test_crprmo_pony")
# And deconstruction
@@ -308,28 +349,34 @@ class OperationTests(OperationTestBase):
self.assertTableExists("test_crummo_pony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_crummo", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_crummo", editor, new_state, project_state
+ )
self.assertTableNotExists("test_crummo_unmanagedpony")
self.assertTableExists("test_crummo_pony")
- @skipUnlessDBFeature('supports_table_check_constraints')
+ @skipUnlessDBFeature("supports_table_check_constraints")
def test_create_model_with_constraint(self):
where = models.Q(pink__gt=2)
- check_constraint = models.CheckConstraint(check=where, name='test_constraint_pony_pink_gt_2')
+ check_constraint = models.CheckConstraint(
+ check=where, name="test_constraint_pony_pink_gt_2"
+ )
operation = migrations.CreateModel(
"Pony",
[
("id", models.AutoField(primary_key=True)),
("pink", models.IntegerField(default=3)),
],
- options={'constraints': [check_constraint]},
+ options={"constraints": [check_constraint]},
)
# Test the state alteration
project_state = ProjectState()
new_state = project_state.clone()
operation.state_forwards("test_crmo", new_state)
- self.assertEqual(len(new_state.models['test_crmo', 'pony'].options['constraints']), 1)
+ self.assertEqual(
+ len(new_state.models["test_crmo", "pony"].options["constraints"]), 1
+ )
# Test database alteration
self.assertTableNotExists("test_crmo_pony")
@@ -349,35 +396,37 @@ class OperationTests(OperationTestBase):
definition = operation.deconstruct()
self.assertEqual(definition[0], "CreateModel")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2]['options']['constraints'], [check_constraint])
+ self.assertEqual(definition[2]["options"]["constraints"], [check_constraint])
def test_create_model_with_partial_unique_constraint(self):
partial_unique_constraint = models.UniqueConstraint(
- fields=['pink'],
+ fields=["pink"],
condition=models.Q(weight__gt=5),
- name='test_constraint_pony_pink_for_weight_gt_5_uniq',
+ name="test_constraint_pony_pink_for_weight_gt_5_uniq",
)
operation = migrations.CreateModel(
- 'Pony',
+ "Pony",
[
- ('id', models.AutoField(primary_key=True)),
- ('pink', models.IntegerField(default=3)),
- ('weight', models.FloatField()),
+ ("id", models.AutoField(primary_key=True)),
+ ("pink", models.IntegerField(default=3)),
+ ("weight", models.FloatField()),
],
- options={'constraints': [partial_unique_constraint]},
+ options={"constraints": [partial_unique_constraint]},
)
# Test the state alteration
project_state = ProjectState()
new_state = project_state.clone()
- operation.state_forwards('test_crmo', new_state)
- self.assertEqual(len(new_state.models['test_crmo', 'pony'].options['constraints']), 1)
+ operation.state_forwards("test_crmo", new_state)
+ self.assertEqual(
+ len(new_state.models["test_crmo", "pony"].options["constraints"]), 1
+ )
# Test database alteration
- self.assertTableNotExists('test_crmo_pony')
+ self.assertTableNotExists("test_crmo_pony")
with connection.schema_editor() as editor:
- operation.database_forwards('test_crmo', editor, project_state, new_state)
- self.assertTableExists('test_crmo_pony')
+ operation.database_forwards("test_crmo", editor, project_state, new_state)
+ self.assertTableExists("test_crmo_pony")
# Test constraint works
- Pony = new_state.apps.get_model('test_crmo', 'Pony')
+ Pony = new_state.apps.get_model("test_crmo", "Pony")
Pony.objects.create(pink=1, weight=4.0)
Pony.objects.create(pink=1, weight=4.0)
Pony.objects.create(pink=1, weight=6.0)
@@ -388,38 +437,42 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1, weight=7.0)
# Test reversal
with connection.schema_editor() as editor:
- operation.database_backwards('test_crmo', editor, new_state, project_state)
- self.assertTableNotExists('test_crmo_pony')
+ operation.database_backwards("test_crmo", editor, new_state, project_state)
+ self.assertTableNotExists("test_crmo_pony")
# Test deconstruction
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'CreateModel')
+ self.assertEqual(definition[0], "CreateModel")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2]['options']['constraints'], [partial_unique_constraint])
+ self.assertEqual(
+ definition[2]["options"]["constraints"], [partial_unique_constraint]
+ )
def test_create_model_with_deferred_unique_constraint(self):
deferred_unique_constraint = models.UniqueConstraint(
- fields=['pink'],
- name='deferrable_pink_constraint',
+ fields=["pink"],
+ name="deferrable_pink_constraint",
deferrable=models.Deferrable.DEFERRED,
)
operation = migrations.CreateModel(
- 'Pony',
+ "Pony",
[
- ('id', models.AutoField(primary_key=True)),
- ('pink', models.IntegerField(default=3)),
+ ("id", models.AutoField(primary_key=True)),
+ ("pink", models.IntegerField(default=3)),
],
- options={'constraints': [deferred_unique_constraint]},
+ options={"constraints": [deferred_unique_constraint]},
)
project_state = ProjectState()
new_state = project_state.clone()
- operation.state_forwards('test_crmo', new_state)
- self.assertEqual(len(new_state.models['test_crmo', 'pony'].options['constraints']), 1)
- self.assertTableNotExists('test_crmo_pony')
+ operation.state_forwards("test_crmo", new_state)
+ self.assertEqual(
+ len(new_state.models["test_crmo", "pony"].options["constraints"]), 1
+ )
+ self.assertTableNotExists("test_crmo_pony")
# Create table.
with connection.schema_editor() as editor:
- operation.database_forwards('test_crmo', editor, project_state, new_state)
- self.assertTableExists('test_crmo_pony')
- Pony = new_state.apps.get_model('test_crmo', 'Pony')
+ operation.database_forwards("test_crmo", editor, project_state, new_state)
+ self.assertTableExists("test_crmo_pony")
+ Pony = new_state.apps.get_model("test_crmo", "Pony")
Pony.objects.create(pink=1)
if connection.features.supports_deferrable_unique_constraints:
# Unique constraint is deferred.
@@ -430,8 +483,10 @@ class OperationTests(OperationTestBase):
# Constraint behavior can be changed with SET CONSTRAINTS.
with self.assertRaises(IntegrityError):
with transaction.atomic(), connection.cursor() as cursor:
- quoted_name = connection.ops.quote_name(deferred_unique_constraint.name)
- cursor.execute('SET CONSTRAINTS %s IMMEDIATE' % quoted_name)
+ quoted_name = connection.ops.quote_name(
+ deferred_unique_constraint.name
+ )
+ cursor.execute("SET CONSTRAINTS %s IMMEDIATE" % quoted_name)
obj = Pony.objects.create(pink=1)
obj.pink = 3
obj.save()
@@ -439,56 +494,58 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1)
# Reversal.
with connection.schema_editor() as editor:
- operation.database_backwards('test_crmo', editor, new_state, project_state)
- self.assertTableNotExists('test_crmo_pony')
+ operation.database_backwards("test_crmo", editor, new_state, project_state)
+ self.assertTableNotExists("test_crmo_pony")
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'CreateModel')
+ self.assertEqual(definition[0], "CreateModel")
self.assertEqual(definition[1], [])
self.assertEqual(
- definition[2]['options']['constraints'],
+ definition[2]["options"]["constraints"],
[deferred_unique_constraint],
)
- @skipUnlessDBFeature('supports_covering_indexes')
+ @skipUnlessDBFeature("supports_covering_indexes")
def test_create_model_with_covering_unique_constraint(self):
covering_unique_constraint = models.UniqueConstraint(
- fields=['pink'],
- include=['weight'],
- name='test_constraint_pony_pink_covering_weight',
+ fields=["pink"],
+ include=["weight"],
+ name="test_constraint_pony_pink_covering_weight",
)
operation = migrations.CreateModel(
- 'Pony',
+ "Pony",
[
- ('id', models.AutoField(primary_key=True)),
- ('pink', models.IntegerField(default=3)),
- ('weight', models.FloatField()),
+ ("id", models.AutoField(primary_key=True)),
+ ("pink", models.IntegerField(default=3)),
+ ("weight", models.FloatField()),
],
- options={'constraints': [covering_unique_constraint]},
+ options={"constraints": [covering_unique_constraint]},
)
project_state = ProjectState()
new_state = project_state.clone()
- operation.state_forwards('test_crmo', new_state)
- self.assertEqual(len(new_state.models['test_crmo', 'pony'].options['constraints']), 1)
- self.assertTableNotExists('test_crmo_pony')
+ operation.state_forwards("test_crmo", new_state)
+ self.assertEqual(
+ len(new_state.models["test_crmo", "pony"].options["constraints"]), 1
+ )
+ self.assertTableNotExists("test_crmo_pony")
# Create table.
with connection.schema_editor() as editor:
- operation.database_forwards('test_crmo', editor, project_state, new_state)
- self.assertTableExists('test_crmo_pony')
- Pony = new_state.apps.get_model('test_crmo', 'Pony')
+ operation.database_forwards("test_crmo", editor, project_state, new_state)
+ self.assertTableExists("test_crmo_pony")
+ Pony = new_state.apps.get_model("test_crmo", "Pony")
Pony.objects.create(pink=1, weight=4.0)
with self.assertRaises(IntegrityError):
Pony.objects.create(pink=1, weight=7.0)
# Reversal.
with connection.schema_editor() as editor:
- operation.database_backwards('test_crmo', editor, new_state, project_state)
- self.assertTableNotExists('test_crmo_pony')
+ operation.database_backwards("test_crmo", editor, new_state, project_state)
+ self.assertTableNotExists("test_crmo_pony")
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'CreateModel')
+ self.assertEqual(definition[0], "CreateModel")
self.assertEqual(definition[1], [])
self.assertEqual(
- definition[2]['options']['constraints'],
+ definition[2]["options"]["constraints"],
[covering_unique_constraint],
)
@@ -507,7 +564,7 @@ class OperationTests(OperationTestBase):
("food_qs", FoodQuerySet.as_manager()),
("food_mgr", FoodManager("a", "b")),
("food_mgr_kwargs", FoodManager("x", "y", 3, 4)),
- ]
+ ],
)
self.assertEqual(operation.describe(), "Create model Food")
new_state = project_state.clone()
@@ -531,7 +588,7 @@ class OperationTests(OperationTestBase):
# Test the state alteration
operation = migrations.DeleteModel("Pony")
self.assertEqual(operation.describe(), "Delete model Pony")
- self.assertEqual(operation.migration_name_fragment, 'delete_pony')
+ self.assertEqual(operation.migration_name_fragment, "delete_pony")
new_state = project_state.clone()
operation.state_forwards("test_dlmo", new_state)
self.assertNotIn(("test_dlmo", "pony"), new_state.models)
@@ -570,32 +627,38 @@ class OperationTests(OperationTestBase):
self.assertTableNotExists("test_dlprmo_proxypony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_dlprmo", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_dlprmo", editor, new_state, project_state
+ )
self.assertTableExists("test_dlprmo_pony")
self.assertTableNotExists("test_dlprmo_proxypony")
def test_delete_mti_model(self):
- project_state = self.set_up_test_model('test_dlmtimo', mti_model=True)
+ project_state = self.set_up_test_model("test_dlmtimo", mti_model=True)
# Test the state alteration
- operation = migrations.DeleteModel('ShetlandPony')
+ operation = migrations.DeleteModel("ShetlandPony")
new_state = project_state.clone()
- operation.state_forwards('test_dlmtimo', new_state)
- self.assertIn(('test_dlmtimo', 'shetlandpony'), project_state.models)
- self.assertNotIn(('test_dlmtimo', 'shetlandpony'), new_state.models)
+ operation.state_forwards("test_dlmtimo", new_state)
+ self.assertIn(("test_dlmtimo", "shetlandpony"), project_state.models)
+ self.assertNotIn(("test_dlmtimo", "shetlandpony"), new_state.models)
# Test the database alteration
- self.assertTableExists('test_dlmtimo_pony')
- self.assertTableExists('test_dlmtimo_shetlandpony')
- self.assertColumnExists('test_dlmtimo_shetlandpony', 'pony_ptr_id')
+ self.assertTableExists("test_dlmtimo_pony")
+ self.assertTableExists("test_dlmtimo_shetlandpony")
+ self.assertColumnExists("test_dlmtimo_shetlandpony", "pony_ptr_id")
with connection.schema_editor() as editor:
- operation.database_forwards('test_dlmtimo', editor, project_state, new_state)
- self.assertTableExists('test_dlmtimo_pony')
- self.assertTableNotExists('test_dlmtimo_shetlandpony')
+ operation.database_forwards(
+ "test_dlmtimo", editor, project_state, new_state
+ )
+ self.assertTableExists("test_dlmtimo_pony")
+ self.assertTableNotExists("test_dlmtimo_shetlandpony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards('test_dlmtimo', editor, new_state, project_state)
- self.assertTableExists('test_dlmtimo_pony')
- self.assertTableExists('test_dlmtimo_shetlandpony')
- self.assertColumnExists('test_dlmtimo_shetlandpony', 'pony_ptr_id')
+ operation.database_backwards(
+ "test_dlmtimo", editor, new_state, project_state
+ )
+ self.assertTableExists("test_dlmtimo_pony")
+ self.assertTableExists("test_dlmtimo_shetlandpony")
+ self.assertColumnExists("test_dlmtimo_shetlandpony", "pony_ptr_id")
def test_rename_model(self):
"""
@@ -605,51 +668,69 @@ class OperationTests(OperationTestBase):
# Test the state alteration
operation = migrations.RenameModel("Pony", "Horse")
self.assertEqual(operation.describe(), "Rename model Pony to Horse")
- self.assertEqual(operation.migration_name_fragment, 'rename_pony_horse')
+ self.assertEqual(operation.migration_name_fragment, "rename_pony_horse")
# Test initial state and database
self.assertIn(("test_rnmo", "pony"), project_state.models)
self.assertNotIn(("test_rnmo", "horse"), project_state.models)
self.assertTableExists("test_rnmo_pony")
self.assertTableNotExists("test_rnmo_horse")
if connection.features.supports_foreign_keys:
- self.assertFKExists("test_rnmo_rider", ["pony_id"], ("test_rnmo_pony", "id"))
- self.assertFKNotExists("test_rnmo_rider", ["pony_id"], ("test_rnmo_horse", "id"))
+ self.assertFKExists(
+ "test_rnmo_rider", ["pony_id"], ("test_rnmo_pony", "id")
+ )
+ self.assertFKNotExists(
+ "test_rnmo_rider", ["pony_id"], ("test_rnmo_horse", "id")
+ )
# Migrate forwards
new_state = project_state.clone()
atomic_rename = connection.features.supports_atomic_references_rename
- new_state = self.apply_operations("test_rnmo", new_state, [operation], atomic=atomic_rename)
+ new_state = self.apply_operations(
+ "test_rnmo", new_state, [operation], atomic=atomic_rename
+ )
# Test new state and database
self.assertNotIn(("test_rnmo", "pony"), new_state.models)
self.assertIn(("test_rnmo", "horse"), new_state.models)
# RenameModel also repoints all incoming FKs and M2Ms
self.assertEqual(
- new_state.models['test_rnmo', 'rider'].fields['pony'].remote_field.model,
- 'test_rnmo.Horse',
+ new_state.models["test_rnmo", "rider"].fields["pony"].remote_field.model,
+ "test_rnmo.Horse",
)
self.assertTableNotExists("test_rnmo_pony")
self.assertTableExists("test_rnmo_horse")
if connection.features.supports_foreign_keys:
- self.assertFKNotExists("test_rnmo_rider", ["pony_id"], ("test_rnmo_pony", "id"))
- self.assertFKExists("test_rnmo_rider", ["pony_id"], ("test_rnmo_horse", "id"))
+ self.assertFKNotExists(
+ "test_rnmo_rider", ["pony_id"], ("test_rnmo_pony", "id")
+ )
+ self.assertFKExists(
+ "test_rnmo_rider", ["pony_id"], ("test_rnmo_horse", "id")
+ )
# Migrate backwards
- original_state = self.unapply_operations("test_rnmo", project_state, [operation], atomic=atomic_rename)
+ original_state = self.unapply_operations(
+ "test_rnmo", project_state, [operation], atomic=atomic_rename
+ )
# Test original state and database
self.assertIn(("test_rnmo", "pony"), original_state.models)
self.assertNotIn(("test_rnmo", "horse"), original_state.models)
self.assertEqual(
- original_state.models['test_rnmo', 'rider'].fields['pony'].remote_field.model,
- 'Pony',
+ original_state.models["test_rnmo", "rider"]
+ .fields["pony"]
+ .remote_field.model,
+ "Pony",
)
self.assertTableExists("test_rnmo_pony")
self.assertTableNotExists("test_rnmo_horse")
if connection.features.supports_foreign_keys:
- self.assertFKExists("test_rnmo_rider", ["pony_id"], ("test_rnmo_pony", "id"))
- self.assertFKNotExists("test_rnmo_rider", ["pony_id"], ("test_rnmo_horse", "id"))
+ self.assertFKExists(
+ "test_rnmo_rider", ["pony_id"], ("test_rnmo_pony", "id")
+ )
+ self.assertFKNotExists(
+ "test_rnmo_rider", ["pony_id"], ("test_rnmo_horse", "id")
+ )
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "RenameModel")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'old_name': "Pony", 'new_name': "Horse"})
+ self.assertEqual(definition[2], {"old_name": "Pony", "new_name": "Horse"})
def test_rename_model_state_forwards(self):
"""
@@ -657,19 +738,19 @@ class OperationTests(OperationTestBase):
on state without prior apps.
"""
state = ProjectState()
- state.add_model(ModelState('migrations', 'Foo', []))
- operation = migrations.RenameModel('Foo', 'Bar')
- operation.state_forwards('migrations', state)
- self.assertNotIn('apps', state.__dict__)
- self.assertNotIn(('migrations', 'foo'), state.models)
- self.assertIn(('migrations', 'bar'), state.models)
+ state.add_model(ModelState("migrations", "Foo", []))
+ operation = migrations.RenameModel("Foo", "Bar")
+ operation.state_forwards("migrations", state)
+ self.assertNotIn("apps", state.__dict__)
+ self.assertNotIn(("migrations", "foo"), state.models)
+ self.assertIn(("migrations", "bar"), state.models)
# Now with apps cached.
apps = state.apps
- operation = migrations.RenameModel('Bar', 'Foo')
- operation.state_forwards('migrations', state)
+ operation = migrations.RenameModel("Bar", "Foo")
+ operation.state_forwards("migrations", state)
self.assertIs(state.apps, apps)
- self.assertNotIn(('migrations', 'bar'), state.models)
- self.assertIn(('migrations', 'foo'), state.models)
+ self.assertNotIn(("migrations", "bar"), state.models)
+ self.assertIn(("migrations", "foo"), state.models)
def test_rename_model_with_self_referential_fk(self):
"""
@@ -685,105 +766,168 @@ class OperationTests(OperationTestBase):
self.assertIn(("test_rmwsrf", "horserider"), new_state.models)
# Remember, RenameModel also repoints all incoming FKs and M2Ms
self.assertEqual(
- 'self',
- new_state.models["test_rmwsrf", "horserider"].fields['friend'].remote_field.model
+ "self",
+ new_state.models["test_rmwsrf", "horserider"]
+ .fields["friend"]
+ .remote_field.model,
+ )
+ HorseRider = new_state.apps.get_model("test_rmwsrf", "horserider")
+ self.assertIs(
+ HorseRider._meta.get_field("horserider").remote_field.model, HorseRider
)
- HorseRider = new_state.apps.get_model('test_rmwsrf', 'horserider')
- self.assertIs(HorseRider._meta.get_field('horserider').remote_field.model, HorseRider)
# Test the database alteration
self.assertTableExists("test_rmwsrf_rider")
self.assertTableNotExists("test_rmwsrf_horserider")
if connection.features.supports_foreign_keys:
- self.assertFKExists("test_rmwsrf_rider", ["friend_id"], ("test_rmwsrf_rider", "id"))
- self.assertFKNotExists("test_rmwsrf_rider", ["friend_id"], ("test_rmwsrf_horserider", "id"))
+ self.assertFKExists(
+ "test_rmwsrf_rider", ["friend_id"], ("test_rmwsrf_rider", "id")
+ )
+ self.assertFKNotExists(
+ "test_rmwsrf_rider", ["friend_id"], ("test_rmwsrf_horserider", "id")
+ )
atomic_rename = connection.features.supports_atomic_references_rename
with connection.schema_editor(atomic=atomic_rename) as editor:
operation.database_forwards("test_rmwsrf", editor, project_state, new_state)
self.assertTableNotExists("test_rmwsrf_rider")
self.assertTableExists("test_rmwsrf_horserider")
if connection.features.supports_foreign_keys:
- self.assertFKNotExists("test_rmwsrf_horserider", ["friend_id"], ("test_rmwsrf_rider", "id"))
- self.assertFKExists("test_rmwsrf_horserider", ["friend_id"], ("test_rmwsrf_horserider", "id"))
+ self.assertFKNotExists(
+ "test_rmwsrf_horserider", ["friend_id"], ("test_rmwsrf_rider", "id")
+ )
+ self.assertFKExists(
+ "test_rmwsrf_horserider",
+ ["friend_id"],
+ ("test_rmwsrf_horserider", "id"),
+ )
# And test reversal
with connection.schema_editor(atomic=atomic_rename) as editor:
- operation.database_backwards("test_rmwsrf", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_rmwsrf", editor, new_state, project_state
+ )
self.assertTableExists("test_rmwsrf_rider")
self.assertTableNotExists("test_rmwsrf_horserider")
if connection.features.supports_foreign_keys:
- self.assertFKExists("test_rmwsrf_rider", ["friend_id"], ("test_rmwsrf_rider", "id"))
- self.assertFKNotExists("test_rmwsrf_rider", ["friend_id"], ("test_rmwsrf_horserider", "id"))
+ self.assertFKExists(
+ "test_rmwsrf_rider", ["friend_id"], ("test_rmwsrf_rider", "id")
+ )
+ self.assertFKNotExists(
+ "test_rmwsrf_rider", ["friend_id"], ("test_rmwsrf_horserider", "id")
+ )
def test_rename_model_with_superclass_fk(self):
"""
Tests the RenameModel operation on a model which has a superclass that
has a foreign key.
"""
- project_state = self.set_up_test_model("test_rmwsc", related_model=True, mti_model=True)
+ project_state = self.set_up_test_model(
+ "test_rmwsc", related_model=True, mti_model=True
+ )
# Test the state alteration
operation = migrations.RenameModel("ShetlandPony", "LittleHorse")
- self.assertEqual(operation.describe(), "Rename model ShetlandPony to LittleHorse")
+ self.assertEqual(
+ operation.describe(), "Rename model ShetlandPony to LittleHorse"
+ )
new_state = project_state.clone()
operation.state_forwards("test_rmwsc", new_state)
self.assertNotIn(("test_rmwsc", "shetlandpony"), new_state.models)
self.assertIn(("test_rmwsc", "littlehorse"), new_state.models)
# RenameModel shouldn't repoint the superclass's relations, only local ones
self.assertEqual(
- project_state.models['test_rmwsc', 'rider'].fields['pony'].remote_field.model,
- new_state.models['test_rmwsc', 'rider'].fields['pony'].remote_field.model,
+ project_state.models["test_rmwsc", "rider"]
+ .fields["pony"]
+ .remote_field.model,
+ new_state.models["test_rmwsc", "rider"].fields["pony"].remote_field.model,
)
# Before running the migration we have a table for Shetland Pony, not Little Horse
self.assertTableExists("test_rmwsc_shetlandpony")
self.assertTableNotExists("test_rmwsc_littlehorse")
if connection.features.supports_foreign_keys:
# and the foreign key on rider points to pony, not shetland pony
- self.assertFKExists("test_rmwsc_rider", ["pony_id"], ("test_rmwsc_pony", "id"))
- self.assertFKNotExists("test_rmwsc_rider", ["pony_id"], ("test_rmwsc_shetlandpony", "id"))
- with connection.schema_editor(atomic=connection.features.supports_atomic_references_rename) as editor:
+ self.assertFKExists(
+ "test_rmwsc_rider", ["pony_id"], ("test_rmwsc_pony", "id")
+ )
+ self.assertFKNotExists(
+ "test_rmwsc_rider", ["pony_id"], ("test_rmwsc_shetlandpony", "id")
+ )
+ with connection.schema_editor(
+ atomic=connection.features.supports_atomic_references_rename
+ ) as editor:
operation.database_forwards("test_rmwsc", editor, project_state, new_state)
# Now we have a little horse table, not shetland pony
self.assertTableNotExists("test_rmwsc_shetlandpony")
self.assertTableExists("test_rmwsc_littlehorse")
if connection.features.supports_foreign_keys:
# but the Foreign keys still point at pony, not little horse
- self.assertFKExists("test_rmwsc_rider", ["pony_id"], ("test_rmwsc_pony", "id"))
- self.assertFKNotExists("test_rmwsc_rider", ["pony_id"], ("test_rmwsc_littlehorse", "id"))
+ self.assertFKExists(
+ "test_rmwsc_rider", ["pony_id"], ("test_rmwsc_pony", "id")
+ )
+ self.assertFKNotExists(
+ "test_rmwsc_rider", ["pony_id"], ("test_rmwsc_littlehorse", "id")
+ )
def test_rename_model_with_self_referential_m2m(self):
app_label = "test_rename_model_with_self_referential_m2m"
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel("ReflexivePony", fields=[
- ("id", models.AutoField(primary_key=True)),
- ("ponies", models.ManyToManyField("self")),
- ]),
- ])
- project_state = self.apply_operations(app_label, project_state, operations=[
- migrations.RenameModel("ReflexivePony", "ReflexivePony2"),
- ], atomic=connection.features.supports_atomic_references_rename)
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "ReflexivePony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("ponies", models.ManyToManyField("self")),
+ ],
+ ),
+ ],
+ )
+ project_state = self.apply_operations(
+ app_label,
+ project_state,
+ operations=[
+ migrations.RenameModel("ReflexivePony", "ReflexivePony2"),
+ ],
+ atomic=connection.features.supports_atomic_references_rename,
+ )
Pony = project_state.apps.get_model(app_label, "ReflexivePony2")
pony = Pony.objects.create()
pony.ponies.add(pony)
def test_rename_model_with_m2m(self):
app_label = "test_rename_model_with_m2m"
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel("Rider", fields=[
- ("id", models.AutoField(primary_key=True)),
- ]),
- migrations.CreateModel("Pony", fields=[
- ("id", models.AutoField(primary_key=True)),
- ("riders", models.ManyToManyField("Rider")),
- ]),
- ])
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("riders", models.ManyToManyField("Rider")),
+ ],
+ ),
+ ],
+ )
Pony = project_state.apps.get_model(app_label, "Pony")
Rider = project_state.apps.get_model(app_label, "Rider")
pony = Pony.objects.create()
rider = Rider.objects.create()
pony.riders.add(rider)
- project_state = self.apply_operations(app_label, project_state, operations=[
- migrations.RenameModel("Pony", "Pony2"),
- ], atomic=connection.features.supports_atomic_references_rename)
+ project_state = self.apply_operations(
+ app_label,
+ project_state,
+ operations=[
+ migrations.RenameModel("Pony", "Pony2"),
+ ],
+ atomic=connection.features.supports_atomic_references_rename,
+ )
Pony = project_state.apps.get_model(app_label, "Pony2")
Rider = project_state.apps.get_model(app_label, "Rider")
pony = Pony.objects.create()
@@ -791,21 +935,37 @@ class OperationTests(OperationTestBase):
pony.riders.add(rider)
self.assertEqual(Pony.objects.count(), 2)
self.assertEqual(Rider.objects.count(), 2)
- self.assertEqual(Pony._meta.get_field('riders').remote_field.through.objects.count(), 2)
+ self.assertEqual(
+ Pony._meta.get_field("riders").remote_field.through.objects.count(), 2
+ )
def test_rename_model_with_db_table_noop(self):
- app_label = 'test_rmwdbtn'
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel('Rider', fields=[
- ('id', models.AutoField(primary_key=True)),
- ], options={'db_table': 'rider'}),
- migrations.CreateModel('Pony', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('rider', models.ForeignKey('%s.Rider' % app_label, models.CASCADE)),
- ]),
- ])
+ app_label = "test_rmwdbtn"
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ options={"db_table": "rider"},
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "rider",
+ models.ForeignKey("%s.Rider" % app_label, models.CASCADE),
+ ),
+ ],
+ ),
+ ],
+ )
new_state = project_state.clone()
- operation = migrations.RenameModel('Rider', 'Runner')
+ operation = migrations.RenameModel("Rider", "Runner")
operation.state_forwards(app_label, new_state)
with connection.schema_editor() as editor:
@@ -813,28 +973,45 @@ class OperationTests(OperationTestBase):
operation.database_forwards(app_label, editor, project_state, new_state)
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
- operation.database_backwards(app_label, editor, new_state, project_state)
+ operation.database_backwards(
+ app_label, editor, new_state, project_state
+ )
def test_rename_m2m_target_model(self):
app_label = "test_rename_m2m_target_model"
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel("Rider", fields=[
- ("id", models.AutoField(primary_key=True)),
- ]),
- migrations.CreateModel("Pony", fields=[
- ("id", models.AutoField(primary_key=True)),
- ("riders", models.ManyToManyField("Rider")),
- ]),
- ])
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("riders", models.ManyToManyField("Rider")),
+ ],
+ ),
+ ],
+ )
Pony = project_state.apps.get_model(app_label, "Pony")
Rider = project_state.apps.get_model(app_label, "Rider")
pony = Pony.objects.create()
rider = Rider.objects.create()
pony.riders.add(rider)
- project_state = self.apply_operations(app_label, project_state, operations=[
- migrations.RenameModel("Rider", "Rider2"),
- ], atomic=connection.features.supports_atomic_references_rename)
+ project_state = self.apply_operations(
+ app_label,
+ project_state,
+ operations=[
+ migrations.RenameModel("Rider", "Rider2"),
+ ],
+ atomic=connection.features.supports_atomic_references_rename,
+ )
Pony = project_state.apps.get_model(app_label, "Pony")
Rider = project_state.apps.get_model(app_label, "Rider2")
pony = Pony.objects.create()
@@ -842,28 +1019,56 @@ class OperationTests(OperationTestBase):
pony.riders.add(rider)
self.assertEqual(Pony.objects.count(), 2)
self.assertEqual(Rider.objects.count(), 2)
- self.assertEqual(Pony._meta.get_field('riders').remote_field.through.objects.count(), 2)
+ self.assertEqual(
+ Pony._meta.get_field("riders").remote_field.through.objects.count(), 2
+ )
def test_rename_m2m_through_model(self):
app_label = "test_rename_through"
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel("Rider", fields=[
- ("id", models.AutoField(primary_key=True)),
- ]),
- migrations.CreateModel("Pony", fields=[
- ("id", models.AutoField(primary_key=True)),
- ]),
- migrations.CreateModel("PonyRider", fields=[
- ("id", models.AutoField(primary_key=True)),
- ("rider", models.ForeignKey("test_rename_through.Rider", models.CASCADE)),
- ("pony", models.ForeignKey("test_rename_through.Pony", models.CASCADE)),
- ]),
- migrations.AddField(
- "Pony",
- "riders",
- models.ManyToManyField("test_rename_through.Rider", through="test_rename_through.PonyRider"),
- ),
- ])
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ "PonyRider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "rider",
+ models.ForeignKey(
+ "test_rename_through.Rider", models.CASCADE
+ ),
+ ),
+ (
+ "pony",
+ models.ForeignKey(
+ "test_rename_through.Pony", models.CASCADE
+ ),
+ ),
+ ],
+ ),
+ migrations.AddField(
+ "Pony",
+ "riders",
+ models.ManyToManyField(
+ "test_rename_through.Rider",
+ through="test_rename_through.PonyRider",
+ ),
+ ),
+ ],
+ )
Pony = project_state.apps.get_model(app_label, "Pony")
Rider = project_state.apps.get_model(app_label, "Rider")
PonyRider = project_state.apps.get_model(app_label, "PonyRider")
@@ -871,9 +1076,13 @@ class OperationTests(OperationTestBase):
rider = Rider.objects.create()
PonyRider.objects.create(pony=pony, rider=rider)
- project_state = self.apply_operations(app_label, project_state, operations=[
- migrations.RenameModel("PonyRider", "PonyRider2"),
- ])
+ project_state = self.apply_operations(
+ app_label,
+ project_state,
+ operations=[
+ migrations.RenameModel("PonyRider", "PonyRider2"),
+ ],
+ )
Pony = project_state.apps.get_model(app_label, "Pony")
Rider = project_state.apps.get_model(app_label, "Rider")
PonyRider = project_state.apps.get_model(app_label, "PonyRider2")
@@ -887,28 +1096,49 @@ class OperationTests(OperationTestBase):
def test_rename_m2m_model_after_rename_field(self):
"""RenameModel renames a many-to-many column after a RenameField."""
- app_label = 'test_rename_multiple'
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel('Pony', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=20)),
- ]),
- migrations.CreateModel('Rider', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('pony', models.ForeignKey('test_rename_multiple.Pony', models.CASCADE)),
- ]),
- migrations.CreateModel('PonyRider', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('riders', models.ManyToManyField('Rider')),
- ]),
- migrations.RenameField(model_name='pony', old_name='name', new_name='fancy_name'),
- migrations.RenameModel(old_name='Rider', new_name='Jockey'),
- ], atomic=connection.features.supports_atomic_references_rename)
- Pony = project_state.apps.get_model(app_label, 'Pony')
- Jockey = project_state.apps.get_model(app_label, 'Jockey')
- PonyRider = project_state.apps.get_model(app_label, 'PonyRider')
+ app_label = "test_rename_multiple"
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=20)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "pony",
+ models.ForeignKey(
+ "test_rename_multiple.Pony", models.CASCADE
+ ),
+ ),
+ ],
+ ),
+ migrations.CreateModel(
+ "PonyRider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("riders", models.ManyToManyField("Rider")),
+ ],
+ ),
+ migrations.RenameField(
+ model_name="pony", old_name="name", new_name="fancy_name"
+ ),
+ migrations.RenameModel(old_name="Rider", new_name="Jockey"),
+ ],
+ atomic=connection.features.supports_atomic_references_rename,
+ )
+ Pony = project_state.apps.get_model(app_label, "Pony")
+ Jockey = project_state.apps.get_model(app_label, "Jockey")
+ PonyRider = project_state.apps.get_model(app_label, "PonyRider")
# No "no such column" error means the column was renamed correctly.
- pony = Pony.objects.create(fancy_name='a good name')
+ pony = Pony.objects.create(fancy_name="a good name")
jockey = Jockey.objects.create(pony=pony)
ponyrider = PonyRider.objects.create()
ponyrider.riders.add(jockey)
@@ -924,10 +1154,10 @@ class OperationTests(OperationTestBase):
models.FloatField(null=True, default=5),
)
self.assertEqual(operation.describe(), "Add field height to Pony")
- self.assertEqual(operation.migration_name_fragment, 'pony_height')
+ self.assertEqual(operation.migration_name_fragment, "pony_height")
project_state, new_state = self.make_test_state("test_adfl", operation)
self.assertEqual(len(new_state.models["test_adfl", "pony"].fields), 4)
- field = new_state.models['test_adfl', 'pony'].fields['height']
+ field = new_state.models["test_adfl", "pony"].fields["height"]
self.assertEqual(field.default, 5)
# Test the database alteration
self.assertColumnNotExists("test_adfl_pony", "height")
@@ -953,30 +1183,34 @@ class OperationTests(OperationTestBase):
Pony = project_state.apps.get_model("test_adchfl", "Pony")
pony = Pony.objects.create(weight=42)
- new_state = self.apply_operations("test_adchfl", project_state, [
- migrations.AddField(
- "Pony",
- "text",
- models.CharField(max_length=10, default="some text"),
- ),
- migrations.AddField(
- "Pony",
- "empty",
- models.CharField(max_length=10, default=""),
- ),
- # If not properly quoted digits would be interpreted as an int.
- migrations.AddField(
- "Pony",
- "digits",
- models.CharField(max_length=10, default="42"),
- ),
- # Manual quoting is fragile and could trip on quotes. Refs #xyz.
- migrations.AddField(
- "Pony",
- "quotes",
- models.CharField(max_length=10, default='"\'"'),
- ),
- ])
+ new_state = self.apply_operations(
+ "test_adchfl",
+ project_state,
+ [
+ migrations.AddField(
+ "Pony",
+ "text",
+ models.CharField(max_length=10, default="some text"),
+ ),
+ migrations.AddField(
+ "Pony",
+ "empty",
+ models.CharField(max_length=10, default=""),
+ ),
+ # If not properly quoted digits would be interpreted as an int.
+ migrations.AddField(
+ "Pony",
+ "digits",
+ models.CharField(max_length=10, default="42"),
+ ),
+ # Manual quoting is fragile and could trip on quotes. Refs #xyz.
+ migrations.AddField(
+ "Pony",
+ "quotes",
+ models.CharField(max_length=10, default='"\'"'),
+ ),
+ ],
+ )
Pony = new_state.apps.get_model("test_adchfl", "Pony")
pony = Pony.objects.get(pk=pony.pk)
@@ -994,30 +1228,34 @@ class OperationTests(OperationTestBase):
Pony = project_state.apps.get_model("test_adtxtfl", "Pony")
pony = Pony.objects.create(weight=42)
- new_state = self.apply_operations("test_adtxtfl", project_state, [
- migrations.AddField(
- "Pony",
- "text",
- models.TextField(default="some text"),
- ),
- migrations.AddField(
- "Pony",
- "empty",
- models.TextField(default=""),
- ),
- # If not properly quoted digits would be interpreted as an int.
- migrations.AddField(
- "Pony",
- "digits",
- models.TextField(default="42"),
- ),
- # Manual quoting is fragile and could trip on quotes. Refs #xyz.
- migrations.AddField(
- "Pony",
- "quotes",
- models.TextField(default='"\'"'),
- ),
- ])
+ new_state = self.apply_operations(
+ "test_adtxtfl",
+ project_state,
+ [
+ migrations.AddField(
+ "Pony",
+ "text",
+ models.TextField(default="some text"),
+ ),
+ migrations.AddField(
+ "Pony",
+ "empty",
+ models.TextField(default=""),
+ ),
+ # If not properly quoted digits would be interpreted as an int.
+ migrations.AddField(
+ "Pony",
+ "digits",
+ models.TextField(default="42"),
+ ),
+ # Manual quoting is fragile and could trip on quotes. Refs #xyz.
+ migrations.AddField(
+ "Pony",
+ "quotes",
+ models.TextField(default='"\'"'),
+ ),
+ ],
+ )
Pony = new_state.apps.get_model("test_adtxtfl", "Pony")
pony = Pony.objects.get(pk=pony.pk)
@@ -1035,30 +1273,34 @@ class OperationTests(OperationTestBase):
Pony = project_state.apps.get_model("test_adbinfl", "Pony")
pony = Pony.objects.create(weight=42)
- new_state = self.apply_operations("test_adbinfl", project_state, [
- migrations.AddField(
- "Pony",
- "blob",
- models.BinaryField(default=b"some text"),
- ),
- migrations.AddField(
- "Pony",
- "empty",
- models.BinaryField(default=b""),
- ),
- # If not properly quoted digits would be interpreted as an int.
- migrations.AddField(
- "Pony",
- "digits",
- models.BinaryField(default=b"42"),
- ),
- # Manual quoting is fragile and could trip on quotes. Refs #xyz.
- migrations.AddField(
- "Pony",
- "quotes",
- models.BinaryField(default=b'"\'"'),
- ),
- ])
+ new_state = self.apply_operations(
+ "test_adbinfl",
+ project_state,
+ [
+ migrations.AddField(
+ "Pony",
+ "blob",
+ models.BinaryField(default=b"some text"),
+ ),
+ migrations.AddField(
+ "Pony",
+ "empty",
+ models.BinaryField(default=b""),
+ ),
+ # If not properly quoted digits would be interpreted as an int.
+ migrations.AddField(
+ "Pony",
+ "digits",
+ models.BinaryField(default=b"42"),
+ ),
+ # Manual quoting is fragile and could trip on quotes. Refs #xyz.
+ migrations.AddField(
+ "Pony",
+ "quotes",
+ models.BinaryField(default=b'"\'"'),
+ ),
+ ],
+ )
Pony = new_state.apps.get_model("test_adbinfl", "Pony")
pony = Pony.objects.get(pk=pony.pk)
@@ -1082,7 +1324,9 @@ class OperationTests(OperationTestBase):
new_state = project_state.clone()
operation.state_forwards("test_regr22168", new_state)
with connection.schema_editor() as editor:
- operation.database_forwards("test_regr22168", editor, project_state, new_state)
+ operation.database_forwards(
+ "test_regr22168", editor, project_state, new_state
+ )
self.assertColumnExists("test_regr22168_pony", "order")
def test_add_field_preserve_default(self):
@@ -1101,7 +1345,7 @@ class OperationTests(OperationTestBase):
new_state = project_state.clone()
operation.state_forwards("test_adflpd", new_state)
self.assertEqual(len(new_state.models["test_adflpd", "pony"].fields), 4)
- field = new_state.models['test_adflpd', 'pony'].fields['height']
+ field = new_state.models["test_adflpd", "pony"].fields["height"]
self.assertEqual(field.default, models.NOT_PROVIDED)
# Test the database alteration
project_state.apps.get_model("test_adflpd", "pony").objects.create(
@@ -1115,7 +1359,9 @@ class OperationTests(OperationTestBase):
definition = operation.deconstruct()
self.assertEqual(definition[0], "AddField")
self.assertEqual(definition[1], [])
- self.assertEqual(sorted(definition[2]), ["field", "model_name", "name", "preserve_default"])
+ self.assertEqual(
+ sorted(definition[2]), ["field", "model_name", "name", "preserve_default"]
+ )
def test_add_field_m2m(self):
"""
@@ -1123,7 +1369,9 @@ class OperationTests(OperationTestBase):
"""
project_state = self.set_up_test_model("test_adflmm", second_model=True)
# Test the state alteration
- operation = migrations.AddField("Pony", "stables", models.ManyToManyField("Stable", related_name="ponies"))
+ operation = migrations.AddField(
+ "Pony", "stables", models.ManyToManyField("Stable", related_name="ponies")
+ )
new_state = project_state.clone()
operation.state_forwards("test_adflmm", new_state)
self.assertEqual(len(new_state.models["test_adflmm", "pony"].fields), 4)
@@ -1142,37 +1390,73 @@ class OperationTests(OperationTestBase):
p.stables.all().delete()
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_adflmm", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_adflmm", editor, new_state, project_state
+ )
self.assertTableNotExists("test_adflmm_pony_stables")
def test_alter_field_m2m(self):
project_state = self.set_up_test_model("test_alflmm", second_model=True)
- project_state = self.apply_operations("test_alflmm", project_state, operations=[
- migrations.AddField("Pony", "stables", models.ManyToManyField("Stable", related_name="ponies"))
- ])
+ project_state = self.apply_operations(
+ "test_alflmm",
+ project_state,
+ operations=[
+ migrations.AddField(
+ "Pony",
+ "stables",
+ models.ManyToManyField("Stable", related_name="ponies"),
+ )
+ ],
+ )
Pony = project_state.apps.get_model("test_alflmm", "Pony")
- self.assertFalse(Pony._meta.get_field('stables').blank)
+ self.assertFalse(Pony._meta.get_field("stables").blank)
- project_state = self.apply_operations("test_alflmm", project_state, operations=[
- migrations.AlterField(
- "Pony", "stables", models.ManyToManyField(to="Stable", related_name="ponies", blank=True)
- )
- ])
+ project_state = self.apply_operations(
+ "test_alflmm",
+ project_state,
+ operations=[
+ migrations.AlterField(
+ "Pony",
+ "stables",
+ models.ManyToManyField(
+ to="Stable", related_name="ponies", blank=True
+ ),
+ )
+ ],
+ )
Pony = project_state.apps.get_model("test_alflmm", "Pony")
- self.assertTrue(Pony._meta.get_field('stables').blank)
+ self.assertTrue(Pony._meta.get_field("stables").blank)
def test_repoint_field_m2m(self):
- project_state = self.set_up_test_model("test_alflmm", second_model=True, third_model=True)
+ project_state = self.set_up_test_model(
+ "test_alflmm", second_model=True, third_model=True
+ )
- project_state = self.apply_operations("test_alflmm", project_state, operations=[
- migrations.AddField("Pony", "places", models.ManyToManyField("Stable", related_name="ponies"))
- ])
+ project_state = self.apply_operations(
+ "test_alflmm",
+ project_state,
+ operations=[
+ migrations.AddField(
+ "Pony",
+ "places",
+ models.ManyToManyField("Stable", related_name="ponies"),
+ )
+ ],
+ )
Pony = project_state.apps.get_model("test_alflmm", "Pony")
- project_state = self.apply_operations("test_alflmm", project_state, operations=[
- migrations.AlterField("Pony", "places", models.ManyToManyField(to="Van", related_name="ponies"))
- ])
+ project_state = self.apply_operations(
+ "test_alflmm",
+ project_state,
+ operations=[
+ migrations.AlterField(
+ "Pony",
+ "places",
+ models.ManyToManyField(to="Van", related_name="ponies"),
+ )
+ ],
+ )
# Ensure the new field actually works
Pony = project_state.apps.get_model("test_alflmm", "Pony")
@@ -1184,14 +1468,24 @@ class OperationTests(OperationTestBase):
def test_remove_field_m2m(self):
project_state = self.set_up_test_model("test_rmflmm", second_model=True)
- project_state = self.apply_operations("test_rmflmm", project_state, operations=[
- migrations.AddField("Pony", "stables", models.ManyToManyField("Stable", related_name="ponies"))
- ])
+ project_state = self.apply_operations(
+ "test_rmflmm",
+ project_state,
+ operations=[
+ migrations.AddField(
+ "Pony",
+ "stables",
+ models.ManyToManyField("Stable", related_name="ponies"),
+ )
+ ],
+ )
self.assertTableExists("test_rmflmm_pony_stables")
with_field_state = project_state.clone()
operations = [migrations.RemoveField("Pony", "stables")]
- project_state = self.apply_operations("test_rmflmm", project_state, operations=operations)
+ project_state = self.apply_operations(
+ "test_rmflmm", project_state, operations=operations
+ )
self.assertTableNotExists("test_rmflmm_pony_stables")
# And test reversal
@@ -1202,19 +1496,40 @@ class OperationTests(OperationTestBase):
project_state = self.set_up_test_model("test_rmflmmwt", second_model=True)
self.assertTableNotExists("test_rmflmmwt_ponystables")
- project_state = self.apply_operations("test_rmflmmwt", project_state, operations=[
- migrations.CreateModel("PonyStables", fields=[
- ("pony", models.ForeignKey('test_rmflmmwt.Pony', models.CASCADE)),
- ("stable", models.ForeignKey('test_rmflmmwt.Stable', models.CASCADE)),
- ]),
- migrations.AddField(
- "Pony", "stables",
- models.ManyToManyField("Stable", related_name="ponies", through='test_rmflmmwt.PonyStables')
- )
- ])
+ project_state = self.apply_operations(
+ "test_rmflmmwt",
+ project_state,
+ operations=[
+ migrations.CreateModel(
+ "PonyStables",
+ fields=[
+ (
+ "pony",
+ models.ForeignKey("test_rmflmmwt.Pony", models.CASCADE),
+ ),
+ (
+ "stable",
+ models.ForeignKey("test_rmflmmwt.Stable", models.CASCADE),
+ ),
+ ],
+ ),
+ migrations.AddField(
+ "Pony",
+ "stables",
+ models.ManyToManyField(
+ "Stable",
+ related_name="ponies",
+ through="test_rmflmmwt.PonyStables",
+ ),
+ ),
+ ],
+ )
self.assertTableExists("test_rmflmmwt_ponystables")
- operations = [migrations.RemoveField("Pony", "stables"), migrations.DeleteModel("PonyStables")]
+ operations = [
+ migrations.RemoveField("Pony", "stables"),
+ migrations.DeleteModel("PonyStables"),
+ ]
self.apply_operations("test_rmflmmwt", project_state, operations=operations)
def test_remove_field(self):
@@ -1225,7 +1540,7 @@ class OperationTests(OperationTestBase):
# Test the state alteration
operation = migrations.RemoveField("Pony", "pink")
self.assertEqual(operation.describe(), "Remove field pink from Pony")
- self.assertEqual(operation.migration_name_fragment, 'remove_pony_pink')
+ self.assertEqual(operation.migration_name_fragment, "remove_pony_pink")
new_state = project_state.clone()
operation.state_forwards("test_rmfl", new_state)
self.assertEqual(len(new_state.models["test_rmfl", "pony"].fields), 2)
@@ -1242,7 +1557,7 @@ class OperationTests(OperationTestBase):
definition = operation.deconstruct()
self.assertEqual(definition[0], "RemoveField")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': "Pony", 'name': 'pink'})
+ self.assertEqual(definition[2], {"model_name": "Pony", "name": "pink"})
def test_remove_fk(self):
"""
@@ -1268,11 +1583,16 @@ class OperationTests(OperationTestBase):
project_state = self.set_up_test_model("test_almota")
# Test the state alteration
operation = migrations.AlterModelTable("Pony", "test_almota_pony_2")
- self.assertEqual(operation.describe(), "Rename table for Pony to test_almota_pony_2")
- self.assertEqual(operation.migration_name_fragment, 'alter_pony_table')
+ self.assertEqual(
+ operation.describe(), "Rename table for Pony to test_almota_pony_2"
+ )
+ self.assertEqual(operation.migration_name_fragment, "alter_pony_table")
new_state = project_state.clone()
operation.state_forwards("test_almota", new_state)
- self.assertEqual(new_state.models["test_almota", "pony"].options["db_table"], "test_almota_pony_2")
+ self.assertEqual(
+ new_state.models["test_almota", "pony"].options["db_table"],
+ "test_almota_pony_2",
+ )
# Test the database alteration
self.assertTableExists("test_almota_pony")
self.assertTableNotExists("test_almota_pony_2")
@@ -1282,14 +1602,16 @@ class OperationTests(OperationTestBase):
self.assertTableExists("test_almota_pony_2")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_almota", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_almota", editor, new_state, project_state
+ )
self.assertTableExists("test_almota_pony")
self.assertTableNotExists("test_almota_pony_2")
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "AlterModelTable")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'name': "Pony", 'table': "test_almota_pony_2"})
+ self.assertEqual(definition[2], {"name": "Pony", "table": "test_almota_pony_2"})
def test_alter_model_table_none(self):
"""
@@ -1307,7 +1629,10 @@ class OperationTests(OperationTestBase):
operation = migrations.AlterModelTable("Pony", "test_almota_pony")
new_state = project_state.clone()
operation.state_forwards("test_almota", new_state)
- self.assertEqual(new_state.models["test_almota", "pony"].options["db_table"], "test_almota_pony")
+ self.assertEqual(
+ new_state.models["test_almota", "pony"].options["db_table"],
+ "test_almota_pony",
+ )
# Test the database alteration
self.assertTableExists("test_almota_pony")
with connection.schema_editor() as editor:
@@ -1315,7 +1640,9 @@ class OperationTests(OperationTestBase):
self.assertTableExists("test_almota_pony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_almota", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_almota", editor, new_state, project_state
+ )
self.assertTableExists("test_almota_pony")
def test_alter_model_table_m2m(self):
@@ -1323,11 +1650,15 @@ class OperationTests(OperationTestBase):
AlterModelTable should rename auto-generated M2M tables.
"""
app_label = "test_talflmltlm2m"
- pony_db_table = 'pony_foo'
- project_state = self.set_up_test_model(app_label, second_model=True, db_table=pony_db_table)
+ pony_db_table = "pony_foo"
+ project_state = self.set_up_test_model(
+ app_label, second_model=True, db_table=pony_db_table
+ )
# Add the M2M field
first_state = project_state.clone()
- operation = migrations.AddField("Pony", "stables", models.ManyToManyField("Stable"))
+ operation = migrations.AddField(
+ "Pony", "stables", models.ManyToManyField("Stable")
+ )
operation.state_forwards(app_label, first_state)
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, project_state, first_state)
@@ -1337,7 +1668,7 @@ class OperationTests(OperationTestBase):
self.assertTableNotExists(new_m2m_table)
# Rename the Pony db_table which should also rename the m2m table.
second_state = first_state.clone()
- operation = migrations.AlterModelTable(name='pony', table=None)
+ operation = migrations.AlterModelTable(name="pony", table=None)
operation.state_forwards(app_label, second_state)
atomic_rename = connection.features.supports_atomic_references_rename
with connection.schema_editor(atomic=atomic_rename) as editor:
@@ -1356,13 +1687,17 @@ class OperationTests(OperationTestBase):
"""
project_state = self.set_up_test_model("test_alfl")
# Test the state alteration
- operation = migrations.AlterField("Pony", "pink", models.IntegerField(null=True))
+ operation = migrations.AlterField(
+ "Pony", "pink", models.IntegerField(null=True)
+ )
self.assertEqual(operation.describe(), "Alter field pink on Pony")
- self.assertEqual(operation.migration_name_fragment, 'alter_pony_pink')
+ self.assertEqual(operation.migration_name_fragment, "alter_pony_pink")
new_state = project_state.clone()
operation.state_forwards("test_alfl", new_state)
- self.assertIs(project_state.models['test_alfl', 'pony'].fields['pink'].null, False)
- self.assertIs(new_state.models['test_alfl', 'pony'].fields['pink'].null, True)
+ self.assertIs(
+ project_state.models["test_alfl", "pony"].fields["pink"].null, False
+ )
+ self.assertIs(new_state.models["test_alfl", "pony"].fields["pink"].null, True)
# Test the database alteration
self.assertColumnNotNull("test_alfl_pony", "pink")
with connection.schema_editor() as editor:
@@ -1383,53 +1718,57 @@ class OperationTests(OperationTestBase):
AlterField operation is a noop when adding only a db_column and the
column name is not changed.
"""
- app_label = 'test_afadbn'
+ app_label = "test_afadbn"
project_state = self.set_up_test_model(app_label, related_model=True)
- pony_table = '%s_pony' % app_label
+ pony_table = "%s_pony" % app_label
new_state = project_state.clone()
- operation = migrations.AlterField('Pony', 'weight', models.FloatField(db_column='weight'))
+ operation = migrations.AlterField(
+ "Pony", "weight", models.FloatField(db_column="weight")
+ )
operation.state_forwards(app_label, new_state)
self.assertIsNone(
- project_state.models[app_label, 'pony'].fields['weight'].db_column,
+ project_state.models[app_label, "pony"].fields["weight"].db_column,
)
self.assertEqual(
- new_state.models[app_label, 'pony'].fields['weight'].db_column,
- 'weight',
+ new_state.models[app_label, "pony"].fields["weight"].db_column,
+ "weight",
)
- self.assertColumnExists(pony_table, 'weight')
+ self.assertColumnExists(pony_table, "weight")
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
operation.database_forwards(app_label, editor, project_state, new_state)
- self.assertColumnExists(pony_table, 'weight')
+ self.assertColumnExists(pony_table, "weight")
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
- operation.database_backwards(app_label, editor, new_state, project_state)
- self.assertColumnExists(pony_table, 'weight')
+ operation.database_backwards(
+ app_label, editor, new_state, project_state
+ )
+ self.assertColumnExists(pony_table, "weight")
- rider_table = '%s_rider' % app_label
+ rider_table = "%s_rider" % app_label
new_state = project_state.clone()
operation = migrations.AlterField(
- 'Rider',
- 'pony',
- models.ForeignKey('Pony', models.CASCADE, db_column='pony_id'),
+ "Rider",
+ "pony",
+ models.ForeignKey("Pony", models.CASCADE, db_column="pony_id"),
)
operation.state_forwards(app_label, new_state)
self.assertIsNone(
- project_state.models[app_label, 'rider'].fields['pony'].db_column,
+ project_state.models[app_label, "rider"].fields["pony"].db_column,
)
self.assertIs(
- new_state.models[app_label, 'rider'].fields['pony'].db_column,
- 'pony_id',
+ new_state.models[app_label, "rider"].fields["pony"].db_column,
+ "pony_id",
)
- self.assertColumnExists(rider_table, 'pony_id')
+ self.assertColumnExists(rider_table, "pony_id")
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
operation.database_forwards(app_label, editor, project_state, new_state)
- self.assertColumnExists(rider_table, 'pony_id')
+ self.assertColumnExists(rider_table, "pony_id")
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
operation.database_forwards(app_label, editor, new_state, project_state)
- self.assertColumnExists(rider_table, 'pony_id')
+ self.assertColumnExists(rider_table, "pony_id")
def test_alter_field_pk(self):
"""
@@ -1437,15 +1776,17 @@ class OperationTests(OperationTestBase):
"""
project_state = self.set_up_test_model("test_alflpk")
# Test the state alteration
- operation = migrations.AlterField("Pony", "id", models.IntegerField(primary_key=True))
+ operation = migrations.AlterField(
+ "Pony", "id", models.IntegerField(primary_key=True)
+ )
new_state = project_state.clone()
operation.state_forwards("test_alflpk", new_state)
self.assertIsInstance(
- project_state.models['test_alflpk', 'pony'].fields['id'],
+ project_state.models["test_alflpk", "pony"].fields["id"],
models.AutoField,
)
self.assertIsInstance(
- new_state.models['test_alflpk', 'pony'].fields['id'],
+ new_state.models["test_alflpk", "pony"].fields["id"],
models.IntegerField,
)
# Test the database alteration
@@ -1453,34 +1794,45 @@ class OperationTests(OperationTestBase):
operation.database_forwards("test_alflpk", editor, project_state, new_state)
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_alflpk", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_alflpk", editor, new_state, project_state
+ )
- @skipUnlessDBFeature('supports_foreign_keys')
+ @skipUnlessDBFeature("supports_foreign_keys")
def test_alter_field_pk_fk(self):
"""
Tests the AlterField operation on primary keys changes any FKs pointing to it.
"""
project_state = self.set_up_test_model("test_alflpkfk", related_model=True)
- project_state = self.apply_operations('test_alflpkfk', project_state, [
- migrations.CreateModel('Stable', fields=[
- ('ponies', models.ManyToManyField('Pony')),
- ]),
- migrations.AddField(
- 'Pony',
- 'stables',
- models.ManyToManyField('Stable'),
- ),
- ])
+ project_state = self.apply_operations(
+ "test_alflpkfk",
+ project_state,
+ [
+ migrations.CreateModel(
+ "Stable",
+ fields=[
+ ("ponies", models.ManyToManyField("Pony")),
+ ],
+ ),
+ migrations.AddField(
+ "Pony",
+ "stables",
+ models.ManyToManyField("Stable"),
+ ),
+ ],
+ )
# Test the state alteration
- operation = migrations.AlterField("Pony", "id", models.FloatField(primary_key=True))
+ operation = migrations.AlterField(
+ "Pony", "id", models.FloatField(primary_key=True)
+ )
new_state = project_state.clone()
operation.state_forwards("test_alflpkfk", new_state)
self.assertIsInstance(
- project_state.models['test_alflpkfk', 'pony'].fields['id'],
+ project_state.models["test_alflpkfk", "pony"].fields["id"],
models.AutoField,
)
self.assertIsInstance(
- new_state.models['test_alflpkfk', 'pony'].fields['id'],
+ new_state.models["test_alflpkfk", "pony"].fields["id"],
models.FloatField,
)
@@ -1488,27 +1840,33 @@ class OperationTests(OperationTestBase):
with connection.cursor() as cursor:
id_type, id_null = [
(c.type_code, c.null_ok)
- for c in connection.introspection.get_table_description(cursor, "test_alflpkfk_pony")
+ for c in connection.introspection.get_table_description(
+ cursor, "test_alflpkfk_pony"
+ )
if c.name == "id"
][0]
fk_type, fk_null = [
(c.type_code, c.null_ok)
- for c in connection.introspection.get_table_description(cursor, "test_alflpkfk_rider")
+ for c in connection.introspection.get_table_description(
+ cursor, "test_alflpkfk_rider"
+ )
if c.name == "pony_id"
][0]
m2m_fk_type, m2m_fk_null = [
(c.type_code, c.null_ok)
for c in connection.introspection.get_table_description(
cursor,
- 'test_alflpkfk_pony_stables',
- ) if c.name == 'pony_id'
+ "test_alflpkfk_pony_stables",
+ )
+ if c.name == "pony_id"
][0]
remote_m2m_fk_type, remote_m2m_fk_null = [
(c.type_code, c.null_ok)
for c in connection.introspection.get_table_description(
cursor,
- 'test_alflpkfk_stable_ponies',
- ) if c.name == 'pony_id'
+ "test_alflpkfk_stable_ponies",
+ )
+ if c.name == "pony_id"
][0]
self.assertEqual(id_type, fk_type)
self.assertEqual(id_type, m2m_fk_type)
@@ -1520,55 +1878,68 @@ class OperationTests(OperationTestBase):
assertIdTypeEqualsFkType()
# Test the database alteration
with connection.schema_editor() as editor:
- operation.database_forwards("test_alflpkfk", editor, project_state, new_state)
+ operation.database_forwards(
+ "test_alflpkfk", editor, project_state, new_state
+ )
assertIdTypeEqualsFkType()
if connection.features.supports_foreign_keys:
self.assertFKExists(
- 'test_alflpkfk_pony_stables',
- ['pony_id'],
- ('test_alflpkfk_pony', 'id'),
+ "test_alflpkfk_pony_stables",
+ ["pony_id"],
+ ("test_alflpkfk_pony", "id"),
)
self.assertFKExists(
- 'test_alflpkfk_stable_ponies',
- ['pony_id'],
- ('test_alflpkfk_pony', 'id'),
+ "test_alflpkfk_stable_ponies",
+ ["pony_id"],
+ ("test_alflpkfk_pony", "id"),
)
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_alflpkfk", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_alflpkfk", editor, new_state, project_state
+ )
assertIdTypeEqualsFkType()
if connection.features.supports_foreign_keys:
self.assertFKExists(
- 'test_alflpkfk_pony_stables',
- ['pony_id'],
- ('test_alflpkfk_pony', 'id'),
+ "test_alflpkfk_pony_stables",
+ ["pony_id"],
+ ("test_alflpkfk_pony", "id"),
)
self.assertFKExists(
- 'test_alflpkfk_stable_ponies',
- ['pony_id'],
- ('test_alflpkfk_pony', 'id'),
+ "test_alflpkfk_stable_ponies",
+ ["pony_id"],
+ ("test_alflpkfk_pony", "id"),
)
def test_alter_field_pk_mti_fk(self):
- app_label = 'test_alflpkmtifk'
+ app_label = "test_alflpkmtifk"
project_state = self.set_up_test_model(app_label, mti_model=True)
- project_state = self.apply_operations(app_label, project_state, [
- migrations.CreateModel('ShetlandRider', fields=[
- (
- 'pony',
- models.ForeignKey(f'{app_label}.ShetlandPony', models.CASCADE),
+ project_state = self.apply_operations(
+ app_label,
+ project_state,
+ [
+ migrations.CreateModel(
+ "ShetlandRider",
+ fields=[
+ (
+ "pony",
+ models.ForeignKey(
+ f"{app_label}.ShetlandPony", models.CASCADE
+ ),
+ ),
+ ],
),
- ]),
- ])
+ ],
+ )
operation = migrations.AlterField(
- 'Pony',
- 'id',
+ "Pony",
+ "id",
models.BigAutoField(primary_key=True),
)
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
self.assertIsInstance(
- new_state.models[app_label, 'pony'].fields['id'],
+ new_state.models[app_label, "pony"].fields["id"],
models.BigAutoField,
)
@@ -1577,16 +1948,18 @@ class OperationTests(OperationTestBase):
c.type_code
for c in connection.introspection.get_table_description(
cursor,
- f'{app_label}_{table}',
+ f"{app_label}_{table}",
)
if c.name == column
][0]
def assertIdTypeEqualsMTIFkType():
with connection.cursor() as cursor:
- parent_id_type = _get_column_id_type(cursor, 'pony', 'id')
- child_id_type = _get_column_id_type(cursor, 'shetlandpony', 'pony_ptr_id')
- mti_id_type = _get_column_id_type(cursor, 'shetlandrider', 'pony_id')
+ parent_id_type = _get_column_id_type(cursor, "pony", "id")
+ child_id_type = _get_column_id_type(
+ cursor, "shetlandpony", "pony_ptr_id"
+ )
+ mti_id_type = _get_column_id_type(cursor, "shetlandrider", "pony_id")
self.assertEqual(parent_id_type, child_id_type)
self.assertEqual(parent_id_type, mti_id_type)
@@ -1597,14 +1970,14 @@ class OperationTests(OperationTestBase):
assertIdTypeEqualsMTIFkType()
if connection.features.supports_foreign_keys:
self.assertFKExists(
- f'{app_label}_shetlandpony',
- ['pony_ptr_id'],
- (f'{app_label}_pony', 'id'),
+ f"{app_label}_shetlandpony",
+ ["pony_ptr_id"],
+ (f"{app_label}_pony", "id"),
)
self.assertFKExists(
- f'{app_label}_shetlandrider',
- ['pony_id'],
- (f'{app_label}_shetlandpony', 'pony_ptr_id'),
+ f"{app_label}_shetlandrider",
+ ["pony_id"],
+ (f"{app_label}_shetlandpony", "pony_ptr_id"),
)
# Reversal.
with connection.schema_editor() as editor:
@@ -1612,30 +1985,32 @@ class OperationTests(OperationTestBase):
assertIdTypeEqualsMTIFkType()
if connection.features.supports_foreign_keys:
self.assertFKExists(
- f'{app_label}_shetlandpony',
- ['pony_ptr_id'],
- (f'{app_label}_pony', 'id'),
+ f"{app_label}_shetlandpony",
+ ["pony_ptr_id"],
+ (f"{app_label}_pony", "id"),
)
self.assertFKExists(
- f'{app_label}_shetlandrider',
- ['pony_id'],
- (f'{app_label}_shetlandpony', 'pony_ptr_id'),
+ f"{app_label}_shetlandrider",
+ ["pony_id"],
+ (f"{app_label}_shetlandpony", "pony_ptr_id"),
)
def test_alter_field_pk_mti_and_fk_to_base(self):
- app_label = 'test_alflpkmtiftb'
+ app_label = "test_alflpkmtiftb"
project_state = self.set_up_test_model(
- app_label, mti_model=True, related_model=True,
+ app_label,
+ mti_model=True,
+ related_model=True,
)
operation = migrations.AlterField(
- 'Pony',
- 'id',
+ "Pony",
+ "id",
models.BigAutoField(primary_key=True),
)
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
self.assertIsInstance(
- new_state.models[app_label, 'pony'].fields['id'],
+ new_state.models[app_label, "pony"].fields["id"],
models.BigAutoField,
)
@@ -1644,16 +2019,18 @@ class OperationTests(OperationTestBase):
c.type_code
for c in connection.introspection.get_table_description(
cursor,
- f'{app_label}_{table}',
+ f"{app_label}_{table}",
)
if c.name == column
][0]
def assertIdTypeEqualsMTIFkType():
with connection.cursor() as cursor:
- parent_id_type = _get_column_id_type(cursor, 'pony', 'id')
- fk_id_type = _get_column_id_type(cursor, 'rider', 'pony_id')
- child_id_type = _get_column_id_type(cursor, 'shetlandpony', 'pony_ptr_id')
+ parent_id_type = _get_column_id_type(cursor, "pony", "id")
+ fk_id_type = _get_column_id_type(cursor, "rider", "pony_id")
+ child_id_type = _get_column_id_type(
+ cursor, "shetlandpony", "pony_ptr_id"
+ )
self.assertEqual(parent_id_type, child_id_type)
self.assertEqual(parent_id_type, fk_id_type)
@@ -1664,14 +2041,14 @@ class OperationTests(OperationTestBase):
assertIdTypeEqualsMTIFkType()
if connection.features.supports_foreign_keys:
self.assertFKExists(
- f'{app_label}_shetlandpony',
- ['pony_ptr_id'],
- (f'{app_label}_pony', 'id'),
+ f"{app_label}_shetlandpony",
+ ["pony_ptr_id"],
+ (f"{app_label}_pony", "id"),
)
self.assertFKExists(
- f'{app_label}_rider',
- ['pony_id'],
- (f'{app_label}_pony', 'id'),
+ f"{app_label}_rider",
+ ["pony_id"],
+ (f"{app_label}_pony", "id"),
)
# Reversal.
with connection.schema_editor() as editor:
@@ -1679,69 +2056,99 @@ class OperationTests(OperationTestBase):
assertIdTypeEqualsMTIFkType()
if connection.features.supports_foreign_keys:
self.assertFKExists(
- f'{app_label}_shetlandpony',
- ['pony_ptr_id'],
- (f'{app_label}_pony', 'id'),
+ f"{app_label}_shetlandpony",
+ ["pony_ptr_id"],
+ (f"{app_label}_pony", "id"),
)
self.assertFKExists(
- f'{app_label}_rider',
- ['pony_id'],
- (f'{app_label}_pony', 'id'),
+ f"{app_label}_rider",
+ ["pony_id"],
+ (f"{app_label}_pony", "id"),
)
- @skipUnlessDBFeature('supports_foreign_keys')
+ @skipUnlessDBFeature("supports_foreign_keys")
def test_alter_field_reloads_state_on_fk_with_to_field_target_type_change(self):
- app_label = 'test_alflrsfkwtflttc'
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel('Rider', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('code', models.IntegerField(unique=True)),
- ]),
- migrations.CreateModel('Pony', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('rider', models.ForeignKey('%s.Rider' % app_label, models.CASCADE, to_field='code')),
- ]),
- ])
+ app_label = "test_alflrsfkwtflttc"
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("code", models.IntegerField(unique=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "rider",
+ models.ForeignKey(
+ "%s.Rider" % app_label, models.CASCADE, to_field="code"
+ ),
+ ),
+ ],
+ ),
+ ],
+ )
operation = migrations.AlterField(
- 'Rider',
- 'code',
+ "Rider",
+ "code",
models.CharField(max_length=100, unique=True),
)
self.apply_operations(app_label, project_state, operations=[operation])
id_type, id_null = [
(c.type_code, c.null_ok)
- for c in self.get_table_description('%s_rider' % app_label)
- if c.name == 'code'
+ for c in self.get_table_description("%s_rider" % app_label)
+ if c.name == "code"
][0]
fk_type, fk_null = [
(c.type_code, c.null_ok)
- for c in self.get_table_description('%s_pony' % app_label)
- if c.name == 'rider_id'
+ for c in self.get_table_description("%s_pony" % app_label)
+ if c.name == "rider_id"
][0]
self.assertEqual(id_type, fk_type)
self.assertEqual(id_null, fk_null)
- @skipUnlessDBFeature('supports_foreign_keys')
- def test_alter_field_reloads_state_on_fk_with_to_field_related_name_target_type_change(self):
- app_label = 'test_alflrsfkwtflrnttc'
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel('Rider', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('code', models.PositiveIntegerField(unique=True)),
- ]),
- migrations.CreateModel('Pony', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('rider', models.ForeignKey(
- '%s.Rider' % app_label,
- models.CASCADE,
- to_field='code',
- related_name='+',
- )),
- ]),
- ])
+ @skipUnlessDBFeature("supports_foreign_keys")
+ def test_alter_field_reloads_state_on_fk_with_to_field_related_name_target_type_change(
+ self,
+ ):
+ app_label = "test_alflrsfkwtflrnttc"
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("code", models.PositiveIntegerField(unique=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "rider",
+ models.ForeignKey(
+ "%s.Rider" % app_label,
+ models.CASCADE,
+ to_field="code",
+ related_name="+",
+ ),
+ ),
+ ],
+ ),
+ ],
+ )
operation = migrations.AlterField(
- 'Rider',
- 'code',
+ "Rider",
+ "code",
models.CharField(max_length=100, unique=True),
)
self.apply_operations(app_label, project_state, operations=[operation])
@@ -1752,24 +2159,51 @@ class OperationTests(OperationTestBase):
crashes on MySQL due to not dropping the PonyRider.pony foreign key
constraint before modifying the column.
"""
- app_label = 'alter_alter_field_reloads_state_on_fk_target_changes'
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel('Rider', fields=[
- ('id', models.CharField(primary_key=True, max_length=100)),
- ]),
- migrations.CreateModel('Pony', fields=[
- ('id', models.CharField(primary_key=True, max_length=100)),
- ('rider', models.ForeignKey('%s.Rider' % app_label, models.CASCADE)),
- ]),
- migrations.CreateModel('PonyRider', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('pony', models.ForeignKey('%s.Pony' % app_label, models.CASCADE)),
- ]),
- ])
- project_state = self.apply_operations(app_label, project_state, operations=[
- migrations.AlterField('Rider', 'id', models.CharField(primary_key=True, max_length=99)),
- migrations.AlterField('Pony', 'id', models.CharField(primary_key=True, max_length=99)),
- ])
+ app_label = "alter_alter_field_reloads_state_on_fk_target_changes"
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.CharField(primary_key=True, max_length=100)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.CharField(primary_key=True, max_length=100)),
+ (
+ "rider",
+ models.ForeignKey("%s.Rider" % app_label, models.CASCADE),
+ ),
+ ],
+ ),
+ migrations.CreateModel(
+ "PonyRider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "pony",
+ models.ForeignKey("%s.Pony" % app_label, models.CASCADE),
+ ),
+ ],
+ ),
+ ],
+ )
+ project_state = self.apply_operations(
+ app_label,
+ project_state,
+ operations=[
+ migrations.AlterField(
+ "Rider", "id", models.CharField(primary_key=True, max_length=99)
+ ),
+ migrations.AlterField(
+ "Pony", "id", models.CharField(primary_key=True, max_length=99)
+ ),
+ ],
+ )
def test_alter_field_reloads_state_on_fk_with_to_field_target_changes(self):
"""
@@ -1777,26 +2211,57 @@ class OperationTests(OperationTestBase):
crashes on MySQL due to not dropping the PonyRider.pony foreign key
constraint before modifying the column.
"""
- app_label = 'alter_alter_field_reloads_state_on_fk_with_to_field_target_changes'
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel('Rider', fields=[
- ('id', models.CharField(primary_key=True, max_length=100)),
- ('slug', models.CharField(unique=True, max_length=100)),
- ]),
- migrations.CreateModel('Pony', fields=[
- ('id', models.CharField(primary_key=True, max_length=100)),
- ('rider', models.ForeignKey('%s.Rider' % app_label, models.CASCADE, to_field='slug')),
- ('slug', models.CharField(unique=True, max_length=100)),
- ]),
- migrations.CreateModel('PonyRider', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('pony', models.ForeignKey('%s.Pony' % app_label, models.CASCADE, to_field='slug')),
- ]),
- ])
- project_state = self.apply_operations(app_label, project_state, operations=[
- migrations.AlterField('Rider', 'slug', models.CharField(unique=True, max_length=99)),
- migrations.AlterField('Pony', 'slug', models.CharField(unique=True, max_length=99)),
- ])
+ app_label = "alter_alter_field_reloads_state_on_fk_with_to_field_target_changes"
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.CharField(primary_key=True, max_length=100)),
+ ("slug", models.CharField(unique=True, max_length=100)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.CharField(primary_key=True, max_length=100)),
+ (
+ "rider",
+ models.ForeignKey(
+ "%s.Rider" % app_label, models.CASCADE, to_field="slug"
+ ),
+ ),
+ ("slug", models.CharField(unique=True, max_length=100)),
+ ],
+ ),
+ migrations.CreateModel(
+ "PonyRider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "pony",
+ models.ForeignKey(
+ "%s.Pony" % app_label, models.CASCADE, to_field="slug"
+ ),
+ ),
+ ],
+ ),
+ ],
+ )
+ project_state = self.apply_operations(
+ app_label,
+ project_state,
+ operations=[
+ migrations.AlterField(
+ "Rider", "slug", models.CharField(unique=True, max_length=99)
+ ),
+ migrations.AlterField(
+ "Pony", "slug", models.CharField(unique=True, max_length=99)
+ ),
+ ],
+ )
def test_rename_field_reloads_state_on_fk_target_changes(self):
"""
@@ -1804,44 +2269,80 @@ class OperationTests(OperationTestBase):
crashes on MySQL due to not dropping the PonyRider.pony foreign key
constraint before modifying the column.
"""
- app_label = 'alter_rename_field_reloads_state_on_fk_target_changes'
- project_state = self.apply_operations(app_label, ProjectState(), operations=[
- migrations.CreateModel('Rider', fields=[
- ('id', models.CharField(primary_key=True, max_length=100)),
- ]),
- migrations.CreateModel('Pony', fields=[
- ('id', models.CharField(primary_key=True, max_length=100)),
- ('rider', models.ForeignKey('%s.Rider' % app_label, models.CASCADE)),
- ]),
- migrations.CreateModel('PonyRider', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('pony', models.ForeignKey('%s.Pony' % app_label, models.CASCADE)),
- ]),
- ])
- project_state = self.apply_operations(app_label, project_state, operations=[
- migrations.RenameField('Rider', 'id', 'id2'),
- migrations.AlterField('Pony', 'id', models.CharField(primary_key=True, max_length=99)),
- ], atomic=connection.features.supports_atomic_references_rename)
+ app_label = "alter_rename_field_reloads_state_on_fk_target_changes"
+ project_state = self.apply_operations(
+ app_label,
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Rider",
+ fields=[
+ ("id", models.CharField(primary_key=True, max_length=100)),
+ ],
+ ),
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.CharField(primary_key=True, max_length=100)),
+ (
+ "rider",
+ models.ForeignKey("%s.Rider" % app_label, models.CASCADE),
+ ),
+ ],
+ ),
+ migrations.CreateModel(
+ "PonyRider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "pony",
+ models.ForeignKey("%s.Pony" % app_label, models.CASCADE),
+ ),
+ ],
+ ),
+ ],
+ )
+ project_state = self.apply_operations(
+ app_label,
+ project_state,
+ operations=[
+ migrations.RenameField("Rider", "id", "id2"),
+ migrations.AlterField(
+ "Pony", "id", models.CharField(primary_key=True, max_length=99)
+ ),
+ ],
+ atomic=connection.features.supports_atomic_references_rename,
+ )
def test_rename_field(self):
"""
Tests the RenameField operation.
"""
- project_state = self.set_up_test_model("test_rnfl", unique_together=True, index_together=True)
+ project_state = self.set_up_test_model(
+ "test_rnfl", unique_together=True, index_together=True
+ )
# Test the state alteration
operation = migrations.RenameField("Pony", "pink", "blue")
self.assertEqual(operation.describe(), "Rename field pink on Pony to blue")
- self.assertEqual(operation.migration_name_fragment, 'rename_pink_pony_blue')
+ self.assertEqual(operation.migration_name_fragment, "rename_pink_pony_blue")
new_state = project_state.clone()
operation.state_forwards("test_rnfl", new_state)
self.assertIn("blue", new_state.models["test_rnfl", "pony"].fields)
self.assertNotIn("pink", new_state.models["test_rnfl", "pony"].fields)
# Make sure the unique_together has the renamed column too
- self.assertIn("blue", new_state.models["test_rnfl", "pony"].options['unique_together'][0])
- self.assertNotIn("pink", new_state.models["test_rnfl", "pony"].options['unique_together'][0])
+ self.assertIn(
+ "blue", new_state.models["test_rnfl", "pony"].options["unique_together"][0]
+ )
+ self.assertNotIn(
+ "pink", new_state.models["test_rnfl", "pony"].options["unique_together"][0]
+ )
# Make sure the index_together has the renamed column too
- self.assertIn("blue", new_state.models["test_rnfl", "pony"].options['index_together'][0])
- self.assertNotIn("pink", new_state.models["test_rnfl", "pony"].options['index_together'][0])
+ self.assertIn(
+ "blue", new_state.models["test_rnfl", "pony"].options["index_together"][0]
+ )
+ self.assertNotIn(
+ "pink", new_state.models["test_rnfl", "pony"].options["index_together"][0]
+ )
# Test the database alteration
self.assertColumnExists("test_rnfl_pony", "pink")
self.assertColumnNotExists("test_rnfl_pony", "blue")
@@ -1854,7 +2355,9 @@ class OperationTests(OperationTestBase):
cursor.execute("INSERT INTO test_rnfl_pony (blue, weight) VALUES (1, 1)")
with self.assertRaises(IntegrityError):
with atomic():
- cursor.execute("INSERT INTO test_rnfl_pony (blue, weight) VALUES (1, 1)")
+ cursor.execute(
+ "INSERT INTO test_rnfl_pony (blue, weight) VALUES (1, 1)"
+ )
cursor.execute("DELETE FROM test_rnfl_pony")
# Ensure the index constraint has been ported over
self.assertIndexExists("test_rnfl_pony", ["weight", "blue"])
@@ -1869,105 +2372,189 @@ class OperationTests(OperationTestBase):
definition = operation.deconstruct()
self.assertEqual(definition[0], "RenameField")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': "Pony", 'old_name': "pink", 'new_name': "blue"})
+ self.assertEqual(
+ definition[2],
+ {"model_name": "Pony", "old_name": "pink", "new_name": "blue"},
+ )
def test_rename_field_with_db_column(self):
- project_state = self.apply_operations('test_rfwdbc', ProjectState(), operations=[
- migrations.CreateModel('Pony', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('field', models.IntegerField(db_column='db_field')),
- ('fk_field', models.ForeignKey(
- 'Pony',
- models.CASCADE,
- db_column='db_fk_field',
- )),
- ]),
- ])
+ project_state = self.apply_operations(
+ "test_rfwdbc",
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("field", models.IntegerField(db_column="db_field")),
+ (
+ "fk_field",
+ models.ForeignKey(
+ "Pony",
+ models.CASCADE,
+ db_column="db_fk_field",
+ ),
+ ),
+ ],
+ ),
+ ],
+ )
new_state = project_state.clone()
- operation = migrations.RenameField('Pony', 'field', 'renamed_field')
- operation.state_forwards('test_rfwdbc', new_state)
- self.assertIn('renamed_field', new_state.models['test_rfwdbc', 'pony'].fields)
- self.assertNotIn('field', new_state.models['test_rfwdbc', 'pony'].fields)
- self.assertColumnExists('test_rfwdbc_pony', 'db_field')
+ operation = migrations.RenameField("Pony", "field", "renamed_field")
+ operation.state_forwards("test_rfwdbc", new_state)
+ self.assertIn("renamed_field", new_state.models["test_rfwdbc", "pony"].fields)
+ self.assertNotIn("field", new_state.models["test_rfwdbc", "pony"].fields)
+ self.assertColumnExists("test_rfwdbc_pony", "db_field")
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
- operation.database_forwards('test_rfwdbc', editor, project_state, new_state)
- self.assertColumnExists('test_rfwdbc_pony', 'db_field')
+ operation.database_forwards(
+ "test_rfwdbc", editor, project_state, new_state
+ )
+ self.assertColumnExists("test_rfwdbc_pony", "db_field")
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
- operation.database_backwards('test_rfwdbc', editor, new_state, project_state)
- self.assertColumnExists('test_rfwdbc_pony', 'db_field')
+ operation.database_backwards(
+ "test_rfwdbc", editor, new_state, project_state
+ )
+ self.assertColumnExists("test_rfwdbc_pony", "db_field")
new_state = project_state.clone()
- operation = migrations.RenameField('Pony', 'fk_field', 'renamed_fk_field')
- operation.state_forwards('test_rfwdbc', new_state)
- self.assertIn('renamed_fk_field', new_state.models['test_rfwdbc', 'pony'].fields)
- self.assertNotIn('fk_field', new_state.models['test_rfwdbc', 'pony'].fields)
- self.assertColumnExists('test_rfwdbc_pony', 'db_fk_field')
+ operation = migrations.RenameField("Pony", "fk_field", "renamed_fk_field")
+ operation.state_forwards("test_rfwdbc", new_state)
+ self.assertIn(
+ "renamed_fk_field", new_state.models["test_rfwdbc", "pony"].fields
+ )
+ self.assertNotIn("fk_field", new_state.models["test_rfwdbc", "pony"].fields)
+ self.assertColumnExists("test_rfwdbc_pony", "db_fk_field")
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
- operation.database_forwards('test_rfwdbc', editor, project_state, new_state)
- self.assertColumnExists('test_rfwdbc_pony', 'db_fk_field')
+ operation.database_forwards(
+ "test_rfwdbc", editor, project_state, new_state
+ )
+ self.assertColumnExists("test_rfwdbc_pony", "db_fk_field")
with connection.schema_editor() as editor:
with self.assertNumQueries(0):
- operation.database_backwards('test_rfwdbc', editor, new_state, project_state)
- self.assertColumnExists('test_rfwdbc_pony', 'db_fk_field')
+ operation.database_backwards(
+ "test_rfwdbc", editor, new_state, project_state
+ )
+ self.assertColumnExists("test_rfwdbc_pony", "db_fk_field")
def test_rename_field_case(self):
- project_state = self.apply_operations('test_rfmx', ProjectState(), operations=[
- migrations.CreateModel('Pony', fields=[
- ('id', models.AutoField(primary_key=True)),
- ('field', models.IntegerField()),
- ]),
- ])
+ project_state = self.apply_operations(
+ "test_rfmx",
+ ProjectState(),
+ operations=[
+ migrations.CreateModel(
+ "Pony",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("field", models.IntegerField()),
+ ],
+ ),
+ ],
+ )
new_state = project_state.clone()
- operation = migrations.RenameField('Pony', 'field', 'FiElD')
- operation.state_forwards('test_rfmx', new_state)
- self.assertIn('FiElD', new_state.models['test_rfmx', 'pony'].fields)
- self.assertColumnExists('test_rfmx_pony', 'field')
+ operation = migrations.RenameField("Pony", "field", "FiElD")
+ operation.state_forwards("test_rfmx", new_state)
+ self.assertIn("FiElD", new_state.models["test_rfmx", "pony"].fields)
+ self.assertColumnExists("test_rfmx_pony", "field")
with connection.schema_editor() as editor:
- operation.database_forwards('test_rfmx', editor, project_state, new_state)
+ operation.database_forwards("test_rfmx", editor, project_state, new_state)
self.assertColumnExists(
- 'test_rfmx_pony',
- connection.introspection.identifier_converter('FiElD'),
+ "test_rfmx_pony",
+ connection.introspection.identifier_converter("FiElD"),
)
with connection.schema_editor() as editor:
- operation.database_backwards('test_rfmx', editor, new_state, project_state)
- self.assertColumnExists('test_rfmx_pony', 'field')
+ operation.database_backwards("test_rfmx", editor, new_state, project_state)
+ self.assertColumnExists("test_rfmx_pony", "field")
def test_rename_missing_field(self):
state = ProjectState()
- state.add_model(ModelState('app', 'model', []))
- with self.assertRaisesMessage(FieldDoesNotExist, "app.model has no field named 'field'"):
- migrations.RenameField('model', 'field', 'new_field').state_forwards('app', state)
+ state.add_model(ModelState("app", "model", []))
+ with self.assertRaisesMessage(
+ FieldDoesNotExist, "app.model has no field named 'field'"
+ ):
+ migrations.RenameField("model", "field", "new_field").state_forwards(
+ "app", state
+ )
def test_rename_referenced_field_state_forward(self):
state = ProjectState()
- state.add_model(ModelState('app', 'Model', [
- ('id', models.AutoField(primary_key=True)),
- ('field', models.IntegerField(unique=True)),
- ]))
- state.add_model(ModelState('app', 'OtherModel', [
- ('id', models.AutoField(primary_key=True)),
- ('fk', models.ForeignKey('Model', models.CASCADE, to_field='field')),
- ('fo', models.ForeignObject('Model', models.CASCADE, from_fields=('fk',), to_fields=('field',))),
- ]))
- operation = migrations.RenameField('Model', 'field', 'renamed')
+ state.add_model(
+ ModelState(
+ "app",
+ "Model",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("field", models.IntegerField(unique=True)),
+ ],
+ )
+ )
+ state.add_model(
+ ModelState(
+ "app",
+ "OtherModel",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ (
+ "fk",
+ models.ForeignKey("Model", models.CASCADE, to_field="field"),
+ ),
+ (
+ "fo",
+ models.ForeignObject(
+ "Model",
+ models.CASCADE,
+ from_fields=("fk",),
+ to_fields=("field",),
+ ),
+ ),
+ ],
+ )
+ )
+ operation = migrations.RenameField("Model", "field", "renamed")
new_state = state.clone()
- operation.state_forwards('app', new_state)
- self.assertEqual(new_state.models['app', 'othermodel'].fields['fk'].remote_field.field_name, 'renamed')
- self.assertEqual(new_state.models['app', 'othermodel'].fields['fk'].from_fields, ['self'])
- self.assertEqual(new_state.models['app', 'othermodel'].fields['fk'].to_fields, ('renamed',))
- self.assertEqual(new_state.models['app', 'othermodel'].fields['fo'].from_fields, ('fk',))
- self.assertEqual(new_state.models['app', 'othermodel'].fields['fo'].to_fields, ('renamed',))
- operation = migrations.RenameField('OtherModel', 'fk', 'renamed_fk')
+ operation.state_forwards("app", new_state)
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["fk"].remote_field.field_name,
+ "renamed",
+ )
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["fk"].from_fields, ["self"]
+ )
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["fk"].to_fields, ("renamed",)
+ )
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["fo"].from_fields, ("fk",)
+ )
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["fo"].to_fields, ("renamed",)
+ )
+ operation = migrations.RenameField("OtherModel", "fk", "renamed_fk")
new_state = state.clone()
- operation.state_forwards('app', new_state)
- self.assertEqual(new_state.models['app', 'othermodel'].fields['renamed_fk'].remote_field.field_name, 'renamed')
- self.assertEqual(new_state.models['app', 'othermodel'].fields['renamed_fk'].from_fields, ('self',))
- self.assertEqual(new_state.models['app', 'othermodel'].fields['renamed_fk'].to_fields, ('renamed',))
- self.assertEqual(new_state.models['app', 'othermodel'].fields['fo'].from_fields, ('renamed_fk',))
- self.assertEqual(new_state.models['app', 'othermodel'].fields['fo'].to_fields, ('renamed',))
+ operation.state_forwards("app", new_state)
+ self.assertEqual(
+ new_state.models["app", "othermodel"]
+ .fields["renamed_fk"]
+ .remote_field.field_name,
+ "renamed",
+ )
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["renamed_fk"].from_fields,
+ ("self",),
+ )
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["renamed_fk"].to_fields,
+ ("renamed",),
+ )
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["fo"].from_fields,
+ ("renamed_fk",),
+ )
+ self.assertEqual(
+ new_state.models["app", "othermodel"].fields["fo"].to_fields, ("renamed",)
+ )
def test_alter_unique_together(self):
"""
@@ -1976,15 +2563,31 @@ class OperationTests(OperationTestBase):
project_state = self.set_up_test_model("test_alunto")
# Test the state alteration
operation = migrations.AlterUniqueTogether("Pony", [("pink", "weight")])
- self.assertEqual(operation.describe(), "Alter unique_together for Pony (1 constraint(s))")
+ self.assertEqual(
+ operation.describe(), "Alter unique_together for Pony (1 constraint(s))"
+ )
self.assertEqual(
operation.migration_name_fragment,
- 'alter_pony_unique_together',
+ "alter_pony_unique_together",
)
new_state = project_state.clone()
operation.state_forwards("test_alunto", new_state)
- self.assertEqual(len(project_state.models["test_alunto", "pony"].options.get("unique_together", set())), 0)
- self.assertEqual(len(new_state.models["test_alunto", "pony"].options.get("unique_together", set())), 1)
+ self.assertEqual(
+ len(
+ project_state.models["test_alunto", "pony"].options.get(
+ "unique_together", set()
+ )
+ ),
+ 0,
+ )
+ self.assertEqual(
+ len(
+ new_state.models["test_alunto", "pony"].options.get(
+ "unique_together", set()
+ )
+ ),
+ 1,
+ )
# Make sure we can insert duplicate rows
with connection.cursor() as cursor:
cursor.execute("INSERT INTO test_alunto_pony (pink, weight) VALUES (1, 1)")
@@ -1992,31 +2595,48 @@ class OperationTests(OperationTestBase):
cursor.execute("DELETE FROM test_alunto_pony")
# Test the database alteration
with connection.schema_editor() as editor:
- operation.database_forwards("test_alunto", editor, project_state, new_state)
+ operation.database_forwards(
+ "test_alunto", editor, project_state, new_state
+ )
cursor.execute("INSERT INTO test_alunto_pony (pink, weight) VALUES (1, 1)")
with self.assertRaises(IntegrityError):
with atomic():
- cursor.execute("INSERT INTO test_alunto_pony (pink, weight) VALUES (1, 1)")
+ cursor.execute(
+ "INSERT INTO test_alunto_pony (pink, weight) VALUES (1, 1)"
+ )
cursor.execute("DELETE FROM test_alunto_pony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_alunto", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_alunto", editor, new_state, project_state
+ )
cursor.execute("INSERT INTO test_alunto_pony (pink, weight) VALUES (1, 1)")
cursor.execute("INSERT INTO test_alunto_pony (pink, weight) VALUES (1, 1)")
cursor.execute("DELETE FROM test_alunto_pony")
# Test flat unique_together
operation = migrations.AlterUniqueTogether("Pony", ("pink", "weight"))
operation.state_forwards("test_alunto", new_state)
- self.assertEqual(len(new_state.models["test_alunto", "pony"].options.get("unique_together", set())), 1)
+ self.assertEqual(
+ len(
+ new_state.models["test_alunto", "pony"].options.get(
+ "unique_together", set()
+ )
+ ),
+ 1,
+ )
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "AlterUniqueTogether")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'name': "Pony", 'unique_together': {("pink", "weight")}})
+ self.assertEqual(
+ definition[2], {"name": "Pony", "unique_together": {("pink", "weight")}}
+ )
def test_alter_unique_together_remove(self):
operation = migrations.AlterUniqueTogether("Pony", None)
- self.assertEqual(operation.describe(), "Alter unique_together for Pony (0 constraint(s))")
+ self.assertEqual(
+ operation.describe(), "Alter unique_together for Pony (0 constraint(s))"
+ )
def test_add_index(self):
"""
@@ -2031,15 +2651,20 @@ class OperationTests(OperationTestBase):
migrations.AddIndex("Pony", models.Index(fields=["pink"]))
index = models.Index(fields=["pink"], name="test_adin_pony_pink_idx")
operation = migrations.AddIndex("Pony", index)
- self.assertEqual(operation.describe(), "Create index test_adin_pony_pink_idx on field(s) pink of model Pony")
+ self.assertEqual(
+ operation.describe(),
+ "Create index test_adin_pony_pink_idx on field(s) pink of model Pony",
+ )
self.assertEqual(
operation.migration_name_fragment,
- 'pony_test_adin_pony_pink_idx',
+ "pony_test_adin_pony_pink_idx",
)
new_state = project_state.clone()
operation.state_forwards("test_adin", new_state)
# Test the database alteration
- self.assertEqual(len(new_state.models["test_adin", "pony"].options['indexes']), 1)
+ self.assertEqual(
+ len(new_state.models["test_adin", "pony"].options["indexes"]), 1
+ )
self.assertIndexNotExists("test_adin_pony", ["pink"])
with connection.schema_editor() as editor:
operation.database_forwards("test_adin", editor, project_state, new_state)
@@ -2052,7 +2677,7 @@ class OperationTests(OperationTestBase):
definition = operation.deconstruct()
self.assertEqual(definition[0], "AddIndex")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': "Pony", 'index': index})
+ self.assertEqual(definition[2], {"model_name": "Pony", "index": index})
def test_remove_index(self):
"""
@@ -2065,12 +2690,14 @@ class OperationTests(OperationTestBase):
self.assertEqual(operation.describe(), "Remove index pony_test_idx from Pony")
self.assertEqual(
operation.migration_name_fragment,
- 'remove_pony_pony_test_idx',
+ "remove_pony_pony_test_idx",
)
new_state = project_state.clone()
operation.state_forwards("test_rmin", new_state)
# Test the state alteration
- self.assertEqual(len(new_state.models["test_rmin", "pony"].options['indexes']), 0)
+ self.assertEqual(
+ len(new_state.models["test_rmin", "pony"].options["indexes"]), 0
+ )
self.assertIndexExists("test_rmin_pony", ["pink", "weight"])
# Test the database alteration
with connection.schema_editor() as editor:
@@ -2084,7 +2711,7 @@ class OperationTests(OperationTestBase):
definition = operation.deconstruct()
self.assertEqual(definition[0], "RemoveIndex")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': "Pony", 'name': "pony_test_idx"})
+ self.assertEqual(definition[2], {"model_name": "Pony", "name": "pony_test_idx"})
# Also test a field dropped with index - sqlite remake issue
operations = [
@@ -2095,7 +2722,7 @@ class OperationTests(OperationTestBase):
self.assertIndexExists("test_rmin_pony", ["pink", "weight"])
# Test database alteration
new_state = project_state.clone()
- self.apply_operations('test_rmin', new_state, operations=operations)
+ self.apply_operations("test_rmin", new_state, operations=operations)
self.assertColumnNotExists("test_rmin_pony", "pink")
self.assertIndexNotExists("test_rmin_pony", ["pink", "weight"])
# And test reversal
@@ -2103,47 +2730,47 @@ class OperationTests(OperationTestBase):
self.assertIndexExists("test_rmin_pony", ["pink", "weight"])
def test_add_index_state_forwards(self):
- project_state = self.set_up_test_model('test_adinsf')
- index = models.Index(fields=['pink'], name='test_adinsf_pony_pink_idx')
- old_model = project_state.apps.get_model('test_adinsf', 'Pony')
+ project_state = self.set_up_test_model("test_adinsf")
+ index = models.Index(fields=["pink"], name="test_adinsf_pony_pink_idx")
+ old_model = project_state.apps.get_model("test_adinsf", "Pony")
new_state = project_state.clone()
- operation = migrations.AddIndex('Pony', index)
- operation.state_forwards('test_adinsf', new_state)
- new_model = new_state.apps.get_model('test_adinsf', 'Pony')
+ operation = migrations.AddIndex("Pony", index)
+ operation.state_forwards("test_adinsf", new_state)
+ new_model = new_state.apps.get_model("test_adinsf", "Pony")
self.assertIsNot(old_model, new_model)
def test_remove_index_state_forwards(self):
- project_state = self.set_up_test_model('test_rminsf')
- index = models.Index(fields=['pink'], name='test_rminsf_pony_pink_idx')
- migrations.AddIndex('Pony', index).state_forwards('test_rminsf', project_state)
- old_model = project_state.apps.get_model('test_rminsf', 'Pony')
+ project_state = self.set_up_test_model("test_rminsf")
+ index = models.Index(fields=["pink"], name="test_rminsf_pony_pink_idx")
+ migrations.AddIndex("Pony", index).state_forwards("test_rminsf", project_state)
+ old_model = project_state.apps.get_model("test_rminsf", "Pony")
new_state = project_state.clone()
- operation = migrations.RemoveIndex('Pony', 'test_rminsf_pony_pink_idx')
- operation.state_forwards('test_rminsf', new_state)
- new_model = new_state.apps.get_model('test_rminsf', 'Pony')
+ operation = migrations.RemoveIndex("Pony", "test_rminsf_pony_pink_idx")
+ operation.state_forwards("test_rminsf", new_state)
+ new_model = new_state.apps.get_model("test_rminsf", "Pony")
self.assertIsNot(old_model, new_model)
- @skipUnlessDBFeature('supports_expression_indexes')
+ @skipUnlessDBFeature("supports_expression_indexes")
def test_add_func_index(self):
- app_label = 'test_addfuncin'
- index_name = f'{app_label}_pony_abs_idx'
- table_name = f'{app_label}_pony'
+ app_label = "test_addfuncin"
+ index_name = f"{app_label}_pony_abs_idx"
+ table_name = f"{app_label}_pony"
project_state = self.set_up_test_model(app_label)
- index = models.Index(Abs('weight'), name=index_name)
- operation = migrations.AddIndex('Pony', index)
+ index = models.Index(Abs("weight"), name=index_name)
+ operation = migrations.AddIndex("Pony", index)
self.assertEqual(
operation.describe(),
- 'Create index test_addfuncin_pony_abs_idx on Abs(F(weight)) on model Pony',
+ "Create index test_addfuncin_pony_abs_idx on Abs(F(weight)) on model Pony",
)
self.assertEqual(
operation.migration_name_fragment,
- 'pony_test_addfuncin_pony_abs_idx',
+ "pony_test_addfuncin_pony_abs_idx",
)
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
- self.assertEqual(len(new_state.models[app_label, 'pony'].options['indexes']), 1)
+ self.assertEqual(len(new_state.models[app_label, "pony"].options["indexes"]), 1)
self.assertIndexNameNotExists(table_name, index_name)
# Add index.
with connection.schema_editor() as editor:
@@ -2155,32 +2782,35 @@ class OperationTests(OperationTestBase):
self.assertIndexNameNotExists(table_name, index_name)
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'AddIndex')
+ self.assertEqual(definition[0], "AddIndex")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': 'Pony', 'index': index})
+ self.assertEqual(definition[2], {"model_name": "Pony", "index": index})
- @skipUnlessDBFeature('supports_expression_indexes')
+ @skipUnlessDBFeature("supports_expression_indexes")
def test_remove_func_index(self):
- app_label = 'test_rmfuncin'
- index_name = f'{app_label}_pony_abs_idx'
- table_name = f'{app_label}_pony'
- project_state = self.set_up_test_model(app_label, indexes=[
- models.Index(Abs('weight'), name=index_name),
- ])
+ app_label = "test_rmfuncin"
+ index_name = f"{app_label}_pony_abs_idx"
+ table_name = f"{app_label}_pony"
+ project_state = self.set_up_test_model(
+ app_label,
+ indexes=[
+ models.Index(Abs("weight"), name=index_name),
+ ],
+ )
self.assertTableExists(table_name)
self.assertIndexNameExists(table_name, index_name)
- operation = migrations.RemoveIndex('Pony', index_name)
+ operation = migrations.RemoveIndex("Pony", index_name)
self.assertEqual(
operation.describe(),
- 'Remove index test_rmfuncin_pony_abs_idx from Pony',
+ "Remove index test_rmfuncin_pony_abs_idx from Pony",
)
self.assertEqual(
operation.migration_name_fragment,
- 'remove_pony_test_rmfuncin_pony_abs_idx',
+ "remove_pony_test_rmfuncin_pony_abs_idx",
)
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
- self.assertEqual(len(new_state.models[app_label, 'pony'].options['indexes']), 0)
+ self.assertEqual(len(new_state.models[app_label, "pony"].options["indexes"]), 0)
# Remove index.
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, project_state, new_state)
@@ -2191,20 +2821,22 @@ class OperationTests(OperationTestBase):
self.assertIndexNameExists(table_name, index_name)
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'RemoveIndex')
+ self.assertEqual(definition[0], "RemoveIndex")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': 'Pony', 'name': index_name})
+ self.assertEqual(definition[2], {"model_name": "Pony", "name": index_name})
- @skipUnlessDBFeature('supports_expression_indexes')
+ @skipUnlessDBFeature("supports_expression_indexes")
def test_alter_field_with_func_index(self):
- app_label = 'test_alfuncin'
- index_name = f'{app_label}_pony_idx'
- table_name = f'{app_label}_pony'
+ app_label = "test_alfuncin"
+ index_name = f"{app_label}_pony_idx"
+ table_name = f"{app_label}_pony"
project_state = self.set_up_test_model(
app_label,
- indexes=[models.Index(Abs('pink'), name=index_name)],
+ indexes=[models.Index(Abs("pink"), name=index_name)],
+ )
+ operation = migrations.AlterField(
+ "Pony", "pink", models.IntegerField(null=True)
)
- operation = migrations.AlterField('Pony', 'pink', models.IntegerField(null=True))
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
with connection.schema_editor() as editor:
@@ -2220,7 +2852,9 @@ class OperationTests(OperationTestBase):
Meta.indexes don't get dropped with sqlite3 remake.
"""
project_state = self.set_up_test_model("test_alflin", index=True)
- operation = migrations.AlterField("Pony", "pink", models.IntegerField(null=True))
+ operation = migrations.AlterField(
+ "Pony", "pink", models.IntegerField(null=True)
+ )
new_state = project_state.clone()
operation.state_forwards("test_alflin", new_state)
# Test the database alteration
@@ -2231,7 +2865,9 @@ class OperationTests(OperationTestBase):
self.assertIndexExists("test_alflin_pony", ["pink"])
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_alflin", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_alflin", editor, new_state, project_state
+ )
# Ensure the index is still there
self.assertIndexExists("test_alflin_pony", ["pink"])
@@ -2242,15 +2878,31 @@ class OperationTests(OperationTestBase):
project_state = self.set_up_test_model("test_alinto")
# Test the state alteration
operation = migrations.AlterIndexTogether("Pony", [("pink", "weight")])
- self.assertEqual(operation.describe(), "Alter index_together for Pony (1 constraint(s))")
+ self.assertEqual(
+ operation.describe(), "Alter index_together for Pony (1 constraint(s))"
+ )
self.assertEqual(
operation.migration_name_fragment,
- 'alter_pony_index_together',
+ "alter_pony_index_together",
)
new_state = project_state.clone()
operation.state_forwards("test_alinto", new_state)
- self.assertEqual(len(project_state.models["test_alinto", "pony"].options.get("index_together", set())), 0)
- self.assertEqual(len(new_state.models["test_alinto", "pony"].options.get("index_together", set())), 1)
+ self.assertEqual(
+ len(
+ project_state.models["test_alinto", "pony"].options.get(
+ "index_together", set()
+ )
+ ),
+ 0,
+ )
+ self.assertEqual(
+ len(
+ new_state.models["test_alinto", "pony"].options.get(
+ "index_together", set()
+ )
+ ),
+ 1,
+ )
# Make sure there's no matching index
self.assertIndexNotExists("test_alinto_pony", ["pink", "weight"])
# Test the database alteration
@@ -2259,263 +2911,332 @@ class OperationTests(OperationTestBase):
self.assertIndexExists("test_alinto_pony", ["pink", "weight"])
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_alinto", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_alinto", editor, new_state, project_state
+ )
self.assertIndexNotExists("test_alinto_pony", ["pink", "weight"])
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "AlterIndexTogether")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'name': "Pony", 'index_together': {("pink", "weight")}})
+ self.assertEqual(
+ definition[2], {"name": "Pony", "index_together": {("pink", "weight")}}
+ )
def test_alter_index_together_remove(self):
operation = migrations.AlterIndexTogether("Pony", None)
- self.assertEqual(operation.describe(), "Alter index_together for Pony (0 constraint(s))")
+ self.assertEqual(
+ operation.describe(), "Alter index_together for Pony (0 constraint(s))"
+ )
- @skipUnlessDBFeature('allows_multiple_constraints_on_same_fields')
+ @skipUnlessDBFeature("allows_multiple_constraints_on_same_fields")
def test_alter_index_together_remove_with_unique_together(self):
- app_label = 'test_alintoremove_wunto'
- table_name = '%s_pony' % app_label
+ app_label = "test_alintoremove_wunto"
+ table_name = "%s_pony" % app_label
project_state = self.set_up_test_model(app_label, unique_together=True)
- self.assertUniqueConstraintExists(table_name, ['pink', 'weight'])
+ self.assertUniqueConstraintExists(table_name, ["pink", "weight"])
# Add index together.
new_state = project_state.clone()
- operation = migrations.AlterIndexTogether('Pony', [('pink', 'weight')])
+ operation = migrations.AlterIndexTogether("Pony", [("pink", "weight")])
operation.state_forwards(app_label, new_state)
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, project_state, new_state)
- self.assertIndexExists(table_name, ['pink', 'weight'])
+ self.assertIndexExists(table_name, ["pink", "weight"])
# Remove index together.
project_state = new_state
new_state = project_state.clone()
- operation = migrations.AlterIndexTogether('Pony', set())
+ operation = migrations.AlterIndexTogether("Pony", set())
operation.state_forwards(app_label, new_state)
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, project_state, new_state)
- self.assertIndexNotExists(table_name, ['pink', 'weight'])
- self.assertUniqueConstraintExists(table_name, ['pink', 'weight'])
+ self.assertIndexNotExists(table_name, ["pink", "weight"])
+ self.assertUniqueConstraintExists(table_name, ["pink", "weight"])
- @skipUnlessDBFeature('supports_table_check_constraints')
+ @skipUnlessDBFeature("supports_table_check_constraints")
def test_add_constraint(self):
project_state = self.set_up_test_model("test_addconstraint")
gt_check = models.Q(pink__gt=2)
- gt_constraint = models.CheckConstraint(check=gt_check, name="test_add_constraint_pony_pink_gt_2")
+ gt_constraint = models.CheckConstraint(
+ check=gt_check, name="test_add_constraint_pony_pink_gt_2"
+ )
gt_operation = migrations.AddConstraint("Pony", gt_constraint)
self.assertEqual(
- gt_operation.describe(), "Create constraint test_add_constraint_pony_pink_gt_2 on model Pony"
+ gt_operation.describe(),
+ "Create constraint test_add_constraint_pony_pink_gt_2 on model Pony",
)
self.assertEqual(
gt_operation.migration_name_fragment,
- 'pony_test_add_constraint_pony_pink_gt_2',
+ "pony_test_add_constraint_pony_pink_gt_2",
)
# Test the state alteration
new_state = project_state.clone()
gt_operation.state_forwards("test_addconstraint", new_state)
- self.assertEqual(len(new_state.models["test_addconstraint", "pony"].options["constraints"]), 1)
+ self.assertEqual(
+ len(new_state.models["test_addconstraint", "pony"].options["constraints"]),
+ 1,
+ )
Pony = new_state.apps.get_model("test_addconstraint", "Pony")
self.assertEqual(len(Pony._meta.constraints), 1)
# Test the database alteration
with connection.schema_editor() as editor:
- gt_operation.database_forwards("test_addconstraint", editor, project_state, new_state)
+ gt_operation.database_forwards(
+ "test_addconstraint", editor, project_state, new_state
+ )
with self.assertRaises(IntegrityError), transaction.atomic():
Pony.objects.create(pink=1, weight=1.0)
# Add another one.
lt_check = models.Q(pink__lt=100)
- lt_constraint = models.CheckConstraint(check=lt_check, name="test_add_constraint_pony_pink_lt_100")
+ lt_constraint = models.CheckConstraint(
+ check=lt_check, name="test_add_constraint_pony_pink_lt_100"
+ )
lt_operation = migrations.AddConstraint("Pony", lt_constraint)
lt_operation.state_forwards("test_addconstraint", new_state)
- self.assertEqual(len(new_state.models["test_addconstraint", "pony"].options["constraints"]), 2)
+ self.assertEqual(
+ len(new_state.models["test_addconstraint", "pony"].options["constraints"]),
+ 2,
+ )
Pony = new_state.apps.get_model("test_addconstraint", "Pony")
self.assertEqual(len(Pony._meta.constraints), 2)
with connection.schema_editor() as editor:
- lt_operation.database_forwards("test_addconstraint", editor, project_state, new_state)
+ lt_operation.database_forwards(
+ "test_addconstraint", editor, project_state, new_state
+ )
with self.assertRaises(IntegrityError), transaction.atomic():
Pony.objects.create(pink=100, weight=1.0)
# Test reversal
with connection.schema_editor() as editor:
- gt_operation.database_backwards("test_addconstraint", editor, new_state, project_state)
+ gt_operation.database_backwards(
+ "test_addconstraint", editor, new_state, project_state
+ )
Pony.objects.create(pink=1, weight=1.0)
# Test deconstruction
definition = gt_operation.deconstruct()
self.assertEqual(definition[0], "AddConstraint")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': "Pony", 'constraint': gt_constraint})
+ self.assertEqual(
+ definition[2], {"model_name": "Pony", "constraint": gt_constraint}
+ )
- @skipUnlessDBFeature('supports_table_check_constraints')
+ @skipUnlessDBFeature("supports_table_check_constraints")
def test_add_constraint_percent_escaping(self):
- app_label = 'add_constraint_string_quoting'
+ app_label = "add_constraint_string_quoting"
operations = [
migrations.CreateModel(
- 'Author',
+ "Author",
fields=[
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=100)),
- ('surname', models.CharField(max_length=100, default='')),
- ('rebate', models.CharField(max_length=100)),
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=100)),
+ ("surname", models.CharField(max_length=100, default="")),
+ ("rebate", models.CharField(max_length=100)),
],
),
]
from_state = self.apply_operations(app_label, ProjectState(), operations)
# "%" generated in startswith lookup should be escaped in a way that is
# considered a leading wildcard.
- check = models.Q(name__startswith='Albert')
- constraint = models.CheckConstraint(check=check, name='name_constraint')
- operation = migrations.AddConstraint('Author', constraint)
+ check = models.Q(name__startswith="Albert")
+ constraint = models.CheckConstraint(check=check, name="name_constraint")
+ operation = migrations.AddConstraint("Author", constraint)
to_state = from_state.clone()
operation.state_forwards(app_label, to_state)
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, from_state, to_state)
- Author = to_state.apps.get_model(app_label, 'Author')
+ Author = to_state.apps.get_model(app_label, "Author")
with self.assertRaises(IntegrityError), transaction.atomic():
- Author.objects.create(name='Artur')
+ Author.objects.create(name="Artur")
# Literal "%" should be escaped in a way that is not a considered a
# wildcard.
- check = models.Q(rebate__endswith='%')
- constraint = models.CheckConstraint(check=check, name='rebate_constraint')
- operation = migrations.AddConstraint('Author', constraint)
+ check = models.Q(rebate__endswith="%")
+ constraint = models.CheckConstraint(check=check, name="rebate_constraint")
+ operation = migrations.AddConstraint("Author", constraint)
from_state = to_state
to_state = from_state.clone()
operation.state_forwards(app_label, to_state)
- Author = to_state.apps.get_model(app_label, 'Author')
+ Author = to_state.apps.get_model(app_label, "Author")
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, from_state, to_state)
- Author = to_state.apps.get_model(app_label, 'Author')
+ Author = to_state.apps.get_model(app_label, "Author")
with self.assertRaises(IntegrityError), transaction.atomic():
- Author.objects.create(name='Albert', rebate='10$')
- author = Author.objects.create(name='Albert', rebate='10%')
+ Author.objects.create(name="Albert", rebate="10$")
+ author = Author.objects.create(name="Albert", rebate="10%")
self.assertEqual(Author.objects.get(), author)
# Right-hand-side baked "%" literals should not be used for parameters
# interpolation.
- check = ~models.Q(surname__startswith=models.F('name'))
- constraint = models.CheckConstraint(check=check, name='name_constraint_rhs')
- operation = migrations.AddConstraint('Author', constraint)
+ check = ~models.Q(surname__startswith=models.F("name"))
+ constraint = models.CheckConstraint(check=check, name="name_constraint_rhs")
+ operation = migrations.AddConstraint("Author", constraint)
from_state = to_state
to_state = from_state.clone()
operation.state_forwards(app_label, to_state)
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, from_state, to_state)
- Author = to_state.apps.get_model(app_label, 'Author')
+ Author = to_state.apps.get_model(app_label, "Author")
with self.assertRaises(IntegrityError), transaction.atomic():
- Author.objects.create(name='Albert', surname='Alberto')
+ Author.objects.create(name="Albert", surname="Alberto")
- @skipUnlessDBFeature('supports_table_check_constraints')
+ @skipUnlessDBFeature("supports_table_check_constraints")
def test_add_or_constraint(self):
- app_label = 'test_addorconstraint'
- constraint_name = 'add_constraint_or'
+ app_label = "test_addorconstraint"
+ constraint_name = "add_constraint_or"
from_state = self.set_up_test_model(app_label)
check = models.Q(pink__gt=2, weight__gt=2) | models.Q(weight__lt=0)
constraint = models.CheckConstraint(check=check, name=constraint_name)
- operation = migrations.AddConstraint('Pony', constraint)
+ operation = migrations.AddConstraint("Pony", constraint)
to_state = from_state.clone()
operation.state_forwards(app_label, to_state)
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, from_state, to_state)
- Pony = to_state.apps.get_model(app_label, 'Pony')
+ Pony = to_state.apps.get_model(app_label, "Pony")
with self.assertRaises(IntegrityError), transaction.atomic():
Pony.objects.create(pink=2, weight=3.0)
with self.assertRaises(IntegrityError), transaction.atomic():
Pony.objects.create(pink=3, weight=1.0)
- Pony.objects.bulk_create([
- Pony(pink=3, weight=-1.0),
- Pony(pink=1, weight=-1.0),
- Pony(pink=3, weight=3.0),
- ])
+ Pony.objects.bulk_create(
+ [
+ Pony(pink=3, weight=-1.0),
+ Pony(pink=1, weight=-1.0),
+ Pony(pink=3, weight=3.0),
+ ]
+ )
- @skipUnlessDBFeature('supports_table_check_constraints')
+ @skipUnlessDBFeature("supports_table_check_constraints")
def test_add_constraint_combinable(self):
- app_label = 'test_addconstraint_combinable'
+ app_label = "test_addconstraint_combinable"
operations = [
migrations.CreateModel(
- 'Book',
+ "Book",
fields=[
- ('id', models.AutoField(primary_key=True)),
- ('read', models.PositiveIntegerField()),
- ('unread', models.PositiveIntegerField()),
+ ("id", models.AutoField(primary_key=True)),
+ ("read", models.PositiveIntegerField()),
+ ("unread", models.PositiveIntegerField()),
],
),
]
from_state = self.apply_operations(app_label, ProjectState(), operations)
constraint = models.CheckConstraint(
- check=models.Q(read=(100 - models.F('unread'))),
- name='test_addconstraint_combinable_sum_100',
+ check=models.Q(read=(100 - models.F("unread"))),
+ name="test_addconstraint_combinable_sum_100",
)
- operation = migrations.AddConstraint('Book', constraint)
+ operation = migrations.AddConstraint("Book", constraint)
to_state = from_state.clone()
operation.state_forwards(app_label, to_state)
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, from_state, to_state)
- Book = to_state.apps.get_model(app_label, 'Book')
+ Book = to_state.apps.get_model(app_label, "Book")
with self.assertRaises(IntegrityError), transaction.atomic():
Book.objects.create(read=70, unread=10)
Book.objects.create(read=70, unread=30)
- @skipUnlessDBFeature('supports_table_check_constraints')
+ @skipUnlessDBFeature("supports_table_check_constraints")
def test_remove_constraint(self):
- project_state = self.set_up_test_model("test_removeconstraint", constraints=[
- models.CheckConstraint(check=models.Q(pink__gt=2), name="test_remove_constraint_pony_pink_gt_2"),
- models.CheckConstraint(check=models.Q(pink__lt=100), name="test_remove_constraint_pony_pink_lt_100"),
- ])
- gt_operation = migrations.RemoveConstraint("Pony", "test_remove_constraint_pony_pink_gt_2")
+ project_state = self.set_up_test_model(
+ "test_removeconstraint",
+ constraints=[
+ models.CheckConstraint(
+ check=models.Q(pink__gt=2),
+ name="test_remove_constraint_pony_pink_gt_2",
+ ),
+ models.CheckConstraint(
+ check=models.Q(pink__lt=100),
+ name="test_remove_constraint_pony_pink_lt_100",
+ ),
+ ],
+ )
+ gt_operation = migrations.RemoveConstraint(
+ "Pony", "test_remove_constraint_pony_pink_gt_2"
+ )
self.assertEqual(
- gt_operation.describe(), "Remove constraint test_remove_constraint_pony_pink_gt_2 from model Pony"
+ gt_operation.describe(),
+ "Remove constraint test_remove_constraint_pony_pink_gt_2 from model Pony",
)
self.assertEqual(
gt_operation.migration_name_fragment,
- 'remove_pony_test_remove_constraint_pony_pink_gt_2',
+ "remove_pony_test_remove_constraint_pony_pink_gt_2",
)
# Test state alteration
new_state = project_state.clone()
gt_operation.state_forwards("test_removeconstraint", new_state)
- self.assertEqual(len(new_state.models["test_removeconstraint", "pony"].options['constraints']), 1)
+ self.assertEqual(
+ len(
+ new_state.models["test_removeconstraint", "pony"].options["constraints"]
+ ),
+ 1,
+ )
Pony = new_state.apps.get_model("test_removeconstraint", "Pony")
self.assertEqual(len(Pony._meta.constraints), 1)
# Test database alteration
with connection.schema_editor() as editor:
- gt_operation.database_forwards("test_removeconstraint", editor, project_state, new_state)
+ gt_operation.database_forwards(
+ "test_removeconstraint", editor, project_state, new_state
+ )
Pony.objects.create(pink=1, weight=1.0).delete()
with self.assertRaises(IntegrityError), transaction.atomic():
Pony.objects.create(pink=100, weight=1.0)
# Remove the other one.
- lt_operation = migrations.RemoveConstraint("Pony", "test_remove_constraint_pony_pink_lt_100")
+ lt_operation = migrations.RemoveConstraint(
+ "Pony", "test_remove_constraint_pony_pink_lt_100"
+ )
lt_operation.state_forwards("test_removeconstraint", new_state)
- self.assertEqual(len(new_state.models["test_removeconstraint", "pony"].options['constraints']), 0)
+ self.assertEqual(
+ len(
+ new_state.models["test_removeconstraint", "pony"].options["constraints"]
+ ),
+ 0,
+ )
Pony = new_state.apps.get_model("test_removeconstraint", "Pony")
self.assertEqual(len(Pony._meta.constraints), 0)
with connection.schema_editor() as editor:
- lt_operation.database_forwards("test_removeconstraint", editor, project_state, new_state)
+ lt_operation.database_forwards(
+ "test_removeconstraint", editor, project_state, new_state
+ )
Pony.objects.create(pink=100, weight=1.0).delete()
# Test reversal
with connection.schema_editor() as editor:
- gt_operation.database_backwards("test_removeconstraint", editor, new_state, project_state)
+ gt_operation.database_backwards(
+ "test_removeconstraint", editor, new_state, project_state
+ )
with self.assertRaises(IntegrityError), transaction.atomic():
Pony.objects.create(pink=1, weight=1.0)
# Test deconstruction
definition = gt_operation.deconstruct()
self.assertEqual(definition[0], "RemoveConstraint")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': "Pony", 'name': "test_remove_constraint_pony_pink_gt_2"})
+ self.assertEqual(
+ definition[2],
+ {"model_name": "Pony", "name": "test_remove_constraint_pony_pink_gt_2"},
+ )
def test_add_partial_unique_constraint(self):
- project_state = self.set_up_test_model('test_addpartialuniqueconstraint')
+ project_state = self.set_up_test_model("test_addpartialuniqueconstraint")
partial_unique_constraint = models.UniqueConstraint(
- fields=['pink'],
+ fields=["pink"],
condition=models.Q(weight__gt=5),
- name='test_constraint_pony_pink_for_weight_gt_5_uniq',
+ name="test_constraint_pony_pink_for_weight_gt_5_uniq",
)
- operation = migrations.AddConstraint('Pony', partial_unique_constraint)
+ operation = migrations.AddConstraint("Pony", partial_unique_constraint)
self.assertEqual(
operation.describe(),
- 'Create constraint test_constraint_pony_pink_for_weight_gt_5_uniq '
- 'on model Pony'
+ "Create constraint test_constraint_pony_pink_for_weight_gt_5_uniq "
+ "on model Pony",
)
# Test the state alteration
new_state = project_state.clone()
- operation.state_forwards('test_addpartialuniqueconstraint', new_state)
- self.assertEqual(len(new_state.models['test_addpartialuniqueconstraint', 'pony'].options['constraints']), 1)
- Pony = new_state.apps.get_model('test_addpartialuniqueconstraint', 'Pony')
+ operation.state_forwards("test_addpartialuniqueconstraint", new_state)
+ self.assertEqual(
+ len(
+ new_state.models["test_addpartialuniqueconstraint", "pony"].options[
+ "constraints"
+ ]
+ ),
+ 1,
+ )
+ Pony = new_state.apps.get_model("test_addpartialuniqueconstraint", "Pony")
self.assertEqual(len(Pony._meta.constraints), 1)
# Test the database alteration
with connection.schema_editor() as editor:
- operation.database_forwards('test_addpartialuniqueconstraint', editor, project_state, new_state)
+ operation.database_forwards(
+ "test_addpartialuniqueconstraint", editor, project_state, new_state
+ )
# Test constraint works
Pony.objects.create(pink=1, weight=4.0)
Pony.objects.create(pink=1, weight=4.0)
@@ -2527,36 +3248,56 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1, weight=7.0)
# Test reversal
with connection.schema_editor() as editor:
- operation.database_backwards('test_addpartialuniqueconstraint', editor, new_state, project_state)
+ operation.database_backwards(
+ "test_addpartialuniqueconstraint", editor, new_state, project_state
+ )
# Test constraint doesn't work
Pony.objects.create(pink=1, weight=7.0)
# Test deconstruction
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'AddConstraint')
+ self.assertEqual(definition[0], "AddConstraint")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': 'Pony', 'constraint': partial_unique_constraint})
+ self.assertEqual(
+ definition[2],
+ {"model_name": "Pony", "constraint": partial_unique_constraint},
+ )
def test_remove_partial_unique_constraint(self):
- project_state = self.set_up_test_model('test_removepartialuniqueconstraint', constraints=[
- models.UniqueConstraint(
- fields=['pink'],
- condition=models.Q(weight__gt=5),
- name='test_constraint_pony_pink_for_weight_gt_5_uniq',
- ),
- ])
- gt_operation = migrations.RemoveConstraint('Pony', 'test_constraint_pony_pink_for_weight_gt_5_uniq')
+ project_state = self.set_up_test_model(
+ "test_removepartialuniqueconstraint",
+ constraints=[
+ models.UniqueConstraint(
+ fields=["pink"],
+ condition=models.Q(weight__gt=5),
+ name="test_constraint_pony_pink_for_weight_gt_5_uniq",
+ ),
+ ],
+ )
+ gt_operation = migrations.RemoveConstraint(
+ "Pony", "test_constraint_pony_pink_for_weight_gt_5_uniq"
+ )
self.assertEqual(
- gt_operation.describe(), 'Remove constraint test_constraint_pony_pink_for_weight_gt_5_uniq from model Pony'
+ gt_operation.describe(),
+ "Remove constraint test_constraint_pony_pink_for_weight_gt_5_uniq from model Pony",
)
# Test state alteration
new_state = project_state.clone()
- gt_operation.state_forwards('test_removepartialuniqueconstraint', new_state)
- self.assertEqual(len(new_state.models['test_removepartialuniqueconstraint', 'pony'].options['constraints']), 0)
- Pony = new_state.apps.get_model('test_removepartialuniqueconstraint', 'Pony')
+ gt_operation.state_forwards("test_removepartialuniqueconstraint", new_state)
+ self.assertEqual(
+ len(
+ new_state.models["test_removepartialuniqueconstraint", "pony"].options[
+ "constraints"
+ ]
+ ),
+ 0,
+ )
+ Pony = new_state.apps.get_model("test_removepartialuniqueconstraint", "Pony")
self.assertEqual(len(Pony._meta.constraints), 0)
# Test database alteration
with connection.schema_editor() as editor:
- gt_operation.database_forwards('test_removepartialuniqueconstraint', editor, project_state, new_state)
+ gt_operation.database_forwards(
+ "test_removepartialuniqueconstraint", editor, project_state, new_state
+ )
# Test constraint doesn't work
Pony.objects.create(pink=1, weight=4.0)
Pony.objects.create(pink=1, weight=4.0)
@@ -2564,7 +3305,9 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1, weight=7.0).delete()
# Test reversal
with connection.schema_editor() as editor:
- gt_operation.database_backwards('test_removepartialuniqueconstraint', editor, new_state, project_state)
+ gt_operation.database_backwards(
+ "test_removepartialuniqueconstraint", editor, new_state, project_state
+ )
# Test constraint works
if connection.features.supports_partial_indexes:
with self.assertRaises(IntegrityError), transaction.atomic():
@@ -2573,33 +3316,40 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1, weight=7.0)
# Test deconstruction
definition = gt_operation.deconstruct()
- self.assertEqual(definition[0], 'RemoveConstraint')
+ self.assertEqual(definition[0], "RemoveConstraint")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {
- 'model_name': 'Pony',
- 'name': 'test_constraint_pony_pink_for_weight_gt_5_uniq',
- })
+ self.assertEqual(
+ definition[2],
+ {
+ "model_name": "Pony",
+ "name": "test_constraint_pony_pink_for_weight_gt_5_uniq",
+ },
+ )
def test_add_deferred_unique_constraint(self):
- app_label = 'test_adddeferred_uc'
+ app_label = "test_adddeferred_uc"
project_state = self.set_up_test_model(app_label)
deferred_unique_constraint = models.UniqueConstraint(
- fields=['pink'],
- name='deferred_pink_constraint_add',
+ fields=["pink"],
+ name="deferred_pink_constraint_add",
deferrable=models.Deferrable.DEFERRED,
)
- operation = migrations.AddConstraint('Pony', deferred_unique_constraint)
+ operation = migrations.AddConstraint("Pony", deferred_unique_constraint)
self.assertEqual(
operation.describe(),
- 'Create constraint deferred_pink_constraint_add on model Pony',
+ "Create constraint deferred_pink_constraint_add on model Pony",
)
# Add constraint.
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
- self.assertEqual(len(new_state.models[app_label, 'pony'].options['constraints']), 1)
- Pony = new_state.apps.get_model(app_label, 'Pony')
+ self.assertEqual(
+ len(new_state.models[app_label, "pony"].options["constraints"]), 1
+ )
+ Pony = new_state.apps.get_model(app_label, "Pony")
self.assertEqual(len(Pony._meta.constraints), 1)
- with connection.schema_editor() as editor, CaptureQueriesContext(connection) as ctx:
+ with connection.schema_editor() as editor, CaptureQueriesContext(
+ connection
+ ) as ctx:
operation.database_forwards(app_label, editor, project_state, new_state)
Pony.objects.create(pink=1, weight=4.0)
if connection.features.supports_deferrable_unique_constraints:
@@ -2611,8 +3361,10 @@ class OperationTests(OperationTestBase):
# Constraint behavior can be changed with SET CONSTRAINTS.
with self.assertRaises(IntegrityError):
with transaction.atomic(), connection.cursor() as cursor:
- quoted_name = connection.ops.quote_name(deferred_unique_constraint.name)
- cursor.execute('SET CONSTRAINTS %s IMMEDIATE' % quoted_name)
+ quoted_name = connection.ops.quote_name(
+ deferred_unique_constraint.name
+ )
+ cursor.execute("SET CONSTRAINTS %s IMMEDIATE" % quoted_name)
obj = Pony.objects.create(pink=1, weight=4.0)
obj.pink = 3
obj.save()
@@ -2626,33 +3378,39 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1, weight=4.0)
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'AddConstraint')
+ self.assertEqual(definition[0], "AddConstraint")
self.assertEqual(definition[1], [])
self.assertEqual(
definition[2],
- {'model_name': 'Pony', 'constraint': deferred_unique_constraint},
+ {"model_name": "Pony", "constraint": deferred_unique_constraint},
)
def test_remove_deferred_unique_constraint(self):
- app_label = 'test_removedeferred_uc'
+ app_label = "test_removedeferred_uc"
deferred_unique_constraint = models.UniqueConstraint(
- fields=['pink'],
- name='deferred_pink_constraint_rm',
+ fields=["pink"],
+ name="deferred_pink_constraint_rm",
deferrable=models.Deferrable.DEFERRED,
)
- project_state = self.set_up_test_model(app_label, constraints=[deferred_unique_constraint])
- operation = migrations.RemoveConstraint('Pony', deferred_unique_constraint.name)
+ project_state = self.set_up_test_model(
+ app_label, constraints=[deferred_unique_constraint]
+ )
+ operation = migrations.RemoveConstraint("Pony", deferred_unique_constraint.name)
self.assertEqual(
operation.describe(),
- 'Remove constraint deferred_pink_constraint_rm from model Pony',
+ "Remove constraint deferred_pink_constraint_rm from model Pony",
)
# Remove constraint.
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
- self.assertEqual(len(new_state.models[app_label, 'pony'].options['constraints']), 0)
- Pony = new_state.apps.get_model(app_label, 'Pony')
+ self.assertEqual(
+ len(new_state.models[app_label, "pony"].options["constraints"]), 0
+ )
+ Pony = new_state.apps.get_model(app_label, "Pony")
self.assertEqual(len(Pony._meta.constraints), 0)
- with connection.schema_editor() as editor, CaptureQueriesContext(connection) as ctx:
+ with connection.schema_editor() as editor, CaptureQueriesContext(
+ connection
+ ) as ctx:
operation.database_forwards(app_label, editor, project_state, new_state)
# Constraint doesn't work.
Pony.objects.create(pink=1, weight=4.0)
@@ -2671,8 +3429,10 @@ class OperationTests(OperationTestBase):
# Constraint behavior can be changed with SET CONSTRAINTS.
with self.assertRaises(IntegrityError):
with transaction.atomic(), connection.cursor() as cursor:
- quoted_name = connection.ops.quote_name(deferred_unique_constraint.name)
- cursor.execute('SET CONSTRAINTS %s IMMEDIATE' % quoted_name)
+ quoted_name = connection.ops.quote_name(
+ deferred_unique_constraint.name
+ )
+ cursor.execute("SET CONSTRAINTS %s IMMEDIATE" % quoted_name)
obj = Pony.objects.create(pink=1, weight=4.0)
obj.pink = 3
obj.save()
@@ -2680,33 +3440,40 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1, weight=4.0)
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'RemoveConstraint')
+ self.assertEqual(definition[0], "RemoveConstraint")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {
- 'model_name': 'Pony',
- 'name': 'deferred_pink_constraint_rm',
- })
+ self.assertEqual(
+ definition[2],
+ {
+ "model_name": "Pony",
+ "name": "deferred_pink_constraint_rm",
+ },
+ )
def test_add_covering_unique_constraint(self):
- app_label = 'test_addcovering_uc'
+ app_label = "test_addcovering_uc"
project_state = self.set_up_test_model(app_label)
covering_unique_constraint = models.UniqueConstraint(
- fields=['pink'],
- name='covering_pink_constraint_add',
- include=['weight'],
+ fields=["pink"],
+ name="covering_pink_constraint_add",
+ include=["weight"],
)
- operation = migrations.AddConstraint('Pony', covering_unique_constraint)
+ operation = migrations.AddConstraint("Pony", covering_unique_constraint)
self.assertEqual(
operation.describe(),
- 'Create constraint covering_pink_constraint_add on model Pony',
+ "Create constraint covering_pink_constraint_add on model Pony",
)
# Add constraint.
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
- self.assertEqual(len(new_state.models[app_label, 'pony'].options['constraints']), 1)
- Pony = new_state.apps.get_model(app_label, 'Pony')
+ self.assertEqual(
+ len(new_state.models[app_label, "pony"].options["constraints"]), 1
+ )
+ Pony = new_state.apps.get_model(app_label, "Pony")
self.assertEqual(len(Pony._meta.constraints), 1)
- with connection.schema_editor() as editor, CaptureQueriesContext(connection) as ctx:
+ with connection.schema_editor() as editor, CaptureQueriesContext(
+ connection
+ ) as ctx:
operation.database_forwards(app_label, editor, project_state, new_state)
Pony.objects.create(pink=1, weight=4.0)
if connection.features.supports_covering_indexes:
@@ -2722,33 +3489,39 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1, weight=4.0)
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'AddConstraint')
+ self.assertEqual(definition[0], "AddConstraint")
self.assertEqual(definition[1], [])
self.assertEqual(
definition[2],
- {'model_name': 'Pony', 'constraint': covering_unique_constraint},
+ {"model_name": "Pony", "constraint": covering_unique_constraint},
)
def test_remove_covering_unique_constraint(self):
- app_label = 'test_removecovering_uc'
+ app_label = "test_removecovering_uc"
covering_unique_constraint = models.UniqueConstraint(
- fields=['pink'],
- name='covering_pink_constraint_rm',
- include=['weight'],
+ fields=["pink"],
+ name="covering_pink_constraint_rm",
+ include=["weight"],
+ )
+ project_state = self.set_up_test_model(
+ app_label, constraints=[covering_unique_constraint]
)
- project_state = self.set_up_test_model(app_label, constraints=[covering_unique_constraint])
- operation = migrations.RemoveConstraint('Pony', covering_unique_constraint.name)
+ operation = migrations.RemoveConstraint("Pony", covering_unique_constraint.name)
self.assertEqual(
operation.describe(),
- 'Remove constraint covering_pink_constraint_rm from model Pony',
+ "Remove constraint covering_pink_constraint_rm from model Pony",
)
# Remove constraint.
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
- self.assertEqual(len(new_state.models[app_label, 'pony'].options['constraints']), 0)
- Pony = new_state.apps.get_model(app_label, 'Pony')
+ self.assertEqual(
+ len(new_state.models[app_label, "pony"].options["constraints"]), 0
+ )
+ Pony = new_state.apps.get_model(app_label, "Pony")
self.assertEqual(len(Pony._meta.constraints), 0)
- with connection.schema_editor() as editor, CaptureQueriesContext(connection) as ctx:
+ with connection.schema_editor() as editor, CaptureQueriesContext(
+ connection
+ ) as ctx:
operation.database_forwards(app_label, editor, project_state, new_state)
# Constraint doesn't work.
Pony.objects.create(pink=1, weight=4.0)
@@ -2765,22 +3538,29 @@ class OperationTests(OperationTestBase):
Pony.objects.create(pink=1, weight=4.0)
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'RemoveConstraint')
+ self.assertEqual(definition[0], "RemoveConstraint")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {
- 'model_name': 'Pony',
- 'name': 'covering_pink_constraint_rm',
- })
+ self.assertEqual(
+ definition[2],
+ {
+ "model_name": "Pony",
+ "name": "covering_pink_constraint_rm",
+ },
+ )
def test_alter_field_with_func_unique_constraint(self):
- app_label = 'test_alfuncuc'
- constraint_name = f'{app_label}_pony_uq'
- table_name = f'{app_label}_pony'
+ app_label = "test_alfuncuc"
+ constraint_name = f"{app_label}_pony_uq"
+ table_name = f"{app_label}_pony"
project_state = self.set_up_test_model(
app_label,
- constraints=[models.UniqueConstraint('pink', 'weight', name=constraint_name)]
+ constraints=[
+ models.UniqueConstraint("pink", "weight", name=constraint_name)
+ ],
+ )
+ operation = migrations.AlterField(
+ "Pony", "pink", models.IntegerField(null=True)
)
- operation = migrations.AlterField('Pony', 'pink', models.IntegerField(null=True))
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
with connection.schema_editor() as editor:
@@ -2793,28 +3573,30 @@ class OperationTests(OperationTestBase):
self.assertIndexNameExists(table_name, constraint_name)
def test_add_func_unique_constraint(self):
- app_label = 'test_adfuncuc'
- constraint_name = f'{app_label}_pony_abs_uq'
- table_name = f'{app_label}_pony'
+ app_label = "test_adfuncuc"
+ constraint_name = f"{app_label}_pony_abs_uq"
+ table_name = f"{app_label}_pony"
project_state = self.set_up_test_model(app_label)
- constraint = models.UniqueConstraint(Abs('weight'), name=constraint_name)
- operation = migrations.AddConstraint('Pony', constraint)
+ constraint = models.UniqueConstraint(Abs("weight"), name=constraint_name)
+ operation = migrations.AddConstraint("Pony", constraint)
self.assertEqual(
operation.describe(),
- 'Create constraint test_adfuncuc_pony_abs_uq on model Pony',
+ "Create constraint test_adfuncuc_pony_abs_uq on model Pony",
)
self.assertEqual(
operation.migration_name_fragment,
- 'pony_test_adfuncuc_pony_abs_uq',
+ "pony_test_adfuncuc_pony_abs_uq",
)
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
- self.assertEqual(len(new_state.models[app_label, 'pony'].options['constraints']), 1)
+ self.assertEqual(
+ len(new_state.models[app_label, "pony"].options["constraints"]), 1
+ )
self.assertIndexNameNotExists(table_name, constraint_name)
# Add constraint.
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, project_state, new_state)
- Pony = new_state.apps.get_model(app_label, 'Pony')
+ Pony = new_state.apps.get_model(app_label, "Pony")
Pony.objects.create(weight=4.0)
if connection.features.supports_expression_indexes:
self.assertIndexNameExists(table_name, constraint_name)
@@ -2831,36 +3613,41 @@ class OperationTests(OperationTestBase):
Pony.objects.create(weight=-4.0)
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'AddConstraint')
+ self.assertEqual(definition[0], "AddConstraint")
self.assertEqual(definition[1], [])
self.assertEqual(
definition[2],
- {'model_name': 'Pony', 'constraint': constraint},
+ {"model_name": "Pony", "constraint": constraint},
)
def test_remove_func_unique_constraint(self):
- app_label = 'test_rmfuncuc'
- constraint_name = f'{app_label}_pony_abs_uq'
- table_name = f'{app_label}_pony'
- project_state = self.set_up_test_model(app_label, constraints=[
- models.UniqueConstraint(Abs('weight'), name=constraint_name),
- ])
+ app_label = "test_rmfuncuc"
+ constraint_name = f"{app_label}_pony_abs_uq"
+ table_name = f"{app_label}_pony"
+ project_state = self.set_up_test_model(
+ app_label,
+ constraints=[
+ models.UniqueConstraint(Abs("weight"), name=constraint_name),
+ ],
+ )
self.assertTableExists(table_name)
if connection.features.supports_expression_indexes:
self.assertIndexNameExists(table_name, constraint_name)
- operation = migrations.RemoveConstraint('Pony', constraint_name)
+ operation = migrations.RemoveConstraint("Pony", constraint_name)
self.assertEqual(
operation.describe(),
- 'Remove constraint test_rmfuncuc_pony_abs_uq from model Pony',
+ "Remove constraint test_rmfuncuc_pony_abs_uq from model Pony",
)
self.assertEqual(
operation.migration_name_fragment,
- 'remove_pony_test_rmfuncuc_pony_abs_uq',
+ "remove_pony_test_rmfuncuc_pony_abs_uq",
)
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
- self.assertEqual(len(new_state.models[app_label, 'pony'].options['constraints']), 0)
- Pony = new_state.apps.get_model(app_label, 'Pony')
+ self.assertEqual(
+ len(new_state.models[app_label, "pony"].options["constraints"]), 0
+ )
+ Pony = new_state.apps.get_model(app_label, "Pony")
self.assertEqual(len(Pony._meta.constraints), 0)
# Remove constraint.
with connection.schema_editor() as editor:
@@ -2881,9 +3668,9 @@ class OperationTests(OperationTestBase):
Pony.objects.create(weight=-4.0)
# Deconstruction.
definition = operation.deconstruct()
- self.assertEqual(definition[0], 'RemoveConstraint')
+ self.assertEqual(definition[0], "RemoveConstraint")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'model_name': 'Pony', 'name': constraint_name})
+ self.assertEqual(definition[2], {"model_name": "Pony", "name": constraint_name})
def test_alter_model_options(self):
"""
@@ -2891,19 +3678,37 @@ class OperationTests(OperationTestBase):
"""
project_state = self.set_up_test_model("test_almoop")
# Test the state alteration (no DB alteration to test)
- operation = migrations.AlterModelOptions("Pony", {"permissions": [("can_groom", "Can groom")]})
+ operation = migrations.AlterModelOptions(
+ "Pony", {"permissions": [("can_groom", "Can groom")]}
+ )
self.assertEqual(operation.describe(), "Change Meta options on Pony")
- self.assertEqual(operation.migration_name_fragment, 'alter_pony_options')
+ self.assertEqual(operation.migration_name_fragment, "alter_pony_options")
new_state = project_state.clone()
operation.state_forwards("test_almoop", new_state)
- self.assertEqual(len(project_state.models["test_almoop", "pony"].options.get("permissions", [])), 0)
- self.assertEqual(len(new_state.models["test_almoop", "pony"].options.get("permissions", [])), 1)
- self.assertEqual(new_state.models["test_almoop", "pony"].options["permissions"][0][0], "can_groom")
+ self.assertEqual(
+ len(
+ project_state.models["test_almoop", "pony"].options.get(
+ "permissions", []
+ )
+ ),
+ 0,
+ )
+ self.assertEqual(
+ len(new_state.models["test_almoop", "pony"].options.get("permissions", [])),
+ 1,
+ )
+ self.assertEqual(
+ new_state.models["test_almoop", "pony"].options["permissions"][0][0],
+ "can_groom",
+ )
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "AlterModelOptions")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'name': "Pony", 'options': {"permissions": [("can_groom", "Can groom")]}})
+ self.assertEqual(
+ definition[2],
+ {"name": "Pony", "options": {"permissions": [("can_groom", "Can groom")]}},
+ )
def test_alter_model_options_emptying(self):
"""
@@ -2915,13 +3720,23 @@ class OperationTests(OperationTestBase):
self.assertEqual(operation.describe(), "Change Meta options on Pony")
new_state = project_state.clone()
operation.state_forwards("test_almoop", new_state)
- self.assertEqual(len(project_state.models["test_almoop", "pony"].options.get("permissions", [])), 1)
- self.assertEqual(len(new_state.models["test_almoop", "pony"].options.get("permissions", [])), 0)
+ self.assertEqual(
+ len(
+ project_state.models["test_almoop", "pony"].options.get(
+ "permissions", []
+ )
+ ),
+ 1,
+ )
+ self.assertEqual(
+ len(new_state.models["test_almoop", "pony"].options.get("permissions", [])),
+ 0,
+ )
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "AlterModelOptions")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'name': "Pony", 'options': {}})
+ self.assertEqual(definition[2], {"name": "Pony", "options": {}})
def test_alter_order_with_respect_to(self):
"""
@@ -2930,48 +3745,68 @@ class OperationTests(OperationTestBase):
project_state = self.set_up_test_model("test_alorwrtto", related_model=True)
# Test the state alteration
operation = migrations.AlterOrderWithRespectTo("Rider", "pony")
- self.assertEqual(operation.describe(), "Set order_with_respect_to on Rider to pony")
+ self.assertEqual(
+ operation.describe(), "Set order_with_respect_to on Rider to pony"
+ )
self.assertEqual(
operation.migration_name_fragment,
- 'alter_rider_order_with_respect_to',
+ "alter_rider_order_with_respect_to",
)
new_state = project_state.clone()
operation.state_forwards("test_alorwrtto", new_state)
self.assertIsNone(
- project_state.models["test_alorwrtto", "rider"].options.get("order_with_respect_to", None)
+ project_state.models["test_alorwrtto", "rider"].options.get(
+ "order_with_respect_to", None
+ )
)
self.assertEqual(
- new_state.models["test_alorwrtto", "rider"].options.get("order_with_respect_to", None),
- "pony"
+ new_state.models["test_alorwrtto", "rider"].options.get(
+ "order_with_respect_to", None
+ ),
+ "pony",
)
# Make sure there's no matching index
self.assertColumnNotExists("test_alorwrtto_rider", "_order")
# Create some rows before alteration
rendered_state = project_state.apps
- pony = rendered_state.get_model("test_alorwrtto", "Pony").objects.create(weight=50)
- rider1 = rendered_state.get_model("test_alorwrtto", "Rider").objects.create(pony=pony)
+ pony = rendered_state.get_model("test_alorwrtto", "Pony").objects.create(
+ weight=50
+ )
+ rider1 = rendered_state.get_model("test_alorwrtto", "Rider").objects.create(
+ pony=pony
+ )
rider1.friend = rider1
rider1.save()
- rider2 = rendered_state.get_model("test_alorwrtto", "Rider").objects.create(pony=pony)
+ rider2 = rendered_state.get_model("test_alorwrtto", "Rider").objects.create(
+ pony=pony
+ )
rider2.friend = rider2
rider2.save()
# Test the database alteration
with connection.schema_editor() as editor:
- operation.database_forwards("test_alorwrtto", editor, project_state, new_state)
+ operation.database_forwards(
+ "test_alorwrtto", editor, project_state, new_state
+ )
self.assertColumnExists("test_alorwrtto_rider", "_order")
# Check for correct value in rows
- updated_riders = new_state.apps.get_model("test_alorwrtto", "Rider").objects.all()
+ updated_riders = new_state.apps.get_model(
+ "test_alorwrtto", "Rider"
+ ).objects.all()
self.assertEqual(updated_riders[0]._order, 0)
self.assertEqual(updated_riders[1]._order, 0)
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_alorwrtto", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_alorwrtto", editor, new_state, project_state
+ )
self.assertColumnNotExists("test_alorwrtto_rider", "_order")
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "AlterOrderWithRespectTo")
self.assertEqual(definition[1], [])
- self.assertEqual(definition[2], {'name': "Rider", 'order_with_respect_to': "pony"})
+ self.assertEqual(
+ definition[2], {"name": "Rider", "order_with_respect_to": "pony"}
+ )
def test_alter_model_managers(self):
"""
@@ -2985,10 +3820,10 @@ class OperationTests(OperationTestBase):
("food_qs", FoodQuerySet.as_manager()),
("food_mgr", FoodManager("a", "b")),
("food_mgr_kwargs", FoodManager("x", "y", 3, 4)),
- ]
+ ],
)
self.assertEqual(operation.describe(), "Change managers on Pony")
- self.assertEqual(operation.migration_name_fragment, 'alter_pony_managers')
+ self.assertEqual(operation.migration_name_fragment, "alter_pony_managers")
managers = project_state.models["test_almoma", "pony"].managers
self.assertEqual(managers, [])
@@ -3005,7 +3840,7 @@ class OperationTests(OperationTestBase):
self.assertIsInstance(managers[2][1], FoodManager)
self.assertEqual(managers[2][1].args, ("x", "y", 3, 4))
rendered_state = new_state.apps
- model = rendered_state.get_model('test_almoma', 'pony')
+ model = rendered_state.get_model("test_almoma", "pony")
self.assertIsInstance(model.food_qs, models.Manager)
self.assertIsInstance(model.food_mgr, FoodManager)
self.assertIsInstance(model.food_mgr_kwargs, FoodManager)
@@ -3051,15 +3886,19 @@ class OperationTests(OperationTestBase):
create_state = project_state.clone()
create_operation.state_forwards("test_alfk", create_state)
alter_operation = migrations.AlterField(
- model_name='Rider',
- name='pony',
+ model_name="Rider",
+ name="pony",
field=models.ForeignKey("Pony", models.CASCADE, editable=False),
)
alter_state = create_state.clone()
alter_operation.state_forwards("test_alfk", alter_state)
with connection.schema_editor() as editor:
- create_operation.database_forwards("test_alfk", editor, project_state, create_state)
- alter_operation.database_forwards("test_alfk", editor, create_state, alter_state)
+ create_operation.database_forwards(
+ "test_alfk", editor, project_state, create_state
+ )
+ alter_operation.database_forwards(
+ "test_alfk", editor, create_state, alter_state
+ )
def test_alter_fk_non_fk(self):
"""
@@ -3071,7 +3910,9 @@ class OperationTests(OperationTestBase):
name="pony",
field=models.FloatField(),
)
- project_state, new_state = self.make_test_state("test_afknfk", operation, related_model=True)
+ project_state, new_state = self.make_test_state(
+ "test_afknfk", operation, related_model=True
+ )
# Test the database alteration
self.assertColumnExists("test_afknfk_rider", "pony_id")
self.assertColumnNotExists("test_afknfk_rider", "pony")
@@ -3081,7 +3922,9 @@ class OperationTests(OperationTestBase):
self.assertColumnNotExists("test_afknfk_rider", "pony_id")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_afknfk", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_afknfk", editor, new_state, project_state
+ )
self.assertColumnExists("test_afknfk_rider", "pony_id")
self.assertColumnNotExists("test_afknfk_rider", "pony")
@@ -3098,27 +3941,33 @@ class OperationTests(OperationTestBase):
"INSERT INTO i_love_ponies (id, special_thing) VALUES (2, 'i love django');\n"
"UPDATE i_love_ponies SET special_thing = 'Ponies' WHERE special_thing LIKE '%%ponies';"
"UPDATE i_love_ponies SET special_thing = 'Django' WHERE special_thing LIKE '%django';",
-
# Run delete queries to test for parameter substitution failure
# reported in #23426
"DELETE FROM i_love_ponies WHERE special_thing LIKE '%Django%';"
"DELETE FROM i_love_ponies WHERE special_thing LIKE '%%Ponies%%';"
"DROP TABLE i_love_ponies",
-
- state_operations=[migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))])],
+ state_operations=[
+ migrations.CreateModel(
+ "SomethingElse", [("id", models.AutoField(primary_key=True))]
+ )
+ ],
)
self.assertEqual(operation.describe(), "Raw SQL operation")
# Test the state alteration
new_state = project_state.clone()
operation.state_forwards("test_runsql", new_state)
- self.assertEqual(len(new_state.models["test_runsql", "somethingelse"].fields), 1)
+ self.assertEqual(
+ len(new_state.models["test_runsql", "somethingelse"].fields), 1
+ )
# Make sure there's no table
self.assertTableNotExists("i_love_ponies")
# Test SQL collection
with connection.schema_editor(collect_sql=True) as editor:
operation.database_forwards("test_runsql", editor, project_state, new_state)
self.assertIn("LIKE '%%ponies';", "\n".join(editor.collected_sql))
- operation.database_backwards("test_runsql", editor, project_state, new_state)
+ operation.database_backwards(
+ "test_runsql", editor, project_state, new_state
+ )
self.assertIn("LIKE '%%Ponies%%';", "\n".join(editor.collected_sql))
# Test the database alteration
with connection.schema_editor() as editor:
@@ -3128,23 +3977,31 @@ class OperationTests(OperationTestBase):
with connection.cursor() as cursor:
cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
self.assertEqual(cursor.fetchall()[0][0], 2)
- cursor.execute("SELECT COUNT(*) FROM i_love_ponies WHERE special_thing = 'Django'")
+ cursor.execute(
+ "SELECT COUNT(*) FROM i_love_ponies WHERE special_thing = 'Django'"
+ )
self.assertEqual(cursor.fetchall()[0][0], 1)
- cursor.execute("SELECT COUNT(*) FROM i_love_ponies WHERE special_thing = 'Ponies'")
+ cursor.execute(
+ "SELECT COUNT(*) FROM i_love_ponies WHERE special_thing = 'Ponies'"
+ )
self.assertEqual(cursor.fetchall()[0][0], 1)
# And test reversal
self.assertTrue(operation.reversible)
with connection.schema_editor() as editor:
- operation.database_backwards("test_runsql", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_runsql", editor, new_state, project_state
+ )
self.assertTableNotExists("i_love_ponies")
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "RunSQL")
self.assertEqual(definition[1], [])
- self.assertEqual(sorted(definition[2]), ["reverse_sql", "sql", "state_operations"])
+ self.assertEqual(
+ sorted(definition[2]), ["reverse_sql", "sql", "state_operations"]
+ )
# And elidable reduction
self.assertIs(False, operation.reduce(operation, []))
- elidable_operation = migrations.RunSQL('SELECT 1 FROM void;', elidable=True)
+ elidable_operation = migrations.RunSQL("SELECT 1 FROM void;", elidable=True)
self.assertEqual(elidable_operation.reduce(operation, []), [operation])
def test_run_sql_params(self):
@@ -3161,15 +4018,27 @@ class OperationTests(OperationTestBase):
# forwards
(
"INSERT INTO i_love_ponies (id, special_thing) VALUES (1, 'Django');",
- ["INSERT INTO i_love_ponies (id, special_thing) VALUES (2, %s);", ['Ponies']],
- ("INSERT INTO i_love_ponies (id, special_thing) VALUES (%s, %s);", (3, 'Python',)),
+ [
+ "INSERT INTO i_love_ponies (id, special_thing) VALUES (2, %s);",
+ ["Ponies"],
+ ],
+ (
+ "INSERT INTO i_love_ponies (id, special_thing) VALUES (%s, %s);",
+ (
+ 3,
+ "Python",
+ ),
+ ),
),
# backwards
[
"DELETE FROM i_love_ponies WHERE special_thing = 'Django';",
["DELETE FROM i_love_ponies WHERE special_thing = 'Ponies';", None],
- ("DELETE FROM i_love_ponies WHERE id = %s OR special_thing = %s;", [3, 'Python']),
- ]
+ (
+ "DELETE FROM i_love_ponies WHERE id = %s OR special_thing = %s;",
+ [3, "Python"],
+ ),
+ ],
)
# Make sure there's no table
@@ -3181,21 +4050,27 @@ class OperationTests(OperationTestBase):
# Test parameter passing
with connection.schema_editor() as editor:
- param_operation.database_forwards("test_runsql", editor, project_state, new_state)
+ param_operation.database_forwards(
+ "test_runsql", editor, project_state, new_state
+ )
# Make sure all the SQL was processed
with connection.cursor() as cursor:
cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
self.assertEqual(cursor.fetchall()[0][0], 3)
with connection.schema_editor() as editor:
- param_operation.database_backwards("test_runsql", editor, new_state, project_state)
+ param_operation.database_backwards(
+ "test_runsql", editor, new_state, project_state
+ )
with connection.cursor() as cursor:
cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
self.assertEqual(cursor.fetchall()[0][0], 0)
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_runsql", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_runsql", editor, new_state, project_state
+ )
self.assertTableNotExists("i_love_ponies")
def test_run_sql_params_invalid(self):
@@ -3207,22 +4082,22 @@ class OperationTests(OperationTestBase):
new_state = project_state.clone()
operation = migrations.RunSQL(
# forwards
- [
- ["INSERT INTO foo (bar) VALUES ('buz');"]
- ],
+ [["INSERT INTO foo (bar) VALUES ('buz');"]],
# backwards
- (
- ("DELETE FROM foo WHERE bar = 'buz';", 'invalid', 'parameter count'),
- ),
+ (("DELETE FROM foo WHERE bar = 'buz';", "invalid", "parameter count"),),
)
with connection.schema_editor() as editor:
with self.assertRaisesMessage(ValueError, "Expected a 2-tuple but got 1"):
- operation.database_forwards("test_runsql", editor, project_state, new_state)
+ operation.database_forwards(
+ "test_runsql", editor, project_state, new_state
+ )
with connection.schema_editor() as editor:
with self.assertRaisesMessage(ValueError, "Expected a 2-tuple but got 3"):
- operation.database_backwards("test_runsql", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_runsql", editor, new_state, project_state
+ )
def test_run_sql_noop(self):
"""
@@ -3234,19 +4109,21 @@ class OperationTests(OperationTestBase):
operation.database_backwards("test_runsql", editor, None, None)
def test_run_sql_add_missing_semicolon_on_collect_sql(self):
- project_state = self.set_up_test_model('test_runsql')
+ project_state = self.set_up_test_model("test_runsql")
new_state = project_state.clone()
tests = [
- 'INSERT INTO test_runsql_pony (pink, weight) VALUES (1, 1);\n',
- 'INSERT INTO test_runsql_pony (pink, weight) VALUES (1, 1)\n',
+ "INSERT INTO test_runsql_pony (pink, weight) VALUES (1, 1);\n",
+ "INSERT INTO test_runsql_pony (pink, weight) VALUES (1, 1)\n",
]
for sql in tests:
with self.subTest(sql=sql):
operation = migrations.RunSQL(sql, migrations.RunPython.noop)
with connection.schema_editor(collect_sql=True) as editor:
- operation.database_forwards('test_runsql', editor, project_state, new_state)
- collected_sql = '\n'.join(editor.collected_sql)
- self.assertEqual(collected_sql.count(';'), 1)
+ operation.database_forwards(
+ "test_runsql", editor, project_state, new_state
+ )
+ collected_sql = "\n".join(editor.collected_sql)
+ self.assertEqual(collected_sql.count(";"), 1)
def test_run_python(self):
"""
@@ -3265,24 +4142,39 @@ class OperationTests(OperationTestBase):
Pony = models.get_model("test_runpython", "Pony")
Pony.objects.filter(pink=1, weight=3.55).delete()
Pony.objects.filter(weight=5).delete()
- operation = migrations.RunPython(inner_method, reverse_code=inner_method_reverse)
+
+ operation = migrations.RunPython(
+ inner_method, reverse_code=inner_method_reverse
+ )
self.assertEqual(operation.describe(), "Raw Python operation")
# Test the state alteration does nothing
new_state = project_state.clone()
operation.state_forwards("test_runpython", new_state)
self.assertEqual(new_state, project_state)
# Test the database alteration
- self.assertEqual(project_state.apps.get_model("test_runpython", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model("test_runpython", "Pony").objects.count(), 0
+ )
with connection.schema_editor() as editor:
- operation.database_forwards("test_runpython", editor, project_state, new_state)
- self.assertEqual(project_state.apps.get_model("test_runpython", "Pony").objects.count(), 2)
+ operation.database_forwards(
+ "test_runpython", editor, project_state, new_state
+ )
+ self.assertEqual(
+ project_state.apps.get_model("test_runpython", "Pony").objects.count(), 2
+ )
# Now test reversal
self.assertTrue(operation.reversible)
with connection.schema_editor() as editor:
- operation.database_backwards("test_runpython", editor, project_state, new_state)
- self.assertEqual(project_state.apps.get_model("test_runpython", "Pony").objects.count(), 0)
+ operation.database_backwards(
+ "test_runpython", editor, project_state, new_state
+ )
+ self.assertEqual(
+ project_state.apps.get_model("test_runpython", "Pony").objects.count(), 0
+ )
# Now test we can't use a string
- with self.assertRaisesMessage(ValueError, 'RunPython must be supplied with a callable'):
+ with self.assertRaisesMessage(
+ ValueError, "RunPython must be supplied with a callable"
+ ):
migrations.RunPython("print 'ahahaha'")
# And deconstruction
definition = operation.deconstruct()
@@ -3294,10 +4186,16 @@ class OperationTests(OperationTestBase):
no_reverse_operation = migrations.RunPython(inner_method)
self.assertFalse(no_reverse_operation.reversible)
with connection.schema_editor() as editor:
- no_reverse_operation.database_forwards("test_runpython", editor, project_state, new_state)
+ no_reverse_operation.database_forwards(
+ "test_runpython", editor, project_state, new_state
+ )
with self.assertRaises(NotImplementedError):
- no_reverse_operation.database_backwards("test_runpython", editor, new_state, project_state)
- self.assertEqual(project_state.apps.get_model("test_runpython", "Pony").objects.count(), 2)
+ no_reverse_operation.database_backwards(
+ "test_runpython", editor, new_state, project_state
+ )
+ self.assertEqual(
+ project_state.apps.get_model("test_runpython", "Pony").objects.count(), 2
+ )
def create_ponies(models, schema_editor):
Pony = models.get_model("test_runpython", "Pony")
@@ -3309,8 +4207,12 @@ class OperationTests(OperationTestBase):
operation = migrations.RunPython(create_ponies)
with connection.schema_editor() as editor:
- operation.database_forwards("test_runpython", editor, project_state, new_state)
- self.assertEqual(project_state.apps.get_model("test_runpython", "Pony").objects.count(), 4)
+ operation.database_forwards(
+ "test_runpython", editor, project_state, new_state
+ )
+ self.assertEqual(
+ project_state.apps.get_model("test_runpython", "Pony").objects.count(), 4
+ )
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "RunPython")
@@ -3327,9 +4229,18 @@ class OperationTests(OperationTestBase):
operation = migrations.RunPython(create_shetlandponies)
with connection.schema_editor() as editor:
- operation.database_forwards("test_runpython", editor, project_state, new_state)
- self.assertEqual(project_state.apps.get_model("test_runpython", "Pony").objects.count(), 6)
- self.assertEqual(project_state.apps.get_model("test_runpython", "ShetlandPony").objects.count(), 2)
+ operation.database_forwards(
+ "test_runpython", editor, project_state, new_state
+ )
+ self.assertEqual(
+ project_state.apps.get_model("test_runpython", "Pony").objects.count(), 6
+ )
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpython", "ShetlandPony"
+ ).objects.count(),
+ 2,
+ )
# And elidable reduction
self.assertIs(False, operation.reduce(operation, []))
elidable_operation = migrations.RunPython(inner_method, elidable=True)
@@ -3348,55 +4259,121 @@ class OperationTests(OperationTestBase):
# Verify atomicity when applying.
atomic_migration = Migration("test", "test_runpythonatomic")
- atomic_migration.operations = [migrations.RunPython(inner_method, reverse_code=inner_method)]
+ atomic_migration.operations = [
+ migrations.RunPython(inner_method, reverse_code=inner_method)
+ ]
non_atomic_migration = Migration("test", "test_runpythonatomic")
- non_atomic_migration.operations = [migrations.RunPython(inner_method, reverse_code=inner_method, atomic=False)]
+ non_atomic_migration.operations = [
+ migrations.RunPython(inner_method, reverse_code=inner_method, atomic=False)
+ ]
# If we're a fully-transactional database, both versions should rollback
if connection.features.can_rollback_ddl:
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
with self.assertRaises(ValueError):
with connection.schema_editor() as editor:
atomic_migration.apply(project_state, editor)
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
with self.assertRaises(ValueError):
with connection.schema_editor() as editor:
non_atomic_migration.apply(project_state, editor)
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
# Otherwise, the non-atomic operation should leave a row there
else:
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
with self.assertRaises(ValueError):
with connection.schema_editor() as editor:
atomic_migration.apply(project_state, editor)
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
with self.assertRaises(ValueError):
with connection.schema_editor() as editor:
non_atomic_migration.apply(project_state, editor)
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 1)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 1,
+ )
# Reset object count to zero and verify atomicity when unapplying.
- project_state.apps.get_model("test_runpythonatomic", "Pony").objects.all().delete()
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.all().delete()
# On a fully-transactional database, both versions rollback.
if connection.features.can_rollback_ddl:
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
with self.assertRaises(ValueError):
with connection.schema_editor() as editor:
atomic_migration.unapply(project_state, editor)
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
with self.assertRaises(ValueError):
with connection.schema_editor() as editor:
non_atomic_migration.unapply(project_state, editor)
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
# Otherwise, the non-atomic operation leaves a row there.
else:
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
with self.assertRaises(ValueError):
with connection.schema_editor() as editor:
atomic_migration.unapply(project_state, editor)
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 0)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 0,
+ )
with self.assertRaises(ValueError):
with connection.schema_editor() as editor:
non_atomic_migration.unapply(project_state, editor)
- self.assertEqual(project_state.apps.get_model("test_runpythonatomic", "Pony").objects.count(), 1)
+ self.assertEqual(
+ project_state.apps.get_model(
+ "test_runpythonatomic", "Pony"
+ ).objects.count(),
+ 1,
+ )
# Verify deconstruction.
definition = non_atomic_migration.operations[0].deconstruct()
self.assertEqual(definition[0], "RunPython")
@@ -3428,7 +4405,7 @@ class OperationTests(OperationTestBase):
[
("id", models.AutoField(primary_key=True)),
("title", models.CharField(max_length=100)),
- ("author", models.ForeignKey("test_authors.Author", models.CASCADE))
+ ("author", models.ForeignKey("test_authors.Author", models.CASCADE)),
],
options={},
)
@@ -3443,35 +4420,44 @@ class OperationTests(OperationTestBase):
new_state = project_state.clone()
with connection.schema_editor() as editor:
create_author.state_forwards("test_authors", new_state)
- create_author.database_forwards("test_authors", editor, project_state, new_state)
+ create_author.database_forwards(
+ "test_authors", editor, project_state, new_state
+ )
project_state = new_state
new_state = new_state.clone()
with connection.schema_editor() as editor:
create_book.state_forwards("test_books", new_state)
- create_book.database_forwards("test_books", editor, project_state, new_state)
+ create_book.database_forwards(
+ "test_books", editor, project_state, new_state
+ )
project_state = new_state
new_state = new_state.clone()
with connection.schema_editor() as editor:
add_hometown.state_forwards("test_authors", new_state)
- add_hometown.database_forwards("test_authors", editor, project_state, new_state)
+ add_hometown.database_forwards(
+ "test_authors", editor, project_state, new_state
+ )
project_state = new_state
new_state = new_state.clone()
with connection.schema_editor() as editor:
create_old_man.state_forwards("test_books", new_state)
- create_old_man.database_forwards("test_books", editor, project_state, new_state)
+ create_old_man.database_forwards(
+ "test_books", editor, project_state, new_state
+ )
def test_model_with_bigautofield(self):
"""
A model with BigAutoField can be created.
"""
+
def create_data(models, schema_editor):
Author = models.get_model("test_author", "Author")
Book = models.get_model("test_book", "Book")
author1 = Author.objects.create(name="Hemingway")
Book.objects.create(title="Old Man and The Sea", author=author1)
- Book.objects.create(id=2 ** 33, title="A farewell to arms", author=author1)
+ Book.objects.create(id=2**33, title="A farewell to arms", author=author1)
- author2 = Author.objects.create(id=2 ** 33, name="Remarque")
+ author2 = Author.objects.create(id=2**33, name="Remarque")
Book.objects.create(title="All quiet on the western front", author=author2)
Book.objects.create(title="Arc de Triomphe", author=author2)
@@ -3488,7 +4474,12 @@ class OperationTests(OperationTestBase):
[
("id", models.BigAutoField(primary_key=True)),
("title", models.CharField(max_length=100)),
- ("author", models.ForeignKey(to="test_author.Author", on_delete=models.CASCADE))
+ (
+ "author",
+ models.ForeignKey(
+ to="test_author.Author", on_delete=models.CASCADE
+ ),
+ ),
],
options={},
)
@@ -3498,7 +4489,9 @@ class OperationTests(OperationTestBase):
new_state = project_state.clone()
with connection.schema_editor() as editor:
create_author.state_forwards("test_author", new_state)
- create_author.database_forwards("test_author", editor, project_state, new_state)
+ create_author.database_forwards(
+ "test_author", editor, project_state, new_state
+ )
project_state = new_state
new_state = new_state.clone()
@@ -3512,7 +4505,9 @@ class OperationTests(OperationTestBase):
fill_data.state_forwards("fill_data", new_state)
fill_data.database_forwards("fill_data", editor, project_state, new_state)
- def _test_autofield_foreignfield_growth(self, source_field, target_field, target_value):
+ def _test_autofield_foreignfield_growth(
+ self, source_field, target_field, target_value
+ ):
"""
A field may be migrated in the following ways:
@@ -3520,6 +4515,7 @@ class OperationTests(OperationTestBase):
- SmallAutoField to AutoField
- SmallAutoField to BigAutoField
"""
+
def create_initial_data(models, schema_editor):
Article = models.get_model("test_article", "Article")
Blog = models.get_model("test_blog", "Blog")
@@ -3546,17 +4542,26 @@ class OperationTests(OperationTestBase):
"Article",
[
("id", source_field(primary_key=True)),
- ("blog", models.ForeignKey(to="test_blog.Blog", on_delete=models.CASCADE)),
+ (
+ "blog",
+ models.ForeignKey(to="test_blog.Blog", on_delete=models.CASCADE),
+ ),
("name", models.CharField(max_length=100)),
("data", models.TextField(default="")),
],
options={},
)
- fill_initial_data = migrations.RunPython(create_initial_data, create_initial_data)
+ fill_initial_data = migrations.RunPython(
+ create_initial_data, create_initial_data
+ )
fill_big_data = migrations.RunPython(create_big_data, create_big_data)
- grow_article_id = migrations.AlterField('Article', 'id', target_field(primary_key=True))
- grow_blog_id = migrations.AlterField('Blog', 'id', target_field(primary_key=True))
+ grow_article_id = migrations.AlterField(
+ "Article", "id", target_field(primary_key=True)
+ )
+ grow_blog_id = migrations.AlterField(
+ "Blog", "id", target_field(primary_key=True)
+ )
project_state = ProjectState()
new_state = project_state.clone()
@@ -3568,19 +4573,25 @@ class OperationTests(OperationTestBase):
new_state = new_state.clone()
with connection.schema_editor() as editor:
create_article.state_forwards("test_article", new_state)
- create_article.database_forwards("test_article", editor, project_state, new_state)
+ create_article.database_forwards(
+ "test_article", editor, project_state, new_state
+ )
project_state = new_state
new_state = new_state.clone()
with connection.schema_editor() as editor:
fill_initial_data.state_forwards("fill_initial_data", new_state)
- fill_initial_data.database_forwards("fill_initial_data", editor, project_state, new_state)
+ fill_initial_data.database_forwards(
+ "fill_initial_data", editor, project_state, new_state
+ )
project_state = new_state
new_state = new_state.clone()
with connection.schema_editor() as editor:
grow_article_id.state_forwards("test_article", new_state)
- grow_article_id.database_forwards("test_article", editor, project_state, new_state)
+ grow_article_id.database_forwards(
+ "test_article", editor, project_state, new_state
+ )
state = new_state.clone()
article = state.apps.get_model("test_article.Article")
@@ -3590,7 +4601,9 @@ class OperationTests(OperationTestBase):
new_state = new_state.clone()
with connection.schema_editor() as editor:
grow_blog_id.state_forwards("test_blog", new_state)
- grow_blog_id.database_forwards("test_blog", editor, project_state, new_state)
+ grow_blog_id.database_forwards(
+ "test_blog", editor, project_state, new_state
+ )
state = new_state.clone()
blog = state.apps.get_model("test_blog.Blog")
@@ -3600,14 +4613,16 @@ class OperationTests(OperationTestBase):
new_state = new_state.clone()
with connection.schema_editor() as editor:
fill_big_data.state_forwards("fill_big_data", new_state)
- fill_big_data.database_forwards("fill_big_data", editor, project_state, new_state)
+ fill_big_data.database_forwards(
+ "fill_big_data", editor, project_state, new_state
+ )
def test_autofield__bigautofield_foreignfield_growth(self):
"""A field may be migrated from AutoField to BigAutoField."""
self._test_autofield_foreignfield_growth(
models.AutoField,
models.BigAutoField,
- 2 ** 33,
+ 2**33,
)
def test_smallfield_autofield_foreignfield_growth(self):
@@ -3615,7 +4630,7 @@ class OperationTests(OperationTestBase):
self._test_autofield_foreignfield_growth(
models.SmallAutoField,
models.AutoField,
- 2 ** 22,
+ 2**22,
)
def test_smallfield_bigautofield_foreignfield_growth(self):
@@ -3623,7 +4638,7 @@ class OperationTests(OperationTestBase):
self._test_autofield_foreignfield_growth(
models.SmallAutoField,
models.BigAutoField,
- 2 ** 33,
+ 2**33,
)
def test_run_python_noop(self):
@@ -3632,10 +4647,16 @@ class OperationTests(OperationTestBase):
"""
project_state = ProjectState()
new_state = project_state.clone()
- operation = migrations.RunPython(migrations.RunPython.noop, migrations.RunPython.noop)
+ operation = migrations.RunPython(
+ migrations.RunPython.noop, migrations.RunPython.noop
+ )
with connection.schema_editor() as editor:
- operation.database_forwards("test_runpython", editor, project_state, new_state)
- operation.database_backwards("test_runpython", editor, new_state, project_state)
+ operation.database_forwards(
+ "test_runpython", editor, project_state, new_state
+ )
+ operation.database_backwards(
+ "test_runpython", editor, new_state, project_state
+ )
def test_separate_database_and_state(self):
"""
@@ -3645,34 +4666,50 @@ class OperationTests(OperationTestBase):
# Create the operation
database_operation = migrations.RunSQL(
"CREATE TABLE i_love_ponies (id int, special_thing int);",
- "DROP TABLE i_love_ponies;"
+ "DROP TABLE i_love_ponies;",
+ )
+ state_operation = migrations.CreateModel(
+ "SomethingElse", [("id", models.AutoField(primary_key=True))]
)
- state_operation = migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))])
operation = migrations.SeparateDatabaseAndState(
- state_operations=[state_operation],
- database_operations=[database_operation]
+ state_operations=[state_operation], database_operations=[database_operation]
+ )
+ self.assertEqual(
+ operation.describe(), "Custom state/database change combination"
)
- self.assertEqual(operation.describe(), "Custom state/database change combination")
# Test the state alteration
new_state = project_state.clone()
operation.state_forwards("test_separatedatabaseandstate", new_state)
- self.assertEqual(len(new_state.models["test_separatedatabaseandstate", "somethingelse"].fields), 1)
+ self.assertEqual(
+ len(
+ new_state.models[
+ "test_separatedatabaseandstate", "somethingelse"
+ ].fields
+ ),
+ 1,
+ )
# Make sure there's no table
self.assertTableNotExists("i_love_ponies")
# Test the database alteration
with connection.schema_editor() as editor:
- operation.database_forwards("test_separatedatabaseandstate", editor, project_state, new_state)
+ operation.database_forwards(
+ "test_separatedatabaseandstate", editor, project_state, new_state
+ )
self.assertTableExists("i_love_ponies")
# And test reversal
self.assertTrue(operation.reversible)
with connection.schema_editor() as editor:
- operation.database_backwards("test_separatedatabaseandstate", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_separatedatabaseandstate", editor, new_state, project_state
+ )
self.assertTableNotExists("i_love_ponies")
# And deconstruction
definition = operation.deconstruct()
self.assertEqual(definition[0], "SeparateDatabaseAndState")
self.assertEqual(definition[1], [])
- self.assertEqual(sorted(definition[2]), ["database_operations", "state_operations"])
+ self.assertEqual(
+ sorted(definition[2]), ["database_operations", "state_operations"]
+ )
def test_separate_database_and_state2(self):
"""
@@ -3728,7 +4765,10 @@ class OperationTests(OperationTestBase):
def assertModelsAndTables(after_db):
# Tables and models exist, or don't, as they should:
self.assertNotIn((app_label, "somethingelse"), new_state.models)
- self.assertEqual(len(new_state.models[app_label, "somethingcompletelydifferent"].fields), 1)
+ self.assertEqual(
+ len(new_state.models[app_label, "somethingcompletelydifferent"].fields),
+ 1,
+ )
self.assertNotIn((app_label, "iloveponiesonies"), new_state.models)
self.assertNotIn((app_label, "ilovemoreponies"), new_state.models)
self.assertNotIn((app_label, "iloveevenmoreponies"), new_state.models)
@@ -3761,7 +4801,7 @@ class SwappableOperationTests(OperationTestBase):
is in a common base class anyway)
"""
- available_apps = ['migrations']
+ available_apps = ["migrations"]
@override_settings(TEST_SWAP_MODEL="migrations.SomeFakeModel")
def test_create_ignore_swapped(self):
@@ -3791,7 +4831,9 @@ class SwappableOperationTests(OperationTestBase):
self.assertTableNotExists("test_crigsw_pony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_crigsw", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_crigsw", editor, new_state, project_state
+ )
self.assertTableNotExists("test_crigsw_pony")
@override_settings(TEST_SWAP_MODEL="migrations.SomeFakeModel")
@@ -3808,7 +4850,9 @@ class SwappableOperationTests(OperationTestBase):
self.assertTableNotExists("test_dligsw_pony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_dligsw", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_dligsw", editor, new_state, project_state
+ )
self.assertTableNotExists("test_dligsw_pony")
@override_settings(TEST_SWAP_MODEL="migrations.SomeFakeModel")
@@ -3826,87 +4870,142 @@ class SwappableOperationTests(OperationTestBase):
# Test the database alteration
self.assertTableNotExists("test_adfligsw_pony")
with connection.schema_editor() as editor:
- operation.database_forwards("test_adfligsw", editor, project_state, new_state)
+ operation.database_forwards(
+ "test_adfligsw", editor, project_state, new_state
+ )
self.assertTableNotExists("test_adfligsw_pony")
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards("test_adfligsw", editor, new_state, project_state)
+ operation.database_backwards(
+ "test_adfligsw", editor, new_state, project_state
+ )
self.assertTableNotExists("test_adfligsw_pony")
- @override_settings(TEST_SWAP_MODEL='migrations.SomeFakeModel')
+ @override_settings(TEST_SWAP_MODEL="migrations.SomeFakeModel")
def test_indexes_ignore_swapped(self):
"""
Add/RemoveIndex operations ignore swapped models.
"""
- operation = migrations.AddIndex('Pony', models.Index(fields=['pink'], name='my_name_idx'))
- project_state, new_state = self.make_test_state('test_adinigsw', operation)
+ operation = migrations.AddIndex(
+ "Pony", models.Index(fields=["pink"], name="my_name_idx")
+ )
+ project_state, new_state = self.make_test_state("test_adinigsw", operation)
with connection.schema_editor() as editor:
# No database queries should be run for swapped models
- operation.database_forwards('test_adinigsw', editor, project_state, new_state)
- operation.database_backwards('test_adinigsw', editor, new_state, project_state)
+ operation.database_forwards(
+ "test_adinigsw", editor, project_state, new_state
+ )
+ operation.database_backwards(
+ "test_adinigsw", editor, new_state, project_state
+ )
- operation = migrations.RemoveIndex('Pony', models.Index(fields=['pink'], name='my_name_idx'))
+ operation = migrations.RemoveIndex(
+ "Pony", models.Index(fields=["pink"], name="my_name_idx")
+ )
project_state, new_state = self.make_test_state("test_rminigsw", operation)
with connection.schema_editor() as editor:
- operation.database_forwards('test_rminigsw', editor, project_state, new_state)
- operation.database_backwards('test_rminigsw', editor, new_state, project_state)
+ operation.database_forwards(
+ "test_rminigsw", editor, project_state, new_state
+ )
+ operation.database_backwards(
+ "test_rminigsw", editor, new_state, project_state
+ )
class TestCreateModel(SimpleTestCase):
-
def test_references_model_mixin(self):
migrations.CreateModel(
- 'name',
+ "name",
fields=[],
bases=(Mixin, models.Model),
- ).references_model('other_model', 'migrations')
+ ).references_model("other_model", "migrations")
class FieldOperationTests(SimpleTestCase):
def test_references_model(self):
- operation = FieldOperation('MoDel', 'field', models.ForeignKey('Other', models.CASCADE))
+ operation = FieldOperation(
+ "MoDel", "field", models.ForeignKey("Other", models.CASCADE)
+ )
# Model name match.
- self.assertIs(operation.references_model('mOdEl', 'migrations'), True)
+ self.assertIs(operation.references_model("mOdEl", "migrations"), True)
# Referenced field.
- self.assertIs(operation.references_model('oTher', 'migrations'), True)
+ self.assertIs(operation.references_model("oTher", "migrations"), True)
# Doesn't reference.
- self.assertIs(operation.references_model('Whatever', 'migrations'), False)
+ self.assertIs(operation.references_model("Whatever", "migrations"), False)
def test_references_field_by_name(self):
- operation = FieldOperation('MoDel', 'field', models.BooleanField(default=False))
- self.assertIs(operation.references_field('model', 'field', 'migrations'), True)
+ operation = FieldOperation("MoDel", "field", models.BooleanField(default=False))
+ self.assertIs(operation.references_field("model", "field", "migrations"), True)
def test_references_field_by_remote_field_model(self):
- operation = FieldOperation('Model', 'field', models.ForeignKey('Other', models.CASCADE))
- self.assertIs(operation.references_field('Other', 'whatever', 'migrations'), True)
- self.assertIs(operation.references_field('Missing', 'whatever', 'migrations'), False)
+ operation = FieldOperation(
+ "Model", "field", models.ForeignKey("Other", models.CASCADE)
+ )
+ self.assertIs(
+ operation.references_field("Other", "whatever", "migrations"), True
+ )
+ self.assertIs(
+ operation.references_field("Missing", "whatever", "migrations"), False
+ )
def test_references_field_by_from_fields(self):
operation = FieldOperation(
- 'Model', 'field', models.fields.related.ForeignObject('Other', models.CASCADE, ['from'], ['to'])
+ "Model",
+ "field",
+ models.fields.related.ForeignObject(
+ "Other", models.CASCADE, ["from"], ["to"]
+ ),
)
- self.assertIs(operation.references_field('Model', 'from', 'migrations'), True)
- self.assertIs(operation.references_field('Model', 'to', 'migrations'), False)
- self.assertIs(operation.references_field('Other', 'from', 'migrations'), False)
- self.assertIs(operation.references_field('Model', 'to', 'migrations'), False)
+ self.assertIs(operation.references_field("Model", "from", "migrations"), True)
+ self.assertIs(operation.references_field("Model", "to", "migrations"), False)
+ self.assertIs(operation.references_field("Other", "from", "migrations"), False)
+ self.assertIs(operation.references_field("Model", "to", "migrations"), False)
def test_references_field_by_to_fields(self):
- operation = FieldOperation('Model', 'field', models.ForeignKey('Other', models.CASCADE, to_field='field'))
- self.assertIs(operation.references_field('Other', 'field', 'migrations'), True)
- self.assertIs(operation.references_field('Other', 'whatever', 'migrations'), False)
- self.assertIs(operation.references_field('Missing', 'whatever', 'migrations'), False)
+ operation = FieldOperation(
+ "Model",
+ "field",
+ models.ForeignKey("Other", models.CASCADE, to_field="field"),
+ )
+ self.assertIs(operation.references_field("Other", "field", "migrations"), True)
+ self.assertIs(
+ operation.references_field("Other", "whatever", "migrations"), False
+ )
+ self.assertIs(
+ operation.references_field("Missing", "whatever", "migrations"), False
+ )
def test_references_field_by_through(self):
- operation = FieldOperation('Model', 'field', models.ManyToManyField('Other', through='Through'))
- self.assertIs(operation.references_field('Other', 'whatever', 'migrations'), True)
- self.assertIs(operation.references_field('Through', 'whatever', 'migrations'), True)
- self.assertIs(operation.references_field('Missing', 'whatever', 'migrations'), False)
+ operation = FieldOperation(
+ "Model", "field", models.ManyToManyField("Other", through="Through")
+ )
+ self.assertIs(
+ operation.references_field("Other", "whatever", "migrations"), True
+ )
+ self.assertIs(
+ operation.references_field("Through", "whatever", "migrations"), True
+ )
+ self.assertIs(
+ operation.references_field("Missing", "whatever", "migrations"), False
+ )
def test_reference_field_by_through_fields(self):
operation = FieldOperation(
- 'Model', 'field', models.ManyToManyField('Other', through='Through', through_fields=('first', 'second'))
+ "Model",
+ "field",
+ models.ManyToManyField(
+ "Other", through="Through", through_fields=("first", "second")
+ ),
+ )
+ self.assertIs(
+ operation.references_field("Other", "whatever", "migrations"), True
+ )
+ self.assertIs(
+ operation.references_field("Through", "whatever", "migrations"), False
+ )
+ self.assertIs(
+ operation.references_field("Through", "first", "migrations"), True
+ )
+ self.assertIs(
+ operation.references_field("Through", "second", "migrations"), True
)
- self.assertIs(operation.references_field('Other', 'whatever', 'migrations'), True)
- self.assertIs(operation.references_field('Through', 'whatever', 'migrations'), False)
- self.assertIs(operation.references_field('Through', 'first', 'migrations'), True)
- self.assertIs(operation.references_field('Through', 'second', 'migrations'), True)
diff --git a/tests/migrations/test_optimizer.py b/tests/migrations/test_optimizer.py
index 0caaf66f9e..b69563ebab 100644
--- a/tests/migrations/test_optimizer.py
+++ b/tests/migrations/test_optimizer.py
@@ -22,18 +22,22 @@ class OptimizerTests(SimpleTestCase):
def serialize(self, value):
return serializer_factory(value).serialize()[0]
- def assertOptimizesTo(self, operations, expected, exact=None, less_than=None, app_label=None):
- result, iterations = self.optimize(operations, app_label or 'migrations')
+ def assertOptimizesTo(
+ self, operations, expected, exact=None, less_than=None, app_label=None
+ ):
+ result, iterations = self.optimize(operations, app_label or "migrations")
result = [self.serialize(f) for f in result]
expected = [self.serialize(f) for f in expected]
self.assertEqual(expected, result)
if exact is not None and iterations != exact:
raise self.failureException(
- "Optimization did not take exactly %s iterations (it took %s)" % (exact, iterations)
+ "Optimization did not take exactly %s iterations (it took %s)"
+ % (exact, iterations)
)
if less_than is not None and iterations >= less_than:
raise self.failureException(
- "Optimization did not take less than %s iterations (it took %s)" % (less_than, iterations)
+ "Optimization did not take less than %s iterations (it took %s)"
+ % (less_than, iterations)
)
def assertDoesNotOptimize(self, operations, **kwargs):
@@ -41,7 +45,7 @@ class OptimizerTests(SimpleTestCase):
def test_none_app_label(self):
optimizer = MigrationOptimizer()
- with self.assertRaisesMessage(TypeError, 'app_label must be a str'):
+ with self.assertRaisesMessage(TypeError, "app_label must be a str"):
optimizer.optimize([], None)
def test_single(self):
@@ -61,7 +65,9 @@ class OptimizerTests(SimpleTestCase):
"""
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
migrations.DeleteModel("Foo"),
],
[],
@@ -71,13 +77,13 @@ class OptimizerTests(SimpleTestCase):
"""
CreateModel should absorb RenameModels.
"""
- managers = [('objects', EmptyManager())]
+ managers = [("objects", EmptyManager())]
self.assertOptimizesTo(
[
migrations.CreateModel(
name="Foo",
fields=[("name", models.CharField(max_length=255))],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -87,7 +93,7 @@ class OptimizerTests(SimpleTestCase):
migrations.CreateModel(
"Bar",
[("name", models.CharField(max_length=255))],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
)
@@ -111,46 +117,50 @@ class OptimizerTests(SimpleTestCase):
def test_create_alter_model_options(self):
self.assertOptimizesTo(
[
- migrations.CreateModel('Foo', fields=[]),
- migrations.AlterModelOptions(name='Foo', options={'verbose_name_plural': 'Foozes'}),
+ migrations.CreateModel("Foo", fields=[]),
+ migrations.AlterModelOptions(
+ name="Foo", options={"verbose_name_plural": "Foozes"}
+ ),
],
[
- migrations.CreateModel('Foo', fields=[], options={'verbose_name_plural': 'Foozes'}),
- ]
+ migrations.CreateModel(
+ "Foo", fields=[], options={"verbose_name_plural": "Foozes"}
+ ),
+ ],
)
def test_create_model_and_remove_model_options(self):
self.assertOptimizesTo(
[
migrations.CreateModel(
- 'MyModel',
+ "MyModel",
fields=[],
- options={'verbose_name': 'My Model'},
+ options={"verbose_name": "My Model"},
),
- migrations.AlterModelOptions('MyModel', options={}),
+ migrations.AlterModelOptions("MyModel", options={}),
],
- [migrations.CreateModel('MyModel', fields=[])],
+ [migrations.CreateModel("MyModel", fields=[])],
)
self.assertOptimizesTo(
[
migrations.CreateModel(
- 'MyModel',
+ "MyModel",
fields=[],
options={
- 'verbose_name': 'My Model',
- 'verbose_name_plural': 'My Model plural',
+ "verbose_name": "My Model",
+ "verbose_name_plural": "My Model plural",
},
),
migrations.AlterModelOptions(
- 'MyModel',
- options={'verbose_name': 'My Model'},
+ "MyModel",
+ options={"verbose_name": "My Model"},
),
],
[
migrations.CreateModel(
- 'MyModel',
+ "MyModel",
fields=[],
- options={'verbose_name': 'My Model'},
+ options={"verbose_name": "My Model"},
),
],
)
@@ -162,7 +172,9 @@ class OptimizerTests(SimpleTestCase):
"""
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
migrations.AlterModelTable("Foo", "woohoo"),
alter_foo,
migrations.DeleteModel("Foo"),
@@ -171,13 +183,19 @@ class OptimizerTests(SimpleTestCase):
)
def test_create_alter_unique_delete_model(self):
- self._test_create_alter_foo_delete_model(migrations.AlterUniqueTogether("Foo", [["a", "b"]]))
+ self._test_create_alter_foo_delete_model(
+ migrations.AlterUniqueTogether("Foo", [["a", "b"]])
+ )
def test_create_alter_index_delete_model(self):
- self._test_create_alter_foo_delete_model(migrations.AlterIndexTogether("Foo", [["a", "b"]]))
+ self._test_create_alter_foo_delete_model(
+ migrations.AlterIndexTogether("Foo", [["a", "b"]])
+ )
def test_create_alter_owrt_delete_model(self):
- self._test_create_alter_foo_delete_model(migrations.AlterOrderWithRespectTo("Foo", "a"))
+ self._test_create_alter_foo_delete_model(
+ migrations.AlterOrderWithRespectTo("Foo", "a")
+ )
def _test_alter_alter_model(self, alter_foo, alter_bar):
"""
@@ -227,7 +245,9 @@ class OptimizerTests(SimpleTestCase):
# These should work
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
migrations.CreateModel("Bar", [("size", models.IntegerField())]),
migrations.DeleteModel("Foo"),
],
@@ -237,7 +257,9 @@ class OptimizerTests(SimpleTestCase):
)
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
migrations.CreateModel("Bar", [("size", models.IntegerField())]),
migrations.DeleteModel("Bar"),
migrations.DeleteModel("Foo"),
@@ -246,7 +268,9 @@ class OptimizerTests(SimpleTestCase):
)
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
migrations.CreateModel("Bar", [("size", models.IntegerField())]),
migrations.DeleteModel("Foo"),
migrations.DeleteModel("Bar"),
@@ -257,12 +281,18 @@ class OptimizerTests(SimpleTestCase):
# other app.
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
- migrations.CreateModel("Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]
+ ),
migrations.DeleteModel("Foo"),
],
[
- migrations.CreateModel("Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]),
+ migrations.CreateModel(
+ "Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]
+ ),
],
app_label="otherapp",
)
@@ -270,15 +300,23 @@ class OptimizerTests(SimpleTestCase):
# app_label.
self.assertDoesNotOptimize(
[
- migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]),
- migrations.CreateModel('Bar', [('other', models.ForeignKey('Foo', models.CASCADE))]),
- migrations.DeleteModel('Foo'),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Bar", [("other", models.ForeignKey("Foo", models.CASCADE))]
+ ),
+ migrations.DeleteModel("Foo"),
],
)
self.assertDoesNotOptimize(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
- migrations.CreateModel("Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]
+ ),
migrations.DeleteModel("Foo"),
],
app_label="testapp",
@@ -286,37 +324,55 @@ class OptimizerTests(SimpleTestCase):
# This should not work - bases should block it
self.assertDoesNotOptimize(
[
- migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]),
- migrations.CreateModel('Bar', [('size', models.IntegerField())], bases=('Foo',)),
- migrations.DeleteModel('Foo'),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Bar", [("size", models.IntegerField())], bases=("Foo",)
+ ),
+ migrations.DeleteModel("Foo"),
],
)
self.assertDoesNotOptimize(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
- migrations.CreateModel("Bar", [("size", models.IntegerField())], bases=("testapp.Foo",)),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Bar", [("size", models.IntegerField())], bases=("testapp.Foo",)
+ ),
migrations.DeleteModel("Foo"),
],
- app_label='testapp',
+ app_label="testapp",
)
# The same operations should be optimized if app_label and none of
# bases belong to that app.
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
- migrations.CreateModel("Bar", [("size", models.IntegerField())], bases=("testapp.Foo",)),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Bar", [("size", models.IntegerField())], bases=("testapp.Foo",)
+ ),
migrations.DeleteModel("Foo"),
],
[
- migrations.CreateModel("Bar", [("size", models.IntegerField())], bases=("testapp.Foo",)),
+ migrations.CreateModel(
+ "Bar", [("size", models.IntegerField())], bases=("testapp.Foo",)
+ ),
],
app_label="otherapp",
)
# But it shouldn't work if some of bases belongs to the specified app.
self.assertDoesNotOptimize(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
- migrations.CreateModel("Bar", [("size", models.IntegerField())], bases=("testapp.Foo",)),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Bar", [("size", models.IntegerField())], bases=("testapp.Foo",)
+ ),
migrations.DeleteModel("Foo"),
],
app_label="testapp",
@@ -324,37 +380,64 @@ class OptimizerTests(SimpleTestCase):
self.assertOptimizesTo(
[
- migrations.CreateModel('Book', [('name', models.CharField(max_length=255))]),
- migrations.CreateModel('Person', [('name', models.CharField(max_length=255))]),
- migrations.AddField('book', 'author', models.ForeignKey('test_app.Person', models.CASCADE)),
- migrations.CreateModel('Review', [('book', models.ForeignKey('test_app.Book', models.CASCADE))]),
- migrations.CreateModel('Reviewer', [('name', models.CharField(max_length=255))]),
- migrations.AddField('review', 'reviewer', models.ForeignKey('test_app.Reviewer', models.CASCADE)),
- migrations.RemoveField('book', 'author'),
- migrations.DeleteModel('Person'),
+ migrations.CreateModel(
+ "Book", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Person", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.AddField(
+ "book",
+ "author",
+ models.ForeignKey("test_app.Person", models.CASCADE),
+ ),
+ migrations.CreateModel(
+ "Review",
+ [("book", models.ForeignKey("test_app.Book", models.CASCADE))],
+ ),
+ migrations.CreateModel(
+ "Reviewer", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.AddField(
+ "review",
+ "reviewer",
+ models.ForeignKey("test_app.Reviewer", models.CASCADE),
+ ),
+ migrations.RemoveField("book", "author"),
+ migrations.DeleteModel("Person"),
],
[
- migrations.CreateModel('Book', [('name', models.CharField(max_length=255))]),
- migrations.CreateModel('Reviewer', [('name', models.CharField(max_length=255))]),
- migrations.CreateModel('Review', [
- ('book', models.ForeignKey('test_app.Book', models.CASCADE)),
- ('reviewer', models.ForeignKey('test_app.Reviewer', models.CASCADE)),
- ]),
+ migrations.CreateModel(
+ "Book", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Reviewer", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Review",
+ [
+ ("book", models.ForeignKey("test_app.Book", models.CASCADE)),
+ (
+ "reviewer",
+ models.ForeignKey("test_app.Reviewer", models.CASCADE),
+ ),
+ ],
+ ),
],
- app_label='test_app',
+ app_label="test_app",
)
def test_create_model_add_field(self):
"""
AddField should optimize into CreateModel.
"""
- managers = [('objects', EmptyManager())]
+ managers = [("objects", EmptyManager())]
self.assertOptimizesTo(
[
migrations.CreateModel(
name="Foo",
fields=[("name", models.CharField(max_length=255))],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -367,7 +450,7 @@ class OptimizerTests(SimpleTestCase):
("name", models.CharField(max_length=255)),
("age", models.IntegerField()),
],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -382,16 +465,23 @@ class OptimizerTests(SimpleTestCase):
"""
self.assertOptimizesTo(
[
- migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]),
- migrations.CreateModel('Link', [('url', models.TextField())]),
- migrations.AddField('Foo', 'link', models.ForeignKey('migrations.Link', models.CASCADE)),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel("Link", [("url", models.TextField())]),
+ migrations.AddField(
+ "Foo", "link", models.ForeignKey("migrations.Link", models.CASCADE)
+ ),
],
[
- migrations.CreateModel('Link', [('url', models.TextField())]),
- migrations.CreateModel('Foo', [
- ('name', models.CharField(max_length=255)),
- ('link', models.ForeignKey('migrations.Link', models.CASCADE))
- ]),
+ migrations.CreateModel("Link", [("url", models.TextField())]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("name", models.CharField(max_length=255)),
+ ("link", models.ForeignKey("migrations.Link", models.CASCADE)),
+ ],
+ ),
],
)
@@ -402,18 +492,31 @@ class OptimizerTests(SimpleTestCase):
"""
self.assertOptimizesTo(
[
- migrations.CreateModel('Bar', [('url', models.TextField())]),
- migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]),
- migrations.AddField('Bar', 'foo_fk', models.ForeignKey('migrations.Foo', models.CASCADE)),
- migrations.AddField('Foo', 'bar_fk', models.ForeignKey('migrations.Bar', models.CASCADE)),
+ migrations.CreateModel("Bar", [("url", models.TextField())]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.AddField(
+ "Bar", "foo_fk", models.ForeignKey("migrations.Foo", models.CASCADE)
+ ),
+ migrations.AddField(
+ "Foo", "bar_fk", models.ForeignKey("migrations.Bar", models.CASCADE)
+ ),
],
[
- migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]),
- migrations.CreateModel('Bar', [
- ('url', models.TextField()),
- ('foo_fk', models.ForeignKey('migrations.Foo', models.CASCADE)),
- ]),
- migrations.AddField('Foo', 'bar_fk', models.ForeignKey('migrations.Bar', models.CASCADE)),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "Bar",
+ [
+ ("url", models.TextField()),
+ ("foo_fk", models.ForeignKey("migrations.Foo", models.CASCADE)),
+ ],
+ ),
+ migrations.AddField(
+ "Foo", "bar_fk", models.ForeignKey("migrations.Bar", models.CASCADE)
+ ),
],
)
@@ -424,9 +527,15 @@ class OptimizerTests(SimpleTestCase):
"""
self.assertDoesNotOptimize(
[
- migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]),
- migrations.CreateModel('Link', [('url', models.TextField())]),
- migrations.AddField('Other', 'link', models.ForeignKey('migrations.Link', models.CASCADE)),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel("Link", [("url", models.TextField())]),
+ migrations.AddField(
+ "Other",
+ "link",
+ models.ForeignKey("migrations.Link", models.CASCADE),
+ ),
],
)
@@ -437,27 +546,41 @@ class OptimizerTests(SimpleTestCase):
"""
self.assertOptimizesTo(
[
- migrations.CreateModel('Other', [('foo', models.CharField(max_length=255))]),
- migrations.CreateModel('ParentModel', [('bar', models.CharField(max_length=255))]),
migrations.CreateModel(
- 'ChildModel',
- [('baz', models.CharField(max_length=255))],
- bases=('migrations.parentmodel',),
+ "Other", [("foo", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "ParentModel", [("bar", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "ChildModel",
+ [("baz", models.CharField(max_length=255))],
+ bases=("migrations.parentmodel",),
+ ),
+ migrations.AddField(
+ "Other",
+ "fk",
+ models.ForeignKey("migrations.ChildModel", models.CASCADE),
),
- migrations.AddField('Other', 'fk', models.ForeignKey('migrations.ChildModel', models.CASCADE)),
],
[
- migrations.CreateModel('ParentModel', [('bar', models.CharField(max_length=255))]),
migrations.CreateModel(
- 'ChildModel',
- [('baz', models.CharField(max_length=255))],
- bases=('migrations.parentmodel',),
+ "ParentModel", [("bar", models.CharField(max_length=255))]
+ ),
+ migrations.CreateModel(
+ "ChildModel",
+ [("baz", models.CharField(max_length=255))],
+ bases=("migrations.parentmodel",),
),
migrations.CreateModel(
- 'Other', [
- ('foo', models.CharField(max_length=255)),
- ('fk', models.ForeignKey('migrations.ChildModel', models.CASCADE)),
- ]
+ "Other",
+ [
+ ("foo", models.CharField(max_length=255)),
+ (
+ "fk",
+ models.ForeignKey("migrations.ChildModel", models.CASCADE),
+ ),
+ ],
),
],
)
@@ -469,16 +592,28 @@ class OptimizerTests(SimpleTestCase):
"""
self.assertDoesNotOptimize(
[
- migrations.CreateModel('Employee', []),
- migrations.CreateModel('Employer', []),
- migrations.CreateModel('Employment', [
- ('employee', models.ForeignKey('migrations.Employee', models.CASCADE)),
- ('employment', models.ForeignKey('migrations.Employer', models.CASCADE)),
- ]),
+ migrations.CreateModel("Employee", []),
+ migrations.CreateModel("Employer", []),
+ migrations.CreateModel(
+ "Employment",
+ [
+ (
+ "employee",
+ models.ForeignKey("migrations.Employee", models.CASCADE),
+ ),
+ (
+ "employment",
+ models.ForeignKey("migrations.Employer", models.CASCADE),
+ ),
+ ],
+ ),
migrations.AddField(
- 'Employer', 'employees', models.ManyToManyField(
- 'migrations.Employee', through='migrations.Employment',
- )
+ "Employer",
+ "employees",
+ models.ManyToManyField(
+ "migrations.Employee",
+ through="migrations.Employment",
+ ),
),
],
)
@@ -487,13 +622,13 @@ class OptimizerTests(SimpleTestCase):
"""
AlterField should optimize into CreateModel.
"""
- managers = [('objects', EmptyManager())]
+ managers = [("objects", EmptyManager())]
self.assertOptimizesTo(
[
migrations.CreateModel(
name="Foo",
fields=[("name", models.CharField(max_length=255))],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -505,7 +640,7 @@ class OptimizerTests(SimpleTestCase):
fields=[
("name", models.IntegerField()),
],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -516,13 +651,13 @@ class OptimizerTests(SimpleTestCase):
"""
RenameField should optimize into CreateModel.
"""
- managers = [('objects', EmptyManager())]
+ managers = [("objects", EmptyManager())]
self.assertOptimizesTo(
[
migrations.CreateModel(
name="Foo",
fields=[("name", models.CharField(max_length=255))],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -534,7 +669,7 @@ class OptimizerTests(SimpleTestCase):
fields=[
("title", models.CharField(max_length=255)),
],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -576,16 +711,16 @@ class OptimizerTests(SimpleTestCase):
self.assertDoesNotOptimize(
[
migrations.CreateModel(
- 'MyModel',
+ "MyModel",
[
- ('field_a', models.IntegerField()),
- ('field_b', models.IntegerField()),
+ ("field_a", models.IntegerField()),
+ ("field_b", models.IntegerField()),
],
),
migrations.RunPython(migrations.RunPython.noop),
- migrations.RenameField('MyModel', 'field_a', 'field_c'),
- migrations.RenameField('MyModel', 'field_b', 'field_a'),
- migrations.RenameField('MyModel', 'field_c', 'field_b'),
+ migrations.RenameField("MyModel", "field_a", "field_c"),
+ migrations.RenameField("MyModel", "field_b", "field_a"),
+ migrations.RenameField("MyModel", "field_c", "field_b"),
],
)
@@ -593,7 +728,7 @@ class OptimizerTests(SimpleTestCase):
"""
RemoveField should optimize into CreateModel.
"""
- managers = [('objects', EmptyManager())]
+ managers = [("objects", EmptyManager())]
self.assertOptimizesTo(
[
migrations.CreateModel(
@@ -602,7 +737,7 @@ class OptimizerTests(SimpleTestCase):
("name", models.CharField(max_length=255)),
("age", models.IntegerField()),
],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -614,7 +749,7 @@ class OptimizerTests(SimpleTestCase):
fields=[
("name", models.CharField(max_length=255)),
],
- options={'verbose_name': 'Foo'},
+ options={"verbose_name": "Foo"},
bases=(UnicodeModel,),
managers=managers,
),
@@ -631,7 +766,9 @@ class OptimizerTests(SimpleTestCase):
migrations.AlterField("Foo", "age", models.FloatField(default=2.4)),
],
[
- migrations.AddField("Foo", name="age", field=models.FloatField(default=2.4)),
+ migrations.AddField(
+ "Foo", name="age", field=models.FloatField(default=2.4)
+ ),
],
)
@@ -672,119 +809,162 @@ class OptimizerTests(SimpleTestCase):
# AddField
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ],
+ ),
alter,
migrations.AddField("Foo", "c", models.IntegerField()),
],
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ("c", models.IntegerField()),
- ], options=options),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ("c", models.IntegerField()),
+ ],
+ options=options,
+ ),
],
)
# AlterField
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ],
+ ),
alter,
migrations.AlterField("Foo", "b", models.CharField(max_length=255)),
],
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.CharField(max_length=255)),
- ], options=options),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.CharField(max_length=255)),
+ ],
+ options=options,
+ ),
],
)
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ("c", models.IntegerField()),
- ]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ("c", models.IntegerField()),
+ ],
+ ),
alter,
migrations.AlterField("Foo", "c", models.CharField(max_length=255)),
],
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ("c", models.CharField(max_length=255)),
- ], options=options),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ("c", models.CharField(max_length=255)),
+ ],
+ options=options,
+ ),
],
)
# RenameField
if isinstance(option_value, str):
- renamed_options = {alter.option_name: 'c'}
+ renamed_options = {alter.option_name: "c"}
else:
renamed_options = {
alter.option_name: {
- tuple('c' if value == 'b' else value for value in item) for item in option_value
+ tuple("c" if value == "b" else value for value in item)
+ for item in option_value
}
}
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ],
+ ),
alter,
migrations.RenameField("Foo", "b", "c"),
],
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("c", models.IntegerField()),
- ], options=renamed_options),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("c", models.IntegerField()),
+ ],
+ options=renamed_options,
+ ),
],
)
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ],
+ ),
alter,
migrations.RenameField("Foo", "b", "x"),
migrations.RenameField("Foo", "x", "c"),
],
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("c", models.IntegerField()),
- ], options=renamed_options),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("c", models.IntegerField()),
+ ],
+ options=renamed_options,
+ ),
],
)
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ("c", models.IntegerField()),
- ]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ("c", models.IntegerField()),
+ ],
+ ),
alter,
migrations.RenameField("Foo", "c", "d"),
],
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ("d", models.IntegerField()),
- ], options=options),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ("d", models.IntegerField()),
+ ],
+ options=options,
+ ),
],
)
@@ -794,51 +974,72 @@ class OptimizerTests(SimpleTestCase):
else:
removed_options = {
alter.option_name: {
- tuple(value for value in item if value != 'b') for item in option_value
+ tuple(value for value in item if value != "b")
+ for item in option_value
}
}
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ],
+ ),
alter,
migrations.RemoveField("Foo", "b"),
],
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ], options=removed_options),
- ]
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ],
+ options=removed_options,
+ ),
+ ],
)
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ("c", models.IntegerField()),
- ]),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ("c", models.IntegerField()),
+ ],
+ ),
alter,
migrations.RemoveField("Foo", "c"),
],
[
- migrations.CreateModel("Foo", [
- ("a", models.IntegerField()),
- ("b", models.IntegerField()),
- ], options=options),
+ migrations.CreateModel(
+ "Foo",
+ [
+ ("a", models.IntegerField()),
+ ("b", models.IntegerField()),
+ ],
+ options=options,
+ ),
],
)
def test_create_alter_unique_field(self):
- self._test_create_alter_foo_field(migrations.AlterUniqueTogether("Foo", [["a", "b"]]))
+ self._test_create_alter_foo_field(
+ migrations.AlterUniqueTogether("Foo", [["a", "b"]])
+ )
def test_create_alter_index_field(self):
- self._test_create_alter_foo_field(migrations.AlterIndexTogether("Foo", [["a", "b"]]))
+ self._test_create_alter_foo_field(
+ migrations.AlterIndexTogether("Foo", [["a", "b"]])
+ )
def test_create_alter_owrt_field(self):
- self._test_create_alter_foo_field(migrations.AlterOrderWithRespectTo("Foo", "b"))
+ self._test_create_alter_foo_field(
+ migrations.AlterOrderWithRespectTo("Foo", "b")
+ )
def test_optimize_through_fields(self):
"""
@@ -848,7 +1049,9 @@ class OptimizerTests(SimpleTestCase):
"""
self.assertOptimizesTo(
[
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
migrations.CreateModel("Bar", [("size", models.IntegerField())]),
migrations.AddField("Foo", "age", models.IntegerField()),
migrations.AddField("Bar", "width", models.IntegerField()),
@@ -871,7 +1074,9 @@ class OptimizerTests(SimpleTestCase):
self.assertOptimizesTo(
[
elidable_operation,
- migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
+ migrations.CreateModel(
+ "Foo", [("name", models.CharField(max_length=255))]
+ ),
elidable_operation,
migrations.CreateModel("Bar", [("size", models.IntegerField())]),
elidable_operation,
@@ -880,6 +1085,8 @@ class OptimizerTests(SimpleTestCase):
elidable_operation,
],
[
- migrations.CreateModel("Phou", [("name", models.CharField(max_length=255))]),
+ migrations.CreateModel(
+ "Phou", [("name", models.CharField(max_length=255))]
+ ),
],
)
diff --git a/tests/migrations/test_questioner.py b/tests/migrations/test_questioner.py
index 472a3f248f..c1aebcb224 100644
--- a/tests/migrations/test_questioner.py
+++ b/tests/migrations/test_questioner.py
@@ -4,7 +4,8 @@ from unittest import mock
from django.core.management.base import OutputWrapper
from django.db.migrations.questioner import (
- InteractiveMigrationQuestioner, MigrationQuestioner,
+ InteractiveMigrationQuestioner,
+ MigrationQuestioner,
)
from django.db.models import NOT_PROVIDED
from django.test import SimpleTestCase
@@ -13,21 +14,25 @@ from django.test.utils import override_settings
class QuestionerTests(SimpleTestCase):
@override_settings(
- INSTALLED_APPS=['migrations'],
- MIGRATION_MODULES={'migrations': None},
+ INSTALLED_APPS=["migrations"],
+ MIGRATION_MODULES={"migrations": None},
)
def test_ask_initial_with_disabled_migrations(self):
questioner = MigrationQuestioner()
- self.assertIs(False, questioner.ask_initial('migrations'))
+ self.assertIs(False, questioner.ask_initial("migrations"))
def test_ask_not_null_alteration(self):
questioner = MigrationQuestioner()
- self.assertIsNone(questioner.ask_not_null_alteration('field_name', 'model_name'))
+ self.assertIsNone(
+ questioner.ask_not_null_alteration("field_name", "model_name")
+ )
- @mock.patch('builtins.input', return_value='2')
+ @mock.patch("builtins.input", return_value="2")
def test_ask_not_null_alteration_not_provided(self, mock):
- questioner = InteractiveMigrationQuestioner(prompt_output=OutputWrapper(StringIO()))
- question = questioner.ask_not_null_alteration('field_name', 'model_name')
+ questioner = InteractiveMigrationQuestioner(
+ prompt_output=OutputWrapper(StringIO())
+ )
+ question = questioner.ask_not_null_alteration("field_name", "model_name")
self.assertEqual(question, NOT_PROVIDED)
@@ -36,17 +41,17 @@ class QuestionerHelperMethodsTests(SimpleTestCase):
self.prompt = OutputWrapper(StringIO())
self.questioner = InteractiveMigrationQuestioner(prompt_output=self.prompt)
- @mock.patch('builtins.input', return_value='datetime.timedelta(days=1)')
+ @mock.patch("builtins.input", return_value="datetime.timedelta(days=1)")
def test_questioner_default_timedelta(self, mock_input):
value = self.questioner._ask_default()
self.assertEqual(value, datetime.timedelta(days=1))
- @mock.patch('builtins.input', return_value='')
+ @mock.patch("builtins.input", return_value="")
def test_questioner_default_no_user_entry(self, mock_input):
- value = self.questioner._ask_default(default='datetime.timedelta(days=1)')
+ value = self.questioner._ask_default(default="datetime.timedelta(days=1)")
self.assertEqual(value, datetime.timedelta(days=1))
- @mock.patch('builtins.input', side_effect=['', 'exit'])
+ @mock.patch("builtins.input", side_effect=["", "exit"])
def test_questioner_no_default_no_user_entry(self, mock_input):
with self.assertRaises(SystemExit):
self.questioner._ask_default()
@@ -55,31 +60,26 @@ class QuestionerHelperMethodsTests(SimpleTestCase):
self.prompt.getvalue(),
)
- @mock.patch('builtins.input', side_effect=['bad code', 'exit'])
+ @mock.patch("builtins.input", side_effect=["bad code", "exit"])
def test_questioner_no_default_bad_user_entry_code(self, mock_input):
with self.assertRaises(SystemExit):
self.questioner._ask_default()
- self.assertIn('Invalid input: ', self.prompt.getvalue())
+ self.assertIn("Invalid input: ", self.prompt.getvalue())
- @mock.patch('builtins.input', side_effect=['', 'n'])
+ @mock.patch("builtins.input", side_effect=["", "n"])
def test_questioner_no_default_no_user_entry_boolean(self, mock_input):
- value = self.questioner._boolean_input('Proceed?')
+ value = self.questioner._boolean_input("Proceed?")
self.assertIs(value, False)
- @mock.patch('builtins.input', return_value='')
+ @mock.patch("builtins.input", return_value="")
def test_questioner_default_no_user_entry_boolean(self, mock_input):
- value = self.questioner._boolean_input('Proceed?', default=True)
+ value = self.questioner._boolean_input("Proceed?", default=True)
self.assertIs(value, True)
- @mock.patch('builtins.input', side_effect=[10, 'garbage', 1])
+ @mock.patch("builtins.input", side_effect=[10, "garbage", 1])
def test_questioner_bad_user_choice(self, mock_input):
- question = 'Make a choice:'
- value = self.questioner._choice_input(question, choices='abc')
- expected_msg = (
- f'{question}\n'
- f' 1) a\n'
- f' 2) b\n'
- f' 3) c\n'
- )
+ question = "Make a choice:"
+ value = self.questioner._choice_input(question, choices="abc")
+ expected_msg = f"{question}\n" f" 1) a\n" f" 2) b\n" f" 3) c\n"
self.assertIn(expected_msg, self.prompt.getvalue())
self.assertEqual(value, 1)
diff --git a/tests/migrations/test_state.py b/tests/migrations/test_state.py
index 9536f19e83..dfb17ae7d8 100644
--- a/tests/migrations/test_state.py
+++ b/tests/migrations/test_state.py
@@ -3,16 +3,24 @@ from django.contrib.contenttypes.fields import GenericForeignKey
from django.db import models
from django.db.migrations.exceptions import InvalidBasesError
from django.db.migrations.operations import (
- AddField, AlterField, DeleteModel, RemoveField,
+ AddField,
+ AlterField,
+ DeleteModel,
+ RemoveField,
)
from django.db.migrations.state import (
- ModelState, ProjectState, get_related_models_recursive,
+ ModelState,
+ ProjectState,
+ get_related_models_recursive,
)
from django.test import SimpleTestCase, override_settings
from django.test.utils import isolate_apps
from .models import (
- FoodManager, FoodQuerySet, ModelWithCustomBase, NoMigrationFoodManager,
+ FoodManager,
+ FoodQuerySet,
+ ModelWithCustomBase,
+ NoMigrationFoodManager,
UnicodeModel,
)
@@ -64,42 +72,41 @@ class StateTests(SimpleTestCase):
apps = new_apps
verbose_name = "tome"
db_table = "test_tome"
- indexes = [models.Index(fields=['title'])]
+ indexes = [models.Index(fields=["title"])]
class Food(models.Model):
- food_mgr = FoodManager('a', 'b')
+ food_mgr = FoodManager("a", "b")
food_qs = FoodQuerySet.as_manager()
- food_no_mgr = NoMigrationFoodManager('x', 'y')
+ food_no_mgr = NoMigrationFoodManager("x", "y")
class Meta:
app_label = "migrations"
apps = new_apps
class FoodNoManagers(models.Model):
-
class Meta:
app_label = "migrations"
apps = new_apps
class FoodNoDefaultManager(models.Model):
- food_no_mgr = NoMigrationFoodManager('x', 'y')
- food_mgr = FoodManager('a', 'b')
+ food_no_mgr = NoMigrationFoodManager("x", "y")
+ food_mgr = FoodManager("a", "b")
food_qs = FoodQuerySet.as_manager()
class Meta:
app_label = "migrations"
apps = new_apps
- mgr1 = FoodManager('a', 'b')
- mgr2 = FoodManager('x', 'y', c=3, d=4)
+ mgr1 = FoodManager("a", "b")
+ mgr2 = FoodManager("x", "y", c=3, d=4)
class FoodOrderedManagers(models.Model):
# The managers on this model should be ordered by their creation
# counter and not by the order in model body
- food_no_mgr = NoMigrationFoodManager('x', 'y')
+ food_no_mgr = NoMigrationFoodManager("x", "y")
food_mgr2 = mgr2
food_mgr1 = mgr1
@@ -108,23 +115,27 @@ class StateTests(SimpleTestCase):
apps = new_apps
project_state = ProjectState.from_apps(new_apps)
- author_state = project_state.models['migrations', 'author']
- author_proxy_state = project_state.models['migrations', 'authorproxy']
- sub_author_state = project_state.models['migrations', 'subauthor']
- book_state = project_state.models['migrations', 'book']
- food_state = project_state.models['migrations', 'food']
- food_no_managers_state = project_state.models['migrations', 'foodnomanagers']
- food_no_default_manager_state = project_state.models['migrations', 'foodnodefaultmanager']
- food_order_manager_state = project_state.models['migrations', 'foodorderedmanagers']
- book_index = models.Index(fields=['title'])
+ author_state = project_state.models["migrations", "author"]
+ author_proxy_state = project_state.models["migrations", "authorproxy"]
+ sub_author_state = project_state.models["migrations", "subauthor"]
+ book_state = project_state.models["migrations", "book"]
+ food_state = project_state.models["migrations", "food"]
+ food_no_managers_state = project_state.models["migrations", "foodnomanagers"]
+ food_no_default_manager_state = project_state.models[
+ "migrations", "foodnodefaultmanager"
+ ]
+ food_order_manager_state = project_state.models[
+ "migrations", "foodorderedmanagers"
+ ]
+ book_index = models.Index(fields=["title"])
book_index.set_name_with_model(Book)
self.assertEqual(author_state.app_label, "migrations")
self.assertEqual(author_state.name, "Author")
self.assertEqual(list(author_state.fields), ["id", "name", "bio", "age"])
- self.assertEqual(author_state.fields['name'].max_length, 255)
- self.assertIs(author_state.fields['bio'].null, False)
- self.assertIs(author_state.fields['age'].null, True)
+ self.assertEqual(author_state.fields["name"].max_length, 255)
+ self.assertIs(author_state.fields["bio"].null, False)
+ self.assertIs(author_state.fields["age"].null, True)
self.assertEqual(
author_state.options,
{
@@ -132,19 +143,28 @@ class StateTests(SimpleTestCase):
"index_together": {("bio", "age")},
"indexes": [],
"constraints": [],
- }
+ },
)
self.assertEqual(author_state.bases, (models.Model,))
self.assertEqual(book_state.app_label, "migrations")
self.assertEqual(book_state.name, "Book")
- self.assertEqual(list(book_state.fields), ["id", "title", "author", "contributors"])
- self.assertEqual(book_state.fields['title'].max_length, 1000)
- self.assertIs(book_state.fields['author'].null, False)
- self.assertEqual(book_state.fields['contributors'].__class__.__name__, 'ManyToManyField')
+ self.assertEqual(
+ list(book_state.fields), ["id", "title", "author", "contributors"]
+ )
+ self.assertEqual(book_state.fields["title"].max_length, 1000)
+ self.assertIs(book_state.fields["author"].null, False)
+ self.assertEqual(
+ book_state.fields["contributors"].__class__.__name__, "ManyToManyField"
+ )
self.assertEqual(
book_state.options,
- {"verbose_name": "tome", "db_table": "test_tome", "indexes": [book_index], "constraints": []},
+ {
+ "verbose_name": "tome",
+ "db_table": "test_tome",
+ "indexes": [book_index],
+ "constraints": [],
+ },
)
self.assertEqual(book_state.bases, (models.Model,))
@@ -163,33 +183,50 @@ class StateTests(SimpleTestCase):
self.assertEqual(sub_author_state.bases, ("migrations.author",))
# The default manager is used in migrations
- self.assertEqual([name for name, mgr in food_state.managers], ['food_mgr'])
+ self.assertEqual([name for name, mgr in food_state.managers], ["food_mgr"])
self.assertTrue(all(isinstance(name, str) for name, mgr in food_state.managers))
- self.assertEqual(food_state.managers[0][1].args, ('a', 'b', 1, 2))
+ self.assertEqual(food_state.managers[0][1].args, ("a", "b", 1, 2))
# No explicit managers defined. Migrations will fall back to the default
self.assertEqual(food_no_managers_state.managers, [])
# food_mgr is used in migration but isn't the default mgr, hence add the
# default
- self.assertEqual([name for name, mgr in food_no_default_manager_state.managers],
- ['food_no_mgr', 'food_mgr'])
- self.assertTrue(all(isinstance(name, str) for name, mgr in food_no_default_manager_state.managers))
- self.assertEqual(food_no_default_manager_state.managers[0][1].__class__, models.Manager)
+ self.assertEqual(
+ [name for name, mgr in food_no_default_manager_state.managers],
+ ["food_no_mgr", "food_mgr"],
+ )
+ self.assertTrue(
+ all(
+ isinstance(name, str)
+ for name, mgr in food_no_default_manager_state.managers
+ )
+ )
+ self.assertEqual(
+ food_no_default_manager_state.managers[0][1].__class__, models.Manager
+ )
self.assertIsInstance(food_no_default_manager_state.managers[1][1], FoodManager)
- self.assertEqual([name for name, mgr in food_order_manager_state.managers],
- ['food_mgr1', 'food_mgr2'])
- self.assertTrue(all(isinstance(name, str) for name, mgr in food_order_manager_state.managers))
- self.assertEqual([mgr.args for name, mgr in food_order_manager_state.managers],
- [('a', 'b', 1, 2), ('x', 'y', 3, 4)])
+ self.assertEqual(
+ [name for name, mgr in food_order_manager_state.managers],
+ ["food_mgr1", "food_mgr2"],
+ )
+ self.assertTrue(
+ all(
+ isinstance(name, str) for name, mgr in food_order_manager_state.managers
+ )
+ )
+ self.assertEqual(
+ [mgr.args for name, mgr in food_order_manager_state.managers],
+ [("a", "b", 1, 2), ("x", "y", 3, 4)],
+ )
def test_custom_default_manager_added_to_the_model_state(self):
"""
When the default manager of the model is a custom manager,
it needs to be added to the model state.
"""
- new_apps = Apps(['migrations'])
+ new_apps = Apps(["migrations"])
custom_manager = models.Manager()
class Author(models.Model):
@@ -197,12 +234,12 @@ class StateTests(SimpleTestCase):
authors = custom_manager
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
project_state = ProjectState.from_apps(new_apps)
- author_state = project_state.models['migrations', 'author']
- self.assertEqual(author_state.managers, [('authors', custom_manager)])
+ author_state = project_state.models["migrations", "author"]
+ self.assertEqual(author_state.managers, [("authors", custom_manager)])
def test_custom_default_manager_named_objects_with_false_migration_flag(self):
"""
@@ -210,17 +247,17 @@ class StateTests(SimpleTestCase):
have `use_in_migrations = True`, no migration should be added to the
model state (#26643).
"""
- new_apps = Apps(['migrations'])
+ new_apps = Apps(["migrations"])
class Author(models.Model):
objects = models.Manager()
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
project_state = ProjectState.from_apps(new_apps)
- author_state = project_state.models['migrations', 'author']
+ author_state = project_state.models["migrations", "author"]
self.assertEqual(author_state.managers, [])
def test_no_duplicate_managers(self):
@@ -229,7 +266,7 @@ class StateTests(SimpleTestCase):
model had a manager with the same name and `use_in_migrations = True`,
the parent's manager shouldn't appear in the model state (#26881).
"""
- new_apps = Apps(['migrations'])
+ new_apps = Apps(["migrations"])
class PersonManager(models.Manager):
use_in_migrations = True
@@ -247,65 +284,71 @@ class StateTests(SimpleTestCase):
objects = BossManager()
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
project_state = ProjectState.from_apps(new_apps)
- boss_state = project_state.models['migrations', 'boss']
- self.assertEqual(boss_state.managers, [('objects', Boss.objects)])
+ boss_state = project_state.models["migrations", "boss"]
+ self.assertEqual(boss_state.managers, [("objects", Boss.objects)])
def test_custom_default_manager(self):
- new_apps = Apps(['migrations'])
+ new_apps = Apps(["migrations"])
class Author(models.Model):
manager1 = models.Manager()
manager2 = models.Manager()
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
- default_manager_name = 'manager2'
+ default_manager_name = "manager2"
project_state = ProjectState.from_apps(new_apps)
- author_state = project_state.models['migrations', 'author']
- self.assertEqual(author_state.options['default_manager_name'], 'manager2')
- self.assertEqual(author_state.managers, [('manager2', Author.manager1)])
+ author_state = project_state.models["migrations", "author"]
+ self.assertEqual(author_state.options["default_manager_name"], "manager2")
+ self.assertEqual(author_state.managers, [("manager2", Author.manager1)])
def test_custom_base_manager(self):
- new_apps = Apps(['migrations'])
+ new_apps = Apps(["migrations"])
class Author(models.Model):
manager1 = models.Manager()
manager2 = models.Manager()
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
- base_manager_name = 'manager2'
+ base_manager_name = "manager2"
class Author2(models.Model):
manager1 = models.Manager()
manager2 = models.Manager()
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
- base_manager_name = 'manager1'
+ base_manager_name = "manager1"
project_state = ProjectState.from_apps(new_apps)
- author_state = project_state.models['migrations', 'author']
- self.assertEqual(author_state.options['base_manager_name'], 'manager2')
- self.assertEqual(author_state.managers, [
- ('manager1', Author.manager1),
- ('manager2', Author.manager2),
- ])
+ author_state = project_state.models["migrations", "author"]
+ self.assertEqual(author_state.options["base_manager_name"], "manager2")
+ self.assertEqual(
+ author_state.managers,
+ [
+ ("manager1", Author.manager1),
+ ("manager2", Author.manager2),
+ ],
+ )
- author2_state = project_state.models['migrations', 'author2']
- self.assertEqual(author2_state.options['base_manager_name'], 'manager1')
- self.assertEqual(author2_state.managers, [
- ('manager1', Author2.manager1),
- ])
+ author2_state = project_state.models["migrations", "author2"]
+ self.assertEqual(author2_state.options["base_manager_name"], "manager1")
+ self.assertEqual(
+ author2_state.managers,
+ [
+ ("manager1", Author2.manager1),
+ ],
+ )
def test_apps_bulk_update(self):
"""
@@ -328,62 +371,83 @@ class StateTests(SimpleTestCase):
Tests rendering a ProjectState into an Apps.
"""
project_state = ProjectState()
- project_state.add_model(ModelState(
- app_label="migrations",
- name="Tag",
- fields=[
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=100)),
- ("hidden", models.BooleanField()),
- ],
- ))
- project_state.add_model(ModelState(
- app_label="migrations",
- name="SubTag",
- fields=[
- ('tag_ptr', models.OneToOneField(
- 'migrations.Tag',
- models.CASCADE,
- auto_created=True,
- parent_link=True,
- primary_key=True,
- to_field='id',
- serialize=False,
- )),
- ("awesome", models.BooleanField()),
- ],
- bases=("migrations.Tag",),
- ))
+ project_state.add_model(
+ ModelState(
+ app_label="migrations",
+ name="Tag",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=100)),
+ ("hidden", models.BooleanField()),
+ ],
+ )
+ )
+ project_state.add_model(
+ ModelState(
+ app_label="migrations",
+ name="SubTag",
+ fields=[
+ (
+ "tag_ptr",
+ models.OneToOneField(
+ "migrations.Tag",
+ models.CASCADE,
+ auto_created=True,
+ parent_link=True,
+ primary_key=True,
+ to_field="id",
+ serialize=False,
+ ),
+ ),
+ ("awesome", models.BooleanField()),
+ ],
+ bases=("migrations.Tag",),
+ )
+ )
base_mgr = models.Manager()
- mgr1 = FoodManager('a', 'b')
- mgr2 = FoodManager('x', 'y', c=3, d=4)
- project_state.add_model(ModelState(
- app_label="migrations",
- name="Food",
- fields=[
- ("id", models.AutoField(primary_key=True)),
- ],
- managers=[
- # The ordering we really want is objects, mgr1, mgr2
- ('default', base_mgr),
- ('food_mgr2', mgr2),
- ('food_mgr1', mgr1),
- ]
- ))
+ mgr1 = FoodManager("a", "b")
+ mgr2 = FoodManager("x", "y", c=3, d=4)
+ project_state.add_model(
+ ModelState(
+ app_label="migrations",
+ name="Food",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ],
+ managers=[
+ # The ordering we really want is objects, mgr1, mgr2
+ ("default", base_mgr),
+ ("food_mgr2", mgr2),
+ ("food_mgr1", mgr1),
+ ],
+ )
+ )
new_apps = project_state.apps
- self.assertEqual(new_apps.get_model("migrations", "Tag")._meta.get_field("name").max_length, 100)
- self.assertIs(new_apps.get_model("migrations", "Tag")._meta.get_field("hidden").null, False)
+ self.assertEqual(
+ new_apps.get_model("migrations", "Tag")._meta.get_field("name").max_length,
+ 100,
+ )
+ self.assertIs(
+ new_apps.get_model("migrations", "Tag")._meta.get_field("hidden").null,
+ False,
+ )
- self.assertEqual(len(new_apps.get_model("migrations", "SubTag")._meta.local_fields), 2)
+ self.assertEqual(
+ len(new_apps.get_model("migrations", "SubTag")._meta.local_fields), 2
+ )
Food = new_apps.get_model("migrations", "Food")
- self.assertEqual([mgr.name for mgr in Food._meta.managers],
- ['default', 'food_mgr1', 'food_mgr2'])
+ self.assertEqual(
+ [mgr.name for mgr in Food._meta.managers],
+ ["default", "food_mgr1", "food_mgr2"],
+ )
self.assertTrue(all(isinstance(mgr.name, str) for mgr in Food._meta.managers))
- self.assertEqual([mgr.__class__ for mgr in Food._meta.managers],
- [models.Manager, FoodManager, FoodManager])
+ self.assertEqual(
+ [mgr.__class__ for mgr in Food._meta.managers],
+ [models.Manager, FoodManager, FoodManager],
+ )
def test_render_model_inheritance(self):
class Book(models.Model):
@@ -449,9 +513,13 @@ class StateTests(SimpleTestCase):
ModelState.from_model(Bar).render(apps)
self.assertSequenceEqual(ModelState.from_model(Bar).bases, [models.Model])
ModelState.from_model(FooBar).render(apps)
- self.assertSequenceEqual(ModelState.from_model(FooBar).bases, ['migrations.foo', 'migrations.bar'])
+ self.assertSequenceEqual(
+ ModelState.from_model(FooBar).bases, ["migrations.foo", "migrations.bar"]
+ )
ModelState.from_model(SubFooBar).render(apps)
- self.assertSequenceEqual(ModelState.from_model(SubFooBar).bases, ['migrations.foobar'])
+ self.assertSequenceEqual(
+ ModelState.from_model(SubFooBar).bases, ["migrations.foobar"]
+ )
def test_render_project_dependencies(self):
"""
@@ -518,6 +586,7 @@ class StateTests(SimpleTestCase):
ImproperlyConfigured exception about unique labels if two dotted app
names have the same last part.
"""
+
class A(models.Model):
class Meta:
app_label = "django.contrib.auth"
@@ -539,50 +608,80 @@ class StateTests(SimpleTestCase):
"""
project_state = ProjectState()
project_state.apps # Render project state.
- project_state.add_model(ModelState('migrations', 'A', []))
- project_state.add_model(ModelState('migrations', 'B', [
- ('a', models.ForeignKey('A', models.CASCADE)),
- ]))
- project_state.add_model(ModelState('migrations', 'C', [
- ('b', models.ForeignKey('B', models.CASCADE)),
- ('name', models.TextField()),
- ]))
- project_state.add_model(ModelState('migrations', 'D', [
- ('a', models.ForeignKey('A', models.CASCADE)),
- ]))
+ project_state.add_model(ModelState("migrations", "A", []))
+ project_state.add_model(
+ ModelState(
+ "migrations",
+ "B",
+ [
+ ("a", models.ForeignKey("A", models.CASCADE)),
+ ],
+ )
+ )
+ project_state.add_model(
+ ModelState(
+ "migrations",
+ "C",
+ [
+ ("b", models.ForeignKey("B", models.CASCADE)),
+ ("name", models.TextField()),
+ ],
+ )
+ )
+ project_state.add_model(
+ ModelState(
+ "migrations",
+ "D",
+ [
+ ("a", models.ForeignKey("A", models.CASCADE)),
+ ],
+ )
+ )
operation = AlterField(
- model_name='C',
- name='name',
+ model_name="C",
+ name="name",
field=models.TextField(blank=True),
)
- operation.state_forwards('migrations', project_state)
- project_state.reload_model('migrations', 'a', delay=True)
- A = project_state.apps.get_model('migrations.A')
- B = project_state.apps.get_model('migrations.B')
- D = project_state.apps.get_model('migrations.D')
- self.assertIs(B._meta.get_field('a').related_model, A)
- self.assertIs(D._meta.get_field('a').related_model, A)
+ operation.state_forwards("migrations", project_state)
+ project_state.reload_model("migrations", "a", delay=True)
+ A = project_state.apps.get_model("migrations.A")
+ B = project_state.apps.get_model("migrations.B")
+ D = project_state.apps.get_model("migrations.D")
+ self.assertIs(B._meta.get_field("a").related_model, A)
+ self.assertIs(D._meta.get_field("a").related_model, A)
def test_reload_model_relationship_consistency(self):
project_state = ProjectState()
- project_state.add_model(ModelState('migrations', 'A', []))
- project_state.add_model(ModelState('migrations', 'B', [
- ('a', models.ForeignKey('A', models.CASCADE)),
- ]))
- project_state.add_model(ModelState('migrations', 'C', [
- ('b', models.ForeignKey('B', models.CASCADE)),
- ]))
- A = project_state.apps.get_model('migrations.A')
- B = project_state.apps.get_model('migrations.B')
- C = project_state.apps.get_model('migrations.C')
+ project_state.add_model(ModelState("migrations", "A", []))
+ project_state.add_model(
+ ModelState(
+ "migrations",
+ "B",
+ [
+ ("a", models.ForeignKey("A", models.CASCADE)),
+ ],
+ )
+ )
+ project_state.add_model(
+ ModelState(
+ "migrations",
+ "C",
+ [
+ ("b", models.ForeignKey("B", models.CASCADE)),
+ ],
+ )
+ )
+ A = project_state.apps.get_model("migrations.A")
+ B = project_state.apps.get_model("migrations.B")
+ C = project_state.apps.get_model("migrations.C")
self.assertEqual([r.related_model for r in A._meta.related_objects], [B])
self.assertEqual([r.related_model for r in B._meta.related_objects], [C])
self.assertEqual([r.related_model for r in C._meta.related_objects], [])
- project_state.reload_model('migrations', 'a', delay=True)
- A = project_state.apps.get_model('migrations.A')
- B = project_state.apps.get_model('migrations.B')
- C = project_state.apps.get_model('migrations.C')
+ project_state.reload_model("migrations", "a", delay=True)
+ A = project_state.apps.get_model("migrations.A")
+ B = project_state.apps.get_model("migrations.B")
+ C = project_state.apps.get_model("migrations.C")
self.assertEqual([r.related_model for r in A._meta.related_objects], [B])
self.assertEqual([r.related_model for r in B._meta.related_objects], [C])
self.assertEqual([r.related_model for r in C._meta.related_objects], [])
@@ -596,17 +695,17 @@ class StateTests(SimpleTestCase):
class A(models.Model):
class Meta:
- app_label = 'something'
+ app_label = "something"
apps = new_apps
class B(A):
class Meta:
- app_label = 'something'
+ app_label = "something"
apps = new_apps
class C(models.Model):
class Meta:
- app_label = 'something'
+ app_label = "something"
apps = new_apps
project_state = ProjectState()
@@ -617,35 +716,39 @@ class StateTests(SimpleTestCase):
project_state.apps # We need to work with rendered models
old_state = project_state.clone()
- model_a_old = old_state.apps.get_model('something', 'A')
- model_b_old = old_state.apps.get_model('something', 'B')
- model_c_old = old_state.apps.get_model('something', 'C')
+ model_a_old = old_state.apps.get_model("something", "A")
+ model_b_old = old_state.apps.get_model("something", "B")
+ model_c_old = old_state.apps.get_model("something", "C")
# The relations between the old models are correct
- self.assertIs(model_a_old._meta.get_field('b').related_model, model_b_old)
- self.assertIs(model_b_old._meta.get_field('a_ptr').related_model, model_a_old)
+ self.assertIs(model_a_old._meta.get_field("b").related_model, model_b_old)
+ self.assertIs(model_b_old._meta.get_field("a_ptr").related_model, model_a_old)
- operation = AddField('c', 'to_a', models.OneToOneField(
- 'something.A',
- models.CASCADE,
- related_name='from_c',
- ))
- operation.state_forwards('something', project_state)
- model_a_new = project_state.apps.get_model('something', 'A')
- model_b_new = project_state.apps.get_model('something', 'B')
- model_c_new = project_state.apps.get_model('something', 'C')
+ operation = AddField(
+ "c",
+ "to_a",
+ models.OneToOneField(
+ "something.A",
+ models.CASCADE,
+ related_name="from_c",
+ ),
+ )
+ operation.state_forwards("something", project_state)
+ model_a_new = project_state.apps.get_model("something", "A")
+ model_b_new = project_state.apps.get_model("something", "B")
+ model_c_new = project_state.apps.get_model("something", "C")
# All models have changed
self.assertIsNot(model_a_old, model_a_new)
self.assertIsNot(model_b_old, model_b_new)
self.assertIsNot(model_c_old, model_c_new)
# The relations between the old models still hold
- self.assertIs(model_a_old._meta.get_field('b').related_model, model_b_old)
- self.assertIs(model_b_old._meta.get_field('a_ptr').related_model, model_a_old)
+ self.assertIs(model_a_old._meta.get_field("b").related_model, model_b_old)
+ self.assertIs(model_b_old._meta.get_field("a_ptr").related_model, model_a_old)
# The relations between the new models correct
- self.assertIs(model_a_new._meta.get_field('b').related_model, model_b_new)
- self.assertIs(model_b_new._meta.get_field('a_ptr').related_model, model_a_new)
- self.assertIs(model_a_new._meta.get_field('from_c').related_model, model_c_new)
- self.assertIs(model_c_new._meta.get_field('to_a').related_model, model_a_new)
+ self.assertIs(model_a_new._meta.get_field("b").related_model, model_b_new)
+ self.assertIs(model_b_new._meta.get_field("a_ptr").related_model, model_a_new)
+ self.assertIs(model_a_new._meta.get_field("from_c").related_model, model_c_new)
+ self.assertIs(model_c_new._meta.get_field("to_a").related_model, model_a_new)
def test_remove_relations(self):
"""
@@ -667,7 +770,9 @@ class StateTests(SimpleTestCase):
apps = new_apps
def get_model_a(state):
- return [mod for mod in state.apps.get_models() if mod._meta.model_name == 'a'][0]
+ return [
+ mod for mod in state.apps.get_models() if mod._meta.model_name == "a"
+ ][0]
project_state = ProjectState()
project_state.add_model(ModelState.from_model(A))
@@ -703,14 +808,17 @@ class StateTests(SimpleTestCase):
#24513 - Modifying an object pointing to itself would cause it to be
rendered twice and thus breaking its related M2M through objects.
"""
+
class A(models.Model):
- to_a = models.ManyToManyField('something.A', symmetrical=False)
+ to_a = models.ManyToManyField("something.A", symmetrical=False)
class Meta:
app_label = "something"
def get_model_a(state):
- return [mod for mod in state.apps.get_models() if mod._meta.model_name == 'a'][0]
+ return [
+ mod for mod in state.apps.get_models() if mod._meta.model_name == "a"
+ ][0]
project_state = ProjectState()
project_state.add_model(ModelState.from_model(A))
@@ -720,7 +828,7 @@ class StateTests(SimpleTestCase):
operation = AlterField(
model_name="a",
name="to_a",
- field=models.ManyToManyField("something.A", symmetrical=False, blank=True)
+ field=models.ManyToManyField("something.A", symmetrical=False, blank=True),
)
# At this point the model would be rendered twice causing its related
# M2M through objects to point to an old copy and thus breaking their
@@ -736,16 +844,28 @@ class StateTests(SimpleTestCase):
self.assertEqual(field_to_a_old.m2m_field_name(), "from_a")
self.assertEqual(field_to_a_old.m2m_reverse_field_name(), "to_a")
self.assertIs(field_to_a_old.related_model, model_a_old)
- self.assertIs(field_to_a_old.remote_field.through._meta.get_field('to_a').related_model, model_a_old)
- self.assertIs(field_to_a_old.remote_field.through._meta.get_field('from_a').related_model, model_a_old)
+ self.assertIs(
+ field_to_a_old.remote_field.through._meta.get_field("to_a").related_model,
+ model_a_old,
+ )
+ self.assertIs(
+ field_to_a_old.remote_field.through._meta.get_field("from_a").related_model,
+ model_a_old,
+ )
# The new model's _meta is still consistent
field_to_a_new = model_a_new._meta.get_field("to_a")
self.assertEqual(field_to_a_new.m2m_field_name(), "from_a")
self.assertEqual(field_to_a_new.m2m_reverse_field_name(), "to_a")
self.assertIs(field_to_a_new.related_model, model_a_new)
- self.assertIs(field_to_a_new.remote_field.through._meta.get_field('to_a').related_model, model_a_new)
- self.assertIs(field_to_a_new.remote_field.through._meta.get_field('from_a').related_model, model_a_new)
+ self.assertIs(
+ field_to_a_new.remote_field.through._meta.get_field("to_a").related_model,
+ model_a_new,
+ )
+ self.assertIs(
+ field_to_a_new.remote_field.through._meta.get_field("from_a").related_model,
+ model_a_new,
+ )
def test_equality(self):
"""
@@ -753,17 +873,19 @@ class StateTests(SimpleTestCase):
"""
# Test two things that should be equal
project_state = ProjectState()
- project_state.add_model(ModelState(
- "migrations",
- "Tag",
- [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=100)),
- ("hidden", models.BooleanField()),
- ],
- {},
- None,
- ))
+ project_state.add_model(
+ ModelState(
+ "migrations",
+ "Tag",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=100)),
+ ("hidden", models.BooleanField()),
+ ],
+ {},
+ None,
+ )
+ )
project_state.apps # Fill the apps cached property
other_state = project_state.clone()
self.assertEqual(project_state, project_state)
@@ -774,17 +896,19 @@ class StateTests(SimpleTestCase):
# Make a very small change (max_len 99) and see if that affects it
project_state = ProjectState()
- project_state.add_model(ModelState(
- "migrations",
- "Tag",
- [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=99)),
- ("hidden", models.BooleanField()),
- ],
- {},
- None,
- ))
+ project_state.add_model(
+ ModelState(
+ "migrations",
+ "Tag",
+ [
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=99)),
+ ("hidden", models.BooleanField()),
+ ],
+ {},
+ None,
+ )
+ )
self.assertNotEqual(project_state, other_state)
self.assertIs(project_state == other_state, False)
@@ -845,9 +969,9 @@ class StateTests(SimpleTestCase):
project_state.add_model(ModelState.from_model(Magazine))
msg = (
"The field migrations.Magazine.authors was declared with a lazy reference "
- "to 'migrations.author\', but app 'migrations' doesn't provide model 'author'.\n"
+ "to 'migrations.author', but app 'migrations' doesn't provide model 'author'.\n"
"The field migrations.Magazine_authors.author was declared with a lazy reference "
- "to \'migrations.author\', but app 'migrations' doesn't provide model 'author'."
+ "to 'migrations.author', but app 'migrations' doesn't provide model 'author'."
)
with self.assertRaisesMessage(ValueError, msg):
project_state.apps
@@ -872,21 +996,21 @@ class StateTests(SimpleTestCase):
class Author(models.Model):
class Meta:
- app_label = 'MiXedCase_migrations'
+ app_label = "MiXedCase_migrations"
apps = new_apps
class Book(models.Model):
author = models.ForeignKey(Author, models.CASCADE)
class Meta:
- app_label = 'MiXedCase_migrations'
+ app_label = "MiXedCase_migrations"
apps = new_apps
class Magazine(models.Model):
authors = models.ManyToManyField(Author)
class Meta:
- app_label = 'MiXedCase_migrations'
+ app_label = "MiXedCase_migrations"
apps = new_apps
project_state = ProjectState()
@@ -916,17 +1040,23 @@ class StateTests(SimpleTestCase):
project_state.apps
# If we include the real app it should succeed
- project_state = ProjectState(real_apps={'contenttypes'})
+ project_state = ProjectState(real_apps={"contenttypes"})
project_state.add_model(ModelState.from_model(TestModel))
rendered_state = project_state.apps
self.assertEqual(
- len([x for x in rendered_state.get_models() if x._meta.app_label == "migrations"]),
+ len(
+ [
+ x
+ for x in rendered_state.get_models()
+ if x._meta.app_label == "migrations"
+ ]
+ ),
1,
)
def test_real_apps_non_set(self):
with self.assertRaises(AssertionError):
- ProjectState(real_apps=['contenttypes'])
+ ProjectState(real_apps=["contenttypes"])
def test_ignore_order_wrt(self):
"""
@@ -955,7 +1085,7 @@ class StateTests(SimpleTestCase):
project_state.add_model(ModelState.from_model(Author))
project_state.add_model(ModelState.from_model(Book))
self.assertEqual(
- list(project_state.models['migrations', 'book'].fields),
+ list(project_state.models["migrations", "book"].fields),
["id", "author"],
)
@@ -966,21 +1096,21 @@ class StateTests(SimpleTestCase):
name = models.TextField()
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
class Book(models.Model):
author = models.ForeignKey(Author, models.CASCADE)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
- order_with_respect_to = 'author'
+ order_with_respect_to = "author"
model_state = ModelState.from_model(Book)
- order_wrt_field = model_state.get_field('_order')
+ order_wrt_field = model_state.get_field("_order")
self.assertIsInstance(order_wrt_field, models.ForeignKey)
- self.assertEqual(order_wrt_field.related_model, 'migrations.author')
+ self.assertEqual(order_wrt_field.related_model, "migrations.author")
def test_modelstate_get_field_no_order_wrt_order_field(self):
new_apps = Apps()
@@ -989,11 +1119,11 @@ class StateTests(SimpleTestCase):
_order = models.PositiveSmallIntegerField()
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
model_state = ModelState.from_model(HistoricalRecord)
- order_field = model_state.get_field('_order')
+ order_field = model_state.get_field("_order")
self.assertIsNone(order_field.related_model)
self.assertIsInstance(order_field, models.PositiveSmallIntegerField)
@@ -1003,26 +1133,28 @@ class StateTests(SimpleTestCase):
historical model
"""
project_state = ProjectState()
- project_state.add_model(ModelState(
- app_label="migrations",
- name="Tag",
- fields=[
- ("id", models.AutoField(primary_key=True)),
- ("hidden", models.BooleanField()),
- ],
- managers=[
- ('food_mgr', FoodManager('a', 'b')),
- ('food_qs', FoodQuerySet.as_manager()),
- ]
- ))
+ project_state.add_model(
+ ModelState(
+ app_label="migrations",
+ name="Tag",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("hidden", models.BooleanField()),
+ ],
+ managers=[
+ ("food_mgr", FoodManager("a", "b")),
+ ("food_qs", FoodQuerySet.as_manager()),
+ ],
+ )
+ )
- old_model = project_state.apps.get_model('migrations', 'tag')
+ old_model = project_state.apps.get_model("migrations", "tag")
new_state = project_state.clone()
operation = RemoveField("tag", "hidden")
operation.state_forwards("migrations", new_state)
- new_model = new_state.apps.get_model('migrations', 'tag')
+ new_model = new_state.apps.get_model("migrations", "tag")
self.assertIsNot(old_model, new_model)
self.assertIs(old_model, old_model.food_mgr.model)
@@ -1040,7 +1172,7 @@ class StateTests(SimpleTestCase):
Field.choices iterators.
"""
new_apps = Apps(["migrations"])
- choices = [('a', 'A'), ('b', 'B')]
+ choices = [("a", "A"), ("b", "B")]
class Author(models.Model):
name = models.CharField(max_length=255)
@@ -1051,7 +1183,7 @@ class StateTests(SimpleTestCase):
apps = new_apps
ProjectState.from_apps(new_apps)
- choices_field = Author._meta.get_field('choice')
+ choices_field = Author._meta.get_field("choice")
self.assertEqual(list(choices_field.choices), choices)
@@ -1061,16 +1193,16 @@ class StateRelationsTests(SimpleTestCase):
class User(models.Model):
class Meta:
- app_label = 'tests'
+ app_label = "tests"
apps = new_apps
class Comment(models.Model):
text = models.TextField()
user = models.ForeignKey(User, models.CASCADE)
- comments = models.ManyToManyField('self')
+ comments = models.ManyToManyField("self")
class Meta:
- app_label = 'tests'
+ app_label = "tests"
apps = new_apps
class Post(models.Model):
@@ -1078,7 +1210,7 @@ class StateRelationsTests(SimpleTestCase):
authors = models.ManyToManyField(User)
class Meta:
- app_label = 'tests'
+ app_label = "tests"
apps = new_apps
project_state = ProjectState()
@@ -1089,31 +1221,40 @@ class StateRelationsTests(SimpleTestCase):
def test_relations_population(self):
tests = [
- ('add_model', [
- ModelState(
- app_label='migrations',
- name='Tag',
- fields=[('id', models.AutoField(primary_key=True))],
- ),
- ]),
- ('remove_model', ['tests', 'comment']),
- ('rename_model', ['tests', 'comment', 'opinion']),
- ('add_field', [
- 'tests',
- 'post',
- 'next_post',
- models.ForeignKey('self', models.CASCADE),
- True,
- ]),
- ('remove_field', ['tests', 'post', 'text']),
- ('rename_field', ['tests', 'comment', 'user', 'author']),
- ('alter_field', [
- 'tests',
- 'comment',
- 'user',
- models.IntegerField(),
- True,
- ]),
+ (
+ "add_model",
+ [
+ ModelState(
+ app_label="migrations",
+ name="Tag",
+ fields=[("id", models.AutoField(primary_key=True))],
+ ),
+ ],
+ ),
+ ("remove_model", ["tests", "comment"]),
+ ("rename_model", ["tests", "comment", "opinion"]),
+ (
+ "add_field",
+ [
+ "tests",
+ "post",
+ "next_post",
+ models.ForeignKey("self", models.CASCADE),
+ True,
+ ],
+ ),
+ ("remove_field", ["tests", "post", "text"]),
+ ("rename_field", ["tests", "comment", "user", "author"]),
+ (
+ "alter_field",
+ [
+ "tests",
+ "comment",
+ "user",
+ models.IntegerField(),
+ True,
+ ],
+ ),
]
for method, args in tests:
with self.subTest(method=method):
@@ -1127,328 +1268,366 @@ class StateRelationsTests(SimpleTestCase):
def test_add_model(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
self.assertEqual(
- list(project_state.relations['tests', 'comment']),
- [('tests', 'comment')],
+ list(project_state.relations["tests", "comment"]),
+ [("tests", "comment")],
)
- self.assertNotIn(('tests', 'post'), project_state.relations)
+ self.assertNotIn(("tests", "post"), project_state.relations)
def test_add_model_no_relations(self):
project_state = ProjectState()
- project_state.add_model(ModelState(
- app_label='migrations',
- name='Tag',
- fields=[('id', models.AutoField(primary_key=True))],
- ))
+ project_state.add_model(
+ ModelState(
+ app_label="migrations",
+ name="Tag",
+ fields=[("id", models.AutoField(primary_key=True))],
+ )
+ )
self.assertEqual(project_state.relations, {})
def test_add_model_other_app(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
+ )
+ project_state.add_model(
+ ModelState(
+ app_label="tests_other",
+ name="comment",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("user", models.ForeignKey("tests.user", models.CASCADE)),
+ ],
+ )
)
- project_state.add_model(ModelState(
- app_label='tests_other',
- name='comment',
- fields=[
- ('id', models.AutoField(primary_key=True)),
- ('user', models.ForeignKey('tests.user', models.CASCADE)),
- ],
- ))
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post'), ('tests_other', 'comment')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post"), ("tests_other", "comment")],
)
def test_remove_model(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
self.assertEqual(
- list(project_state.relations['tests', 'comment']),
- [('tests', 'comment')],
+ list(project_state.relations["tests", "comment"]),
+ [("tests", "comment")],
)
- project_state.remove_model('tests', 'comment')
+ project_state.remove_model("tests", "comment")
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "post")],
)
- self.assertNotIn(('tests', 'comment'), project_state.relations)
- project_state.remove_model('tests', 'post')
+ self.assertNotIn(("tests", "comment"), project_state.relations)
+ project_state.remove_model("tests", "post")
self.assertEqual(project_state.relations, {})
- project_state.remove_model('tests', 'user')
+ project_state.remove_model("tests", "user")
self.assertEqual(project_state.relations, {})
def test_rename_model(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
self.assertEqual(
- list(project_state.relations['tests', 'comment']),
- [('tests', 'comment')],
+ list(project_state.relations["tests", "comment"]),
+ [("tests", "comment")],
)
- related_field = project_state.relations['tests', 'user']['tests', 'comment']
- project_state.rename_model('tests', 'comment', 'opinion')
+ related_field = project_state.relations["tests", "user"]["tests", "comment"]
+ project_state.rename_model("tests", "comment", "opinion")
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'post'), ('tests', 'opinion')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "post"), ("tests", "opinion")],
)
self.assertEqual(
- list(project_state.relations['tests', 'opinion']),
- [('tests', 'opinion')],
+ list(project_state.relations["tests", "opinion"]),
+ [("tests", "opinion")],
)
- self.assertNotIn(('tests', 'comment'), project_state.relations)
+ self.assertNotIn(("tests", "comment"), project_state.relations)
self.assertEqual(
- project_state.relations['tests', 'user']['tests', 'opinion'],
+ project_state.relations["tests", "user"]["tests", "opinion"],
related_field,
)
- project_state.rename_model('tests', 'user', 'author')
+ project_state.rename_model("tests", "user", "author")
self.assertEqual(
- list(project_state.relations['tests', 'author']),
- [('tests', 'post'), ('tests', 'opinion')],
+ list(project_state.relations["tests", "author"]),
+ [("tests", "post"), ("tests", "opinion")],
)
- self.assertNotIn(('tests', 'user'), project_state.relations)
+ self.assertNotIn(("tests", "user"), project_state.relations)
def test_rename_model_no_relations(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
- related_field = project_state.relations['tests', 'user']['tests', 'post']
- self.assertNotIn(('tests', 'post'), project_state.relations)
+ related_field = project_state.relations["tests", "user"]["tests", "post"]
+ self.assertNotIn(("tests", "post"), project_state.relations)
# Rename a model without relations.
- project_state.rename_model('tests', 'post', 'blog')
+ project_state.rename_model("tests", "post", "blog")
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'blog')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "blog")],
)
- self.assertNotIn(('tests', 'blog'), project_state.relations)
+ self.assertNotIn(("tests", "blog"), project_state.relations)
self.assertEqual(
related_field,
- project_state.relations['tests', 'user']['tests', 'blog'],
+ project_state.relations["tests", "user"]["tests", "blog"],
)
def test_add_field(self):
project_state = self.get_base_project_state()
- self.assertNotIn(('tests', 'post'), project_state.relations)
+ self.assertNotIn(("tests", "post"), project_state.relations)
# Add a self-referential foreign key.
- new_field = models.ForeignKey('self', models.CASCADE)
+ new_field = models.ForeignKey("self", models.CASCADE)
project_state.add_field(
- 'tests', 'post', 'next_post', new_field, preserve_default=True,
+ "tests",
+ "post",
+ "next_post",
+ new_field,
+ preserve_default=True,
)
self.assertEqual(
- list(project_state.relations['tests', 'post']),
- [('tests', 'post')],
+ list(project_state.relations["tests", "post"]),
+ [("tests", "post")],
)
self.assertEqual(
- project_state.relations['tests', 'post']['tests', 'post'],
- {'next_post': new_field},
+ project_state.relations["tests", "post"]["tests", "post"],
+ {"next_post": new_field},
)
# Add a foreign key.
- new_field = models.ForeignKey('tests.post', models.CASCADE)
+ new_field = models.ForeignKey("tests.post", models.CASCADE)
project_state.add_field(
- 'tests', 'comment', 'post', new_field, preserve_default=True,
+ "tests",
+ "comment",
+ "post",
+ new_field,
+ preserve_default=True,
)
self.assertEqual(
- list(project_state.relations['tests', 'post']),
- [('tests', 'post'), ('tests', 'comment')],
+ list(project_state.relations["tests", "post"]),
+ [("tests", "post"), ("tests", "comment")],
)
self.assertEqual(
- project_state.relations['tests', 'post']['tests', 'comment'],
- {'post': new_field},
+ project_state.relations["tests", "post"]["tests", "comment"],
+ {"post": new_field},
)
def test_add_field_m2m_with_through(self):
project_state = self.get_base_project_state()
- project_state.add_model(ModelState(
- app_label='tests',
- name='Tag',
- fields=[('id', models.AutoField(primary_key=True))],
- ))
- project_state.add_model(ModelState(
- app_label='tests',
- name='PostTag',
- fields=[
- ('id', models.AutoField(primary_key=True)),
- ('post', models.ForeignKey('tests.post', models.CASCADE)),
- ('tag', models.ForeignKey('tests.tag', models.CASCADE)),
- ],
- ))
+ project_state.add_model(
+ ModelState(
+ app_label="tests",
+ name="Tag",
+ fields=[("id", models.AutoField(primary_key=True))],
+ )
+ )
+ project_state.add_model(
+ ModelState(
+ app_label="tests",
+ name="PostTag",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("post", models.ForeignKey("tests.post", models.CASCADE)),
+ ("tag", models.ForeignKey("tests.tag", models.CASCADE)),
+ ],
+ )
+ )
self.assertEqual(
- list(project_state.relations['tests', 'post']),
- [('tests', 'posttag')],
+ list(project_state.relations["tests", "post"]),
+ [("tests", "posttag")],
)
self.assertEqual(
- list(project_state.relations['tests', 'tag']),
- [('tests', 'posttag')],
+ list(project_state.relations["tests", "tag"]),
+ [("tests", "posttag")],
)
# Add a many-to-many field with the through model.
- new_field = models.ManyToManyField('tests.tag', through='tests.posttag')
+ new_field = models.ManyToManyField("tests.tag", through="tests.posttag")
project_state.add_field(
- 'tests', 'post', 'tags', new_field, preserve_default=True,
+ "tests",
+ "post",
+ "tags",
+ new_field,
+ preserve_default=True,
)
self.assertEqual(
- list(project_state.relations['tests', 'post']),
- [('tests', 'posttag')],
+ list(project_state.relations["tests", "post"]),
+ [("tests", "posttag")],
)
self.assertEqual(
- list(project_state.relations['tests', 'tag']),
- [('tests', 'posttag'), ('tests', 'post')],
+ list(project_state.relations["tests", "tag"]),
+ [("tests", "posttag"), ("tests", "post")],
)
self.assertEqual(
- project_state.relations['tests', 'tag']['tests', 'post'],
- {'tags': new_field},
+ project_state.relations["tests", "tag"]["tests", "post"],
+ {"tags": new_field},
)
def test_remove_field(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
# Remove a many-to-many field.
- project_state.remove_field('tests', 'post', 'authors')
+ project_state.remove_field("tests", "post", "authors")
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment")],
)
# Remove a foreign key.
- project_state.remove_field('tests', 'comment', 'user')
- self.assertEqual(project_state.relations['tests', 'user'], {})
+ project_state.remove_field("tests", "comment", "user")
+ self.assertEqual(project_state.relations["tests", "user"], {})
def test_remove_field_no_relations(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
# Remove a non-relation field.
- project_state.remove_field('tests', 'post', 'text')
+ project_state.remove_field("tests", "post", "text")
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
def test_rename_field(self):
project_state = self.get_base_project_state()
- field = project_state.models['tests', 'comment'].fields['user']
+ field = project_state.models["tests", "comment"].fields["user"]
self.assertEqual(
- project_state.relations['tests', 'user']['tests', 'comment'],
- {'user': field},
+ project_state.relations["tests", "user"]["tests", "comment"],
+ {"user": field},
)
- project_state.rename_field('tests', 'comment', 'user', 'author')
- renamed_field = project_state.models['tests', 'comment'].fields['author']
+ project_state.rename_field("tests", "comment", "user", "author")
+ renamed_field = project_state.models["tests", "comment"].fields["author"]
self.assertEqual(
- project_state.relations['tests', 'user']['tests', 'comment'],
- {'author': renamed_field},
+ project_state.relations["tests", "user"]["tests", "comment"],
+ {"author": renamed_field},
)
self.assertEqual(field, renamed_field)
def test_rename_field_no_relations(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
# Rename a non-relation field.
- project_state.rename_field('tests', 'post', 'text', 'description')
+ project_state.rename_field("tests", "post", "text", "description")
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
def test_alter_field(self):
project_state = self.get_base_project_state()
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
# Alter a foreign key to a non-relation field.
project_state.alter_field(
- 'tests', 'comment', 'user', models.IntegerField(), preserve_default=True,
+ "tests",
+ "comment",
+ "user",
+ models.IntegerField(),
+ preserve_default=True,
)
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "post")],
)
# Alter a non-relation field to a many-to-many field.
- m2m_field = models.ManyToManyField('tests.user')
+ m2m_field = models.ManyToManyField("tests.user")
project_state.alter_field(
- 'tests', 'comment', 'user', m2m_field, preserve_default=True,
+ "tests",
+ "comment",
+ "user",
+ m2m_field,
+ preserve_default=True,
)
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'post'), ('tests', 'comment')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "post"), ("tests", "comment")],
)
self.assertEqual(
- project_state.relations['tests', 'user']['tests', 'comment'],
- {'user': m2m_field},
+ project_state.relations["tests", "user"]["tests", "comment"],
+ {"user": m2m_field},
)
def test_alter_field_m2m_to_fk(self):
project_state = self.get_base_project_state()
- project_state.add_model(ModelState(
- app_label='tests_other',
- name='user_other',
- fields=[('id', models.AutoField(primary_key=True))],
- ))
+ project_state.add_model(
+ ModelState(
+ app_label="tests_other",
+ name="user_other",
+ fields=[("id", models.AutoField(primary_key=True))],
+ )
+ )
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
- self.assertNotIn(('tests_other', 'user_other'), project_state.relations)
+ self.assertNotIn(("tests_other", "user_other"), project_state.relations)
# Alter a many-to-many field to a foreign key.
- foreign_key = models.ForeignKey('tests_other.user_other', models.CASCADE)
+ foreign_key = models.ForeignKey("tests_other.user_other", models.CASCADE)
project_state.alter_field(
- 'tests', 'post', 'authors', foreign_key, preserve_default=True,
+ "tests",
+ "post",
+ "authors",
+ foreign_key,
+ preserve_default=True,
)
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment")],
)
self.assertEqual(
- list(project_state.relations['tests_other', 'user_other']),
- [('tests', 'post')],
+ list(project_state.relations["tests_other", "user_other"]),
+ [("tests", "post")],
)
self.assertEqual(
- project_state.relations['tests_other', 'user_other']['tests', 'post'],
- {'authors': foreign_key},
+ project_state.relations["tests_other", "user_other"]["tests", "post"],
+ {"authors": foreign_key},
)
def test_many_relations_to_same_model(self):
project_state = self.get_base_project_state()
- new_field = models.ForeignKey('tests.user', models.CASCADE)
+ new_field = models.ForeignKey("tests.user", models.CASCADE)
project_state.add_field(
- 'tests', 'comment', 'reviewer', new_field, preserve_default=True,
+ "tests",
+ "comment",
+ "reviewer",
+ new_field,
+ preserve_default=True,
)
self.assertEqual(
- list(project_state.relations['tests', 'user']),
- [('tests', 'comment'), ('tests', 'post')],
+ list(project_state.relations["tests", "user"]),
+ [("tests", "comment"), ("tests", "post")],
)
- comment_rels = project_state.relations['tests', 'user']['tests', 'comment']
+ comment_rels = project_state.relations["tests", "user"]["tests", "comment"]
# Two foreign keys to the same model.
self.assertEqual(len(comment_rels), 2)
- self.assertEqual(comment_rels['reviewer'], new_field)
+ self.assertEqual(comment_rels["reviewer"], new_field)
# Rename the second foreign key.
- project_state.rename_field('tests', 'comment', 'reviewer', 'supervisor')
+ project_state.rename_field("tests", "comment", "reviewer", "supervisor")
self.assertEqual(len(comment_rels), 2)
- self.assertEqual(comment_rels['supervisor'], new_field)
+ self.assertEqual(comment_rels["supervisor"], new_field)
# Remove the first foreign key.
- project_state.remove_field('tests', 'comment', 'user')
- self.assertEqual(comment_rels, {'supervisor': new_field})
+ project_state.remove_field("tests", "comment", "user")
+ self.assertEqual(comment_rels, {"supervisor": new_field})
class ModelStateTests(SimpleTestCase):
@@ -1459,37 +1638,39 @@ class ModelStateTests(SimpleTestCase):
def test_bound_field_sanity_check(self):
field = models.CharField(max_length=1)
field.model = models.Model
- with self.assertRaisesMessage(ValueError, 'ModelState.fields cannot be bound to a model - "field" is.'):
- ModelState('app', 'Model', [('field', field)])
+ with self.assertRaisesMessage(
+ ValueError, 'ModelState.fields cannot be bound to a model - "field" is.'
+ ):
+ ModelState("app", "Model", [("field", field)])
def test_sanity_check_to(self):
field = models.ForeignKey(UnicodeModel, models.CASCADE)
with self.assertRaisesMessage(
ValueError,
'ModelState.fields cannot refer to a model class - "field.to" does. '
- 'Use a string reference instead.'
+ "Use a string reference instead.",
):
- ModelState('app', 'Model', [('field', field)])
+ ModelState("app", "Model", [("field", field)])
def test_sanity_check_through(self):
- field = models.ManyToManyField('UnicodeModel')
+ field = models.ManyToManyField("UnicodeModel")
field.remote_field.through = UnicodeModel
with self.assertRaisesMessage(
ValueError,
'ModelState.fields cannot refer to a model class - "field.through" does. '
- 'Use a string reference instead.'
+ "Use a string reference instead.",
):
- ModelState('app', 'Model', [('field', field)])
+ ModelState("app", "Model", [("field", field)])
def test_sanity_index_name(self):
field = models.IntegerField()
- options = {'indexes': [models.Index(fields=['field'])]}
+ options = {"indexes": [models.Index(fields=["field"])]}
msg = (
"Indexes passed to ModelState require a name attribute. <Index: "
"fields=['field']> doesn't have one."
)
with self.assertRaisesMessage(ValueError, msg):
- ModelState('app', 'Model', [('field', field)], options=options)
+ ModelState("app", "Model", [("field", field)], options=options)
def test_fields_immutability(self):
"""
@@ -1497,48 +1678,52 @@ class ModelStateTests(SimpleTestCase):
"""
apps = Apps()
field = models.CharField(max_length=1)
- state = ModelState('app', 'Model', [('name', field)])
+ state = ModelState("app", "Model", [("name", field)])
Model = state.render(apps)
- self.assertNotEqual(Model._meta.get_field('name'), field)
+ self.assertNotEqual(Model._meta.get_field("name"), field)
def test_repr(self):
field = models.CharField(max_length=1)
- state = ModelState('app', 'Model', [('name', field)], bases=['app.A', 'app.B', 'app.C'])
+ state = ModelState(
+ "app", "Model", [("name", field)], bases=["app.A", "app.B", "app.C"]
+ )
self.assertEqual(repr(state), "<ModelState: 'app.Model'>")
project_state = ProjectState()
project_state.add_model(state)
- with self.assertRaisesMessage(InvalidBasesError, "Cannot resolve bases for [<ModelState: 'app.Model'>]"):
+ with self.assertRaisesMessage(
+ InvalidBasesError, "Cannot resolve bases for [<ModelState: 'app.Model'>]"
+ ):
project_state.apps
def test_fields_ordering_equality(self):
state = ModelState(
- 'migrations',
- 'Tag',
+ "migrations",
+ "Tag",
[
- ('id', models.AutoField(primary_key=True)),
- ('name', models.CharField(max_length=100)),
- ('hidden', models.BooleanField()),
+ ("id", models.AutoField(primary_key=True)),
+ ("name", models.CharField(max_length=100)),
+ ("hidden", models.BooleanField()),
],
)
reordered_state = ModelState(
- 'migrations',
- 'Tag',
+ "migrations",
+ "Tag",
[
- ('id', models.AutoField(primary_key=True)),
+ ("id", models.AutoField(primary_key=True)),
# Purposely re-ordered.
- ('hidden', models.BooleanField()),
- ('name', models.CharField(max_length=100)),
+ ("hidden", models.BooleanField()),
+ ("name", models.CharField(max_length=100)),
],
)
self.assertEqual(state, reordered_state)
- @override_settings(TEST_SWAPPABLE_MODEL='migrations.SomeFakeModel')
+ @override_settings(TEST_SWAPPABLE_MODEL="migrations.SomeFakeModel")
def test_create_swappable(self):
"""
Tests making a ProjectState from an Apps with a swappable model
"""
- new_apps = Apps(['migrations'])
+ new_apps = Apps(["migrations"])
class Author(models.Model):
name = models.CharField(max_length=255)
@@ -1546,34 +1731,37 @@ class ModelStateTests(SimpleTestCase):
age = models.IntegerField(blank=True, null=True)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
- swappable = 'TEST_SWAPPABLE_MODEL'
+ swappable = "TEST_SWAPPABLE_MODEL"
author_state = ModelState.from_model(Author)
- self.assertEqual(author_state.app_label, 'migrations')
- self.assertEqual(author_state.name, 'Author')
- self.assertEqual(list(author_state.fields), ['id', 'name', 'bio', 'age'])
- self.assertEqual(author_state.fields['name'].max_length, 255)
- self.assertIs(author_state.fields['bio'].null, False)
- self.assertIs(author_state.fields['age'].null, True)
- self.assertEqual(author_state.options, {'swappable': 'TEST_SWAPPABLE_MODEL', 'indexes': [], "constraints": []})
+ self.assertEqual(author_state.app_label, "migrations")
+ self.assertEqual(author_state.name, "Author")
+ self.assertEqual(list(author_state.fields), ["id", "name", "bio", "age"])
+ self.assertEqual(author_state.fields["name"].max_length, 255)
+ self.assertIs(author_state.fields["bio"].null, False)
+ self.assertIs(author_state.fields["age"].null, True)
+ self.assertEqual(
+ author_state.options,
+ {"swappable": "TEST_SWAPPABLE_MODEL", "indexes": [], "constraints": []},
+ )
self.assertEqual(author_state.bases, (models.Model,))
self.assertEqual(author_state.managers, [])
- @override_settings(TEST_SWAPPABLE_MODEL='migrations.SomeFakeModel')
+ @override_settings(TEST_SWAPPABLE_MODEL="migrations.SomeFakeModel")
def test_create_swappable_from_abstract(self):
"""
A swappable model inheriting from a hierarchy:
concrete -> abstract -> concrete.
"""
- new_apps = Apps(['migrations'])
+ new_apps = Apps(["migrations"])
class SearchableLocation(models.Model):
keywords = models.CharField(max_length=256)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
class Station(SearchableLocation):
@@ -1587,72 +1775,77 @@ class ModelStateTests(SimpleTestCase):
inbound = models.BooleanField(default=False)
class Meta(Station.Meta):
- app_label = 'migrations'
+ app_label = "migrations"
apps = new_apps
- swappable = 'TEST_SWAPPABLE_MODEL'
+ swappable = "TEST_SWAPPABLE_MODEL"
station_state = ModelState.from_model(BusStation)
- self.assertEqual(station_state.app_label, 'migrations')
- self.assertEqual(station_state.name, 'BusStation')
+ self.assertEqual(station_state.app_label, "migrations")
+ self.assertEqual(station_state.name, "BusStation")
self.assertEqual(
list(station_state.fields),
- ['searchablelocation_ptr', 'name', 'bus_routes', 'inbound']
+ ["searchablelocation_ptr", "name", "bus_routes", "inbound"],
)
- self.assertEqual(station_state.fields['name'].max_length, 128)
- self.assertIs(station_state.fields['bus_routes'].null, False)
+ self.assertEqual(station_state.fields["name"].max_length, 128)
+ self.assertIs(station_state.fields["bus_routes"].null, False)
self.assertEqual(
station_state.options,
- {'abstract': False, 'swappable': 'TEST_SWAPPABLE_MODEL', 'indexes': [], 'constraints': []}
+ {
+ "abstract": False,
+ "swappable": "TEST_SWAPPABLE_MODEL",
+ "indexes": [],
+ "constraints": [],
+ },
)
- self.assertEqual(station_state.bases, ('migrations.searchablelocation',))
+ self.assertEqual(station_state.bases, ("migrations.searchablelocation",))
self.assertEqual(station_state.managers, [])
- @override_settings(TEST_SWAPPABLE_MODEL='migrations.SomeFakeModel')
+ @override_settings(TEST_SWAPPABLE_MODEL="migrations.SomeFakeModel")
def test_custom_manager_swappable(self):
"""
Tests making a ProjectState from unused models with custom managers
"""
- new_apps = Apps(['migrations'])
+ new_apps = Apps(["migrations"])
class Food(models.Model):
- food_mgr = FoodManager('a', 'b')
+ food_mgr = FoodManager("a", "b")
food_qs = FoodQuerySet.as_manager()
- food_no_mgr = NoMigrationFoodManager('x', 'y')
+ food_no_mgr = NoMigrationFoodManager("x", "y")
class Meta:
app_label = "migrations"
apps = new_apps
- swappable = 'TEST_SWAPPABLE_MODEL'
+ swappable = "TEST_SWAPPABLE_MODEL"
food_state = ModelState.from_model(Food)
# The default manager is used in migrations
- self.assertEqual([name for name, mgr in food_state.managers], ['food_mgr'])
- self.assertEqual(food_state.managers[0][1].args, ('a', 'b', 1, 2))
+ self.assertEqual([name for name, mgr in food_state.managers], ["food_mgr"])
+ self.assertEqual(food_state.managers[0][1].args, ("a", "b", 1, 2))
- @isolate_apps('migrations', 'django.contrib.contenttypes')
+ @isolate_apps("migrations", "django.contrib.contenttypes")
def test_order_with_respect_to_private_field(self):
class PrivateFieldModel(models.Model):
- content_type = models.ForeignKey('contenttypes.ContentType', models.CASCADE)
+ content_type = models.ForeignKey("contenttypes.ContentType", models.CASCADE)
object_id = models.PositiveIntegerField()
private = GenericForeignKey()
class Meta:
- order_with_respect_to = 'private'
+ order_with_respect_to = "private"
state = ModelState.from_model(PrivateFieldModel)
- self.assertNotIn('order_with_respect_to', state.options)
+ self.assertNotIn("order_with_respect_to", state.options)
- @isolate_apps('migrations')
+ @isolate_apps("migrations")
def test_abstract_model_children_inherit_indexes(self):
class Abstract(models.Model):
name = models.CharField(max_length=50)
class Meta:
- app_label = 'migrations'
+ app_label = "migrations"
abstract = True
- indexes = [models.Index(fields=['name'])]
+ indexes = [models.Index(fields=["name"])]
class Child1(Abstract):
pass
@@ -1662,66 +1855,69 @@ class ModelStateTests(SimpleTestCase):
child1_state = ModelState.from_model(Child1)
child2_state = ModelState.from_model(Child2)
- index_names = [index.name for index in child1_state.options['indexes']]
- self.assertEqual(index_names, ['migrations__name_b0afd7_idx'])
- index_names = [index.name for index in child2_state.options['indexes']]
- self.assertEqual(index_names, ['migrations__name_016466_idx'])
+ index_names = [index.name for index in child1_state.options["indexes"]]
+ self.assertEqual(index_names, ["migrations__name_b0afd7_idx"])
+ index_names = [index.name for index in child2_state.options["indexes"]]
+ self.assertEqual(index_names, ["migrations__name_016466_idx"])
# Modifying the state doesn't modify the index on the model.
- child1_state.options['indexes'][0].name = 'bar'
- self.assertEqual(Child1._meta.indexes[0].name, 'migrations__name_b0afd7_idx')
+ child1_state.options["indexes"][0].name = "bar"
+ self.assertEqual(Child1._meta.indexes[0].name, "migrations__name_b0afd7_idx")
- @isolate_apps('migrations')
+ @isolate_apps("migrations")
def test_explicit_index_name(self):
class TestModel(models.Model):
name = models.CharField(max_length=50)
class Meta:
- app_label = 'migrations'
- indexes = [models.Index(fields=['name'], name='foo_idx')]
+ app_label = "migrations"
+ indexes = [models.Index(fields=["name"], name="foo_idx")]
model_state = ModelState.from_model(TestModel)
- index_names = [index.name for index in model_state.options['indexes']]
- self.assertEqual(index_names, ['foo_idx'])
+ index_names = [index.name for index in model_state.options["indexes"]]
+ self.assertEqual(index_names, ["foo_idx"])
- @isolate_apps('migrations')
+ @isolate_apps("migrations")
def test_from_model_constraints(self):
class ModelWithConstraints(models.Model):
size = models.IntegerField()
class Meta:
- constraints = [models.CheckConstraint(check=models.Q(size__gt=1), name='size_gt_1')]
+ constraints = [
+ models.CheckConstraint(check=models.Q(size__gt=1), name="size_gt_1")
+ ]
state = ModelState.from_model(ModelWithConstraints)
model_constraints = ModelWithConstraints._meta.constraints
- state_constraints = state.options['constraints']
+ state_constraints = state.options["constraints"]
self.assertEqual(model_constraints, state_constraints)
self.assertIsNot(model_constraints, state_constraints)
self.assertIsNot(model_constraints[0], state_constraints[0])
class RelatedModelsTests(SimpleTestCase):
-
def setUp(self):
- self.apps = Apps(['migrations.related_models_app'])
+ self.apps = Apps(["migrations.related_models_app"])
- def create_model(self, name, foreign_keys=[], bases=(), abstract=False, proxy=False):
- test_name = 'related_models_app'
+ def create_model(
+ self, name, foreign_keys=[], bases=(), abstract=False, proxy=False
+ ):
+ test_name = "related_models_app"
assert not (abstract and proxy)
meta_contents = {
- 'abstract': abstract,
- 'app_label': test_name,
- 'apps': self.apps,
- 'proxy': proxy,
+ "abstract": abstract,
+ "app_label": test_name,
+ "apps": self.apps,
+ "proxy": proxy,
}
meta = type("Meta", (), meta_contents)
if not bases:
bases = (models.Model,)
body = {
- 'Meta': meta,
- '__module__': "__fake__",
+ "Meta": meta,
+ "__module__": "__fake__",
}
- fname_base = fname = '%s_%%d' % name.lower()
+ fname_base = fname = "%s_%%d" % name.lower()
for i, fk in enumerate(foreign_keys, 1):
fname = fname_base % i
body[fname] = fk
@@ -1740,13 +1936,17 @@ class RelatedModelsTests(SimpleTestCase):
self.assertRelated(B, [])
def test_direct_fk(self):
- A = self.create_model("A", foreign_keys=[models.ForeignKey('B', models.CASCADE)])
+ A = self.create_model(
+ "A", foreign_keys=[models.ForeignKey("B", models.CASCADE)]
+ )
B = self.create_model("B")
self.assertRelated(A, [B])
self.assertRelated(B, [A])
def test_direct_hidden_fk(self):
- A = self.create_model("A", foreign_keys=[models.ForeignKey('B', models.CASCADE, related_name='+')])
+ A = self.create_model(
+ "A", foreign_keys=[models.ForeignKey("B", models.CASCADE, related_name="+")]
+ )
B = self.create_model("B")
self.assertRelated(A, [B])
self.assertRelated(B, [A])
@@ -1755,30 +1955,46 @@ class RelatedModelsTests(SimpleTestCase):
A = self.create_model("A")
B = self.create_model("B", bases=(A,), proxy=True)
C = self.create_model("C", bases=(B,), proxy=True)
- D = self.create_model("D", foreign_keys=[models.ForeignKey('C', models.CASCADE)])
+ D = self.create_model(
+ "D", foreign_keys=[models.ForeignKey("C", models.CASCADE)]
+ )
self.assertRelated(A, [B, C, D])
self.assertRelated(B, [A, C, D])
self.assertRelated(C, [A, B, D])
self.assertRelated(D, [A, B, C])
def test_nested_fk(self):
- A = self.create_model("A", foreign_keys=[models.ForeignKey('B', models.CASCADE)])
- B = self.create_model("B", foreign_keys=[models.ForeignKey('C', models.CASCADE)])
+ A = self.create_model(
+ "A", foreign_keys=[models.ForeignKey("B", models.CASCADE)]
+ )
+ B = self.create_model(
+ "B", foreign_keys=[models.ForeignKey("C", models.CASCADE)]
+ )
C = self.create_model("C")
self.assertRelated(A, [B, C])
self.assertRelated(B, [A, C])
self.assertRelated(C, [A, B])
def test_two_sided(self):
- A = self.create_model("A", foreign_keys=[models.ForeignKey('B', models.CASCADE)])
- B = self.create_model("B", foreign_keys=[models.ForeignKey('A', models.CASCADE)])
+ A = self.create_model(
+ "A", foreign_keys=[models.ForeignKey("B", models.CASCADE)]
+ )
+ B = self.create_model(
+ "B", foreign_keys=[models.ForeignKey("A", models.CASCADE)]
+ )
self.assertRelated(A, [B])
self.assertRelated(B, [A])
def test_circle(self):
- A = self.create_model("A", foreign_keys=[models.ForeignKey('B', models.CASCADE)])
- B = self.create_model("B", foreign_keys=[models.ForeignKey('C', models.CASCADE)])
- C = self.create_model("C", foreign_keys=[models.ForeignKey('A', models.CASCADE)])
+ A = self.create_model(
+ "A", foreign_keys=[models.ForeignKey("B", models.CASCADE)]
+ )
+ B = self.create_model(
+ "B", foreign_keys=[models.ForeignKey("C", models.CASCADE)]
+ )
+ C = self.create_model(
+ "C", foreign_keys=[models.ForeignKey("A", models.CASCADE)]
+ )
self.assertRelated(A, [B, C])
self.assertRelated(B, [A, C])
self.assertRelated(C, [A, B])
@@ -1800,7 +2016,13 @@ class RelatedModelsTests(SimpleTestCase):
def test_multiple_bases(self):
A = self.create_model("A")
B = self.create_model("B")
- C = self.create_model("C", bases=(A, B,))
+ C = self.create_model(
+ "C",
+ bases=(
+ A,
+ B,
+ ),
+ )
self.assertRelated(A, [B, C])
self.assertRelated(B, [A, C])
self.assertRelated(C, [A, B])
@@ -1808,10 +2030,22 @@ class RelatedModelsTests(SimpleTestCase):
def test_multiple_nested_bases(self):
A = self.create_model("A")
B = self.create_model("B")
- C = self.create_model("C", bases=(A, B,))
+ C = self.create_model(
+ "C",
+ bases=(
+ A,
+ B,
+ ),
+ )
D = self.create_model("D")
E = self.create_model("E", bases=(D,))
- F = self.create_model("F", bases=(C, E,))
+ F = self.create_model(
+ "F",
+ bases=(
+ C,
+ E,
+ ),
+ )
Y = self.create_model("Y")
Z = self.create_model("Z", bases=(Y,))
self.assertRelated(A, [B, C, D, E, F])
@@ -1824,7 +2058,9 @@ class RelatedModelsTests(SimpleTestCase):
self.assertRelated(Z, [Y])
def test_base_to_base_fk(self):
- A = self.create_model("A", foreign_keys=[models.ForeignKey('Y', models.CASCADE)])
+ A = self.create_model(
+ "A", foreign_keys=[models.ForeignKey("Y", models.CASCADE)]
+ )
B = self.create_model("B", bases=(A,))
Y = self.create_model("Y")
Z = self.create_model("Z", bases=(Y,))
@@ -1834,7 +2070,9 @@ class RelatedModelsTests(SimpleTestCase):
self.assertRelated(Z, [A, B, Y])
def test_base_to_subclass_fk(self):
- A = self.create_model("A", foreign_keys=[models.ForeignKey('Z', models.CASCADE)])
+ A = self.create_model(
+ "A", foreign_keys=[models.ForeignKey("Z", models.CASCADE)]
+ )
B = self.create_model("B", bases=(A,))
Y = self.create_model("Y")
Z = self.create_model("Z", bases=(Y,))
@@ -1844,70 +2082,97 @@ class RelatedModelsTests(SimpleTestCase):
self.assertRelated(Z, [A, B, Y])
def test_direct_m2m(self):
- A = self.create_model("A", foreign_keys=[models.ManyToManyField('B')])
+ A = self.create_model("A", foreign_keys=[models.ManyToManyField("B")])
B = self.create_model("B")
self.assertRelated(A, [A.a_1.rel.through, B])
self.assertRelated(B, [A, A.a_1.rel.through])
def test_direct_m2m_self(self):
- A = self.create_model("A", foreign_keys=[models.ManyToManyField('A')])
+ A = self.create_model("A", foreign_keys=[models.ManyToManyField("A")])
self.assertRelated(A, [A.a_1.rel.through])
def test_intermediate_m2m_self(self):
- A = self.create_model("A", foreign_keys=[models.ManyToManyField('A', through='T')])
- T = self.create_model("T", foreign_keys=[
- models.ForeignKey('A', models.CASCADE),
- models.ForeignKey('A', models.CASCADE),
- ])
+ A = self.create_model(
+ "A", foreign_keys=[models.ManyToManyField("A", through="T")]
+ )
+ T = self.create_model(
+ "T",
+ foreign_keys=[
+ models.ForeignKey("A", models.CASCADE),
+ models.ForeignKey("A", models.CASCADE),
+ ],
+ )
self.assertRelated(A, [T])
self.assertRelated(T, [A])
def test_intermediate_m2m(self):
- A = self.create_model("A", foreign_keys=[models.ManyToManyField('B', through='T')])
+ A = self.create_model(
+ "A", foreign_keys=[models.ManyToManyField("B", through="T")]
+ )
B = self.create_model("B")
- T = self.create_model("T", foreign_keys=[
- models.ForeignKey('A', models.CASCADE),
- models.ForeignKey('B', models.CASCADE),
- ])
+ T = self.create_model(
+ "T",
+ foreign_keys=[
+ models.ForeignKey("A", models.CASCADE),
+ models.ForeignKey("B", models.CASCADE),
+ ],
+ )
self.assertRelated(A, [B, T])
self.assertRelated(B, [A, T])
self.assertRelated(T, [A, B])
def test_intermediate_m2m_extern_fk(self):
- A = self.create_model("A", foreign_keys=[models.ManyToManyField('B', through='T')])
+ A = self.create_model(
+ "A", foreign_keys=[models.ManyToManyField("B", through="T")]
+ )
B = self.create_model("B")
Z = self.create_model("Z")
- T = self.create_model("T", foreign_keys=[
- models.ForeignKey('A', models.CASCADE),
- models.ForeignKey('B', models.CASCADE),
- models.ForeignKey('Z', models.CASCADE),
- ])
+ T = self.create_model(
+ "T",
+ foreign_keys=[
+ models.ForeignKey("A", models.CASCADE),
+ models.ForeignKey("B", models.CASCADE),
+ models.ForeignKey("Z", models.CASCADE),
+ ],
+ )
self.assertRelated(A, [B, T, Z])
self.assertRelated(B, [A, T, Z])
self.assertRelated(T, [A, B, Z])
self.assertRelated(Z, [A, B, T])
def test_intermediate_m2m_base(self):
- A = self.create_model("A", foreign_keys=[models.ManyToManyField('B', through='T')])
+ A = self.create_model(
+ "A", foreign_keys=[models.ManyToManyField("B", through="T")]
+ )
B = self.create_model("B")
S = self.create_model("S")
- T = self.create_model("T", foreign_keys=[
- models.ForeignKey('A', models.CASCADE),
- models.ForeignKey('B', models.CASCADE),
- ], bases=(S,))
+ T = self.create_model(
+ "T",
+ foreign_keys=[
+ models.ForeignKey("A", models.CASCADE),
+ models.ForeignKey("B", models.CASCADE),
+ ],
+ bases=(S,),
+ )
self.assertRelated(A, [B, S, T])
self.assertRelated(B, [A, S, T])
self.assertRelated(S, [A, B, T])
self.assertRelated(T, [A, B, S])
def test_generic_fk(self):
- A = self.create_model("A", foreign_keys=[
- models.ForeignKey('B', models.CASCADE),
- GenericForeignKey(),
- ])
- B = self.create_model("B", foreign_keys=[
- models.ForeignKey('C', models.CASCADE),
- ])
+ A = self.create_model(
+ "A",
+ foreign_keys=[
+ models.ForeignKey("B", models.CASCADE),
+ GenericForeignKey(),
+ ],
+ )
+ B = self.create_model(
+ "B",
+ foreign_keys=[
+ models.ForeignKey("C", models.CASCADE),
+ ],
+ )
self.assertRelated(A, [B])
self.assertRelated(B, [A])
diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py
index f55c48a0d4..0b45247bc5 100644
--- a/tests/migrations/test_writer.py
+++ b/tests/migrations/test_writer.py
@@ -40,37 +40,38 @@ from .models import FoodManager, FoodQuerySet
class DeconstructibleInstances:
def deconstruct(self):
- return ('DeconstructibleInstances', [], {})
+ return ("DeconstructibleInstances", [], {})
class Money(decimal.Decimal):
def deconstruct(self):
return (
- '%s.%s' % (self.__class__.__module__, self.__class__.__name__),
+ "%s.%s" % (self.__class__.__module__, self.__class__.__name__),
[str(self)],
- {}
+ {},
)
class TestModel1:
def upload_to(self):
- return '/somewhere/dynamic/'
+ return "/somewhere/dynamic/"
+
thing = models.FileField(upload_to=upload_to)
class TextEnum(enum.Enum):
- A = 'a-value'
- B = 'value-b'
+ A = "a-value"
+ B = "value-b"
class TextTranslatedEnum(enum.Enum):
- A = _('a-value')
- B = _('value-b')
+ A = _("a-value")
+ B = _("value-b")
class BinaryEnum(enum.Enum):
- A = b'a-value'
- B = b'value-b'
+ A = b"a-value"
+ B = b"value-b"
class IntEnum(enum.IntEnum):
@@ -79,97 +80,100 @@ class IntEnum(enum.IntEnum):
class OperationWriterTests(SimpleTestCase):
-
def test_empty_signature(self):
operation = custom_migration_operations.operations.TestOperation()
buff, imports = OperationWriter(operation, indentation=0).serialize()
- self.assertEqual(imports, {'import custom_migration_operations.operations'})
+ self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
- 'custom_migration_operations.operations.TestOperation(\n),',
+ "custom_migration_operations.operations.TestOperation(\n),",
)
def test_args_signature(self):
operation = custom_migration_operations.operations.ArgsOperation(1, 2)
buff, imports = OperationWriter(operation, indentation=0).serialize()
- self.assertEqual(imports, {'import custom_migration_operations.operations'})
+ self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
- 'custom_migration_operations.operations.ArgsOperation(\n'
- ' arg1=1,\n'
- ' arg2=2,\n'
- '),'
+ "custom_migration_operations.operations.ArgsOperation(\n"
+ " arg1=1,\n"
+ " arg2=2,\n"
+ "),",
)
def test_kwargs_signature(self):
operation = custom_migration_operations.operations.KwargsOperation(kwarg1=1)
buff, imports = OperationWriter(operation, indentation=0).serialize()
- self.assertEqual(imports, {'import custom_migration_operations.operations'})
+ self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
- 'custom_migration_operations.operations.KwargsOperation(\n'
- ' kwarg1=1,\n'
- '),'
+ "custom_migration_operations.operations.KwargsOperation(\n"
+ " kwarg1=1,\n"
+ "),",
)
def test_args_kwargs_signature(self):
- operation = custom_migration_operations.operations.ArgsKwargsOperation(1, 2, kwarg2=4)
+ operation = custom_migration_operations.operations.ArgsKwargsOperation(
+ 1, 2, kwarg2=4
+ )
buff, imports = OperationWriter(operation, indentation=0).serialize()
- self.assertEqual(imports, {'import custom_migration_operations.operations'})
+ self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
- 'custom_migration_operations.operations.ArgsKwargsOperation(\n'
- ' arg1=1,\n'
- ' arg2=2,\n'
- ' kwarg2=4,\n'
- '),'
+ "custom_migration_operations.operations.ArgsKwargsOperation(\n"
+ " arg1=1,\n"
+ " arg2=2,\n"
+ " kwarg2=4,\n"
+ "),",
)
def test_nested_args_signature(self):
operation = custom_migration_operations.operations.ArgsOperation(
custom_migration_operations.operations.ArgsOperation(1, 2),
- custom_migration_operations.operations.KwargsOperation(kwarg1=3, kwarg2=4)
+ custom_migration_operations.operations.KwargsOperation(kwarg1=3, kwarg2=4),
)
buff, imports = OperationWriter(operation, indentation=0).serialize()
- self.assertEqual(imports, {'import custom_migration_operations.operations'})
+ self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
- 'custom_migration_operations.operations.ArgsOperation(\n'
- ' arg1=custom_migration_operations.operations.ArgsOperation(\n'
- ' arg1=1,\n'
- ' arg2=2,\n'
- ' ),\n'
- ' arg2=custom_migration_operations.operations.KwargsOperation(\n'
- ' kwarg1=3,\n'
- ' kwarg2=4,\n'
- ' ),\n'
- '),'
+ "custom_migration_operations.operations.ArgsOperation(\n"
+ " arg1=custom_migration_operations.operations.ArgsOperation(\n"
+ " arg1=1,\n"
+ " arg2=2,\n"
+ " ),\n"
+ " arg2=custom_migration_operations.operations.KwargsOperation(\n"
+ " kwarg1=3,\n"
+ " kwarg2=4,\n"
+ " ),\n"
+ "),",
)
def test_multiline_args_signature(self):
- operation = custom_migration_operations.operations.ArgsOperation("test\n arg1", "test\narg2")
+ operation = custom_migration_operations.operations.ArgsOperation(
+ "test\n arg1", "test\narg2"
+ )
buff, imports = OperationWriter(operation, indentation=0).serialize()
- self.assertEqual(imports, {'import custom_migration_operations.operations'})
+ self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
"custom_migration_operations.operations.ArgsOperation(\n"
" arg1='test\\n arg1',\n"
" arg2='test\\narg2',\n"
- "),"
+ "),",
)
def test_expand_args_signature(self):
operation = custom_migration_operations.operations.ExpandArgsOperation([1, 2])
buff, imports = OperationWriter(operation, indentation=0).serialize()
- self.assertEqual(imports, {'import custom_migration_operations.operations'})
+ self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
- 'custom_migration_operations.operations.ExpandArgsOperation(\n'
- ' arg=[\n'
- ' 1,\n'
- ' 2,\n'
- ' ],\n'
- '),'
+ "custom_migration_operations.operations.ExpandArgsOperation(\n"
+ " arg=[\n"
+ " 1,\n"
+ " 2,\n"
+ " ],\n"
+ "),",
)
def test_nested_operation_expand_args_signature(self):
@@ -182,17 +186,17 @@ class OperationWriterTests(SimpleTestCase):
]
)
buff, imports = OperationWriter(operation, indentation=0).serialize()
- self.assertEqual(imports, {'import custom_migration_operations.operations'})
+ self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
- 'custom_migration_operations.operations.ExpandArgsOperation(\n'
- ' arg=[\n'
- ' custom_migration_operations.operations.KwargsOperation(\n'
- ' kwarg1=1,\n'
- ' kwarg2=2,\n'
- ' ),\n'
- ' ],\n'
- '),'
+ "custom_migration_operations.operations.ExpandArgsOperation(\n"
+ " arg=[\n"
+ " custom_migration_operations.operations.KwargsOperation(\n"
+ " kwarg1=1,\n"
+ " kwarg2=2,\n"
+ " ),\n"
+ " ],\n"
+ "),",
)
@@ -200,13 +204,14 @@ class WriterTests(SimpleTestCase):
"""
Tests the migration writer (makes migration files from Migration instances)
"""
+
class NestedEnum(enum.IntEnum):
A = 1
B = 2
class NestedChoices(models.TextChoices):
- X = 'X', 'X value'
- Y = 'Y', 'Y value'
+ X = "X", "X value"
+ Y = "Y", "Y value"
def safe_exec(self, string, value=None):
d = {}
@@ -214,14 +219,18 @@ class WriterTests(SimpleTestCase):
exec(string, globals(), d)
except Exception as e:
if value:
- self.fail("Could not exec %r (from value %r): %s" % (string.strip(), value, e))
+ self.fail(
+ "Could not exec %r (from value %r): %s" % (string.strip(), value, e)
+ )
else:
self.fail("Could not exec %r: %s" % (string.strip(), e))
return d
def serialize_round_trip(self, value):
string, imports = MigrationWriter.serialize(value)
- return self.safe_exec("%s\ntest_value_result = %s" % ("\n".join(imports), string), value)['test_value_result']
+ return self.safe_exec(
+ "%s\ntest_value_result = %s" % ("\n".join(imports), string), value
+ )["test_value_result"]
def assertSerializedEqual(self, value):
self.assertEqual(self.serialize_round_trip(value), value)
@@ -243,16 +252,15 @@ class WriterTests(SimpleTestCase):
self.assertTrue(math.isinf(self.serialize_round_trip(float("-inf"))))
self.assertTrue(math.isnan(self.serialize_round_trip(float("nan"))))
- self.assertSerializedEqual(decimal.Decimal('1.3'))
+ self.assertSerializedEqual(decimal.Decimal("1.3"))
self.assertSerializedResultEqual(
- decimal.Decimal('1.3'),
- ("Decimal('1.3')", {'from decimal import Decimal'})
+ decimal.Decimal("1.3"), ("Decimal('1.3')", {"from decimal import Decimal"})
)
- self.assertSerializedEqual(Money('1.3'))
+ self.assertSerializedEqual(Money("1.3"))
self.assertSerializedResultEqual(
- Money('1.3'),
- ("migrations.test_writer.Money('1.3')", {'import migrations.test_writer'})
+ Money("1.3"),
+ ("migrations.test_writer.Money('1.3')", {"import migrations.test_writer"}),
)
def test_serialize_constants(self):
@@ -281,54 +289,62 @@ class WriterTests(SimpleTestCase):
self.assertSerializedEqual(["a", 2, True, None])
self.assertSerializedEqual({2, 3, "eighty"})
self.assertSerializedEqual({"lalalala": ["yeah", "no", "maybe"]})
- self.assertSerializedEqual(_('Hello'))
+ self.assertSerializedEqual(_("Hello"))
def test_serialize_builtin_types(self):
self.assertSerializedEqual([list, tuple, dict, set, frozenset])
self.assertSerializedResultEqual(
[list, tuple, dict, set, frozenset],
- ("[list, tuple, dict, set, frozenset]", set())
+ ("[list, tuple, dict, set, frozenset]", set()),
)
def test_serialize_lazy_objects(self):
- pattern = re.compile(r'^foo$')
+ pattern = re.compile(r"^foo$")
lazy_pattern = SimpleLazyObject(lambda: pattern)
self.assertEqual(self.serialize_round_trip(lazy_pattern), pattern)
def test_serialize_enums(self):
self.assertSerializedResultEqual(
TextEnum.A,
- ("migrations.test_writer.TextEnum['A']", {'import migrations.test_writer'})
+ ("migrations.test_writer.TextEnum['A']", {"import migrations.test_writer"}),
)
self.assertSerializedResultEqual(
TextTranslatedEnum.A,
- ("migrations.test_writer.TextTranslatedEnum['A']", {'import migrations.test_writer'})
+ (
+ "migrations.test_writer.TextTranslatedEnum['A']",
+ {"import migrations.test_writer"},
+ ),
)
self.assertSerializedResultEqual(
BinaryEnum.A,
- ("migrations.test_writer.BinaryEnum['A']", {'import migrations.test_writer'})
+ (
+ "migrations.test_writer.BinaryEnum['A']",
+ {"import migrations.test_writer"},
+ ),
)
self.assertSerializedResultEqual(
IntEnum.B,
- ("migrations.test_writer.IntEnum['B']", {'import migrations.test_writer'})
+ ("migrations.test_writer.IntEnum['B']", {"import migrations.test_writer"}),
)
self.assertSerializedResultEqual(
self.NestedEnum.A,
(
"migrations.test_writer.WriterTests.NestedEnum['A']",
- {'import migrations.test_writer'},
+ {"import migrations.test_writer"},
),
)
self.assertSerializedEqual(self.NestedEnum.A)
- field = models.CharField(default=TextEnum.B, choices=[(m.value, m) for m in TextEnum])
+ field = models.CharField(
+ default=TextEnum.B, choices=[(m.value, m) for m in TextEnum]
+ )
string = MigrationWriter.serialize(field)[0]
self.assertEqual(
string,
"models.CharField(choices=["
"('a-value', migrations.test_writer.TextEnum['A']), "
"('value-b', migrations.test_writer.TextEnum['B'])], "
- "default=migrations.test_writer.TextEnum['B'])"
+ "default=migrations.test_writer.TextEnum['B'])",
)
field = models.CharField(
default=TextTranslatedEnum.A,
@@ -340,45 +356,49 @@ class WriterTests(SimpleTestCase):
"models.CharField(choices=["
"('a-value', migrations.test_writer.TextTranslatedEnum['A']), "
"('value-b', migrations.test_writer.TextTranslatedEnum['B'])], "
- "default=migrations.test_writer.TextTranslatedEnum['A'])"
+ "default=migrations.test_writer.TextTranslatedEnum['A'])",
+ )
+ field = models.CharField(
+ default=BinaryEnum.B, choices=[(m.value, m) for m in BinaryEnum]
)
- field = models.CharField(default=BinaryEnum.B, choices=[(m.value, m) for m in BinaryEnum])
string = MigrationWriter.serialize(field)[0]
self.assertEqual(
string,
"models.CharField(choices=["
"(b'a-value', migrations.test_writer.BinaryEnum['A']), "
"(b'value-b', migrations.test_writer.BinaryEnum['B'])], "
- "default=migrations.test_writer.BinaryEnum['B'])"
+ "default=migrations.test_writer.BinaryEnum['B'])",
+ )
+ field = models.IntegerField(
+ default=IntEnum.A, choices=[(m.value, m) for m in IntEnum]
)
- field = models.IntegerField(default=IntEnum.A, choices=[(m.value, m) for m in IntEnum])
string = MigrationWriter.serialize(field)[0]
self.assertEqual(
string,
"models.IntegerField(choices=["
"(1, migrations.test_writer.IntEnum['A']), "
"(2, migrations.test_writer.IntEnum['B'])], "
- "default=migrations.test_writer.IntEnum['A'])"
+ "default=migrations.test_writer.IntEnum['A'])",
)
def test_serialize_choices(self):
class TextChoices(models.TextChoices):
- A = 'A', 'A value'
- B = 'B', 'B value'
+ A = "A", "A value"
+ B = "B", "B value"
class IntegerChoices(models.IntegerChoices):
- A = 1, 'One'
- B = 2, 'Two'
+ A = 1, "One"
+ B = 2, "Two"
class DateChoices(datetime.date, models.Choices):
- DATE_1 = 1969, 7, 20, 'First date'
- DATE_2 = 1969, 11, 19, 'Second date'
+ DATE_1 = 1969, 7, 20, "First date"
+ DATE_2 = 1969, 11, 19, "Second date"
self.assertSerializedResultEqual(TextChoices.A, ("'A'", set()))
- self.assertSerializedResultEqual(IntegerChoices.A, ('1', set()))
+ self.assertSerializedResultEqual(IntegerChoices.A, ("1", set()))
self.assertSerializedResultEqual(
DateChoices.DATE_1,
- ('datetime.date(1969, 7, 20)', {'import datetime'}),
+ ("datetime.date(1969, 7, 20)", {"import datetime"}),
)
field = models.CharField(default=TextChoices.B, choices=TextChoices.choices)
string = MigrationWriter.serialize(field)[0]
@@ -387,20 +407,24 @@ class WriterTests(SimpleTestCase):
"models.CharField(choices=[('A', 'A value'), ('B', 'B value')], "
"default='B')",
)
- field = models.IntegerField(default=IntegerChoices.B, choices=IntegerChoices.choices)
+ field = models.IntegerField(
+ default=IntegerChoices.B, choices=IntegerChoices.choices
+ )
string = MigrationWriter.serialize(field)[0]
self.assertEqual(
string,
"models.IntegerField(choices=[(1, 'One'), (2, 'Two')], default=2)",
)
- field = models.DateField(default=DateChoices.DATE_2, choices=DateChoices.choices)
+ field = models.DateField(
+ default=DateChoices.DATE_2, choices=DateChoices.choices
+ )
string = MigrationWriter.serialize(field)[0]
self.assertEqual(
string,
"models.DateField(choices=["
"(datetime.date(1969, 7, 20), 'First date'), "
"(datetime.date(1969, 11, 19), 'Second date')], "
- "default=datetime.date(1969, 11, 19))"
+ "default=datetime.date(1969, 11, 19))",
)
def test_serialize_nested_class(self):
@@ -411,7 +435,7 @@ class WriterTests(SimpleTestCase):
nested_cls,
(
"migrations.test_writer.WriterTests.%s" % cls_name,
- {'import migrations.test_writer'},
+ {"import migrations.test_writer"},
),
)
@@ -419,56 +443,58 @@ class WriterTests(SimpleTestCase):
self.assertSerializedEqual(uuid.uuid1())
self.assertSerializedEqual(uuid.uuid4())
- uuid_a = uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8')
- uuid_b = uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2')
+ uuid_a = uuid.UUID("5c859437-d061-4847-b3f7-e6b78852f8c8")
+ uuid_b = uuid.UUID("c7853ec1-2ea3-4359-b02d-b54e8f1bcee2")
self.assertSerializedResultEqual(
uuid_a,
- ("uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8')", {'import uuid'})
+ ("uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8')", {"import uuid"}),
)
self.assertSerializedResultEqual(
uuid_b,
- ("uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2')", {'import uuid'})
+ ("uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2')", {"import uuid"}),
)
- field = models.UUIDField(choices=((uuid_a, 'UUID A'), (uuid_b, 'UUID B')), default=uuid_a)
+ field = models.UUIDField(
+ choices=((uuid_a, "UUID A"), (uuid_b, "UUID B")), default=uuid_a
+ )
string = MigrationWriter.serialize(field)[0]
self.assertEqual(
string,
"models.UUIDField(choices=["
"(uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8'), 'UUID A'), "
"(uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2'), 'UUID B')], "
- "default=uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8'))"
+ "default=uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8'))",
)
def test_serialize_pathlib(self):
# Pure path objects work in all platforms.
self.assertSerializedEqual(pathlib.PurePosixPath())
self.assertSerializedEqual(pathlib.PureWindowsPath())
- path = pathlib.PurePosixPath('/path/file.txt')
- expected = ("pathlib.PurePosixPath('/path/file.txt')", {'import pathlib'})
+ path = pathlib.PurePosixPath("/path/file.txt")
+ expected = ("pathlib.PurePosixPath('/path/file.txt')", {"import pathlib"})
self.assertSerializedResultEqual(path, expected)
- path = pathlib.PureWindowsPath('A:\\File.txt')
- expected = ("pathlib.PureWindowsPath('A:/File.txt')", {'import pathlib'})
+ path = pathlib.PureWindowsPath("A:\\File.txt")
+ expected = ("pathlib.PureWindowsPath('A:/File.txt')", {"import pathlib"})
self.assertSerializedResultEqual(path, expected)
# Concrete path objects work on supported platforms.
- if sys.platform == 'win32':
+ if sys.platform == "win32":
self.assertSerializedEqual(pathlib.WindowsPath.cwd())
- path = pathlib.WindowsPath('A:\\File.txt')
- expected = ("pathlib.PureWindowsPath('A:/File.txt')", {'import pathlib'})
+ path = pathlib.WindowsPath("A:\\File.txt")
+ expected = ("pathlib.PureWindowsPath('A:/File.txt')", {"import pathlib"})
self.assertSerializedResultEqual(path, expected)
else:
self.assertSerializedEqual(pathlib.PosixPath.cwd())
- path = pathlib.PosixPath('/path/file.txt')
- expected = ("pathlib.PurePosixPath('/path/file.txt')", {'import pathlib'})
+ path = pathlib.PosixPath("/path/file.txt")
+ expected = ("pathlib.PurePosixPath('/path/file.txt')", {"import pathlib"})
self.assertSerializedResultEqual(path, expected)
- field = models.FilePathField(path=pathlib.PurePosixPath('/home/user'))
+ field = models.FilePathField(path=pathlib.PurePosixPath("/home/user"))
string, imports = MigrationWriter.serialize(field)
self.assertEqual(
string,
"models.FilePathField(path=pathlib.PurePosixPath('/home/user'))",
)
- self.assertIn('import pathlib', imports)
+ self.assertIn("import pathlib", imports)
def test_serialize_path_like(self):
with os.scandir(os.path.dirname(__file__)) as entries:
@@ -478,14 +504,14 @@ class WriterTests(SimpleTestCase):
field = models.FilePathField(path=path_like)
string = MigrationWriter.serialize(field)[0]
- self.assertEqual(string, 'models.FilePathField(path=%r)' % path_like.path)
+ self.assertEqual(string, "models.FilePathField(path=%r)" % path_like.path)
def test_serialize_functions(self):
- with self.assertRaisesMessage(ValueError, 'Cannot serialize function: lambda'):
+ with self.assertRaisesMessage(ValueError, "Cannot serialize function: lambda"):
self.assertSerializedEqual(lambda x: 42)
self.assertSerializedEqual(models.SET_NULL)
string, imports = MigrationWriter.serialize(models.SET(42))
- self.assertEqual(string, 'models.SET(42)')
+ self.assertEqual(string, "models.SET(42)")
self.serialize_round_trip(models.SET(42))
def test_serialize_datetime(self):
@@ -496,11 +522,15 @@ class WriterTests(SimpleTestCase):
self.assertSerializedEqual(datetime.date.today())
self.assertSerializedEqual(datetime.date.today)
self.assertSerializedEqual(datetime.datetime.now().time())
- self.assertSerializedEqual(datetime.datetime(2014, 1, 1, 1, 1, tzinfo=get_default_timezone()))
- self.assertSerializedEqual(datetime.datetime(2013, 12, 31, 22, 1, tzinfo=get_fixed_timezone(180)))
+ self.assertSerializedEqual(
+ datetime.datetime(2014, 1, 1, 1, 1, tzinfo=get_default_timezone())
+ )
+ self.assertSerializedEqual(
+ datetime.datetime(2013, 12, 31, 22, 1, tzinfo=get_fixed_timezone(180))
+ )
self.assertSerializedResultEqual(
datetime.datetime(2014, 1, 1, 1, 1),
- ("datetime.datetime(2014, 1, 1, 1, 1)", {'import datetime'})
+ ("datetime.datetime(2014, 1, 1, 1, 1)", {"import datetime"}),
)
for tzinfo in (utc, datetime.timezone.utc):
with self.subTest(tzinfo=tzinfo):
@@ -508,56 +538,64 @@ class WriterTests(SimpleTestCase):
datetime.datetime(2012, 1, 1, 1, 1, tzinfo=tzinfo),
(
"datetime.datetime(2012, 1, 1, 1, 1, tzinfo=utc)",
- {'import datetime', 'from django.utils.timezone import utc'},
- )
+ {"import datetime", "from django.utils.timezone import utc"},
+ ),
)
self.assertSerializedResultEqual(
- datetime.datetime(2012, 1, 1, 2, 1, tzinfo=zoneinfo.ZoneInfo('Europe/Paris')),
+ datetime.datetime(
+ 2012, 1, 1, 2, 1, tzinfo=zoneinfo.ZoneInfo("Europe/Paris")
+ ),
(
"datetime.datetime(2012, 1, 1, 1, 1, tzinfo=utc)",
- {'import datetime', 'from django.utils.timezone import utc'},
- )
+ {"import datetime", "from django.utils.timezone import utc"},
+ ),
)
if pytz:
self.assertSerializedResultEqual(
- pytz.timezone('Europe/Paris').localize(datetime.datetime(2012, 1, 1, 2, 1)),
+ pytz.timezone("Europe/Paris").localize(
+ datetime.datetime(2012, 1, 1, 2, 1)
+ ),
(
"datetime.datetime(2012, 1, 1, 1, 1, tzinfo=utc)",
- {'import datetime', 'from django.utils.timezone import utc'},
- )
+ {"import datetime", "from django.utils.timezone import utc"},
+ ),
)
def test_serialize_fields(self):
self.assertSerializedFieldEqual(models.CharField(max_length=255))
self.assertSerializedResultEqual(
models.CharField(max_length=255),
- ("models.CharField(max_length=255)", {"from django.db import models"})
+ ("models.CharField(max_length=255)", {"from django.db import models"}),
)
self.assertSerializedFieldEqual(models.TextField(null=True, blank=True))
self.assertSerializedResultEqual(
models.TextField(null=True, blank=True),
- ("models.TextField(blank=True, null=True)", {'from django.db import models'})
+ (
+ "models.TextField(blank=True, null=True)",
+ {"from django.db import models"},
+ ),
)
def test_serialize_settings(self):
- self.assertSerializedEqual(SettingsReference(settings.AUTH_USER_MODEL, "AUTH_USER_MODEL"))
+ self.assertSerializedEqual(
+ SettingsReference(settings.AUTH_USER_MODEL, "AUTH_USER_MODEL")
+ )
self.assertSerializedResultEqual(
SettingsReference("someapp.model", "AUTH_USER_MODEL"),
- ("settings.AUTH_USER_MODEL", {"from django.conf import settings"})
+ ("settings.AUTH_USER_MODEL", {"from django.conf import settings"}),
)
def test_serialize_iterators(self):
self.assertSerializedResultEqual(
- ((x, x * x) for x in range(3)),
- ("((0, 0), (1, 1), (2, 4))", set())
+ ((x, x * x) for x in range(3)), ("((0, 0), (1, 1), (2, 4))", set())
)
def test_serialize_compiled_regex(self):
"""
Make sure compiled regex can be serialized.
"""
- regex = re.compile(r'^\w+$')
+ regex = re.compile(r"^\w+$")
self.assertSerializedEqual(regex)
def test_serialize_class_based_validators(self):
@@ -567,58 +605,82 @@ class WriterTests(SimpleTestCase):
"""
validator = RegexValidator(message="hello")
string = MigrationWriter.serialize(validator)[0]
- self.assertEqual(string, "django.core.validators.RegexValidator(message='hello')")
+ self.assertEqual(
+ string, "django.core.validators.RegexValidator(message='hello')"
+ )
self.serialize_round_trip(validator)
# Test with a compiled regex.
- validator = RegexValidator(regex=re.compile(r'^\w+$'))
+ validator = RegexValidator(regex=re.compile(r"^\w+$"))
string = MigrationWriter.serialize(validator)[0]
- self.assertEqual(string, "django.core.validators.RegexValidator(regex=re.compile('^\\\\w+$'))")
+ self.assertEqual(
+ string,
+ "django.core.validators.RegexValidator(regex=re.compile('^\\\\w+$'))",
+ )
self.serialize_round_trip(validator)
# Test a string regex with flag
- validator = RegexValidator(r'^[0-9]+$', flags=re.S)
+ validator = RegexValidator(r"^[0-9]+$", flags=re.S)
string = MigrationWriter.serialize(validator)[0]
- self.assertEqual(string, "django.core.validators.RegexValidator('^[0-9]+$', flags=re.RegexFlag['DOTALL'])")
+ self.assertEqual(
+ string,
+ "django.core.validators.RegexValidator('^[0-9]+$', flags=re.RegexFlag['DOTALL'])",
+ )
self.serialize_round_trip(validator)
# Test message and code
- validator = RegexValidator('^[-a-zA-Z0-9_]+$', 'Invalid', 'invalid')
+ validator = RegexValidator("^[-a-zA-Z0-9_]+$", "Invalid", "invalid")
string = MigrationWriter.serialize(validator)[0]
- self.assertEqual(string, "django.core.validators.RegexValidator('^[-a-zA-Z0-9_]+$', 'Invalid', 'invalid')")
+ self.assertEqual(
+ string,
+ "django.core.validators.RegexValidator('^[-a-zA-Z0-9_]+$', 'Invalid', 'invalid')",
+ )
self.serialize_round_trip(validator)
# Test with a subclass.
validator = EmailValidator(message="hello")
string = MigrationWriter.serialize(validator)[0]
- self.assertEqual(string, "django.core.validators.EmailValidator(message='hello')")
+ self.assertEqual(
+ string, "django.core.validators.EmailValidator(message='hello')"
+ )
self.serialize_round_trip(validator)
- validator = deconstructible(path="migrations.test_writer.EmailValidator")(EmailValidator)(message="hello")
+ validator = deconstructible(path="migrations.test_writer.EmailValidator")(
+ EmailValidator
+ )(message="hello")
string = MigrationWriter.serialize(validator)[0]
- self.assertEqual(string, "migrations.test_writer.EmailValidator(message='hello')")
+ self.assertEqual(
+ string, "migrations.test_writer.EmailValidator(message='hello')"
+ )
- validator = deconstructible(path="custom.EmailValidator")(EmailValidator)(message="hello")
+ validator = deconstructible(path="custom.EmailValidator")(EmailValidator)(
+ message="hello"
+ )
with self.assertRaisesMessage(ImportError, "No module named 'custom'"):
MigrationWriter.serialize(validator)
- validator = deconstructible(path="django.core.validators.EmailValidator2")(EmailValidator)(message="hello")
- with self.assertRaisesMessage(ValueError, "Could not find object EmailValidator2 in django.core.validators."):
+ validator = deconstructible(path="django.core.validators.EmailValidator2")(
+ EmailValidator
+ )(message="hello")
+ with self.assertRaisesMessage(
+ ValueError,
+ "Could not find object EmailValidator2 in django.core.validators.",
+ ):
MigrationWriter.serialize(validator)
def test_serialize_complex_func_index(self):
index = models.Index(
- models.Func('rating', function='ABS'),
+ models.Func("rating", function="ABS"),
models.Case(
- models.When(name='special', then=models.Value('X')),
- default=models.Value('other'),
+ models.When(name="special", then=models.Value("X")),
+ default=models.Value("other"),
),
models.ExpressionWrapper(
- models.F('pages'),
+ models.F("pages"),
output_field=models.IntegerField(),
),
- models.OrderBy(models.F('name').desc()),
- name='complex_func_index',
+ models.OrderBy(models.F("name").desc()),
+ name="complex_func_index",
)
string, imports = MigrationWriter.serialize(index)
self.assertEqual(
@@ -629,9 +691,9 @@ class WriterTests(SimpleTestCase):
"models.ExpressionWrapper("
"models.F('pages'), output_field=models.IntegerField()), "
"models.OrderBy(models.OrderBy(models.F('name'), descending=True)), "
- "name='complex_func_index')"
+ "name='complex_func_index')",
)
- self.assertEqual(imports, {'from django.db import models'})
+ self.assertEqual(imports, {"from django.db import models"})
def test_serialize_empty_nonempty_tuple(self):
"""
@@ -639,20 +701,20 @@ class WriterTests(SimpleTestCase):
tuple) default_permissions = ()
"""
empty_tuple = ()
- one_item_tuple = ('a',)
- many_items_tuple = ('a', 'b', 'c')
+ one_item_tuple = ("a",)
+ many_items_tuple = ("a", "b", "c")
self.assertSerializedEqual(empty_tuple)
self.assertSerializedEqual(one_item_tuple)
self.assertSerializedEqual(many_items_tuple)
def test_serialize_range(self):
string, imports = MigrationWriter.serialize(range(1, 5))
- self.assertEqual(string, 'range(1, 5)')
+ self.assertEqual(string, "range(1, 5)")
self.assertEqual(imports, set())
def test_serialize_builtins(self):
string, imports = MigrationWriter.serialize(range)
- self.assertEqual(string, 'range')
+ self.assertEqual(string, "range")
self.assertEqual(imports, set())
def test_serialize_unbound_method_reference(self):
@@ -661,22 +723,29 @@ class WriterTests(SimpleTestCase):
def test_serialize_local_function_reference(self):
"""A reference in a local scope can't be serialized."""
+
class TestModel2:
def upload_to(self):
return "somewhere dynamic"
+
thing = models.FileField(upload_to=upload_to)
- with self.assertRaisesMessage(ValueError, 'Could not find function upload_to in migrations.test_writer'):
+ with self.assertRaisesMessage(
+ ValueError, "Could not find function upload_to in migrations.test_writer"
+ ):
self.serialize_round_trip(TestModel2.thing)
def test_serialize_managers(self):
self.assertSerializedEqual(models.Manager())
self.assertSerializedResultEqual(
FoodQuerySet.as_manager(),
- ('migrations.models.FoodQuerySet.as_manager()', {'import migrations.models'})
+ (
+ "migrations.models.FoodQuerySet.as_manager()",
+ {"import migrations.models"},
+ ),
)
- self.assertSerializedEqual(FoodManager('a', 'b'))
- self.assertSerializedEqual(FoodManager('x', 'y', c=3, d=4))
+ self.assertSerializedEqual(FoodManager("a", "b"))
+ self.assertSerializedEqual(FoodManager("x", "y", c=3, d=4))
def test_serialize_frozensets(self):
self.assertSerializedEqual(frozenset())
@@ -684,9 +753,9 @@ class WriterTests(SimpleTestCase):
def test_serialize_set(self):
self.assertSerializedEqual(set())
- self.assertSerializedResultEqual(set(), ('set()', set()))
- self.assertSerializedEqual({'a'})
- self.assertSerializedResultEqual({'a'}, ("{'a'}", set()))
+ self.assertSerializedResultEqual(set(), ("set()", set()))
+ self.assertSerializedEqual({"a"})
+ self.assertSerializedResultEqual({"a"}, ("{'a'}", set()))
def test_serialize_timedelta(self):
self.assertSerializedEqual(datetime.timedelta())
@@ -722,27 +791,40 @@ class WriterTests(SimpleTestCase):
Tests serializing a simple migration.
"""
fields = {
- 'charfield': models.DateTimeField(default=datetime.datetime.now),
- 'datetimefield': models.DateTimeField(default=datetime.datetime.now),
+ "charfield": models.DateTimeField(default=datetime.datetime.now),
+ "datetimefield": models.DateTimeField(default=datetime.datetime.now),
}
options = {
- 'verbose_name': 'My model',
- 'verbose_name_plural': 'My models',
+ "verbose_name": "My model",
+ "verbose_name_plural": "My models",
}
- migration = type("Migration", (migrations.Migration,), {
- "operations": [
- migrations.CreateModel("MyModel", tuple(fields.items()), options, (models.Model,)),
- migrations.CreateModel("MyModel2", tuple(fields.items()), bases=(models.Model,)),
- migrations.CreateModel(
- name="MyModel3", fields=tuple(fields.items()), options=options, bases=(models.Model,)
- ),
- migrations.DeleteModel("MyModel"),
- migrations.AddField("OtherModel", "datetimefield", fields["datetimefield"]),
- ],
- "dependencies": [("testapp", "some_other_one")],
- })
+ migration = type(
+ "Migration",
+ (migrations.Migration,),
+ {
+ "operations": [
+ migrations.CreateModel(
+ "MyModel", tuple(fields.items()), options, (models.Model,)
+ ),
+ migrations.CreateModel(
+ "MyModel2", tuple(fields.items()), bases=(models.Model,)
+ ),
+ migrations.CreateModel(
+ name="MyModel3",
+ fields=tuple(fields.items()),
+ options=options,
+ bases=(models.Model,),
+ ),
+ migrations.DeleteModel("MyModel"),
+ migrations.AddField(
+ "OtherModel", "datetimefield", fields["datetimefield"]
+ ),
+ ],
+ "dependencies": [("testapp", "some_other_one")],
+ },
+ )
writer = MigrationWriter(migration)
output = writer.as_string()
# We don't test the output formatting - that's too fragile.
@@ -752,68 +834,80 @@ class WriterTests(SimpleTestCase):
def test_migration_path(self):
test_apps = [
- 'migrations.migrations_test_apps.normal',
- 'migrations.migrations_test_apps.with_package_model',
- 'migrations.migrations_test_apps.without_init_file',
+ "migrations.migrations_test_apps.normal",
+ "migrations.migrations_test_apps.with_package_model",
+ "migrations.migrations_test_apps.without_init_file",
]
base_dir = os.path.dirname(os.path.dirname(__file__))
for app in test_apps:
- with self.modify_settings(INSTALLED_APPS={'append': app}):
- migration = migrations.Migration('0001_initial', app.split('.')[-1])
- expected_path = os.path.join(base_dir, *(app.split('.') + ['migrations', '0001_initial.py']))
+ with self.modify_settings(INSTALLED_APPS={"append": app}):
+ migration = migrations.Migration("0001_initial", app.split(".")[-1])
+ expected_path = os.path.join(
+ base_dir, *(app.split(".") + ["migrations", "0001_initial.py"])
+ )
writer = MigrationWriter(migration)
self.assertEqual(writer.path, expected_path)
def test_custom_operation(self):
- migration = type("Migration", (migrations.Migration,), {
- "operations": [
- custom_migration_operations.operations.TestOperation(),
- custom_migration_operations.operations.CreateModel(),
- migrations.CreateModel("MyModel", (), {}, (models.Model,)),
- custom_migration_operations.more_operations.TestOperation()
- ],
- "dependencies": []
- })
+ migration = type(
+ "Migration",
+ (migrations.Migration,),
+ {
+ "operations": [
+ custom_migration_operations.operations.TestOperation(),
+ custom_migration_operations.operations.CreateModel(),
+ migrations.CreateModel("MyModel", (), {}, (models.Model,)),
+ custom_migration_operations.more_operations.TestOperation(),
+ ],
+ "dependencies": [],
+ },
+ )
writer = MigrationWriter(migration)
output = writer.as_string()
result = self.safe_exec(output)
self.assertIn("custom_migration_operations", result)
self.assertNotEqual(
- result['custom_migration_operations'].operations.TestOperation,
- result['custom_migration_operations'].more_operations.TestOperation
+ result["custom_migration_operations"].operations.TestOperation,
+ result["custom_migration_operations"].more_operations.TestOperation,
)
def test_sorted_imports(self):
"""
#24155 - Tests ordering of imports.
"""
- migration = type("Migration", (migrations.Migration,), {
- "operations": [
- migrations.AddField("mymodel", "myfield", models.DateTimeField(
- default=datetime.datetime(2012, 1, 1, 1, 1, tzinfo=utc),
- )),
- ]
- })
+ migration = type(
+ "Migration",
+ (migrations.Migration,),
+ {
+ "operations": [
+ migrations.AddField(
+ "mymodel",
+ "myfield",
+ models.DateTimeField(
+ default=datetime.datetime(2012, 1, 1, 1, 1, tzinfo=utc),
+ ),
+ ),
+ ]
+ },
+ )
writer = MigrationWriter(migration)
output = writer.as_string()
self.assertIn(
"import datetime\n"
"from django.db import migrations, models\n"
"from django.utils.timezone import utc\n",
- output
+ output,
)
def test_migration_file_header_comments(self):
"""
Test comments at top of file.
"""
- migration = type("Migration", (migrations.Migration,), {
- "operations": []
- })
+ migration = type("Migration", (migrations.Migration,), {"operations": []})
dt = datetime.datetime(2015, 7, 31, 4, 40, 0, 0, tzinfo=utc)
- with mock.patch('django.db.migrations.writer.now', lambda: dt):
+ with mock.patch("django.db.migrations.writer.now", lambda: dt):
for include_header in (True, False):
with self.subTest(include_header=include_header):
writer = MigrationWriter(migration, include_header)
@@ -822,26 +916,36 @@ class WriterTests(SimpleTestCase):
self.assertEqual(
include_header,
output.startswith(
- "# Generated by Django %s on 2015-07-31 04:40\n\n" % get_version()
- )
+ "# Generated by Django %s on 2015-07-31 04:40\n\n"
+ % get_version()
+ ),
)
if not include_header:
# Make sure the output starts with something that's not
# a comment or indentation or blank line
- self.assertRegex(output.splitlines(keepends=True)[0], r"^[^#\s]+")
+ self.assertRegex(
+ output.splitlines(keepends=True)[0], r"^[^#\s]+"
+ )
def test_models_import_omitted(self):
"""
django.db.models shouldn't be imported if unused.
"""
- migration = type("Migration", (migrations.Migration,), {
- "operations": [
- migrations.AlterModelOptions(
- name='model',
- options={'verbose_name': 'model', 'verbose_name_plural': 'models'},
- ),
- ]
- })
+ migration = type(
+ "Migration",
+ (migrations.Migration,),
+ {
+ "operations": [
+ migrations.AlterModelOptions(
+ name="model",
+ options={
+ "verbose_name": "model",
+ "verbose_name_plural": "models",
+ },
+ ),
+ ]
+ },
+ )
writer = MigrationWriter(migration)
output = writer.as_string()
self.assertIn("from django.db import migrations\n", output)
@@ -850,20 +954,27 @@ class WriterTests(SimpleTestCase):
# Yes, it doesn't make sense to use a class as a default for a
# CharField. It does make sense for custom fields though, for example
# an enumfield that takes the enum class as an argument.
- string = MigrationWriter.serialize(models.CharField(default=DeconstructibleInstances))[0]
- self.assertEqual(string, "models.CharField(default=migrations.test_writer.DeconstructibleInstances)")
+ string = MigrationWriter.serialize(
+ models.CharField(default=DeconstructibleInstances)
+ )[0]
+ self.assertEqual(
+ string,
+ "models.CharField(default=migrations.test_writer.DeconstructibleInstances)",
+ )
def test_register_serializer(self):
class ComplexSerializer(BaseSerializer):
def serialize(self):
- return 'complex(%r)' % self.value, {}
+ return "complex(%r)" % self.value, {}
MigrationWriter.register_serializer(complex, ComplexSerializer)
self.assertSerializedEqual(complex(1, 2))
MigrationWriter.unregister_serializer(complex)
- with self.assertRaisesMessage(ValueError, 'Cannot serialize: (1+2j)'):
+ with self.assertRaisesMessage(ValueError, "Cannot serialize: (1+2j)"):
self.assertSerializedEqual(complex(1, 2))
def test_register_non_serializer(self):
- with self.assertRaisesMessage(ValueError, "'TestModel1' must inherit from 'BaseSerializer'."):
+ with self.assertRaisesMessage(
+ ValueError, "'TestModel1' must inherit from 'BaseSerializer'."
+ ):
MigrationWriter.register_serializer(complex, TestModel1)