1. import functools
    
  2. import re
    
  3. from unittest import mock
    
  4. 
    
  5. from django.apps import apps
    
  6. from django.conf import settings
    
  7. from django.contrib.auth.models import AbstractBaseUser
    
  8. from django.core.validators import RegexValidator, validate_slug
    
  9. from django.db import connection, migrations, models
    
  10. from django.db.migrations.autodetector import MigrationAutodetector
    
  11. from django.db.migrations.graph import MigrationGraph
    
  12. from django.db.migrations.loader import MigrationLoader
    
  13. from django.db.migrations.questioner import MigrationQuestioner
    
  14. from django.db.migrations.state import ModelState, ProjectState
    
  15. from django.test import SimpleTestCase, TestCase, override_settings
    
  16. from django.test.utils import isolate_lru_cache
    
  17. 
    
  18. from .models import FoodManager, FoodQuerySet
    
  19. 
    
  20. 
    
  21. class DeconstructibleObject:
    
  22.     """
    
  23.     A custom deconstructible object.
    
  24.     """
    
  25. 
    
  26.     def __init__(self, *args, **kwargs):
    
  27.         self.args = args
    
  28.         self.kwargs = kwargs
    
  29. 
    
  30.     def deconstruct(self):
    
  31.         return (self.__module__ + "." + self.__class__.__name__, self.args, self.kwargs)
    
  32. 
    
  33. 
    
  34. class AutodetectorTests(TestCase):
    
  35.     """
    
  36.     Tests the migration autodetector.
    
  37.     """
    
  38. 
    
  39.     author_empty = ModelState(
    
  40.         "testapp", "Author", [("id", models.AutoField(primary_key=True))]
    
  41.     )
    
  42.     author_name = ModelState(
    
  43.         "testapp",
    
  44.         "Author",
    
  45.         [
    
  46.             ("id", models.AutoField(primary_key=True)),
    
  47.             ("name", models.CharField(max_length=200)),
    
  48.         ],
    
  49.     )
    
  50.     author_name_null = ModelState(
    
  51.         "testapp",
    
  52.         "Author",
    
  53.         [
    
  54.             ("id", models.AutoField(primary_key=True)),
    
  55.             ("name", models.CharField(max_length=200, null=True)),
    
  56.         ],
    
  57.     )
    
  58.     author_name_longer = ModelState(
    
  59.         "testapp",
    
  60.         "Author",
    
  61.         [
    
  62.             ("id", models.AutoField(primary_key=True)),
    
  63.             ("name", models.CharField(max_length=400)),
    
  64.         ],
    
  65.     )
    
  66.     author_name_renamed = ModelState(
    
  67.         "testapp",
    
  68.         "Author",
    
  69.         [
    
  70.             ("id", models.AutoField(primary_key=True)),
    
  71.             ("names", models.CharField(max_length=200)),
    
  72.         ],
    
  73.     )
    
  74.     author_name_default = ModelState(
    
  75.         "testapp",
    
  76.         "Author",
    
  77.         [
    
  78.             ("id", models.AutoField(primary_key=True)),
    
  79.             ("name", models.CharField(max_length=200, default="Ada Lovelace")),
    
  80.         ],
    
  81.     )
    
  82.     author_name_check_constraint = ModelState(
    
  83.         "testapp",
    
  84.         "Author",
    
  85.         [
    
  86.             ("id", models.AutoField(primary_key=True)),
    
  87.             ("name", models.CharField(max_length=200)),
    
  88.         ],
    
  89.         {
    
  90.             "constraints": [
    
  91.                 models.CheckConstraint(
    
  92.                     check=models.Q(name__contains="Bob"), name="name_contains_bob"
    
  93.                 )
    
  94.             ]
    
  95.         },
    
  96.     )
    
  97.     author_dates_of_birth_auto_now = ModelState(
    
  98.         "testapp",
    
  99.         "Author",
    
  100.         [
    
  101.             ("id", models.AutoField(primary_key=True)),
    
  102.             ("date_of_birth", models.DateField(auto_now=True)),
    
  103.             ("date_time_of_birth", models.DateTimeField(auto_now=True)),
    
  104.             ("time_of_birth", models.TimeField(auto_now=True)),
    
  105.         ],
    
  106.     )
    
  107.     author_dates_of_birth_auto_now_add = ModelState(
    
  108.         "testapp",
    
  109.         "Author",
    
  110.         [
    
  111.             ("id", models.AutoField(primary_key=True)),
    
  112.             ("date_of_birth", models.DateField(auto_now_add=True)),
    
  113.             ("date_time_of_birth", models.DateTimeField(auto_now_add=True)),
    
  114.             ("time_of_birth", models.TimeField(auto_now_add=True)),
    
  115.         ],
    
  116.     )
    
  117.     author_name_deconstructible_1 = ModelState(
    
  118.         "testapp",
    
  119.         "Author",
    
  120.         [
    
  121.             ("id", models.AutoField(primary_key=True)),
    
  122.             ("name", models.CharField(max_length=200, default=DeconstructibleObject())),
    
  123.         ],
    
  124.     )
    
  125.     author_name_deconstructible_2 = ModelState(
    
  126.         "testapp",
    
  127.         "Author",
    
  128.         [
    
  129.             ("id", models.AutoField(primary_key=True)),
    
  130.             ("name", models.CharField(max_length=200, default=DeconstructibleObject())),
    
  131.         ],
    
  132.     )
    
  133.     author_name_deconstructible_3 = ModelState(
    
  134.         "testapp",
    
  135.         "Author",
    
  136.         [
    
  137.             ("id", models.AutoField(primary_key=True)),
    
  138.             ("name", models.CharField(max_length=200, default=models.IntegerField())),
    
  139.         ],
    
  140.     )
    
  141.     author_name_deconstructible_4 = ModelState(
    
  142.         "testapp",
    
  143.         "Author",
    
  144.         [
    
  145.             ("id", models.AutoField(primary_key=True)),
    
  146.             ("name", models.CharField(max_length=200, default=models.IntegerField())),
    
  147.         ],
    
  148.     )
    
  149.     author_name_deconstructible_list_1 = ModelState(
    
  150.         "testapp",
    
  151.         "Author",
    
  152.         [
    
  153.             ("id", models.AutoField(primary_key=True)),
    
  154.             (
    
  155.                 "name",
    
  156.                 models.CharField(
    
  157.                     max_length=200, default=[DeconstructibleObject(), 123]
    
  158.                 ),
    
  159.             ),
    
  160.         ],
    
  161.     )
    
  162.     author_name_deconstructible_list_2 = ModelState(
    
  163.         "testapp",
    
  164.         "Author",
    
  165.         [
    
  166.             ("id", models.AutoField(primary_key=True)),
    
  167.             (
    
  168.                 "name",
    
  169.                 models.CharField(
    
  170.                     max_length=200, default=[DeconstructibleObject(), 123]
    
  171.                 ),
    
  172.             ),
    
  173.         ],
    
  174.     )
    
  175.     author_name_deconstructible_list_3 = ModelState(
    
  176.         "testapp",
    
  177.         "Author",
    
  178.         [
    
  179.             ("id", models.AutoField(primary_key=True)),
    
  180.             (
    
  181.                 "name",
    
  182.                 models.CharField(
    
  183.                     max_length=200, default=[DeconstructibleObject(), 999]
    
  184.                 ),
    
  185.             ),
    
  186.         ],
    
  187.     )
    
  188.     author_name_deconstructible_tuple_1 = ModelState(
    
  189.         "testapp",
    
  190.         "Author",
    
  191.         [
    
  192.             ("id", models.AutoField(primary_key=True)),
    
  193.             (
    
  194.                 "name",
    
  195.                 models.CharField(
    
  196.                     max_length=200, default=(DeconstructibleObject(), 123)
    
  197.                 ),
    
  198.             ),
    
  199.         ],
    
  200.     )
    
  201.     author_name_deconstructible_tuple_2 = ModelState(
    
  202.         "testapp",
    
  203.         "Author",
    
  204.         [
    
  205.             ("id", models.AutoField(primary_key=True)),
    
  206.             (
    
  207.                 "name",
    
  208.                 models.CharField(
    
  209.                     max_length=200, default=(DeconstructibleObject(), 123)
    
  210.                 ),
    
  211.             ),
    
  212.         ],
    
  213.     )
    
  214.     author_name_deconstructible_tuple_3 = ModelState(
    
  215.         "testapp",
    
  216.         "Author",
    
  217.         [
    
  218.             ("id", models.AutoField(primary_key=True)),
    
  219.             (
    
  220.                 "name",
    
  221.                 models.CharField(
    
  222.                     max_length=200, default=(DeconstructibleObject(), 999)
    
  223.                 ),
    
  224.             ),
    
  225.         ],
    
  226.     )
    
  227.     author_name_deconstructible_dict_1 = ModelState(
    
  228.         "testapp",
    
  229.         "Author",
    
  230.         [
    
  231.             ("id", models.AutoField(primary_key=True)),
    
  232.             (
    
  233.                 "name",
    
  234.                 models.CharField(
    
  235.                     max_length=200,
    
  236.                     default={"item": DeconstructibleObject(), "otheritem": 123},
    
  237.                 ),
    
  238.             ),
    
  239.         ],
    
  240.     )
    
  241.     author_name_deconstructible_dict_2 = ModelState(
    
  242.         "testapp",
    
  243.         "Author",
    
  244.         [
    
  245.             ("id", models.AutoField(primary_key=True)),
    
  246.             (
    
  247.                 "name",
    
  248.                 models.CharField(
    
  249.                     max_length=200,
    
  250.                     default={"item": DeconstructibleObject(), "otheritem": 123},
    
  251.                 ),
    
  252.             ),
    
  253.         ],
    
  254.     )
    
  255.     author_name_deconstructible_dict_3 = ModelState(
    
  256.         "testapp",
    
  257.         "Author",
    
  258.         [
    
  259.             ("id", models.AutoField(primary_key=True)),
    
  260.             (
    
  261.                 "name",
    
  262.                 models.CharField(
    
  263.                     max_length=200,
    
  264.                     default={"item": DeconstructibleObject(), "otheritem": 999},
    
  265.                 ),
    
  266.             ),
    
  267.         ],
    
  268.     )
    
  269.     author_name_nested_deconstructible_1 = ModelState(
    
  270.         "testapp",
    
  271.         "Author",
    
  272.         [
    
  273.             ("id", models.AutoField(primary_key=True)),
    
  274.             (
    
  275.                 "name",
    
  276.                 models.CharField(
    
  277.                     max_length=200,
    
  278.                     default=DeconstructibleObject(
    
  279.                         DeconstructibleObject(1),
    
  280.                         (
    
  281.                             DeconstructibleObject("t1"),
    
  282.                             DeconstructibleObject("t2"),
    
  283.                         ),
    
  284.                         a=DeconstructibleObject("A"),
    
  285.                         b=DeconstructibleObject(B=DeconstructibleObject("c")),
    
  286.                     ),
    
  287.                 ),
    
  288.             ),
    
  289.         ],
    
  290.     )
    
  291.     author_name_nested_deconstructible_2 = ModelState(
    
  292.         "testapp",
    
  293.         "Author",
    
  294.         [
    
  295.             ("id", models.AutoField(primary_key=True)),
    
  296.             (
    
  297.                 "name",
    
  298.                 models.CharField(
    
  299.                     max_length=200,
    
  300.                     default=DeconstructibleObject(
    
  301.                         DeconstructibleObject(1),
    
  302.                         (
    
  303.                             DeconstructibleObject("t1"),
    
  304.                             DeconstructibleObject("t2"),
    
  305.                         ),
    
  306.                         a=DeconstructibleObject("A"),
    
  307.                         b=DeconstructibleObject(B=DeconstructibleObject("c")),
    
  308.                     ),
    
  309.                 ),
    
  310.             ),
    
  311.         ],
    
  312.     )
    
  313.     author_name_nested_deconstructible_changed_arg = ModelState(
    
  314.         "testapp",
    
  315.         "Author",
    
  316.         [
    
  317.             ("id", models.AutoField(primary_key=True)),
    
  318.             (
    
  319.                 "name",
    
  320.                 models.CharField(
    
  321.                     max_length=200,
    
  322.                     default=DeconstructibleObject(
    
  323.                         DeconstructibleObject(1),
    
  324.                         (
    
  325.                             DeconstructibleObject("t1"),
    
  326.                             DeconstructibleObject("t2-changed"),
    
  327.                         ),
    
  328.                         a=DeconstructibleObject("A"),
    
  329.                         b=DeconstructibleObject(B=DeconstructibleObject("c")),
    
  330.                     ),
    
  331.                 ),
    
  332.             ),
    
  333.         ],
    
  334.     )
    
  335.     author_name_nested_deconstructible_extra_arg = ModelState(
    
  336.         "testapp",
    
  337.         "Author",
    
  338.         [
    
  339.             ("id", models.AutoField(primary_key=True)),
    
  340.             (
    
  341.                 "name",
    
  342.                 models.CharField(
    
  343.                     max_length=200,
    
  344.                     default=DeconstructibleObject(
    
  345.                         DeconstructibleObject(1),
    
  346.                         (
    
  347.                             DeconstructibleObject("t1"),
    
  348.                             DeconstructibleObject("t2"),
    
  349.                         ),
    
  350.                         None,
    
  351.                         a=DeconstructibleObject("A"),
    
  352.                         b=DeconstructibleObject(B=DeconstructibleObject("c")),
    
  353.                     ),
    
  354.                 ),
    
  355.             ),
    
  356.         ],
    
  357.     )
    
  358.     author_name_nested_deconstructible_changed_kwarg = ModelState(
    
  359.         "testapp",
    
  360.         "Author",
    
  361.         [
    
  362.             ("id", models.AutoField(primary_key=True)),
    
  363.             (
    
  364.                 "name",
    
  365.                 models.CharField(
    
  366.                     max_length=200,
    
  367.                     default=DeconstructibleObject(
    
  368.                         DeconstructibleObject(1),
    
  369.                         (
    
  370.                             DeconstructibleObject("t1"),
    
  371.                             DeconstructibleObject("t2"),
    
  372.                         ),
    
  373.                         a=DeconstructibleObject("A"),
    
  374.                         b=DeconstructibleObject(B=DeconstructibleObject("c-changed")),
    
  375.                     ),
    
  376.                 ),
    
  377.             ),
    
  378.         ],
    
  379.     )
    
  380.     author_name_nested_deconstructible_extra_kwarg = ModelState(
    
  381.         "testapp",
    
  382.         "Author",
    
  383.         [
    
  384.             ("id", models.AutoField(primary_key=True)),
    
  385.             (
    
  386.                 "name",
    
  387.                 models.CharField(
    
  388.                     max_length=200,
    
  389.                     default=DeconstructibleObject(
    
  390.                         DeconstructibleObject(1),
    
  391.                         (
    
  392.                             DeconstructibleObject("t1"),
    
  393.                             DeconstructibleObject("t2"),
    
  394.                         ),
    
  395.                         a=DeconstructibleObject("A"),
    
  396.                         b=DeconstructibleObject(B=DeconstructibleObject("c")),
    
  397.                         c=None,
    
  398.                     ),
    
  399.                 ),
    
  400.             ),
    
  401.         ],
    
  402.     )
    
  403.     author_custom_pk = ModelState(
    
  404.         "testapp", "Author", [("pk_field", models.IntegerField(primary_key=True))]
    
  405.     )
    
  406.     author_with_biography_non_blank = ModelState(
    
  407.         "testapp",
    
  408.         "Author",
    
  409.         [
    
  410.             ("id", models.AutoField(primary_key=True)),
    
  411.             ("name", models.CharField()),
    
  412.             ("biography", models.TextField()),
    
  413.         ],
    
  414.     )
    
  415.     author_with_biography_blank = ModelState(
    
  416.         "testapp",
    
  417.         "Author",
    
  418.         [
    
  419.             ("id", models.AutoField(primary_key=True)),
    
  420.             ("name", models.CharField(blank=True)),
    
  421.             ("biography", models.TextField(blank=True)),
    
  422.         ],
    
  423.     )
    
  424.     author_with_book = ModelState(
    
  425.         "testapp",
    
  426.         "Author",
    
  427.         [
    
  428.             ("id", models.AutoField(primary_key=True)),
    
  429.             ("name", models.CharField(max_length=200)),
    
  430.             ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  431.         ],
    
  432.     )
    
  433.     author_with_book_order_wrt = ModelState(
    
  434.         "testapp",
    
  435.         "Author",
    
  436.         [
    
  437.             ("id", models.AutoField(primary_key=True)),
    
  438.             ("name", models.CharField(max_length=200)),
    
  439.             ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  440.         ],
    
  441.         options={"order_with_respect_to": "book"},
    
  442.     )
    
  443.     author_renamed_with_book = ModelState(
    
  444.         "testapp",
    
  445.         "Writer",
    
  446.         [
    
  447.             ("id", models.AutoField(primary_key=True)),
    
  448.             ("name", models.CharField(max_length=200)),
    
  449.             ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  450.         ],
    
  451.     )
    
  452.     author_with_publisher_string = ModelState(
    
  453.         "testapp",
    
  454.         "Author",
    
  455.         [
    
  456.             ("id", models.AutoField(primary_key=True)),
    
  457.             ("name", models.CharField(max_length=200)),
    
  458.             ("publisher_name", models.CharField(max_length=200)),
    
  459.         ],
    
  460.     )
    
  461.     author_with_publisher = ModelState(
    
  462.         "testapp",
    
  463.         "Author",
    
  464.         [
    
  465.             ("id", models.AutoField(primary_key=True)),
    
  466.             ("name", models.CharField(max_length=200)),
    
  467.             ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
    
  468.         ],
    
  469.     )
    
  470.     author_with_user = ModelState(
    
  471.         "testapp",
    
  472.         "Author",
    
  473.         [
    
  474.             ("id", models.AutoField(primary_key=True)),
    
  475.             ("name", models.CharField(max_length=200)),
    
  476.             ("user", models.ForeignKey("auth.User", models.CASCADE)),
    
  477.         ],
    
  478.     )
    
  479.     author_with_custom_user = ModelState(
    
  480.         "testapp",
    
  481.         "Author",
    
  482.         [
    
  483.             ("id", models.AutoField(primary_key=True)),
    
  484.             ("name", models.CharField(max_length=200)),
    
  485.             ("user", models.ForeignKey("thirdapp.CustomUser", models.CASCADE)),
    
  486.         ],
    
  487.     )
    
  488.     author_proxy = ModelState(
    
  489.         "testapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author",)
    
  490.     )
    
  491.     author_proxy_options = ModelState(
    
  492.         "testapp",
    
  493.         "AuthorProxy",
    
  494.         [],
    
  495.         {
    
  496.             "proxy": True,
    
  497.             "verbose_name": "Super Author",
    
  498.         },
    
  499.         ("testapp.author",),
    
  500.     )
    
  501.     author_proxy_notproxy = ModelState(
    
  502.         "testapp", "AuthorProxy", [], {}, ("testapp.author",)
    
  503.     )
    
  504.     author_proxy_third = ModelState(
    
  505.         "thirdapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author",)
    
  506.     )
    
  507.     author_proxy_third_notproxy = ModelState(
    
  508.         "thirdapp", "AuthorProxy", [], {}, ("testapp.author",)
    
  509.     )
    
  510.     author_proxy_proxy = ModelState(
    
  511.         "testapp", "AAuthorProxyProxy", [], {"proxy": True}, ("testapp.authorproxy",)
    
  512.     )
    
  513.     author_unmanaged = ModelState(
    
  514.         "testapp", "AuthorUnmanaged", [], {"managed": False}, ("testapp.author",)
    
  515.     )
    
  516.     author_unmanaged_managed = ModelState(
    
  517.         "testapp", "AuthorUnmanaged", [], {}, ("testapp.author",)
    
  518.     )
    
  519.     author_unmanaged_default_pk = ModelState(
    
  520.         "testapp", "Author", [("id", models.AutoField(primary_key=True))]
    
  521.     )
    
  522.     author_unmanaged_custom_pk = ModelState(
    
  523.         "testapp",
    
  524.         "Author",
    
  525.         [
    
  526.             ("pk_field", models.IntegerField(primary_key=True)),
    
  527.         ],
    
  528.     )
    
  529.     author_with_m2m = ModelState(
    
  530.         "testapp",
    
  531.         "Author",
    
  532.         [
    
  533.             ("id", models.AutoField(primary_key=True)),
    
  534.             ("publishers", models.ManyToManyField("testapp.Publisher")),
    
  535.         ],
    
  536.     )
    
  537.     author_with_m2m_blank = ModelState(
    
  538.         "testapp",
    
  539.         "Author",
    
  540.         [
    
  541.             ("id", models.AutoField(primary_key=True)),
    
  542.             ("publishers", models.ManyToManyField("testapp.Publisher", blank=True)),
    
  543.         ],
    
  544.     )
    
  545.     author_with_m2m_through = ModelState(
    
  546.         "testapp",
    
  547.         "Author",
    
  548.         [
    
  549.             ("id", models.AutoField(primary_key=True)),
    
  550.             (
    
  551.                 "publishers",
    
  552.                 models.ManyToManyField("testapp.Publisher", through="testapp.Contract"),
    
  553.             ),
    
  554.         ],
    
  555.     )
    
  556.     author_with_renamed_m2m_through = ModelState(
    
  557.         "testapp",
    
  558.         "Author",
    
  559.         [
    
  560.             ("id", models.AutoField(primary_key=True)),
    
  561.             (
    
  562.                 "publishers",
    
  563.                 models.ManyToManyField("testapp.Publisher", through="testapp.Deal"),
    
  564.             ),
    
  565.         ],
    
  566.     )
    
  567.     author_with_former_m2m = ModelState(
    
  568.         "testapp",
    
  569.         "Author",
    
  570.         [
    
  571.             ("id", models.AutoField(primary_key=True)),
    
  572.             ("publishers", models.CharField(max_length=100)),
    
  573.         ],
    
  574.     )
    
  575.     author_with_options = ModelState(
    
  576.         "testapp",
    
  577.         "Author",
    
  578.         [
    
  579.             ("id", models.AutoField(primary_key=True)),
    
  580.         ],
    
  581.         {
    
  582.             "permissions": [("can_hire", "Can hire")],
    
  583.             "verbose_name": "Authi",
    
  584.         },
    
  585.     )
    
  586.     author_with_db_table_options = ModelState(
    
  587.         "testapp",
    
  588.         "Author",
    
  589.         [
    
  590.             ("id", models.AutoField(primary_key=True)),
    
  591.         ],
    
  592.         {"db_table": "author_one"},
    
  593.     )
    
  594.     author_with_new_db_table_options = ModelState(
    
  595.         "testapp",
    
  596.         "Author",
    
  597.         [
    
  598.             ("id", models.AutoField(primary_key=True)),
    
  599.         ],
    
  600.         {"db_table": "author_two"},
    
  601.     )
    
  602.     author_renamed_with_db_table_options = ModelState(
    
  603.         "testapp",
    
  604.         "NewAuthor",
    
  605.         [
    
  606.             ("id", models.AutoField(primary_key=True)),
    
  607.         ],
    
  608.         {"db_table": "author_one"},
    
  609.     )
    
  610.     author_renamed_with_new_db_table_options = ModelState(
    
  611.         "testapp",
    
  612.         "NewAuthor",
    
  613.         [
    
  614.             ("id", models.AutoField(primary_key=True)),
    
  615.         ],
    
  616.         {"db_table": "author_three"},
    
  617.     )
    
  618.     contract = ModelState(
    
  619.         "testapp",
    
  620.         "Contract",
    
  621.         [
    
  622.             ("id", models.AutoField(primary_key=True)),
    
  623.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  624.             ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
    
  625.         ],
    
  626.     )
    
  627.     contract_renamed = ModelState(
    
  628.         "testapp",
    
  629.         "Deal",
    
  630.         [
    
  631.             ("id", models.AutoField(primary_key=True)),
    
  632.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  633.             ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
    
  634.         ],
    
  635.     )
    
  636.     publisher = ModelState(
    
  637.         "testapp",
    
  638.         "Publisher",
    
  639.         [
    
  640.             ("id", models.AutoField(primary_key=True)),
    
  641.             ("name", models.CharField(max_length=100)),
    
  642.         ],
    
  643.     )
    
  644.     publisher_with_author = ModelState(
    
  645.         "testapp",
    
  646.         "Publisher",
    
  647.         [
    
  648.             ("id", models.AutoField(primary_key=True)),
    
  649.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  650.             ("name", models.CharField(max_length=100)),
    
  651.         ],
    
  652.     )
    
  653.     publisher_with_aardvark_author = ModelState(
    
  654.         "testapp",
    
  655.         "Publisher",
    
  656.         [
    
  657.             ("id", models.AutoField(primary_key=True)),
    
  658.             ("author", models.ForeignKey("testapp.Aardvark", models.CASCADE)),
    
  659.             ("name", models.CharField(max_length=100)),
    
  660.         ],
    
  661.     )
    
  662.     publisher_with_book = ModelState(
    
  663.         "testapp",
    
  664.         "Publisher",
    
  665.         [
    
  666.             ("id", models.AutoField(primary_key=True)),
    
  667.             ("author", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  668.             ("name", models.CharField(max_length=100)),
    
  669.         ],
    
  670.     )
    
  671.     other_pony = ModelState(
    
  672.         "otherapp",
    
  673.         "Pony",
    
  674.         [
    
  675.             ("id", models.AutoField(primary_key=True)),
    
  676.         ],
    
  677.     )
    
  678.     other_pony_food = ModelState(
    
  679.         "otherapp",
    
  680.         "Pony",
    
  681.         [
    
  682.             ("id", models.AutoField(primary_key=True)),
    
  683.         ],
    
  684.         managers=[
    
  685.             ("food_qs", FoodQuerySet.as_manager()),
    
  686.             ("food_mgr", FoodManager("a", "b")),
    
  687.             ("food_mgr_kwargs", FoodManager("x", "y", 3, 4)),
    
  688.         ],
    
  689.     )
    
  690.     other_stable = ModelState(
    
  691.         "otherapp", "Stable", [("id", models.AutoField(primary_key=True))]
    
  692.     )
    
  693.     third_thing = ModelState(
    
  694.         "thirdapp", "Thing", [("id", models.AutoField(primary_key=True))]
    
  695.     )
    
  696.     book = ModelState(
    
  697.         "otherapp",
    
  698.         "Book",
    
  699.         [
    
  700.             ("id", models.AutoField(primary_key=True)),
    
  701.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  702.             ("title", models.CharField(max_length=200)),
    
  703.         ],
    
  704.     )
    
  705.     book_proxy_fk = ModelState(
    
  706.         "otherapp",
    
  707.         "Book",
    
  708.         [
    
  709.             ("id", models.AutoField(primary_key=True)),
    
  710.             ("author", models.ForeignKey("thirdapp.AuthorProxy", models.CASCADE)),
    
  711.             ("title", models.CharField(max_length=200)),
    
  712.         ],
    
  713.     )
    
  714.     book_proxy_proxy_fk = ModelState(
    
  715.         "otherapp",
    
  716.         "Book",
    
  717.         [
    
  718.             ("id", models.AutoField(primary_key=True)),
    
  719.             ("author", models.ForeignKey("testapp.AAuthorProxyProxy", models.CASCADE)),
    
  720.         ],
    
  721.     )
    
  722.     book_migrations_fk = ModelState(
    
  723.         "otherapp",
    
  724.         "Book",
    
  725.         [
    
  726.             ("id", models.AutoField(primary_key=True)),
    
  727.             ("author", models.ForeignKey("migrations.UnmigratedModel", models.CASCADE)),
    
  728.             ("title", models.CharField(max_length=200)),
    
  729.         ],
    
  730.     )
    
  731.     book_with_no_author_fk = ModelState(
    
  732.         "otherapp",
    
  733.         "Book",
    
  734.         [
    
  735.             ("id", models.AutoField(primary_key=True)),
    
  736.             ("author", models.IntegerField()),
    
  737.             ("title", models.CharField(max_length=200)),
    
  738.         ],
    
  739.     )
    
  740.     book_with_no_author = ModelState(
    
  741.         "otherapp",
    
  742.         "Book",
    
  743.         [
    
  744.             ("id", models.AutoField(primary_key=True)),
    
  745.             ("title", models.CharField(max_length=200)),
    
  746.         ],
    
  747.     )
    
  748.     book_with_author_renamed = ModelState(
    
  749.         "otherapp",
    
  750.         "Book",
    
  751.         [
    
  752.             ("id", models.AutoField(primary_key=True)),
    
  753.             ("author", models.ForeignKey("testapp.Writer", models.CASCADE)),
    
  754.             ("title", models.CharField(max_length=200)),
    
  755.         ],
    
  756.     )
    
  757.     book_with_field_and_author_renamed = ModelState(
    
  758.         "otherapp",
    
  759.         "Book",
    
  760.         [
    
  761.             ("id", models.AutoField(primary_key=True)),
    
  762.             ("writer", models.ForeignKey("testapp.Writer", models.CASCADE)),
    
  763.             ("title", models.CharField(max_length=200)),
    
  764.         ],
    
  765.     )
    
  766.     book_with_multiple_authors = ModelState(
    
  767.         "otherapp",
    
  768.         "Book",
    
  769.         [
    
  770.             ("id", models.AutoField(primary_key=True)),
    
  771.             ("authors", models.ManyToManyField("testapp.Author")),
    
  772.             ("title", models.CharField(max_length=200)),
    
  773.         ],
    
  774.     )
    
  775.     book_with_multiple_authors_through_attribution = ModelState(
    
  776.         "otherapp",
    
  777.         "Book",
    
  778.         [
    
  779.             ("id", models.AutoField(primary_key=True)),
    
  780.             (
    
  781.                 "authors",
    
  782.                 models.ManyToManyField(
    
  783.                     "testapp.Author", through="otherapp.Attribution"
    
  784.                 ),
    
  785.             ),
    
  786.             ("title", models.CharField(max_length=200)),
    
  787.         ],
    
  788.     )
    
  789.     book_indexes = ModelState(
    
  790.         "otherapp",
    
  791.         "Book",
    
  792.         [
    
  793.             ("id", models.AutoField(primary_key=True)),
    
  794.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  795.             ("title", models.CharField(max_length=200)),
    
  796.         ],
    
  797.         {
    
  798.             "indexes": [
    
  799.                 models.Index(fields=["author", "title"], name="book_title_author_idx")
    
  800.             ],
    
  801.         },
    
  802.     )
    
  803.     book_unordered_indexes = ModelState(
    
  804.         "otherapp",
    
  805.         "Book",
    
  806.         [
    
  807.             ("id", models.AutoField(primary_key=True)),
    
  808.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  809.             ("title", models.CharField(max_length=200)),
    
  810.         ],
    
  811.         {
    
  812.             "indexes": [
    
  813.                 models.Index(fields=["title", "author"], name="book_author_title_idx")
    
  814.             ],
    
  815.         },
    
  816.     )
    
  817.     book_foo_together = ModelState(
    
  818.         "otherapp",
    
  819.         "Book",
    
  820.         [
    
  821.             ("id", models.AutoField(primary_key=True)),
    
  822.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  823.             ("title", models.CharField(max_length=200)),
    
  824.         ],
    
  825.         {
    
  826.             "index_together": {("author", "title")},
    
  827.             "unique_together": {("author", "title")},
    
  828.         },
    
  829.     )
    
  830.     book_foo_together_2 = ModelState(
    
  831.         "otherapp",
    
  832.         "Book",
    
  833.         [
    
  834.             ("id", models.AutoField(primary_key=True)),
    
  835.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  836.             ("title", models.CharField(max_length=200)),
    
  837.         ],
    
  838.         {
    
  839.             "index_together": {("title", "author")},
    
  840.             "unique_together": {("title", "author")},
    
  841.         },
    
  842.     )
    
  843.     book_foo_together_3 = ModelState(
    
  844.         "otherapp",
    
  845.         "Book",
    
  846.         [
    
  847.             ("id", models.AutoField(primary_key=True)),
    
  848.             ("newfield", models.IntegerField()),
    
  849.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  850.             ("title", models.CharField(max_length=200)),
    
  851.         ],
    
  852.         {
    
  853.             "index_together": {("title", "newfield")},
    
  854.             "unique_together": {("title", "newfield")},
    
  855.         },
    
  856.     )
    
  857.     book_foo_together_4 = ModelState(
    
  858.         "otherapp",
    
  859.         "Book",
    
  860.         [
    
  861.             ("id", models.AutoField(primary_key=True)),
    
  862.             ("newfield2", models.IntegerField()),
    
  863.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  864.             ("title", models.CharField(max_length=200)),
    
  865.         ],
    
  866.         {
    
  867.             "index_together": {("title", "newfield2")},
    
  868.             "unique_together": {("title", "newfield2")},
    
  869.         },
    
  870.     )
    
  871.     book_unique_together = ModelState(
    
  872.         "otherapp",
    
  873.         "Book",
    
  874.         [
    
  875.             ("id", models.AutoField(primary_key=True)),
    
  876.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  877.             ("title", models.CharField(max_length=200)),
    
  878.         ],
    
  879.         {
    
  880.             "unique_together": {("author", "title")},
    
  881.         },
    
  882.     )
    
  883.     attribution = ModelState(
    
  884.         "otherapp",
    
  885.         "Attribution",
    
  886.         [
    
  887.             ("id", models.AutoField(primary_key=True)),
    
  888.             ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  889.             ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  890.         ],
    
  891.     )
    
  892.     edition = ModelState(
    
  893.         "thirdapp",
    
  894.         "Edition",
    
  895.         [
    
  896.             ("id", models.AutoField(primary_key=True)),
    
  897.             ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  898.         ],
    
  899.     )
    
  900.     custom_user = ModelState(
    
  901.         "thirdapp",
    
  902.         "CustomUser",
    
  903.         [
    
  904.             ("id", models.AutoField(primary_key=True)),
    
  905.             ("username", models.CharField(max_length=255)),
    
  906.         ],
    
  907.         bases=(AbstractBaseUser,),
    
  908.     )
    
  909.     custom_user_no_inherit = ModelState(
    
  910.         "thirdapp",
    
  911.         "CustomUser",
    
  912.         [
    
  913.             ("id", models.AutoField(primary_key=True)),
    
  914.             ("username", models.CharField(max_length=255)),
    
  915.         ],
    
  916.     )
    
  917.     aardvark = ModelState(
    
  918.         "thirdapp", "Aardvark", [("id", models.AutoField(primary_key=True))]
    
  919.     )
    
  920.     aardvark_testapp = ModelState(
    
  921.         "testapp", "Aardvark", [("id", models.AutoField(primary_key=True))]
    
  922.     )
    
  923.     aardvark_based_on_author = ModelState(
    
  924.         "testapp", "Aardvark", [], bases=("testapp.Author",)
    
  925.     )
    
  926.     aardvark_pk_fk_author = ModelState(
    
  927.         "testapp",
    
  928.         "Aardvark",
    
  929.         [
    
  930.             (
    
  931.                 "id",
    
  932.                 models.OneToOneField(
    
  933.                     "testapp.Author", models.CASCADE, primary_key=True
    
  934.                 ),
    
  935.             ),
    
  936.         ],
    
  937.     )
    
  938.     knight = ModelState("eggs", "Knight", [("id", models.AutoField(primary_key=True))])
    
  939.     rabbit = ModelState(
    
  940.         "eggs",
    
  941.         "Rabbit",
    
  942.         [
    
  943.             ("id", models.AutoField(primary_key=True)),
    
  944.             ("knight", models.ForeignKey("eggs.Knight", models.CASCADE)),
    
  945.             ("parent", models.ForeignKey("eggs.Rabbit", models.CASCADE)),
    
  946.         ],
    
  947.         {
    
  948.             "unique_together": {("parent", "knight")},
    
  949.             "indexes": [
    
  950.                 models.Index(
    
  951.                     fields=["parent", "knight"], name="rabbit_circular_fk_index"
    
  952.                 )
    
  953.             ],
    
  954.         },
    
  955.     )
    
  956. 
    
  957.     def repr_changes(self, changes, include_dependencies=False):
    
  958.         output = ""
    
  959.         for app_label, migrations_ in sorted(changes.items()):
    
  960.             output += "  %s:\n" % app_label
    
  961.             for migration in migrations_:
    
  962.                 output += "    %s\n" % migration.name
    
  963.                 for operation in migration.operations:
    
  964.                     output += "      %s\n" % operation
    
  965.                 if include_dependencies:
    
  966.                     output += "      Dependencies:\n"
    
  967.                     if migration.dependencies:
    
  968.                         for dep in migration.dependencies:
    
  969.                             output += "        %s\n" % (dep,)
    
  970.                     else:
    
  971.                         output += "        None\n"
    
  972.         return output
    
  973. 
    
  974.     def assertNumberMigrations(self, changes, app_label, number):
    
  975.         if len(changes.get(app_label, [])) != number:
    
  976.             self.fail(
    
  977.                 "Incorrect number of migrations (%s) for %s (expected %s)\n%s"
    
  978.                 % (
    
  979.                     len(changes.get(app_label, [])),
    
  980.                     app_label,
    
  981.                     number,
    
  982.                     self.repr_changes(changes),
    
  983.                 )
    
  984.             )
    
  985. 
    
  986.     def assertMigrationDependencies(self, changes, app_label, position, dependencies):
    
  987.         if not changes.get(app_label):
    
  988.             self.fail(
    
  989.                 "No migrations found for %s\n%s"
    
  990.                 % (app_label, self.repr_changes(changes))
    
  991.             )
    
  992.         if len(changes[app_label]) < position + 1:
    
  993.             self.fail(
    
  994.                 "No migration at index %s for %s\n%s"
    
  995.                 % (position, app_label, self.repr_changes(changes))
    
  996.             )
    
  997.         migration = changes[app_label][position]
    
  998.         if set(migration.dependencies) != set(dependencies):
    
  999.             self.fail(
    
  1000.                 "Migration dependencies mismatch for %s.%s (expected %s):\n%s"
    
  1001.                 % (
    
  1002.                     app_label,
    
  1003.                     migration.name,
    
  1004.                     dependencies,
    
  1005.                     self.repr_changes(changes, include_dependencies=True),
    
  1006.                 )
    
  1007.             )
    
  1008. 
    
  1009.     def assertOperationTypes(self, changes, app_label, position, types):
    
  1010.         if not changes.get(app_label):
    
  1011.             self.fail(
    
  1012.                 "No migrations found for %s\n%s"
    
  1013.                 % (app_label, self.repr_changes(changes))
    
  1014.             )
    
  1015.         if len(changes[app_label]) < position + 1:
    
  1016.             self.fail(
    
  1017.                 "No migration at index %s for %s\n%s"
    
  1018.                 % (position, app_label, self.repr_changes(changes))
    
  1019.             )
    
  1020.         migration = changes[app_label][position]
    
  1021.         real_types = [
    
  1022.             operation.__class__.__name__ for operation in migration.operations
    
  1023.         ]
    
  1024.         if types != real_types:
    
  1025.             self.fail(
    
  1026.                 "Operation type mismatch for %s.%s (expected %s):\n%s"
    
  1027.                 % (
    
  1028.                     app_label,
    
  1029.                     migration.name,
    
  1030.                     types,
    
  1031.                     self.repr_changes(changes),
    
  1032.                 )
    
  1033.             )
    
  1034. 
    
  1035.     def assertOperationAttributes(
    
  1036.         self, changes, app_label, position, operation_position, **attrs
    
  1037.     ):
    
  1038.         if not changes.get(app_label):
    
  1039.             self.fail(
    
  1040.                 "No migrations found for %s\n%s"
    
  1041.                 % (app_label, self.repr_changes(changes))
    
  1042.             )
    
  1043.         if len(changes[app_label]) < position + 1:
    
  1044.             self.fail(
    
  1045.                 "No migration at index %s for %s\n%s"
    
  1046.                 % (position, app_label, self.repr_changes(changes))
    
  1047.             )
    
  1048.         migration = changes[app_label][position]
    
  1049.         if len(changes[app_label]) < position + 1:
    
  1050.             self.fail(
    
  1051.                 "No operation at index %s for %s.%s\n%s"
    
  1052.                 % (
    
  1053.                     operation_position,
    
  1054.                     app_label,
    
  1055.                     migration.name,
    
  1056.                     self.repr_changes(changes),
    
  1057.                 )
    
  1058.             )
    
  1059.         operation = migration.operations[operation_position]
    
  1060.         for attr, value in attrs.items():
    
  1061.             if getattr(operation, attr, None) != value:
    
  1062.                 self.fail(
    
  1063.                     "Attribute mismatch for %s.%s op #%s, %s (expected %r, got %r):\n%s"
    
  1064.                     % (
    
  1065.                         app_label,
    
  1066.                         migration.name,
    
  1067.                         operation_position,
    
  1068.                         attr,
    
  1069.                         value,
    
  1070.                         getattr(operation, attr, None),
    
  1071.                         self.repr_changes(changes),
    
  1072.                     )
    
  1073.                 )
    
  1074. 
    
  1075.     def assertOperationFieldAttributes(
    
  1076.         self, changes, app_label, position, operation_position, **attrs
    
  1077.     ):
    
  1078.         if not changes.get(app_label):
    
  1079.             self.fail(
    
  1080.                 "No migrations found for %s\n%s"
    
  1081.                 % (app_label, self.repr_changes(changes))
    
  1082.             )
    
  1083.         if len(changes[app_label]) < position + 1:
    
  1084.             self.fail(
    
  1085.                 "No migration at index %s for %s\n%s"
    
  1086.                 % (position, app_label, self.repr_changes(changes))
    
  1087.             )
    
  1088.         migration = changes[app_label][position]
    
  1089.         if len(changes[app_label]) < position + 1:
    
  1090.             self.fail(
    
  1091.                 "No operation at index %s for %s.%s\n%s"
    
  1092.                 % (
    
  1093.                     operation_position,
    
  1094.                     app_label,
    
  1095.                     migration.name,
    
  1096.                     self.repr_changes(changes),
    
  1097.                 )
    
  1098.             )
    
  1099.         operation = migration.operations[operation_position]
    
  1100.         if not hasattr(operation, "field"):
    
  1101.             self.fail(
    
  1102.                 "No field attribute for %s.%s op #%s."
    
  1103.                 % (
    
  1104.                     app_label,
    
  1105.                     migration.name,
    
  1106.                     operation_position,
    
  1107.                 )
    
  1108.             )
    
  1109.         field = operation.field
    
  1110.         for attr, value in attrs.items():
    
  1111.             if getattr(field, attr, None) != value:
    
  1112.                 self.fail(
    
  1113.                     "Field attribute mismatch for %s.%s op #%s, field.%s (expected %r, "
    
  1114.                     "got %r):\n%s"
    
  1115.                     % (
    
  1116.                         app_label,
    
  1117.                         migration.name,
    
  1118.                         operation_position,
    
  1119.                         attr,
    
  1120.                         value,
    
  1121.                         getattr(field, attr, None),
    
  1122.                         self.repr_changes(changes),
    
  1123.                     )
    
  1124.                 )
    
  1125. 
    
  1126.     def make_project_state(self, model_states):
    
  1127.         "Shortcut to make ProjectStates from lists of predefined models"
    
  1128.         project_state = ProjectState()
    
  1129.         for model_state in model_states:
    
  1130.             project_state.add_model(model_state.clone())
    
  1131.         return project_state
    
  1132. 
    
  1133.     def get_changes(self, before_states, after_states, questioner=None):
    
  1134.         if not isinstance(before_states, ProjectState):
    
  1135.             before_states = self.make_project_state(before_states)
    
  1136.         if not isinstance(after_states, ProjectState):
    
  1137.             after_states = self.make_project_state(after_states)
    
  1138.         return MigrationAutodetector(
    
  1139.             before_states,
    
  1140.             after_states,
    
  1141.             questioner,
    
  1142.         )._detect_changes()
    
  1143. 
    
  1144.     def test_arrange_for_graph(self):
    
  1145.         """Tests auto-naming of migrations for graph matching."""
    
  1146.         # Make a fake graph
    
  1147.         graph = MigrationGraph()
    
  1148.         graph.add_node(("testapp", "0001_initial"), None)
    
  1149.         graph.add_node(("testapp", "0002_foobar"), None)
    
  1150.         graph.add_node(("otherapp", "0001_initial"), None)
    
  1151.         graph.add_dependency(
    
  1152.             "testapp.0002_foobar",
    
  1153.             ("testapp", "0002_foobar"),
    
  1154.             ("testapp", "0001_initial"),
    
  1155.         )
    
  1156.         graph.add_dependency(
    
  1157.             "testapp.0002_foobar",
    
  1158.             ("testapp", "0002_foobar"),
    
  1159.             ("otherapp", "0001_initial"),
    
  1160.         )
    
  1161.         # Use project state to make a new migration change set
    
  1162.         before = self.make_project_state([self.publisher, self.other_pony])
    
  1163.         after = self.make_project_state(
    
  1164.             [
    
  1165.                 self.author_empty,
    
  1166.                 self.publisher,
    
  1167.                 self.other_pony,
    
  1168.                 self.other_stable,
    
  1169.             ]
    
  1170.         )
    
  1171.         autodetector = MigrationAutodetector(before, after)
    
  1172.         changes = autodetector._detect_changes()
    
  1173.         # Run through arrange_for_graph
    
  1174.         changes = autodetector.arrange_for_graph(changes, graph)
    
  1175.         # Make sure there's a new name, deps match, etc.
    
  1176.         self.assertEqual(changes["testapp"][0].name, "0003_author")
    
  1177.         self.assertEqual(
    
  1178.             changes["testapp"][0].dependencies, [("testapp", "0002_foobar")]
    
  1179.         )
    
  1180.         self.assertEqual(changes["otherapp"][0].name, "0002_stable")
    
  1181.         self.assertEqual(
    
  1182.             changes["otherapp"][0].dependencies, [("otherapp", "0001_initial")]
    
  1183.         )
    
  1184. 
    
  1185.     def test_arrange_for_graph_with_multiple_initial(self):
    
  1186.         # Make a fake graph.
    
  1187.         graph = MigrationGraph()
    
  1188.         # Use project state to make a new migration change set.
    
  1189.         before = self.make_project_state([])
    
  1190.         after = self.make_project_state(
    
  1191.             [self.author_with_book, self.book, self.attribution]
    
  1192.         )
    
  1193.         autodetector = MigrationAutodetector(
    
  1194.             before, after, MigrationQuestioner({"ask_initial": True})
    
  1195.         )
    
  1196.         changes = autodetector._detect_changes()
    
  1197.         changes = autodetector.arrange_for_graph(changes, graph)
    
  1198. 
    
  1199.         self.assertEqual(changes["otherapp"][0].name, "0001_initial")
    
  1200.         self.assertEqual(changes["otherapp"][0].dependencies, [])
    
  1201.         self.assertEqual(changes["otherapp"][1].name, "0002_initial")
    
  1202.         self.assertCountEqual(
    
  1203.             changes["otherapp"][1].dependencies,
    
  1204.             [("testapp", "0001_initial"), ("otherapp", "0001_initial")],
    
  1205.         )
    
  1206.         self.assertEqual(changes["testapp"][0].name, "0001_initial")
    
  1207.         self.assertEqual(
    
  1208.             changes["testapp"][0].dependencies, [("otherapp", "0001_initial")]
    
  1209.         )
    
  1210. 
    
  1211.     def test_trim_apps(self):
    
  1212.         """
    
  1213.         Trim does not remove dependencies but does remove unwanted apps.
    
  1214.         """
    
  1215.         # Use project state to make a new migration change set
    
  1216.         before = self.make_project_state([])
    
  1217.         after = self.make_project_state(
    
  1218.             [self.author_empty, self.other_pony, self.other_stable, self.third_thing]
    
  1219.         )
    
  1220.         autodetector = MigrationAutodetector(
    
  1221.             before, after, MigrationQuestioner({"ask_initial": True})
    
  1222.         )
    
  1223.         changes = autodetector._detect_changes()
    
  1224.         # Run through arrange_for_graph
    
  1225.         graph = MigrationGraph()
    
  1226.         changes = autodetector.arrange_for_graph(changes, graph)
    
  1227.         changes["testapp"][0].dependencies.append(("otherapp", "0001_initial"))
    
  1228.         changes = autodetector._trim_to_apps(changes, {"testapp"})
    
  1229.         # Make sure there's the right set of migrations
    
  1230.         self.assertEqual(changes["testapp"][0].name, "0001_initial")
    
  1231.         self.assertEqual(changes["otherapp"][0].name, "0001_initial")
    
  1232.         self.assertNotIn("thirdapp", changes)
    
  1233. 
    
  1234.     def test_custom_migration_name(self):
    
  1235.         """Tests custom naming of migrations for graph matching."""
    
  1236.         # Make a fake graph
    
  1237.         graph = MigrationGraph()
    
  1238.         graph.add_node(("testapp", "0001_initial"), None)
    
  1239.         graph.add_node(("testapp", "0002_foobar"), None)
    
  1240.         graph.add_node(("otherapp", "0001_initial"), None)
    
  1241.         graph.add_dependency(
    
  1242.             "testapp.0002_foobar",
    
  1243.             ("testapp", "0002_foobar"),
    
  1244.             ("testapp", "0001_initial"),
    
  1245.         )
    
  1246. 
    
  1247.         # Use project state to make a new migration change set
    
  1248.         before = self.make_project_state([])
    
  1249.         after = self.make_project_state(
    
  1250.             [self.author_empty, self.other_pony, self.other_stable]
    
  1251.         )
    
  1252.         autodetector = MigrationAutodetector(before, after)
    
  1253.         changes = autodetector._detect_changes()
    
  1254. 
    
  1255.         # Run through arrange_for_graph
    
  1256.         migration_name = "custom_name"
    
  1257.         changes = autodetector.arrange_for_graph(changes, graph, migration_name)
    
  1258. 
    
  1259.         # Make sure there's a new name, deps match, etc.
    
  1260.         self.assertEqual(changes["testapp"][0].name, "0003_%s" % migration_name)
    
  1261.         self.assertEqual(
    
  1262.             changes["testapp"][0].dependencies, [("testapp", "0002_foobar")]
    
  1263.         )
    
  1264.         self.assertEqual(changes["otherapp"][0].name, "0002_%s" % migration_name)
    
  1265.         self.assertEqual(
    
  1266.             changes["otherapp"][0].dependencies, [("otherapp", "0001_initial")]
    
  1267.         )
    
  1268. 
    
  1269.     def test_new_model(self):
    
  1270.         """Tests autodetection of new models."""
    
  1271.         changes = self.get_changes([], [self.other_pony_food])
    
  1272.         # Right number/type of migrations?
    
  1273.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  1274.         self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
    
  1275.         self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Pony")
    
  1276.         self.assertEqual(
    
  1277.             [name for name, mgr in changes["otherapp"][0].operations[0].managers],
    
  1278.             ["food_qs", "food_mgr", "food_mgr_kwargs"],
    
  1279.         )
    
  1280. 
    
  1281.     def test_old_model(self):
    
  1282.         """Tests deletion of old models."""
    
  1283.         changes = self.get_changes([self.author_empty], [])
    
  1284.         # Right number/type of migrations?
    
  1285.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1286.         self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel"])
    
  1287.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  1288. 
    
  1289.     def test_add_field(self):
    
  1290.         """Tests autodetection of new fields."""
    
  1291.         changes = self.get_changes([self.author_empty], [self.author_name])
    
  1292.         # Right number/type of migrations?
    
  1293.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1294.         self.assertOperationTypes(changes, "testapp", 0, ["AddField"])
    
  1295.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="name")
    
  1296. 
    
  1297.     @mock.patch(
    
  1298.         "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition",
    
  1299.         side_effect=AssertionError("Should not have prompted for not null addition"),
    
  1300.     )
    
  1301.     def test_add_date_fields_with_auto_now_not_asking_for_default(
    
  1302.         self, mocked_ask_method
    
  1303.     ):
    
  1304.         changes = self.get_changes(
    
  1305.             [self.author_empty], [self.author_dates_of_birth_auto_now]
    
  1306.         )
    
  1307.         # Right number/type of migrations?
    
  1308.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1309.         self.assertOperationTypes(
    
  1310.             changes, "testapp", 0, ["AddField", "AddField", "AddField"]
    
  1311.         )
    
  1312.         self.assertOperationFieldAttributes(changes, "testapp", 0, 0, auto_now=True)
    
  1313.         self.assertOperationFieldAttributes(changes, "testapp", 0, 1, auto_now=True)
    
  1314.         self.assertOperationFieldAttributes(changes, "testapp", 0, 2, auto_now=True)
    
  1315. 
    
  1316.     @mock.patch(
    
  1317.         "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition",
    
  1318.         side_effect=AssertionError("Should not have prompted for not null addition"),
    
  1319.     )
    
  1320.     def test_add_date_fields_with_auto_now_add_not_asking_for_null_addition(
    
  1321.         self, mocked_ask_method
    
  1322.     ):
    
  1323.         changes = self.get_changes(
    
  1324.             [self.author_empty], [self.author_dates_of_birth_auto_now_add]
    
  1325.         )
    
  1326.         # Right number/type of migrations?
    
  1327.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1328.         self.assertOperationTypes(
    
  1329.             changes, "testapp", 0, ["AddField", "AddField", "AddField"]
    
  1330.         )
    
  1331.         self.assertOperationFieldAttributes(changes, "testapp", 0, 0, auto_now_add=True)
    
  1332.         self.assertOperationFieldAttributes(changes, "testapp", 0, 1, auto_now_add=True)
    
  1333.         self.assertOperationFieldAttributes(changes, "testapp", 0, 2, auto_now_add=True)
    
  1334. 
    
  1335.     @mock.patch(
    
  1336.         "django.db.migrations.questioner.MigrationQuestioner.ask_auto_now_add_addition"
    
  1337.     )
    
  1338.     def test_add_date_fields_with_auto_now_add_asking_for_default(
    
  1339.         self, mocked_ask_method
    
  1340.     ):
    
  1341.         changes = self.get_changes(
    
  1342.             [self.author_empty], [self.author_dates_of_birth_auto_now_add]
    
  1343.         )
    
  1344.         # Right number/type of migrations?
    
  1345.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1346.         self.assertOperationTypes(
    
  1347.             changes, "testapp", 0, ["AddField", "AddField", "AddField"]
    
  1348.         )
    
  1349.         self.assertOperationFieldAttributes(changes, "testapp", 0, 0, auto_now_add=True)
    
  1350.         self.assertOperationFieldAttributes(changes, "testapp", 0, 1, auto_now_add=True)
    
  1351.         self.assertOperationFieldAttributes(changes, "testapp", 0, 2, auto_now_add=True)
    
  1352.         self.assertEqual(mocked_ask_method.call_count, 3)
    
  1353. 
    
  1354.     def test_remove_field(self):
    
  1355.         """Tests autodetection of removed fields."""
    
  1356.         changes = self.get_changes([self.author_name], [self.author_empty])
    
  1357.         # Right number/type of migrations?
    
  1358.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1359.         self.assertOperationTypes(changes, "testapp", 0, ["RemoveField"])
    
  1360.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="name")
    
  1361. 
    
  1362.     def test_alter_field(self):
    
  1363.         """Tests autodetection of new fields."""
    
  1364.         changes = self.get_changes([self.author_name], [self.author_name_longer])
    
  1365.         # Right number/type of migrations?
    
  1366.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1367.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  1368.         self.assertOperationAttributes(
    
  1369.             changes, "testapp", 0, 0, name="name", preserve_default=True
    
  1370.         )
    
  1371. 
    
  1372.     def test_supports_functools_partial(self):
    
  1373.         def _content_file_name(instance, filename, key, **kwargs):
    
  1374.             return "{}/{}".format(instance, filename)
    
  1375. 
    
  1376.         def content_file_name(key, **kwargs):
    
  1377.             return functools.partial(_content_file_name, key, **kwargs)
    
  1378. 
    
  1379.         # An unchanged partial reference.
    
  1380.         before = [
    
  1381.             ModelState(
    
  1382.                 "testapp",
    
  1383.                 "Author",
    
  1384.                 [
    
  1385.                     ("id", models.AutoField(primary_key=True)),
    
  1386.                     (
    
  1387.                         "file",
    
  1388.                         models.FileField(
    
  1389.                             max_length=200, upload_to=content_file_name("file")
    
  1390.                         ),
    
  1391.                     ),
    
  1392.                 ],
    
  1393.             )
    
  1394.         ]
    
  1395.         after = [
    
  1396.             ModelState(
    
  1397.                 "testapp",
    
  1398.                 "Author",
    
  1399.                 [
    
  1400.                     ("id", models.AutoField(primary_key=True)),
    
  1401.                     (
    
  1402.                         "file",
    
  1403.                         models.FileField(
    
  1404.                             max_length=200, upload_to=content_file_name("file")
    
  1405.                         ),
    
  1406.                     ),
    
  1407.                 ],
    
  1408.             )
    
  1409.         ]
    
  1410.         changes = self.get_changes(before, after)
    
  1411.         self.assertNumberMigrations(changes, "testapp", 0)
    
  1412. 
    
  1413.         # A changed partial reference.
    
  1414.         args_changed = [
    
  1415.             ModelState(
    
  1416.                 "testapp",
    
  1417.                 "Author",
    
  1418.                 [
    
  1419.                     ("id", models.AutoField(primary_key=True)),
    
  1420.                     (
    
  1421.                         "file",
    
  1422.                         models.FileField(
    
  1423.                             max_length=200, upload_to=content_file_name("other-file")
    
  1424.                         ),
    
  1425.                     ),
    
  1426.                 ],
    
  1427.             )
    
  1428.         ]
    
  1429.         changes = self.get_changes(before, args_changed)
    
  1430.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1431.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  1432.         # Can't use assertOperationFieldAttributes because we need the
    
  1433.         # deconstructed version, i.e., the exploded func/args/keywords rather
    
  1434.         # than the partial: we don't care if it's not the same instance of the
    
  1435.         # partial, only if it's the same source function, args, and keywords.
    
  1436.         value = changes["testapp"][0].operations[0].field.upload_to
    
  1437.         self.assertEqual(
    
  1438.             (_content_file_name, ("other-file",), {}),
    
  1439.             (value.func, value.args, value.keywords),
    
  1440.         )
    
  1441. 
    
  1442.         kwargs_changed = [
    
  1443.             ModelState(
    
  1444.                 "testapp",
    
  1445.                 "Author",
    
  1446.                 [
    
  1447.                     ("id", models.AutoField(primary_key=True)),
    
  1448.                     (
    
  1449.                         "file",
    
  1450.                         models.FileField(
    
  1451.                             max_length=200,
    
  1452.                             upload_to=content_file_name("file", spam="eggs"),
    
  1453.                         ),
    
  1454.                     ),
    
  1455.                 ],
    
  1456.             )
    
  1457.         ]
    
  1458.         changes = self.get_changes(before, kwargs_changed)
    
  1459.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1460.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  1461.         value = changes["testapp"][0].operations[0].field.upload_to
    
  1462.         self.assertEqual(
    
  1463.             (_content_file_name, ("file",), {"spam": "eggs"}),
    
  1464.             (value.func, value.args, value.keywords),
    
  1465.         )
    
  1466. 
    
  1467.     @mock.patch(
    
  1468.         "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration",
    
  1469.         side_effect=AssertionError("Should not have prompted for not null addition"),
    
  1470.     )
    
  1471.     def test_alter_field_to_not_null_with_default(self, mocked_ask_method):
    
  1472.         """
    
  1473.         #23609 - Tests autodetection of nullable to non-nullable alterations.
    
  1474.         """
    
  1475.         changes = self.get_changes([self.author_name_null], [self.author_name_default])
    
  1476.         # Right number/type of migrations?
    
  1477.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1478.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  1479.         self.assertOperationAttributes(
    
  1480.             changes, "testapp", 0, 0, name="name", preserve_default=True
    
  1481.         )
    
  1482.         self.assertOperationFieldAttributes(
    
  1483.             changes, "testapp", 0, 0, default="Ada Lovelace"
    
  1484.         )
    
  1485. 
    
  1486.     @mock.patch(
    
  1487.         "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration",
    
  1488.         return_value=models.NOT_PROVIDED,
    
  1489.     )
    
  1490.     def test_alter_field_to_not_null_without_default(self, mocked_ask_method):
    
  1491.         """
    
  1492.         #23609 - Tests autodetection of nullable to non-nullable alterations.
    
  1493.         """
    
  1494.         changes = self.get_changes([self.author_name_null], [self.author_name])
    
  1495.         self.assertEqual(mocked_ask_method.call_count, 1)
    
  1496.         # Right number/type of migrations?
    
  1497.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1498.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  1499.         self.assertOperationAttributes(
    
  1500.             changes, "testapp", 0, 0, name="name", preserve_default=True
    
  1501.         )
    
  1502.         self.assertOperationFieldAttributes(
    
  1503.             changes, "testapp", 0, 0, default=models.NOT_PROVIDED
    
  1504.         )
    
  1505. 
    
  1506.     @mock.patch(
    
  1507.         "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_alteration",
    
  1508.         return_value="Some Name",
    
  1509.     )
    
  1510.     def test_alter_field_to_not_null_oneoff_default(self, mocked_ask_method):
    
  1511.         """
    
  1512.         #23609 - Tests autodetection of nullable to non-nullable alterations.
    
  1513.         """
    
  1514.         changes = self.get_changes([self.author_name_null], [self.author_name])
    
  1515.         self.assertEqual(mocked_ask_method.call_count, 1)
    
  1516.         # Right number/type of migrations?
    
  1517.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1518.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  1519.         self.assertOperationAttributes(
    
  1520.             changes, "testapp", 0, 0, name="name", preserve_default=False
    
  1521.         )
    
  1522.         self.assertOperationFieldAttributes(
    
  1523.             changes, "testapp", 0, 0, default="Some Name"
    
  1524.         )
    
  1525. 
    
  1526.     def test_rename_field(self):
    
  1527.         """Tests autodetection of renamed fields."""
    
  1528.         changes = self.get_changes(
    
  1529.             [self.author_name],
    
  1530.             [self.author_name_renamed],
    
  1531.             MigrationQuestioner({"ask_rename": True}),
    
  1532.         )
    
  1533.         # Right number/type of migrations?
    
  1534.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1535.         self.assertOperationTypes(changes, "testapp", 0, ["RenameField"])
    
  1536.         self.assertOperationAttributes(
    
  1537.             changes, "testapp", 0, 0, old_name="name", new_name="names"
    
  1538.         )
    
  1539. 
    
  1540.     def test_rename_field_foreign_key_to_field(self):
    
  1541.         before = [
    
  1542.             ModelState(
    
  1543.                 "app",
    
  1544.                 "Foo",
    
  1545.                 [
    
  1546.                     ("id", models.AutoField(primary_key=True)),
    
  1547.                     ("field", models.IntegerField(unique=True)),
    
  1548.                 ],
    
  1549.             ),
    
  1550.             ModelState(
    
  1551.                 "app",
    
  1552.                 "Bar",
    
  1553.                 [
    
  1554.                     ("id", models.AutoField(primary_key=True)),
    
  1555.                     (
    
  1556.                         "foo",
    
  1557.                         models.ForeignKey("app.Foo", models.CASCADE, to_field="field"),
    
  1558.                     ),
    
  1559.                 ],
    
  1560.             ),
    
  1561.         ]
    
  1562.         after = [
    
  1563.             ModelState(
    
  1564.                 "app",
    
  1565.                 "Foo",
    
  1566.                 [
    
  1567.                     ("id", models.AutoField(primary_key=True)),
    
  1568.                     ("renamed_field", models.IntegerField(unique=True)),
    
  1569.                 ],
    
  1570.             ),
    
  1571.             ModelState(
    
  1572.                 "app",
    
  1573.                 "Bar",
    
  1574.                 [
    
  1575.                     ("id", models.AutoField(primary_key=True)),
    
  1576.                     (
    
  1577.                         "foo",
    
  1578.                         models.ForeignKey(
    
  1579.                             "app.Foo", models.CASCADE, to_field="renamed_field"
    
  1580.                         ),
    
  1581.                     ),
    
  1582.                 ],
    
  1583.             ),
    
  1584.         ]
    
  1585.         changes = self.get_changes(
    
  1586.             before, after, MigrationQuestioner({"ask_rename": True})
    
  1587.         )
    
  1588.         # Right number/type of migrations?
    
  1589.         self.assertNumberMigrations(changes, "app", 1)
    
  1590.         self.assertOperationTypes(changes, "app", 0, ["RenameField"])
    
  1591.         self.assertOperationAttributes(
    
  1592.             changes, "app", 0, 0, old_name="field", new_name="renamed_field"
    
  1593.         )
    
  1594. 
    
  1595.     def test_rename_foreign_object_fields(self):
    
  1596.         fields = ("first", "second")
    
  1597.         renamed_fields = ("first_renamed", "second_renamed")
    
  1598.         before = [
    
  1599.             ModelState(
    
  1600.                 "app",
    
  1601.                 "Foo",
    
  1602.                 [
    
  1603.                     ("id", models.AutoField(primary_key=True)),
    
  1604.                     ("first", models.IntegerField()),
    
  1605.                     ("second", models.IntegerField()),
    
  1606.                 ],
    
  1607.                 options={"unique_together": {fields}},
    
  1608.             ),
    
  1609.             ModelState(
    
  1610.                 "app",
    
  1611.                 "Bar",
    
  1612.                 [
    
  1613.                     ("id", models.AutoField(primary_key=True)),
    
  1614.                     ("first", models.IntegerField()),
    
  1615.                     ("second", models.IntegerField()),
    
  1616.                     (
    
  1617.                         "foo",
    
  1618.                         models.ForeignObject(
    
  1619.                             "app.Foo",
    
  1620.                             models.CASCADE,
    
  1621.                             from_fields=fields,
    
  1622.                             to_fields=fields,
    
  1623.                         ),
    
  1624.                     ),
    
  1625.                 ],
    
  1626.             ),
    
  1627.         ]
    
  1628.         # Case 1: to_fields renames.
    
  1629.         after = [
    
  1630.             ModelState(
    
  1631.                 "app",
    
  1632.                 "Foo",
    
  1633.                 [
    
  1634.                     ("id", models.AutoField(primary_key=True)),
    
  1635.                     ("first_renamed", models.IntegerField()),
    
  1636.                     ("second_renamed", models.IntegerField()),
    
  1637.                 ],
    
  1638.                 options={"unique_together": {renamed_fields}},
    
  1639.             ),
    
  1640.             ModelState(
    
  1641.                 "app",
    
  1642.                 "Bar",
    
  1643.                 [
    
  1644.                     ("id", models.AutoField(primary_key=True)),
    
  1645.                     ("first", models.IntegerField()),
    
  1646.                     ("second", models.IntegerField()),
    
  1647.                     (
    
  1648.                         "foo",
    
  1649.                         models.ForeignObject(
    
  1650.                             "app.Foo",
    
  1651.                             models.CASCADE,
    
  1652.                             from_fields=fields,
    
  1653.                             to_fields=renamed_fields,
    
  1654.                         ),
    
  1655.                     ),
    
  1656.                 ],
    
  1657.             ),
    
  1658.         ]
    
  1659.         changes = self.get_changes(
    
  1660.             before, after, MigrationQuestioner({"ask_rename": True})
    
  1661.         )
    
  1662.         self.assertNumberMigrations(changes, "app", 1)
    
  1663.         self.assertOperationTypes(
    
  1664.             changes, "app", 0, ["RenameField", "RenameField", "AlterUniqueTogether"]
    
  1665.         )
    
  1666.         self.assertOperationAttributes(
    
  1667.             changes,
    
  1668.             "app",
    
  1669.             0,
    
  1670.             0,
    
  1671.             model_name="foo",
    
  1672.             old_name="first",
    
  1673.             new_name="first_renamed",
    
  1674.         )
    
  1675.         self.assertOperationAttributes(
    
  1676.             changes,
    
  1677.             "app",
    
  1678.             0,
    
  1679.             1,
    
  1680.             model_name="foo",
    
  1681.             old_name="second",
    
  1682.             new_name="second_renamed",
    
  1683.         )
    
  1684.         # Case 2: from_fields renames.
    
  1685.         after = [
    
  1686.             ModelState(
    
  1687.                 "app",
    
  1688.                 "Foo",
    
  1689.                 [
    
  1690.                     ("id", models.AutoField(primary_key=True)),
    
  1691.                     ("first", models.IntegerField()),
    
  1692.                     ("second", models.IntegerField()),
    
  1693.                 ],
    
  1694.                 options={"unique_together": {fields}},
    
  1695.             ),
    
  1696.             ModelState(
    
  1697.                 "app",
    
  1698.                 "Bar",
    
  1699.                 [
    
  1700.                     ("id", models.AutoField(primary_key=True)),
    
  1701.                     ("first_renamed", models.IntegerField()),
    
  1702.                     ("second_renamed", models.IntegerField()),
    
  1703.                     (
    
  1704.                         "foo",
    
  1705.                         models.ForeignObject(
    
  1706.                             "app.Foo",
    
  1707.                             models.CASCADE,
    
  1708.                             from_fields=renamed_fields,
    
  1709.                             to_fields=fields,
    
  1710.                         ),
    
  1711.                     ),
    
  1712.                 ],
    
  1713.             ),
    
  1714.         ]
    
  1715.         changes = self.get_changes(
    
  1716.             before, after, MigrationQuestioner({"ask_rename": True})
    
  1717.         )
    
  1718.         self.assertNumberMigrations(changes, "app", 1)
    
  1719.         self.assertOperationTypes(changes, "app", 0, ["RenameField", "RenameField"])
    
  1720.         self.assertOperationAttributes(
    
  1721.             changes,
    
  1722.             "app",
    
  1723.             0,
    
  1724.             0,
    
  1725.             model_name="bar",
    
  1726.             old_name="first",
    
  1727.             new_name="first_renamed",
    
  1728.         )
    
  1729.         self.assertOperationAttributes(
    
  1730.             changes,
    
  1731.             "app",
    
  1732.             0,
    
  1733.             1,
    
  1734.             model_name="bar",
    
  1735.             old_name="second",
    
  1736.             new_name="second_renamed",
    
  1737.         )
    
  1738. 
    
  1739.     def test_rename_referenced_primary_key(self):
    
  1740.         before = [
    
  1741.             ModelState(
    
  1742.                 "app",
    
  1743.                 "Foo",
    
  1744.                 [
    
  1745.                     ("id", models.CharField(primary_key=True, serialize=False)),
    
  1746.                 ],
    
  1747.             ),
    
  1748.             ModelState(
    
  1749.                 "app",
    
  1750.                 "Bar",
    
  1751.                 [
    
  1752.                     ("id", models.AutoField(primary_key=True)),
    
  1753.                     ("foo", models.ForeignKey("app.Foo", models.CASCADE)),
    
  1754.                 ],
    
  1755.             ),
    
  1756.         ]
    
  1757.         after = [
    
  1758.             ModelState(
    
  1759.                 "app",
    
  1760.                 "Foo",
    
  1761.                 [("renamed_id", models.CharField(primary_key=True, serialize=False))],
    
  1762.             ),
    
  1763.             ModelState(
    
  1764.                 "app",
    
  1765.                 "Bar",
    
  1766.                 [
    
  1767.                     ("id", models.AutoField(primary_key=True)),
    
  1768.                     ("foo", models.ForeignKey("app.Foo", models.CASCADE)),
    
  1769.                 ],
    
  1770.             ),
    
  1771.         ]
    
  1772.         changes = self.get_changes(
    
  1773.             before, after, MigrationQuestioner({"ask_rename": True})
    
  1774.         )
    
  1775.         self.assertNumberMigrations(changes, "app", 1)
    
  1776.         self.assertOperationTypes(changes, "app", 0, ["RenameField"])
    
  1777.         self.assertOperationAttributes(
    
  1778.             changes, "app", 0, 0, old_name="id", new_name="renamed_id"
    
  1779.         )
    
  1780. 
    
  1781.     def test_rename_field_preserved_db_column(self):
    
  1782.         """
    
  1783.         RenameField is used if a field is renamed and db_column equal to the
    
  1784.         old field's column is added.
    
  1785.         """
    
  1786.         before = [
    
  1787.             ModelState(
    
  1788.                 "app",
    
  1789.                 "Foo",
    
  1790.                 [
    
  1791.                     ("id", models.AutoField(primary_key=True)),
    
  1792.                     ("field", models.IntegerField()),
    
  1793.                 ],
    
  1794.             ),
    
  1795.         ]
    
  1796.         after = [
    
  1797.             ModelState(
    
  1798.                 "app",
    
  1799.                 "Foo",
    
  1800.                 [
    
  1801.                     ("id", models.AutoField(primary_key=True)),
    
  1802.                     ("renamed_field", models.IntegerField(db_column="field")),
    
  1803.                 ],
    
  1804.             ),
    
  1805.         ]
    
  1806.         changes = self.get_changes(
    
  1807.             before, after, MigrationQuestioner({"ask_rename": True})
    
  1808.         )
    
  1809.         self.assertNumberMigrations(changes, "app", 1)
    
  1810.         self.assertOperationTypes(changes, "app", 0, ["AlterField", "RenameField"])
    
  1811.         self.assertOperationAttributes(
    
  1812.             changes,
    
  1813.             "app",
    
  1814.             0,
    
  1815.             0,
    
  1816.             model_name="foo",
    
  1817.             name="field",
    
  1818.         )
    
  1819.         self.assertEqual(
    
  1820.             changes["app"][0].operations[0].field.deconstruct(),
    
  1821.             (
    
  1822.                 "field",
    
  1823.                 "django.db.models.IntegerField",
    
  1824.                 [],
    
  1825.                 {"db_column": "field"},
    
  1826.             ),
    
  1827.         )
    
  1828.         self.assertOperationAttributes(
    
  1829.             changes,
    
  1830.             "app",
    
  1831.             0,
    
  1832.             1,
    
  1833.             model_name="foo",
    
  1834.             old_name="field",
    
  1835.             new_name="renamed_field",
    
  1836.         )
    
  1837. 
    
  1838.     def test_rename_related_field_preserved_db_column(self):
    
  1839.         before = [
    
  1840.             ModelState(
    
  1841.                 "app",
    
  1842.                 "Foo",
    
  1843.                 [
    
  1844.                     ("id", models.AutoField(primary_key=True)),
    
  1845.                 ],
    
  1846.             ),
    
  1847.             ModelState(
    
  1848.                 "app",
    
  1849.                 "Bar",
    
  1850.                 [
    
  1851.                     ("id", models.AutoField(primary_key=True)),
    
  1852.                     ("foo", models.ForeignKey("app.Foo", models.CASCADE)),
    
  1853.                 ],
    
  1854.             ),
    
  1855.         ]
    
  1856.         after = [
    
  1857.             ModelState(
    
  1858.                 "app",
    
  1859.                 "Foo",
    
  1860.                 [
    
  1861.                     ("id", models.AutoField(primary_key=True)),
    
  1862.                 ],
    
  1863.             ),
    
  1864.             ModelState(
    
  1865.                 "app",
    
  1866.                 "Bar",
    
  1867.                 [
    
  1868.                     ("id", models.AutoField(primary_key=True)),
    
  1869.                     (
    
  1870.                         "renamed_foo",
    
  1871.                         models.ForeignKey(
    
  1872.                             "app.Foo", models.CASCADE, db_column="foo_id"
    
  1873.                         ),
    
  1874.                     ),
    
  1875.                 ],
    
  1876.             ),
    
  1877.         ]
    
  1878.         changes = self.get_changes(
    
  1879.             before, after, MigrationQuestioner({"ask_rename": True})
    
  1880.         )
    
  1881.         self.assertNumberMigrations(changes, "app", 1)
    
  1882.         self.assertOperationTypes(changes, "app", 0, ["AlterField", "RenameField"])
    
  1883.         self.assertOperationAttributes(
    
  1884.             changes,
    
  1885.             "app",
    
  1886.             0,
    
  1887.             0,
    
  1888.             model_name="bar",
    
  1889.             name="foo",
    
  1890.         )
    
  1891.         self.assertEqual(
    
  1892.             changes["app"][0].operations[0].field.deconstruct(),
    
  1893.             (
    
  1894.                 "foo",
    
  1895.                 "django.db.models.ForeignKey",
    
  1896.                 [],
    
  1897.                 {"to": "app.foo", "on_delete": models.CASCADE, "db_column": "foo_id"},
    
  1898.             ),
    
  1899.         )
    
  1900.         self.assertOperationAttributes(
    
  1901.             changes,
    
  1902.             "app",
    
  1903.             0,
    
  1904.             1,
    
  1905.             model_name="bar",
    
  1906.             old_name="foo",
    
  1907.             new_name="renamed_foo",
    
  1908.         )
    
  1909. 
    
  1910.     def test_rename_field_with_renamed_model(self):
    
  1911.         changes = self.get_changes(
    
  1912.             [self.author_name],
    
  1913.             [
    
  1914.                 ModelState(
    
  1915.                     "testapp",
    
  1916.                     "RenamedAuthor",
    
  1917.                     [
    
  1918.                         ("id", models.AutoField(primary_key=True)),
    
  1919.                         ("renamed_name", models.CharField(max_length=200)),
    
  1920.                     ],
    
  1921.                 ),
    
  1922.             ],
    
  1923.             MigrationQuestioner({"ask_rename_model": True, "ask_rename": True}),
    
  1924.         )
    
  1925.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1926.         self.assertOperationTypes(changes, "testapp", 0, ["RenameModel", "RenameField"])
    
  1927.         self.assertOperationAttributes(
    
  1928.             changes,
    
  1929.             "testapp",
    
  1930.             0,
    
  1931.             0,
    
  1932.             old_name="Author",
    
  1933.             new_name="RenamedAuthor",
    
  1934.         )
    
  1935.         self.assertOperationAttributes(
    
  1936.             changes,
    
  1937.             "testapp",
    
  1938.             0,
    
  1939.             1,
    
  1940.             old_name="name",
    
  1941.             new_name="renamed_name",
    
  1942.         )
    
  1943. 
    
  1944.     def test_rename_model(self):
    
  1945.         """Tests autodetection of renamed models."""
    
  1946.         changes = self.get_changes(
    
  1947.             [self.author_with_book, self.book],
    
  1948.             [self.author_renamed_with_book, self.book_with_author_renamed],
    
  1949.             MigrationQuestioner({"ask_rename_model": True}),
    
  1950.         )
    
  1951.         # Right number/type of migrations?
    
  1952.         self.assertNumberMigrations(changes, "testapp", 1)
    
  1953.         self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
    
  1954.         self.assertOperationAttributes(
    
  1955.             changes, "testapp", 0, 0, old_name="Author", new_name="Writer"
    
  1956.         )
    
  1957.         # Now that RenameModel handles related fields too, there should be
    
  1958.         # no AlterField for the related field.
    
  1959.         self.assertNumberMigrations(changes, "otherapp", 0)
    
  1960. 
    
  1961.     def test_rename_model_case(self):
    
  1962.         """
    
  1963.         Model name is case-insensitive. Changing case doesn't lead to any
    
  1964.         autodetected operations.
    
  1965.         """
    
  1966.         author_renamed = ModelState(
    
  1967.             "testapp",
    
  1968.             "author",
    
  1969.             [
    
  1970.                 ("id", models.AutoField(primary_key=True)),
    
  1971.             ],
    
  1972.         )
    
  1973.         changes = self.get_changes(
    
  1974.             [self.author_empty, self.book],
    
  1975.             [author_renamed, self.book],
    
  1976.             questioner=MigrationQuestioner({"ask_rename_model": True}),
    
  1977.         )
    
  1978.         self.assertNumberMigrations(changes, "testapp", 0)
    
  1979.         self.assertNumberMigrations(changes, "otherapp", 0)
    
  1980. 
    
  1981.     def test_renamed_referenced_m2m_model_case(self):
    
  1982.         publisher_renamed = ModelState(
    
  1983.             "testapp",
    
  1984.             "publisher",
    
  1985.             [
    
  1986.                 ("id", models.AutoField(primary_key=True)),
    
  1987.                 ("name", models.CharField(max_length=100)),
    
  1988.             ],
    
  1989.         )
    
  1990.         changes = self.get_changes(
    
  1991.             [self.publisher, self.author_with_m2m],
    
  1992.             [publisher_renamed, self.author_with_m2m],
    
  1993.             questioner=MigrationQuestioner({"ask_rename_model": True}),
    
  1994.         )
    
  1995.         self.assertNumberMigrations(changes, "testapp", 0)
    
  1996.         self.assertNumberMigrations(changes, "otherapp", 0)
    
  1997. 
    
  1998.     def test_rename_m2m_through_model(self):
    
  1999.         """
    
  2000.         Tests autodetection of renamed models that are used in M2M relations as
    
  2001.         through models.
    
  2002.         """
    
  2003.         changes = self.get_changes(
    
  2004.             [self.author_with_m2m_through, self.publisher, self.contract],
    
  2005.             [
    
  2006.                 self.author_with_renamed_m2m_through,
    
  2007.                 self.publisher,
    
  2008.                 self.contract_renamed,
    
  2009.             ],
    
  2010.             MigrationQuestioner({"ask_rename_model": True}),
    
  2011.         )
    
  2012.         # Right number/type of migrations?
    
  2013.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2014.         self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
    
  2015.         self.assertOperationAttributes(
    
  2016.             changes, "testapp", 0, 0, old_name="Contract", new_name="Deal"
    
  2017.         )
    
  2018. 
    
  2019.     def test_rename_model_with_renamed_rel_field(self):
    
  2020.         """
    
  2021.         Tests autodetection of renamed models while simultaneously renaming one
    
  2022.         of the fields that relate to the renamed model.
    
  2023.         """
    
  2024.         changes = self.get_changes(
    
  2025.             [self.author_with_book, self.book],
    
  2026.             [self.author_renamed_with_book, self.book_with_field_and_author_renamed],
    
  2027.             MigrationQuestioner({"ask_rename": True, "ask_rename_model": True}),
    
  2028.         )
    
  2029.         # Right number/type of migrations?
    
  2030.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2031.         self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
    
  2032.         self.assertOperationAttributes(
    
  2033.             changes, "testapp", 0, 0, old_name="Author", new_name="Writer"
    
  2034.         )
    
  2035.         # Right number/type of migrations for related field rename?
    
  2036.         # Alter is already taken care of.
    
  2037.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2038.         self.assertOperationTypes(changes, "otherapp", 0, ["RenameField"])
    
  2039.         self.assertOperationAttributes(
    
  2040.             changes, "otherapp", 0, 0, old_name="author", new_name="writer"
    
  2041.         )
    
  2042. 
    
  2043.     def test_rename_model_with_fks_in_different_position(self):
    
  2044.         """
    
  2045.         #24537 - The order of fields in a model does not influence
    
  2046.         the RenameModel detection.
    
  2047.         """
    
  2048.         before = [
    
  2049.             ModelState(
    
  2050.                 "testapp",
    
  2051.                 "EntityA",
    
  2052.                 [
    
  2053.                     ("id", models.AutoField(primary_key=True)),
    
  2054.                 ],
    
  2055.             ),
    
  2056.             ModelState(
    
  2057.                 "testapp",
    
  2058.                 "EntityB",
    
  2059.                 [
    
  2060.                     ("id", models.AutoField(primary_key=True)),
    
  2061.                     ("some_label", models.CharField(max_length=255)),
    
  2062.                     ("entity_a", models.ForeignKey("testapp.EntityA", models.CASCADE)),
    
  2063.                 ],
    
  2064.             ),
    
  2065.         ]
    
  2066.         after = [
    
  2067.             ModelState(
    
  2068.                 "testapp",
    
  2069.                 "EntityA",
    
  2070.                 [
    
  2071.                     ("id", models.AutoField(primary_key=True)),
    
  2072.                 ],
    
  2073.             ),
    
  2074.             ModelState(
    
  2075.                 "testapp",
    
  2076.                 "RenamedEntityB",
    
  2077.                 [
    
  2078.                     ("id", models.AutoField(primary_key=True)),
    
  2079.                     ("entity_a", models.ForeignKey("testapp.EntityA", models.CASCADE)),
    
  2080.                     ("some_label", models.CharField(max_length=255)),
    
  2081.                 ],
    
  2082.             ),
    
  2083.         ]
    
  2084.         changes = self.get_changes(
    
  2085.             before, after, MigrationQuestioner({"ask_rename_model": True})
    
  2086.         )
    
  2087.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2088.         self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
    
  2089.         self.assertOperationAttributes(
    
  2090.             changes, "testapp", 0, 0, old_name="EntityB", new_name="RenamedEntityB"
    
  2091.         )
    
  2092. 
    
  2093.     def test_rename_model_reverse_relation_dependencies(self):
    
  2094.         """
    
  2095.         The migration to rename a model pointed to by a foreign key in another
    
  2096.         app must run after the other app's migration that adds the foreign key
    
  2097.         with model's original name. Therefore, the renaming migration has a
    
  2098.         dependency on that other migration.
    
  2099.         """
    
  2100.         before = [
    
  2101.             ModelState(
    
  2102.                 "testapp",
    
  2103.                 "EntityA",
    
  2104.                 [
    
  2105.                     ("id", models.AutoField(primary_key=True)),
    
  2106.                 ],
    
  2107.             ),
    
  2108.             ModelState(
    
  2109.                 "otherapp",
    
  2110.                 "EntityB",
    
  2111.                 [
    
  2112.                     ("id", models.AutoField(primary_key=True)),
    
  2113.                     ("entity_a", models.ForeignKey("testapp.EntityA", models.CASCADE)),
    
  2114.                 ],
    
  2115.             ),
    
  2116.         ]
    
  2117.         after = [
    
  2118.             ModelState(
    
  2119.                 "testapp",
    
  2120.                 "RenamedEntityA",
    
  2121.                 [
    
  2122.                     ("id", models.AutoField(primary_key=True)),
    
  2123.                 ],
    
  2124.             ),
    
  2125.             ModelState(
    
  2126.                 "otherapp",
    
  2127.                 "EntityB",
    
  2128.                 [
    
  2129.                     ("id", models.AutoField(primary_key=True)),
    
  2130.                     (
    
  2131.                         "entity_a",
    
  2132.                         models.ForeignKey("testapp.RenamedEntityA", models.CASCADE),
    
  2133.                     ),
    
  2134.                 ],
    
  2135.             ),
    
  2136.         ]
    
  2137.         changes = self.get_changes(
    
  2138.             before, after, MigrationQuestioner({"ask_rename_model": True})
    
  2139.         )
    
  2140.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2141.         self.assertMigrationDependencies(
    
  2142.             changes, "testapp", 0, [("otherapp", "__first__")]
    
  2143.         )
    
  2144.         self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
    
  2145.         self.assertOperationAttributes(
    
  2146.             changes, "testapp", 0, 0, old_name="EntityA", new_name="RenamedEntityA"
    
  2147.         )
    
  2148. 
    
  2149.     def test_fk_dependency(self):
    
  2150.         """Having a ForeignKey automatically adds a dependency."""
    
  2151.         # Note that testapp (author) has no dependencies,
    
  2152.         # otherapp (book) depends on testapp (author),
    
  2153.         # thirdapp (edition) depends on otherapp (book)
    
  2154.         changes = self.get_changes([], [self.author_name, self.book, self.edition])
    
  2155.         # Right number/type of migrations?
    
  2156.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2157.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  2158.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  2159.         self.assertMigrationDependencies(changes, "testapp", 0, [])
    
  2160.         # Right number/type of migrations?
    
  2161.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2162.         self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
    
  2163.         self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Book")
    
  2164.         self.assertMigrationDependencies(
    
  2165.             changes, "otherapp", 0, [("testapp", "auto_1")]
    
  2166.         )
    
  2167.         # Right number/type of migrations?
    
  2168.         self.assertNumberMigrations(changes, "thirdapp", 1)
    
  2169.         self.assertOperationTypes(changes, "thirdapp", 0, ["CreateModel"])
    
  2170.         self.assertOperationAttributes(changes, "thirdapp", 0, 0, name="Edition")
    
  2171.         self.assertMigrationDependencies(
    
  2172.             changes, "thirdapp", 0, [("otherapp", "auto_1")]
    
  2173.         )
    
  2174. 
    
  2175.     def test_proxy_fk_dependency(self):
    
  2176.         """FK dependencies still work on proxy models."""
    
  2177.         # Note that testapp (author) has no dependencies,
    
  2178.         # otherapp (book) depends on testapp (authorproxy)
    
  2179.         changes = self.get_changes(
    
  2180.             [], [self.author_empty, self.author_proxy_third, self.book_proxy_fk]
    
  2181.         )
    
  2182.         # Right number/type of migrations?
    
  2183.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2184.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  2185.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  2186.         self.assertMigrationDependencies(changes, "testapp", 0, [])
    
  2187.         # Right number/type of migrations?
    
  2188.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2189.         self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
    
  2190.         self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Book")
    
  2191.         self.assertMigrationDependencies(
    
  2192.             changes, "otherapp", 0, [("thirdapp", "auto_1")]
    
  2193.         )
    
  2194.         # Right number/type of migrations?
    
  2195.         self.assertNumberMigrations(changes, "thirdapp", 1)
    
  2196.         self.assertOperationTypes(changes, "thirdapp", 0, ["CreateModel"])
    
  2197.         self.assertOperationAttributes(changes, "thirdapp", 0, 0, name="AuthorProxy")
    
  2198.         self.assertMigrationDependencies(
    
  2199.             changes, "thirdapp", 0, [("testapp", "auto_1")]
    
  2200.         )
    
  2201. 
    
  2202.     def test_same_app_no_fk_dependency(self):
    
  2203.         """
    
  2204.         A migration with a FK between two models of the same app
    
  2205.         does not have a dependency to itself.
    
  2206.         """
    
  2207.         changes = self.get_changes([], [self.author_with_publisher, self.publisher])
    
  2208.         # Right number/type of migrations?
    
  2209.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2210.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel"])
    
  2211.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
    
  2212.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Author")
    
  2213.         self.assertMigrationDependencies(changes, "testapp", 0, [])
    
  2214. 
    
  2215.     def test_circular_fk_dependency(self):
    
  2216.         """
    
  2217.         Having a circular ForeignKey dependency automatically
    
  2218.         resolves the situation into 2 migrations on one side and 1 on the other.
    
  2219.         """
    
  2220.         changes = self.get_changes(
    
  2221.             [], [self.author_with_book, self.book, self.publisher_with_book]
    
  2222.         )
    
  2223.         # Right number/type of migrations?
    
  2224.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2225.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel"])
    
  2226.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
    
  2227.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Author")
    
  2228.         self.assertMigrationDependencies(
    
  2229.             changes, "testapp", 0, [("otherapp", "auto_1")]
    
  2230.         )
    
  2231.         # Right number/type of migrations?
    
  2232.         self.assertNumberMigrations(changes, "otherapp", 2)
    
  2233.         self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
    
  2234.         self.assertOperationTypes(changes, "otherapp", 1, ["AddField"])
    
  2235.         self.assertMigrationDependencies(changes, "otherapp", 0, [])
    
  2236.         self.assertMigrationDependencies(
    
  2237.             changes, "otherapp", 1, [("otherapp", "auto_1"), ("testapp", "auto_1")]
    
  2238.         )
    
  2239.         # both split migrations should be `initial`
    
  2240.         self.assertTrue(changes["otherapp"][0].initial)
    
  2241.         self.assertTrue(changes["otherapp"][1].initial)
    
  2242. 
    
  2243.     def test_same_app_circular_fk_dependency(self):
    
  2244.         """
    
  2245.         A migration with a FK between two models of the same app does
    
  2246.         not have a dependency to itself.
    
  2247.         """
    
  2248.         changes = self.get_changes(
    
  2249.             [], [self.author_with_publisher, self.publisher_with_author]
    
  2250.         )
    
  2251.         # Right number/type of migrations?
    
  2252.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2253.         self.assertOperationTypes(
    
  2254.             changes, "testapp", 0, ["CreateModel", "CreateModel", "AddField"]
    
  2255.         )
    
  2256.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  2257.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
    
  2258.         self.assertOperationAttributes(changes, "testapp", 0, 2, name="publisher")
    
  2259.         self.assertMigrationDependencies(changes, "testapp", 0, [])
    
  2260. 
    
  2261.     def test_same_app_circular_fk_dependency_with_unique_together_and_indexes(self):
    
  2262.         """
    
  2263.         #22275 - A migration with circular FK dependency does not try
    
  2264.         to create unique together constraint and indexes before creating all
    
  2265.         required fields first.
    
  2266.         """
    
  2267.         changes = self.get_changes([], [self.knight, self.rabbit])
    
  2268.         # Right number/type of migrations?
    
  2269.         self.assertNumberMigrations(changes, "eggs", 1)
    
  2270.         self.assertOperationTypes(
    
  2271.             changes,
    
  2272.             "eggs",
    
  2273.             0,
    
  2274.             ["CreateModel", "CreateModel", "AddIndex", "AlterUniqueTogether"],
    
  2275.         )
    
  2276.         self.assertNotIn("unique_together", changes["eggs"][0].operations[0].options)
    
  2277.         self.assertNotIn("unique_together", changes["eggs"][0].operations[1].options)
    
  2278.         self.assertMigrationDependencies(changes, "eggs", 0, [])
    
  2279. 
    
  2280.     def test_alter_db_table_add(self):
    
  2281.         """Tests detection for adding db_table in model's options."""
    
  2282.         changes = self.get_changes(
    
  2283.             [self.author_empty], [self.author_with_db_table_options]
    
  2284.         )
    
  2285.         # Right number/type of migrations?
    
  2286.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2287.         self.assertOperationTypes(changes, "testapp", 0, ["AlterModelTable"])
    
  2288.         self.assertOperationAttributes(
    
  2289.             changes, "testapp", 0, 0, name="author", table="author_one"
    
  2290.         )
    
  2291. 
    
  2292.     def test_alter_db_table_change(self):
    
  2293.         """Tests detection for changing db_table in model's options'."""
    
  2294.         changes = self.get_changes(
    
  2295.             [self.author_with_db_table_options], [self.author_with_new_db_table_options]
    
  2296.         )
    
  2297.         # Right number/type of migrations?
    
  2298.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2299.         self.assertOperationTypes(changes, "testapp", 0, ["AlterModelTable"])
    
  2300.         self.assertOperationAttributes(
    
  2301.             changes, "testapp", 0, 0, name="author", table="author_two"
    
  2302.         )
    
  2303. 
    
  2304.     def test_alter_db_table_remove(self):
    
  2305.         """Tests detection for removing db_table in model's options."""
    
  2306.         changes = self.get_changes(
    
  2307.             [self.author_with_db_table_options], [self.author_empty]
    
  2308.         )
    
  2309.         # Right number/type of migrations?
    
  2310.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2311.         self.assertOperationTypes(changes, "testapp", 0, ["AlterModelTable"])
    
  2312.         self.assertOperationAttributes(
    
  2313.             changes, "testapp", 0, 0, name="author", table=None
    
  2314.         )
    
  2315. 
    
  2316.     def test_alter_db_table_no_changes(self):
    
  2317.         """
    
  2318.         Alter_db_table doesn't generate a migration if no changes have been made.
    
  2319.         """
    
  2320.         changes = self.get_changes(
    
  2321.             [self.author_with_db_table_options], [self.author_with_db_table_options]
    
  2322.         )
    
  2323.         # Right number of migrations?
    
  2324.         self.assertEqual(len(changes), 0)
    
  2325. 
    
  2326.     def test_keep_db_table_with_model_change(self):
    
  2327.         """
    
  2328.         Tests when model changes but db_table stays as-is, autodetector must not
    
  2329.         create more than one operation.
    
  2330.         """
    
  2331.         changes = self.get_changes(
    
  2332.             [self.author_with_db_table_options],
    
  2333.             [self.author_renamed_with_db_table_options],
    
  2334.             MigrationQuestioner({"ask_rename_model": True}),
    
  2335.         )
    
  2336.         # Right number/type of migrations?
    
  2337.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2338.         self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"])
    
  2339.         self.assertOperationAttributes(
    
  2340.             changes, "testapp", 0, 0, old_name="Author", new_name="NewAuthor"
    
  2341.         )
    
  2342. 
    
  2343.     def test_alter_db_table_with_model_change(self):
    
  2344.         """
    
  2345.         Tests when model and db_table changes, autodetector must create two
    
  2346.         operations.
    
  2347.         """
    
  2348.         changes = self.get_changes(
    
  2349.             [self.author_with_db_table_options],
    
  2350.             [self.author_renamed_with_new_db_table_options],
    
  2351.             MigrationQuestioner({"ask_rename_model": True}),
    
  2352.         )
    
  2353.         # Right number/type of migrations?
    
  2354.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2355.         self.assertOperationTypes(
    
  2356.             changes, "testapp", 0, ["RenameModel", "AlterModelTable"]
    
  2357.         )
    
  2358.         self.assertOperationAttributes(
    
  2359.             changes, "testapp", 0, 0, old_name="Author", new_name="NewAuthor"
    
  2360.         )
    
  2361.         self.assertOperationAttributes(
    
  2362.             changes, "testapp", 0, 1, name="newauthor", table="author_three"
    
  2363.         )
    
  2364. 
    
  2365.     def test_identical_regex_doesnt_alter(self):
    
  2366.         from_state = ModelState(
    
  2367.             "testapp",
    
  2368.             "model",
    
  2369.             [
    
  2370.                 (
    
  2371.                     "id",
    
  2372.                     models.AutoField(
    
  2373.                         primary_key=True,
    
  2374.                         validators=[
    
  2375.                             RegexValidator(
    
  2376.                                 re.compile("^[-a-zA-Z0-9_]+\\Z"),
    
  2377.                                 "Enter a valid “slug” consisting of letters, numbers, "
    
  2378.                                 "underscores or hyphens.",
    
  2379.                                 "invalid",
    
  2380.                             )
    
  2381.                         ],
    
  2382.                     ),
    
  2383.                 )
    
  2384.             ],
    
  2385.         )
    
  2386.         to_state = ModelState(
    
  2387.             "testapp",
    
  2388.             "model",
    
  2389.             [("id", models.AutoField(primary_key=True, validators=[validate_slug]))],
    
  2390.         )
    
  2391.         changes = self.get_changes([from_state], [to_state])
    
  2392.         # Right number/type of migrations?
    
  2393.         self.assertNumberMigrations(changes, "testapp", 0)
    
  2394. 
    
  2395.     def test_different_regex_does_alter(self):
    
  2396.         from_state = ModelState(
    
  2397.             "testapp",
    
  2398.             "model",
    
  2399.             [
    
  2400.                 (
    
  2401.                     "id",
    
  2402.                     models.AutoField(
    
  2403.                         primary_key=True,
    
  2404.                         validators=[
    
  2405.                             RegexValidator(
    
  2406.                                 re.compile("^[a-z]+\\Z", 32),
    
  2407.                                 "Enter a valid “slug” consisting of letters, numbers, "
    
  2408.                                 "underscores or hyphens.",
    
  2409.                                 "invalid",
    
  2410.                             )
    
  2411.                         ],
    
  2412.                     ),
    
  2413.                 )
    
  2414.             ],
    
  2415.         )
    
  2416.         to_state = ModelState(
    
  2417.             "testapp",
    
  2418.             "model",
    
  2419.             [("id", models.AutoField(primary_key=True, validators=[validate_slug]))],
    
  2420.         )
    
  2421.         changes = self.get_changes([from_state], [to_state])
    
  2422.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2423.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  2424. 
    
  2425.     def test_alter_regex_string_to_compiled_regex(self):
    
  2426.         regex_string = "^[a-z]+$"
    
  2427.         from_state = ModelState(
    
  2428.             "testapp",
    
  2429.             "model",
    
  2430.             [
    
  2431.                 (
    
  2432.                     "id",
    
  2433.                     models.AutoField(
    
  2434.                         primary_key=True, validators=[RegexValidator(regex_string)]
    
  2435.                     ),
    
  2436.                 )
    
  2437.             ],
    
  2438.         )
    
  2439.         to_state = ModelState(
    
  2440.             "testapp",
    
  2441.             "model",
    
  2442.             [
    
  2443.                 (
    
  2444.                     "id",
    
  2445.                     models.AutoField(
    
  2446.                         primary_key=True,
    
  2447.                         validators=[RegexValidator(re.compile(regex_string))],
    
  2448.                     ),
    
  2449.                 )
    
  2450.             ],
    
  2451.         )
    
  2452.         changes = self.get_changes([from_state], [to_state])
    
  2453.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2454.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  2455. 
    
  2456.     def test_empty_foo_together(self):
    
  2457.         """
    
  2458.         #23452 - Empty unique/index_together shouldn't generate a migration.
    
  2459.         """
    
  2460.         # Explicitly testing for not specified, since this is the case after
    
  2461.         # a CreateModel operation w/o any definition on the original model
    
  2462.         model_state_not_specified = ModelState(
    
  2463.             "a", "model", [("id", models.AutoField(primary_key=True))]
    
  2464.         )
    
  2465.         # Explicitly testing for None, since this was the issue in #23452 after
    
  2466.         # an AlterFooTogether operation with e.g. () as value
    
  2467.         model_state_none = ModelState(
    
  2468.             "a",
    
  2469.             "model",
    
  2470.             [("id", models.AutoField(primary_key=True))],
    
  2471.             {
    
  2472.                 "index_together": None,
    
  2473.                 "unique_together": None,
    
  2474.             },
    
  2475.         )
    
  2476.         # Explicitly testing for the empty set, since we now always have sets.
    
  2477.         # During removal (('col1', 'col2'),) --> () this becomes set([])
    
  2478.         model_state_empty = ModelState(
    
  2479.             "a",
    
  2480.             "model",
    
  2481.             [("id", models.AutoField(primary_key=True))],
    
  2482.             {
    
  2483.                 "index_together": set(),
    
  2484.                 "unique_together": set(),
    
  2485.             },
    
  2486.         )
    
  2487. 
    
  2488.         def test(from_state, to_state, msg):
    
  2489.             changes = self.get_changes([from_state], [to_state])
    
  2490.             if changes:
    
  2491.                 ops = ", ".join(
    
  2492.                     o.__class__.__name__ for o in changes["a"][0].operations
    
  2493.                 )
    
  2494.                 self.fail("Created operation(s) %s from %s" % (ops, msg))
    
  2495. 
    
  2496.         tests = (
    
  2497.             (
    
  2498.                 model_state_not_specified,
    
  2499.                 model_state_not_specified,
    
  2500.                 '"not specified" to "not specified"',
    
  2501.             ),
    
  2502.             (model_state_not_specified, model_state_none, '"not specified" to "None"'),
    
  2503.             (
    
  2504.                 model_state_not_specified,
    
  2505.                 model_state_empty,
    
  2506.                 '"not specified" to "empty"',
    
  2507.             ),
    
  2508.             (model_state_none, model_state_not_specified, '"None" to "not specified"'),
    
  2509.             (model_state_none, model_state_none, '"None" to "None"'),
    
  2510.             (model_state_none, model_state_empty, '"None" to "empty"'),
    
  2511.             (
    
  2512.                 model_state_empty,
    
  2513.                 model_state_not_specified,
    
  2514.                 '"empty" to "not specified"',
    
  2515.             ),
    
  2516.             (model_state_empty, model_state_none, '"empty" to "None"'),
    
  2517.             (model_state_empty, model_state_empty, '"empty" to "empty"'),
    
  2518.         )
    
  2519. 
    
  2520.         for t in tests:
    
  2521.             test(*t)
    
  2522. 
    
  2523.     def test_create_model_with_indexes(self):
    
  2524.         """Test creation of new model with indexes already defined."""
    
  2525.         author = ModelState(
    
  2526.             "otherapp",
    
  2527.             "Author",
    
  2528.             [
    
  2529.                 ("id", models.AutoField(primary_key=True)),
    
  2530.                 ("name", models.CharField(max_length=200)),
    
  2531.             ],
    
  2532.             {
    
  2533.                 "indexes": [
    
  2534.                     models.Index(fields=["name"], name="create_model_with_indexes_idx")
    
  2535.                 ]
    
  2536.             },
    
  2537.         )
    
  2538.         changes = self.get_changes([], [author])
    
  2539.         added_index = models.Index(
    
  2540.             fields=["name"], name="create_model_with_indexes_idx"
    
  2541.         )
    
  2542.         # Right number of migrations?
    
  2543.         self.assertEqual(len(changes["otherapp"]), 1)
    
  2544.         # Right number of actions?
    
  2545.         migration = changes["otherapp"][0]
    
  2546.         self.assertEqual(len(migration.operations), 2)
    
  2547.         # Right actions order?
    
  2548.         self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel", "AddIndex"])
    
  2549.         self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Author")
    
  2550.         self.assertOperationAttributes(
    
  2551.             changes, "otherapp", 0, 1, model_name="author", index=added_index
    
  2552.         )
    
  2553. 
    
  2554.     def test_add_indexes(self):
    
  2555.         """Test change detection of new indexes."""
    
  2556.         changes = self.get_changes(
    
  2557.             [self.author_empty, self.book], [self.author_empty, self.book_indexes]
    
  2558.         )
    
  2559.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2560.         self.assertOperationTypes(changes, "otherapp", 0, ["AddIndex"])
    
  2561.         added_index = models.Index(
    
  2562.             fields=["author", "title"], name="book_title_author_idx"
    
  2563.         )
    
  2564.         self.assertOperationAttributes(
    
  2565.             changes, "otherapp", 0, 0, model_name="book", index=added_index
    
  2566.         )
    
  2567. 
    
  2568.     def test_remove_indexes(self):
    
  2569.         """Test change detection of removed indexes."""
    
  2570.         changes = self.get_changes(
    
  2571.             [self.author_empty, self.book_indexes], [self.author_empty, self.book]
    
  2572.         )
    
  2573.         # Right number/type of migrations?
    
  2574.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2575.         self.assertOperationTypes(changes, "otherapp", 0, ["RemoveIndex"])
    
  2576.         self.assertOperationAttributes(
    
  2577.             changes, "otherapp", 0, 0, model_name="book", name="book_title_author_idx"
    
  2578.         )
    
  2579. 
    
  2580.     def test_rename_indexes(self):
    
  2581.         book_renamed_indexes = ModelState(
    
  2582.             "otherapp",
    
  2583.             "Book",
    
  2584.             [
    
  2585.                 ("id", models.AutoField(primary_key=True)),
    
  2586.                 ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  2587.                 ("title", models.CharField(max_length=200)),
    
  2588.             ],
    
  2589.             {
    
  2590.                 "indexes": [
    
  2591.                     models.Index(
    
  2592.                         fields=["author", "title"], name="renamed_book_title_author_idx"
    
  2593.                     )
    
  2594.                 ],
    
  2595.             },
    
  2596.         )
    
  2597.         changes = self.get_changes(
    
  2598.             [self.author_empty, self.book_indexes],
    
  2599.             [self.author_empty, book_renamed_indexes],
    
  2600.         )
    
  2601.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2602.         self.assertOperationTypes(changes, "otherapp", 0, ["RenameIndex"])
    
  2603.         self.assertOperationAttributes(
    
  2604.             changes,
    
  2605.             "otherapp",
    
  2606.             0,
    
  2607.             0,
    
  2608.             model_name="book",
    
  2609.             new_name="renamed_book_title_author_idx",
    
  2610.             old_name="book_title_author_idx",
    
  2611.         )
    
  2612. 
    
  2613.     def test_rename_index_together_to_index(self):
    
  2614.         changes = self.get_changes(
    
  2615.             [self.author_empty, self.book_foo_together],
    
  2616.             [self.author_empty, self.book_indexes],
    
  2617.         )
    
  2618.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2619.         self.assertOperationTypes(
    
  2620.             changes, "otherapp", 0, ["RenameIndex", "AlterUniqueTogether"]
    
  2621.         )
    
  2622.         self.assertOperationAttributes(
    
  2623.             changes,
    
  2624.             "otherapp",
    
  2625.             0,
    
  2626.             0,
    
  2627.             model_name="book",
    
  2628.             new_name="book_title_author_idx",
    
  2629.             old_fields=("author", "title"),
    
  2630.         )
    
  2631.         self.assertOperationAttributes(
    
  2632.             changes,
    
  2633.             "otherapp",
    
  2634.             0,
    
  2635.             1,
    
  2636.             name="book",
    
  2637.             unique_together=set(),
    
  2638.         )
    
  2639. 
    
  2640.     def test_rename_index_together_to_index_extra_options(self):
    
  2641.         # Indexes with extra options don't match indexes in index_together.
    
  2642.         book_partial_index = ModelState(
    
  2643.             "otherapp",
    
  2644.             "Book",
    
  2645.             [
    
  2646.                 ("id", models.AutoField(primary_key=True)),
    
  2647.                 ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
    
  2648.                 ("title", models.CharField(max_length=200)),
    
  2649.             ],
    
  2650.             {
    
  2651.                 "indexes": [
    
  2652.                     models.Index(
    
  2653.                         fields=["author", "title"],
    
  2654.                         condition=models.Q(title__startswith="The"),
    
  2655.                         name="book_title_author_idx",
    
  2656.                     )
    
  2657.                 ],
    
  2658.             },
    
  2659.         )
    
  2660.         changes = self.get_changes(
    
  2661.             [self.author_empty, self.book_foo_together],
    
  2662.             [self.author_empty, book_partial_index],
    
  2663.         )
    
  2664.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2665.         self.assertOperationTypes(
    
  2666.             changes,
    
  2667.             "otherapp",
    
  2668.             0,
    
  2669.             ["AlterUniqueTogether", "AlterIndexTogether", "AddIndex"],
    
  2670.         )
    
  2671. 
    
  2672.     def test_rename_index_together_to_index_order_fields(self):
    
  2673.         # Indexes with reordered fields don't match indexes in index_together.
    
  2674.         changes = self.get_changes(
    
  2675.             [self.author_empty, self.book_foo_together],
    
  2676.             [self.author_empty, self.book_unordered_indexes],
    
  2677.         )
    
  2678.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2679.         self.assertOperationTypes(
    
  2680.             changes,
    
  2681.             "otherapp",
    
  2682.             0,
    
  2683.             ["AlterUniqueTogether", "AlterIndexTogether", "AddIndex"],
    
  2684.         )
    
  2685. 
    
  2686.     def test_order_fields_indexes(self):
    
  2687.         """Test change detection of reordering of fields in indexes."""
    
  2688.         changes = self.get_changes(
    
  2689.             [self.author_empty, self.book_indexes],
    
  2690.             [self.author_empty, self.book_unordered_indexes],
    
  2691.         )
    
  2692.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2693.         self.assertOperationTypes(changes, "otherapp", 0, ["RemoveIndex", "AddIndex"])
    
  2694.         self.assertOperationAttributes(
    
  2695.             changes, "otherapp", 0, 0, model_name="book", name="book_title_author_idx"
    
  2696.         )
    
  2697.         added_index = models.Index(
    
  2698.             fields=["title", "author"], name="book_author_title_idx"
    
  2699.         )
    
  2700.         self.assertOperationAttributes(
    
  2701.             changes, "otherapp", 0, 1, model_name="book", index=added_index
    
  2702.         )
    
  2703. 
    
  2704.     def test_create_model_with_check_constraint(self):
    
  2705.         """Test creation of new model with constraints already defined."""
    
  2706.         author = ModelState(
    
  2707.             "otherapp",
    
  2708.             "Author",
    
  2709.             [
    
  2710.                 ("id", models.AutoField(primary_key=True)),
    
  2711.                 ("name", models.CharField(max_length=200)),
    
  2712.             ],
    
  2713.             {
    
  2714.                 "constraints": [
    
  2715.                     models.CheckConstraint(
    
  2716.                         check=models.Q(name__contains="Bob"), name="name_contains_bob"
    
  2717.                     )
    
  2718.                 ]
    
  2719.             },
    
  2720.         )
    
  2721.         changes = self.get_changes([], [author])
    
  2722.         added_constraint = models.CheckConstraint(
    
  2723.             check=models.Q(name__contains="Bob"), name="name_contains_bob"
    
  2724.         )
    
  2725.         # Right number of migrations?
    
  2726.         self.assertEqual(len(changes["otherapp"]), 1)
    
  2727.         # Right number of actions?
    
  2728.         migration = changes["otherapp"][0]
    
  2729.         self.assertEqual(len(migration.operations), 2)
    
  2730.         # Right actions order?
    
  2731.         self.assertOperationTypes(
    
  2732.             changes, "otherapp", 0, ["CreateModel", "AddConstraint"]
    
  2733.         )
    
  2734.         self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Author")
    
  2735.         self.assertOperationAttributes(
    
  2736.             changes, "otherapp", 0, 1, model_name="author", constraint=added_constraint
    
  2737.         )
    
  2738. 
    
  2739.     def test_add_constraints(self):
    
  2740.         """Test change detection of new constraints."""
    
  2741.         changes = self.get_changes(
    
  2742.             [self.author_name], [self.author_name_check_constraint]
    
  2743.         )
    
  2744.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2745.         self.assertOperationTypes(changes, "testapp", 0, ["AddConstraint"])
    
  2746.         added_constraint = models.CheckConstraint(
    
  2747.             check=models.Q(name__contains="Bob"), name="name_contains_bob"
    
  2748.         )
    
  2749.         self.assertOperationAttributes(
    
  2750.             changes, "testapp", 0, 0, model_name="author", constraint=added_constraint
    
  2751.         )
    
  2752. 
    
  2753.     def test_remove_constraints(self):
    
  2754.         """Test change detection of removed constraints."""
    
  2755.         changes = self.get_changes(
    
  2756.             [self.author_name_check_constraint], [self.author_name]
    
  2757.         )
    
  2758.         # Right number/type of migrations?
    
  2759.         self.assertNumberMigrations(changes, "testapp", 1)
    
  2760.         self.assertOperationTypes(changes, "testapp", 0, ["RemoveConstraint"])
    
  2761.         self.assertOperationAttributes(
    
  2762.             changes, "testapp", 0, 0, model_name="author", name="name_contains_bob"
    
  2763.         )
    
  2764. 
    
  2765.     def test_add_foo_together(self):
    
  2766.         """Tests index/unique_together detection."""
    
  2767.         changes = self.get_changes(
    
  2768.             [self.author_empty, self.book], [self.author_empty, self.book_foo_together]
    
  2769.         )
    
  2770.         # Right number/type of migrations?
    
  2771.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2772.         self.assertOperationTypes(
    
  2773.             changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"]
    
  2774.         )
    
  2775.         self.assertOperationAttributes(
    
  2776.             changes,
    
  2777.             "otherapp",
    
  2778.             0,
    
  2779.             0,
    
  2780.             name="book",
    
  2781.             unique_together={("author", "title")},
    
  2782.         )
    
  2783.         self.assertOperationAttributes(
    
  2784.             changes, "otherapp", 0, 1, name="book", index_together={("author", "title")}
    
  2785.         )
    
  2786. 
    
  2787.     def test_remove_foo_together(self):
    
  2788.         """Tests index/unique_together detection."""
    
  2789.         changes = self.get_changes(
    
  2790.             [self.author_empty, self.book_foo_together], [self.author_empty, self.book]
    
  2791.         )
    
  2792.         # Right number/type of migrations?
    
  2793.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2794.         self.assertOperationTypes(
    
  2795.             changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"]
    
  2796.         )
    
  2797.         self.assertOperationAttributes(
    
  2798.             changes, "otherapp", 0, 0, name="book", unique_together=set()
    
  2799.         )
    
  2800.         self.assertOperationAttributes(
    
  2801.             changes, "otherapp", 0, 1, name="book", index_together=set()
    
  2802.         )
    
  2803. 
    
  2804.     def test_foo_together_remove_fk(self):
    
  2805.         """Tests unique_together and field removal detection & ordering"""
    
  2806.         changes = self.get_changes(
    
  2807.             [self.author_empty, self.book_foo_together],
    
  2808.             [self.author_empty, self.book_with_no_author],
    
  2809.         )
    
  2810.         # Right number/type of migrations?
    
  2811.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2812.         self.assertOperationTypes(
    
  2813.             changes,
    
  2814.             "otherapp",
    
  2815.             0,
    
  2816.             ["AlterUniqueTogether", "AlterIndexTogether", "RemoveField"],
    
  2817.         )
    
  2818.         self.assertOperationAttributes(
    
  2819.             changes, "otherapp", 0, 0, name="book", unique_together=set()
    
  2820.         )
    
  2821.         self.assertOperationAttributes(
    
  2822.             changes, "otherapp", 0, 1, name="book", index_together=set()
    
  2823.         )
    
  2824.         self.assertOperationAttributes(
    
  2825.             changes, "otherapp", 0, 2, model_name="book", name="author"
    
  2826.         )
    
  2827. 
    
  2828.     def test_foo_together_no_changes(self):
    
  2829.         """
    
  2830.         index/unique_together doesn't generate a migration if no
    
  2831.         changes have been made.
    
  2832.         """
    
  2833.         changes = self.get_changes(
    
  2834.             [self.author_empty, self.book_foo_together],
    
  2835.             [self.author_empty, self.book_foo_together],
    
  2836.         )
    
  2837.         # Right number of migrations?
    
  2838.         self.assertEqual(len(changes), 0)
    
  2839. 
    
  2840.     def test_foo_together_ordering(self):
    
  2841.         """
    
  2842.         index/unique_together also triggers on ordering changes.
    
  2843.         """
    
  2844.         changes = self.get_changes(
    
  2845.             [self.author_empty, self.book_foo_together],
    
  2846.             [self.author_empty, self.book_foo_together_2],
    
  2847.         )
    
  2848.         # Right number/type of migrations?
    
  2849.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2850.         self.assertOperationTypes(
    
  2851.             changes,
    
  2852.             "otherapp",
    
  2853.             0,
    
  2854.             [
    
  2855.                 "AlterUniqueTogether",
    
  2856.                 "AlterIndexTogether",
    
  2857.             ],
    
  2858.         )
    
  2859.         self.assertOperationAttributes(
    
  2860.             changes,
    
  2861.             "otherapp",
    
  2862.             0,
    
  2863.             0,
    
  2864.             name="book",
    
  2865.             unique_together={("title", "author")},
    
  2866.         )
    
  2867.         self.assertOperationAttributes(
    
  2868.             changes,
    
  2869.             "otherapp",
    
  2870.             0,
    
  2871.             1,
    
  2872.             name="book",
    
  2873.             index_together={("title", "author")},
    
  2874.         )
    
  2875. 
    
  2876.     def test_add_field_and_foo_together(self):
    
  2877.         """
    
  2878.         Added fields will be created before using them in index/unique_together.
    
  2879.         """
    
  2880.         changes = self.get_changes(
    
  2881.             [self.author_empty, self.book],
    
  2882.             [self.author_empty, self.book_foo_together_3],
    
  2883.         )
    
  2884.         # Right number/type of migrations?
    
  2885.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2886.         self.assertOperationTypes(
    
  2887.             changes,
    
  2888.             "otherapp",
    
  2889.             0,
    
  2890.             ["AddField", "AlterUniqueTogether", "AlterIndexTogether"],
    
  2891.         )
    
  2892.         self.assertOperationAttributes(
    
  2893.             changes,
    
  2894.             "otherapp",
    
  2895.             0,
    
  2896.             1,
    
  2897.             name="book",
    
  2898.             unique_together={("title", "newfield")},
    
  2899.         )
    
  2900.         self.assertOperationAttributes(
    
  2901.             changes,
    
  2902.             "otherapp",
    
  2903.             0,
    
  2904.             2,
    
  2905.             name="book",
    
  2906.             index_together={("title", "newfield")},
    
  2907.         )
    
  2908. 
    
  2909.     def test_create_model_and_unique_together(self):
    
  2910.         author = ModelState(
    
  2911.             "otherapp",
    
  2912.             "Author",
    
  2913.             [
    
  2914.                 ("id", models.AutoField(primary_key=True)),
    
  2915.                 ("name", models.CharField(max_length=200)),
    
  2916.             ],
    
  2917.         )
    
  2918.         book_with_author = ModelState(
    
  2919.             "otherapp",
    
  2920.             "Book",
    
  2921.             [
    
  2922.                 ("id", models.AutoField(primary_key=True)),
    
  2923.                 ("author", models.ForeignKey("otherapp.Author", models.CASCADE)),
    
  2924.                 ("title", models.CharField(max_length=200)),
    
  2925.             ],
    
  2926.             {
    
  2927.                 "index_together": {("title", "author")},
    
  2928.                 "unique_together": {("title", "author")},
    
  2929.             },
    
  2930.         )
    
  2931.         changes = self.get_changes(
    
  2932.             [self.book_with_no_author], [author, book_with_author]
    
  2933.         )
    
  2934.         # Right number of migrations?
    
  2935.         self.assertEqual(len(changes["otherapp"]), 1)
    
  2936.         # Right number of actions?
    
  2937.         migration = changes["otherapp"][0]
    
  2938.         self.assertEqual(len(migration.operations), 4)
    
  2939.         # Right actions order?
    
  2940.         self.assertOperationTypes(
    
  2941.             changes,
    
  2942.             "otherapp",
    
  2943.             0,
    
  2944.             ["CreateModel", "AddField", "AlterUniqueTogether", "AlterIndexTogether"],
    
  2945.         )
    
  2946. 
    
  2947.     def test_remove_field_and_foo_together(self):
    
  2948.         """
    
  2949.         Removed fields will be removed after updating index/unique_together.
    
  2950.         """
    
  2951.         changes = self.get_changes(
    
  2952.             [self.author_empty, self.book_foo_together_3],
    
  2953.             [self.author_empty, self.book_foo_together],
    
  2954.         )
    
  2955.         # Right number/type of migrations?
    
  2956.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  2957.         self.assertOperationTypes(
    
  2958.             changes,
    
  2959.             "otherapp",
    
  2960.             0,
    
  2961.             [
    
  2962.                 "AlterUniqueTogether",
    
  2963.                 "AlterIndexTogether",
    
  2964.                 "RemoveField",
    
  2965.             ],
    
  2966.         )
    
  2967.         self.assertOperationAttributes(
    
  2968.             changes,
    
  2969.             "otherapp",
    
  2970.             0,
    
  2971.             0,
    
  2972.             name="book",
    
  2973.             unique_together={("author", "title")},
    
  2974.         )
    
  2975.         self.assertOperationAttributes(
    
  2976.             changes,
    
  2977.             "otherapp",
    
  2978.             0,
    
  2979.             1,
    
  2980.             name="book",
    
  2981.             index_together={("author", "title")},
    
  2982.         )
    
  2983.         self.assertOperationAttributes(
    
  2984.             changes,
    
  2985.             "otherapp",
    
  2986.             0,
    
  2987.             2,
    
  2988.             model_name="book",
    
  2989.             name="newfield",
    
  2990.         )
    
  2991. 
    
  2992.     def test_alter_field_and_foo_together(self):
    
  2993.         """Fields are altered after deleting some index/unique_together."""
    
  2994.         initial_author = ModelState(
    
  2995.             "testapp",
    
  2996.             "Author",
    
  2997.             [
    
  2998.                 ("id", models.AutoField(primary_key=True)),
    
  2999.                 ("name", models.CharField(max_length=200)),
    
  3000.                 ("age", models.IntegerField(db_index=True)),
    
  3001.             ],
    
  3002.             {
    
  3003.                 "unique_together": {("name",)},
    
  3004.             },
    
  3005.         )
    
  3006.         author_reversed_constraints = ModelState(
    
  3007.             "testapp",
    
  3008.             "Author",
    
  3009.             [
    
  3010.                 ("id", models.AutoField(primary_key=True)),
    
  3011.                 ("name", models.CharField(max_length=200, unique=True)),
    
  3012.                 ("age", models.IntegerField()),
    
  3013.             ],
    
  3014.             {
    
  3015.                 "index_together": {("age",)},
    
  3016.             },
    
  3017.         )
    
  3018.         changes = self.get_changes([initial_author], [author_reversed_constraints])
    
  3019. 
    
  3020.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3021.         self.assertOperationTypes(
    
  3022.             changes,
    
  3023.             "testapp",
    
  3024.             0,
    
  3025.             [
    
  3026.                 "AlterUniqueTogether",
    
  3027.                 "AlterField",
    
  3028.                 "AlterField",
    
  3029.                 "AlterIndexTogether",
    
  3030.             ],
    
  3031.         )
    
  3032.         self.assertOperationAttributes(
    
  3033.             changes,
    
  3034.             "testapp",
    
  3035.             0,
    
  3036.             0,
    
  3037.             name="author",
    
  3038.             unique_together=set(),
    
  3039.         )
    
  3040.         self.assertOperationAttributes(
    
  3041.             changes,
    
  3042.             "testapp",
    
  3043.             0,
    
  3044.             1,
    
  3045.             model_name="author",
    
  3046.             name="age",
    
  3047.         )
    
  3048.         self.assertOperationAttributes(
    
  3049.             changes,
    
  3050.             "testapp",
    
  3051.             0,
    
  3052.             2,
    
  3053.             model_name="author",
    
  3054.             name="name",
    
  3055.         )
    
  3056.         self.assertOperationAttributes(
    
  3057.             changes,
    
  3058.             "testapp",
    
  3059.             0,
    
  3060.             3,
    
  3061.             name="author",
    
  3062.             index_together={("age",)},
    
  3063.         )
    
  3064. 
    
  3065.     def test_partly_alter_foo_together(self):
    
  3066.         initial_author = ModelState(
    
  3067.             "testapp",
    
  3068.             "Author",
    
  3069.             [
    
  3070.                 ("id", models.AutoField(primary_key=True)),
    
  3071.                 ("name", models.CharField(max_length=200)),
    
  3072.                 ("age", models.IntegerField()),
    
  3073.             ],
    
  3074.             {
    
  3075.                 "unique_together": {("name",), ("age",)},
    
  3076.                 "index_together": {("name",)},
    
  3077.             },
    
  3078.         )
    
  3079.         author_reversed_constraints = ModelState(
    
  3080.             "testapp",
    
  3081.             "Author",
    
  3082.             [
    
  3083.                 ("id", models.AutoField(primary_key=True)),
    
  3084.                 ("name", models.CharField(max_length=200)),
    
  3085.                 ("age", models.IntegerField()),
    
  3086.             ],
    
  3087.             {
    
  3088.                 "unique_together": {("age",)},
    
  3089.                 "index_together": {("name",), ("age",)},
    
  3090.             },
    
  3091.         )
    
  3092.         changes = self.get_changes([initial_author], [author_reversed_constraints])
    
  3093. 
    
  3094.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3095.         self.assertOperationTypes(
    
  3096.             changes,
    
  3097.             "testapp",
    
  3098.             0,
    
  3099.             [
    
  3100.                 "AlterUniqueTogether",
    
  3101.                 "AlterIndexTogether",
    
  3102.             ],
    
  3103.         )
    
  3104.         self.assertOperationAttributes(
    
  3105.             changes,
    
  3106.             "testapp",
    
  3107.             0,
    
  3108.             0,
    
  3109.             name="author",
    
  3110.             unique_together={("age",)},
    
  3111.         )
    
  3112.         self.assertOperationAttributes(
    
  3113.             changes,
    
  3114.             "testapp",
    
  3115.             0,
    
  3116.             1,
    
  3117.             name="author",
    
  3118.             index_together={("name",), ("age",)},
    
  3119.         )
    
  3120. 
    
  3121.     def test_rename_field_and_foo_together(self):
    
  3122.         """Fields are renamed before updating index/unique_together."""
    
  3123.         changes = self.get_changes(
    
  3124.             [self.author_empty, self.book_foo_together_3],
    
  3125.             [self.author_empty, self.book_foo_together_4],
    
  3126.             MigrationQuestioner({"ask_rename": True}),
    
  3127.         )
    
  3128.         # Right number/type of migrations?
    
  3129.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  3130.         self.assertOperationTypes(
    
  3131.             changes,
    
  3132.             "otherapp",
    
  3133.             0,
    
  3134.             [
    
  3135.                 "RenameField",
    
  3136.                 "AlterUniqueTogether",
    
  3137.                 "AlterIndexTogether",
    
  3138.             ],
    
  3139.         )
    
  3140.         self.assertOperationAttributes(
    
  3141.             changes,
    
  3142.             "otherapp",
    
  3143.             0,
    
  3144.             1,
    
  3145.             name="book",
    
  3146.             unique_together={("title", "newfield2")},
    
  3147.         )
    
  3148.         self.assertOperationAttributes(
    
  3149.             changes,
    
  3150.             "otherapp",
    
  3151.             0,
    
  3152.             2,
    
  3153.             name="book",
    
  3154.             index_together={("title", "newfield2")},
    
  3155.         )
    
  3156. 
    
  3157.     def test_proxy(self):
    
  3158.         """The autodetector correctly deals with proxy models."""
    
  3159.         # First, we test adding a proxy model
    
  3160.         changes = self.get_changes(
    
  3161.             [self.author_empty], [self.author_empty, self.author_proxy]
    
  3162.         )
    
  3163.         # Right number/type of migrations?
    
  3164.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3165.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  3166.         self.assertOperationAttributes(
    
  3167.             changes,
    
  3168.             "testapp",
    
  3169.             0,
    
  3170.             0,
    
  3171.             name="AuthorProxy",
    
  3172.             options={"proxy": True, "indexes": [], "constraints": []},
    
  3173.         )
    
  3174.         # Now, we test turning a proxy model into a non-proxy model
    
  3175.         # It should delete the proxy then make the real one
    
  3176.         changes = self.get_changes(
    
  3177.             [self.author_empty, self.author_proxy],
    
  3178.             [self.author_empty, self.author_proxy_notproxy],
    
  3179.         )
    
  3180.         # Right number/type of migrations?
    
  3181.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3182.         self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel", "CreateModel"])
    
  3183.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="AuthorProxy")
    
  3184.         self.assertOperationAttributes(
    
  3185.             changes, "testapp", 0, 1, name="AuthorProxy", options={}
    
  3186.         )
    
  3187. 
    
  3188.     def test_proxy_non_model_parent(self):
    
  3189.         class Mixin:
    
  3190.             pass
    
  3191. 
    
  3192.         author_proxy_non_model_parent = ModelState(
    
  3193.             "testapp",
    
  3194.             "AuthorProxy",
    
  3195.             [],
    
  3196.             {"proxy": True},
    
  3197.             (Mixin, "testapp.author"),
    
  3198.         )
    
  3199.         changes = self.get_changes(
    
  3200.             [self.author_empty],
    
  3201.             [self.author_empty, author_proxy_non_model_parent],
    
  3202.         )
    
  3203.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3204.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  3205.         self.assertOperationAttributes(
    
  3206.             changes,
    
  3207.             "testapp",
    
  3208.             0,
    
  3209.             0,
    
  3210.             name="AuthorProxy",
    
  3211.             options={"proxy": True, "indexes": [], "constraints": []},
    
  3212.             bases=(Mixin, "testapp.author"),
    
  3213.         )
    
  3214. 
    
  3215.     def test_proxy_custom_pk(self):
    
  3216.         """
    
  3217.         #23415 - The autodetector must correctly deal with custom FK on proxy
    
  3218.         models.
    
  3219.         """
    
  3220.         # First, we test the default pk field name
    
  3221.         changes = self.get_changes(
    
  3222.             [], [self.author_empty, self.author_proxy_third, self.book_proxy_fk]
    
  3223.         )
    
  3224.         # The model the FK is pointing from and to.
    
  3225.         self.assertEqual(
    
  3226.             changes["otherapp"][0].operations[0].fields[2][1].remote_field.model,
    
  3227.             "thirdapp.AuthorProxy",
    
  3228.         )
    
  3229.         # Now, we test the custom pk field name
    
  3230.         changes = self.get_changes(
    
  3231.             [], [self.author_custom_pk, self.author_proxy_third, self.book_proxy_fk]
    
  3232.         )
    
  3233.         # The model the FK is pointing from and to.
    
  3234.         self.assertEqual(
    
  3235.             changes["otherapp"][0].operations[0].fields[2][1].remote_field.model,
    
  3236.             "thirdapp.AuthorProxy",
    
  3237.         )
    
  3238. 
    
  3239.     def test_proxy_to_mti_with_fk_to_proxy(self):
    
  3240.         # First, test the pk table and field name.
    
  3241.         to_state = self.make_project_state(
    
  3242.             [self.author_empty, self.author_proxy_third, self.book_proxy_fk],
    
  3243.         )
    
  3244.         changes = self.get_changes([], to_state)
    
  3245.         fk_field = changes["otherapp"][0].operations[0].fields[2][1]
    
  3246.         self.assertEqual(
    
  3247.             to_state.get_concrete_model_key(fk_field.remote_field.model),
    
  3248.             ("testapp", "author"),
    
  3249.         )
    
  3250.         self.assertEqual(fk_field.remote_field.model, "thirdapp.AuthorProxy")
    
  3251. 
    
  3252.         # Change AuthorProxy to use MTI.
    
  3253.         from_state = to_state.clone()
    
  3254.         to_state = self.make_project_state(
    
  3255.             [self.author_empty, self.author_proxy_third_notproxy, self.book_proxy_fk],
    
  3256.         )
    
  3257.         changes = self.get_changes(from_state, to_state)
    
  3258.         # Right number/type of migrations for the AuthorProxy model?
    
  3259.         self.assertNumberMigrations(changes, "thirdapp", 1)
    
  3260.         self.assertOperationTypes(
    
  3261.             changes, "thirdapp", 0, ["DeleteModel", "CreateModel"]
    
  3262.         )
    
  3263.         # Right number/type of migrations for the Book model with a FK to
    
  3264.         # AuthorProxy?
    
  3265.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  3266.         self.assertOperationTypes(changes, "otherapp", 0, ["AlterField"])
    
  3267.         # otherapp should depend on thirdapp.
    
  3268.         self.assertMigrationDependencies(
    
  3269.             changes, "otherapp", 0, [("thirdapp", "auto_1")]
    
  3270.         )
    
  3271.         # Now, test the pk table and field name.
    
  3272.         fk_field = changes["otherapp"][0].operations[0].field
    
  3273.         self.assertEqual(
    
  3274.             to_state.get_concrete_model_key(fk_field.remote_field.model),
    
  3275.             ("thirdapp", "authorproxy"),
    
  3276.         )
    
  3277.         self.assertEqual(fk_field.remote_field.model, "thirdapp.AuthorProxy")
    
  3278. 
    
  3279.     def test_proxy_to_mti_with_fk_to_proxy_proxy(self):
    
  3280.         # First, test the pk table and field name.
    
  3281.         to_state = self.make_project_state(
    
  3282.             [
    
  3283.                 self.author_empty,
    
  3284.                 self.author_proxy,
    
  3285.                 self.author_proxy_proxy,
    
  3286.                 self.book_proxy_proxy_fk,
    
  3287.             ]
    
  3288.         )
    
  3289.         changes = self.get_changes([], to_state)
    
  3290.         fk_field = changes["otherapp"][0].operations[0].fields[1][1]
    
  3291.         self.assertEqual(
    
  3292.             to_state.get_concrete_model_key(fk_field.remote_field.model),
    
  3293.             ("testapp", "author"),
    
  3294.         )
    
  3295.         self.assertEqual(fk_field.remote_field.model, "testapp.AAuthorProxyProxy")
    
  3296. 
    
  3297.         # Change AuthorProxy to use MTI. FK still points to AAuthorProxyProxy,
    
  3298.         # a proxy of AuthorProxy.
    
  3299.         from_state = to_state.clone()
    
  3300.         to_state = self.make_project_state(
    
  3301.             [
    
  3302.                 self.author_empty,
    
  3303.                 self.author_proxy_notproxy,
    
  3304.                 self.author_proxy_proxy,
    
  3305.                 self.book_proxy_proxy_fk,
    
  3306.             ]
    
  3307.         )
    
  3308.         changes = self.get_changes(from_state, to_state)
    
  3309.         # Right number/type of migrations for the AuthorProxy model?
    
  3310.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3311.         self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel", "CreateModel"])
    
  3312.         # Right number/type of migrations for the Book model with a FK to
    
  3313.         # AAuthorProxyProxy?
    
  3314.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  3315.         self.assertOperationTypes(changes, "otherapp", 0, ["AlterField"])
    
  3316.         # otherapp should depend on testapp.
    
  3317.         self.assertMigrationDependencies(
    
  3318.             changes, "otherapp", 0, [("testapp", "auto_1")]
    
  3319.         )
    
  3320.         # Now, test the pk table and field name.
    
  3321.         fk_field = changes["otherapp"][0].operations[0].field
    
  3322.         self.assertEqual(
    
  3323.             to_state.get_concrete_model_key(fk_field.remote_field.model),
    
  3324.             ("testapp", "authorproxy"),
    
  3325.         )
    
  3326.         self.assertEqual(fk_field.remote_field.model, "testapp.AAuthorProxyProxy")
    
  3327. 
    
  3328.     def test_unmanaged_create(self):
    
  3329.         """The autodetector correctly deals with managed models."""
    
  3330.         # First, we test adding an unmanaged model
    
  3331.         changes = self.get_changes(
    
  3332.             [self.author_empty], [self.author_empty, self.author_unmanaged]
    
  3333.         )
    
  3334.         # Right number/type of migrations?
    
  3335.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3336.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  3337.         self.assertOperationAttributes(
    
  3338.             changes, "testapp", 0, 0, name="AuthorUnmanaged", options={"managed": False}
    
  3339.         )
    
  3340. 
    
  3341.     def test_unmanaged_delete(self):
    
  3342.         changes = self.get_changes(
    
  3343.             [self.author_empty, self.author_unmanaged], [self.author_empty]
    
  3344.         )
    
  3345.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3346.         self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel"])
    
  3347. 
    
  3348.     def test_unmanaged_to_managed(self):
    
  3349.         # Now, we test turning an unmanaged model into a managed model
    
  3350.         changes = self.get_changes(
    
  3351.             [self.author_empty, self.author_unmanaged],
    
  3352.             [self.author_empty, self.author_unmanaged_managed],
    
  3353.         )
    
  3354.         # Right number/type of migrations?
    
  3355.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3356.         self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
    
  3357.         self.assertOperationAttributes(
    
  3358.             changes, "testapp", 0, 0, name="authorunmanaged", options={}
    
  3359.         )
    
  3360. 
    
  3361.     def test_managed_to_unmanaged(self):
    
  3362.         # Now, we turn managed to unmanaged.
    
  3363.         changes = self.get_changes(
    
  3364.             [self.author_empty, self.author_unmanaged_managed],
    
  3365.             [self.author_empty, self.author_unmanaged],
    
  3366.         )
    
  3367.         # Right number/type of migrations?
    
  3368.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3369.         self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
    
  3370.         self.assertOperationAttributes(
    
  3371.             changes, "testapp", 0, 0, name="authorunmanaged", options={"managed": False}
    
  3372.         )
    
  3373. 
    
  3374.     def test_unmanaged_custom_pk(self):
    
  3375.         """
    
  3376.         #23415 - The autodetector must correctly deal with custom FK on
    
  3377.         unmanaged models.
    
  3378.         """
    
  3379.         # First, we test the default pk field name
    
  3380.         changes = self.get_changes([], [self.author_unmanaged_default_pk, self.book])
    
  3381.         # The model the FK on the book model points to.
    
  3382.         fk_field = changes["otherapp"][0].operations[0].fields[2][1]
    
  3383.         self.assertEqual(fk_field.remote_field.model, "testapp.Author")
    
  3384.         # Now, we test the custom pk field name
    
  3385.         changes = self.get_changes([], [self.author_unmanaged_custom_pk, self.book])
    
  3386.         # The model the FK on the book model points to.
    
  3387.         fk_field = changes["otherapp"][0].operations[0].fields[2][1]
    
  3388.         self.assertEqual(fk_field.remote_field.model, "testapp.Author")
    
  3389. 
    
  3390.     @override_settings(AUTH_USER_MODEL="thirdapp.CustomUser")
    
  3391.     def test_swappable(self):
    
  3392.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  3393.             changes = self.get_changes(
    
  3394.                 [self.custom_user], [self.custom_user, self.author_with_custom_user]
    
  3395.             )
    
  3396.         # Right number/type of migrations?
    
  3397.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3398.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  3399.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  3400.         self.assertMigrationDependencies(
    
  3401.             changes, "testapp", 0, [("__setting__", "AUTH_USER_MODEL")]
    
  3402.         )
    
  3403. 
    
  3404.     def test_swappable_lowercase(self):
    
  3405.         model_state = ModelState(
    
  3406.             "testapp",
    
  3407.             "Document",
    
  3408.             [
    
  3409.                 ("id", models.AutoField(primary_key=True)),
    
  3410.                 (
    
  3411.                     "owner",
    
  3412.                     models.ForeignKey(
    
  3413.                         settings.AUTH_USER_MODEL.lower(),
    
  3414.                         models.CASCADE,
    
  3415.                     ),
    
  3416.                 ),
    
  3417.             ],
    
  3418.         )
    
  3419.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  3420.             changes = self.get_changes([], [model_state])
    
  3421.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3422.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  3423.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Document")
    
  3424.         self.assertMigrationDependencies(
    
  3425.             changes,
    
  3426.             "testapp",
    
  3427.             0,
    
  3428.             [("__setting__", "AUTH_USER_MODEL")],
    
  3429.         )
    
  3430. 
    
  3431.     @override_settings(AUTH_USER_MODEL="thirdapp.CustomUser")
    
  3432.     def test_swappable_many_to_many_model_case(self):
    
  3433.         document_lowercase = ModelState(
    
  3434.             "testapp",
    
  3435.             "Document",
    
  3436.             [
    
  3437.                 ("id", models.AutoField(primary_key=True)),
    
  3438.                 ("owners", models.ManyToManyField(settings.AUTH_USER_MODEL.lower())),
    
  3439.             ],
    
  3440.         )
    
  3441.         document = ModelState(
    
  3442.             "testapp",
    
  3443.             "Document",
    
  3444.             [
    
  3445.                 ("id", models.AutoField(primary_key=True)),
    
  3446.                 ("owners", models.ManyToManyField(settings.AUTH_USER_MODEL)),
    
  3447.             ],
    
  3448.         )
    
  3449.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  3450.             changes = self.get_changes(
    
  3451.                 [self.custom_user, document_lowercase],
    
  3452.                 [self.custom_user, document],
    
  3453.             )
    
  3454.         self.assertEqual(len(changes), 0)
    
  3455. 
    
  3456.     def test_swappable_changed(self):
    
  3457.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  3458.             before = self.make_project_state([self.custom_user, self.author_with_user])
    
  3459.             with override_settings(AUTH_USER_MODEL="thirdapp.CustomUser"):
    
  3460.                 after = self.make_project_state(
    
  3461.                     [self.custom_user, self.author_with_custom_user]
    
  3462.                 )
    
  3463.             autodetector = MigrationAutodetector(before, after)
    
  3464.             changes = autodetector._detect_changes()
    
  3465.         # Right number/type of migrations?
    
  3466.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3467.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  3468.         self.assertOperationAttributes(
    
  3469.             changes, "testapp", 0, 0, model_name="author", name="user"
    
  3470.         )
    
  3471.         fk_field = changes["testapp"][0].operations[0].field
    
  3472.         self.assertEqual(fk_field.remote_field.model, "thirdapp.CustomUser")
    
  3473. 
    
  3474.     def test_add_field_with_default(self):
    
  3475.         """#22030 - Adding a field with a default should work."""
    
  3476.         changes = self.get_changes([self.author_empty], [self.author_name_default])
    
  3477.         # Right number/type of migrations?
    
  3478.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3479.         self.assertOperationTypes(changes, "testapp", 0, ["AddField"])
    
  3480.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="name")
    
  3481. 
    
  3482.     def test_custom_deconstructible(self):
    
  3483.         """
    
  3484.         Two instances which deconstruct to the same value aren't considered a
    
  3485.         change.
    
  3486.         """
    
  3487.         changes = self.get_changes(
    
  3488.             [self.author_name_deconstructible_1], [self.author_name_deconstructible_2]
    
  3489.         )
    
  3490.         # Right number of migrations?
    
  3491.         self.assertEqual(len(changes), 0)
    
  3492. 
    
  3493.     def test_deconstruct_field_kwarg(self):
    
  3494.         """Field instances are handled correctly by nested deconstruction."""
    
  3495.         changes = self.get_changes(
    
  3496.             [self.author_name_deconstructible_3], [self.author_name_deconstructible_4]
    
  3497.         )
    
  3498.         self.assertEqual(changes, {})
    
  3499. 
    
  3500.     def test_deconstructible_list(self):
    
  3501.         """Nested deconstruction descends into lists."""
    
  3502.         # When lists contain items that deconstruct to identical values, those lists
    
  3503.         # should be considered equal for the purpose of detecting state changes
    
  3504.         # (even if the original items are unequal).
    
  3505.         changes = self.get_changes(
    
  3506.             [self.author_name_deconstructible_list_1],
    
  3507.             [self.author_name_deconstructible_list_2],
    
  3508.         )
    
  3509.         self.assertEqual(changes, {})
    
  3510.         # Legitimate differences within the deconstructed lists should be reported
    
  3511.         # as a change
    
  3512.         changes = self.get_changes(
    
  3513.             [self.author_name_deconstructible_list_1],
    
  3514.             [self.author_name_deconstructible_list_3],
    
  3515.         )
    
  3516.         self.assertEqual(len(changes), 1)
    
  3517. 
    
  3518.     def test_deconstructible_tuple(self):
    
  3519.         """Nested deconstruction descends into tuples."""
    
  3520.         # When tuples contain items that deconstruct to identical values, those tuples
    
  3521.         # should be considered equal for the purpose of detecting state changes
    
  3522.         # (even if the original items are unequal).
    
  3523.         changes = self.get_changes(
    
  3524.             [self.author_name_deconstructible_tuple_1],
    
  3525.             [self.author_name_deconstructible_tuple_2],
    
  3526.         )
    
  3527.         self.assertEqual(changes, {})
    
  3528.         # Legitimate differences within the deconstructed tuples should be reported
    
  3529.         # as a change
    
  3530.         changes = self.get_changes(
    
  3531.             [self.author_name_deconstructible_tuple_1],
    
  3532.             [self.author_name_deconstructible_tuple_3],
    
  3533.         )
    
  3534.         self.assertEqual(len(changes), 1)
    
  3535. 
    
  3536.     def test_deconstructible_dict(self):
    
  3537.         """Nested deconstruction descends into dict values."""
    
  3538.         # When dicts contain items whose values deconstruct to identical values,
    
  3539.         # those dicts should be considered equal for the purpose of detecting
    
  3540.         # state changes (even if the original values are unequal).
    
  3541.         changes = self.get_changes(
    
  3542.             [self.author_name_deconstructible_dict_1],
    
  3543.             [self.author_name_deconstructible_dict_2],
    
  3544.         )
    
  3545.         self.assertEqual(changes, {})
    
  3546.         # Legitimate differences within the deconstructed dicts should be reported
    
  3547.         # as a change
    
  3548.         changes = self.get_changes(
    
  3549.             [self.author_name_deconstructible_dict_1],
    
  3550.             [self.author_name_deconstructible_dict_3],
    
  3551.         )
    
  3552.         self.assertEqual(len(changes), 1)
    
  3553. 
    
  3554.     def test_nested_deconstructible_objects(self):
    
  3555.         """
    
  3556.         Nested deconstruction is applied recursively to the args/kwargs of
    
  3557.         deconstructed objects.
    
  3558.         """
    
  3559.         # If the items within a deconstructed object's args/kwargs have the same
    
  3560.         # deconstructed values - whether or not the items themselves are different
    
  3561.         # instances - then the object as a whole is regarded as unchanged.
    
  3562.         changes = self.get_changes(
    
  3563.             [self.author_name_nested_deconstructible_1],
    
  3564.             [self.author_name_nested_deconstructible_2],
    
  3565.         )
    
  3566.         self.assertEqual(changes, {})
    
  3567.         # Differences that exist solely within the args list of a deconstructed object
    
  3568.         # should be reported as changes
    
  3569.         changes = self.get_changes(
    
  3570.             [self.author_name_nested_deconstructible_1],
    
  3571.             [self.author_name_nested_deconstructible_changed_arg],
    
  3572.         )
    
  3573.         self.assertEqual(len(changes), 1)
    
  3574.         # Additional args should also be reported as a change
    
  3575.         changes = self.get_changes(
    
  3576.             [self.author_name_nested_deconstructible_1],
    
  3577.             [self.author_name_nested_deconstructible_extra_arg],
    
  3578.         )
    
  3579.         self.assertEqual(len(changes), 1)
    
  3580.         # Differences that exist solely within the kwargs dict of a deconstructed object
    
  3581.         # should be reported as changes
    
  3582.         changes = self.get_changes(
    
  3583.             [self.author_name_nested_deconstructible_1],
    
  3584.             [self.author_name_nested_deconstructible_changed_kwarg],
    
  3585.         )
    
  3586.         self.assertEqual(len(changes), 1)
    
  3587.         # Additional kwargs should also be reported as a change
    
  3588.         changes = self.get_changes(
    
  3589.             [self.author_name_nested_deconstructible_1],
    
  3590.             [self.author_name_nested_deconstructible_extra_kwarg],
    
  3591.         )
    
  3592.         self.assertEqual(len(changes), 1)
    
  3593. 
    
  3594.     def test_deconstruct_type(self):
    
  3595.         """
    
  3596.         #22951 -- Uninstantiated classes with deconstruct are correctly returned
    
  3597.         by deep_deconstruct during serialization.
    
  3598.         """
    
  3599.         author = ModelState(
    
  3600.             "testapp",
    
  3601.             "Author",
    
  3602.             [
    
  3603.                 ("id", models.AutoField(primary_key=True)),
    
  3604.                 (
    
  3605.                     "name",
    
  3606.                     models.CharField(
    
  3607.                         max_length=200,
    
  3608.                         # IntegerField intentionally not instantiated.
    
  3609.                         default=models.IntegerField,
    
  3610.                     ),
    
  3611.                 ),
    
  3612.             ],
    
  3613.         )
    
  3614.         changes = self.get_changes([], [author])
    
  3615.         # Right number/type of migrations?
    
  3616.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3617.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  3618. 
    
  3619.     def test_replace_string_with_foreignkey(self):
    
  3620.         """
    
  3621.         #22300 - Adding an FK in the same "spot" as a deleted CharField should
    
  3622.         work.
    
  3623.         """
    
  3624.         changes = self.get_changes(
    
  3625.             [self.author_with_publisher_string],
    
  3626.             [self.author_with_publisher, self.publisher],
    
  3627.         )
    
  3628.         # Right number/type of migrations?
    
  3629.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3630.         self.assertOperationTypes(
    
  3631.             changes, "testapp", 0, ["CreateModel", "RemoveField", "AddField"]
    
  3632.         )
    
  3633.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
    
  3634.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="publisher_name")
    
  3635.         self.assertOperationAttributes(changes, "testapp", 0, 2, name="publisher")
    
  3636. 
    
  3637.     def test_foreign_key_removed_before_target_model(self):
    
  3638.         """
    
  3639.         Removing an FK and the model it targets in the same change must remove
    
  3640.         the FK field before the model to maintain consistency.
    
  3641.         """
    
  3642.         changes = self.get_changes(
    
  3643.             [self.author_with_publisher, self.publisher], [self.author_name]
    
  3644.         )  # removes both the model and FK
    
  3645.         # Right number/type of migrations?
    
  3646.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3647.         self.assertOperationTypes(changes, "testapp", 0, ["RemoveField", "DeleteModel"])
    
  3648.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="publisher")
    
  3649.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
    
  3650. 
    
  3651.     @mock.patch(
    
  3652.         "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition",
    
  3653.         side_effect=AssertionError("Should not have prompted for not null addition"),
    
  3654.     )
    
  3655.     def test_add_many_to_many(self, mocked_ask_method):
    
  3656.         """#22435 - Adding a ManyToManyField should not prompt for a default."""
    
  3657.         changes = self.get_changes(
    
  3658.             [self.author_empty, self.publisher], [self.author_with_m2m, self.publisher]
    
  3659.         )
    
  3660.         # Right number/type of migrations?
    
  3661.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3662.         self.assertOperationTypes(changes, "testapp", 0, ["AddField"])
    
  3663.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="publishers")
    
  3664. 
    
  3665.     def test_alter_many_to_many(self):
    
  3666.         changes = self.get_changes(
    
  3667.             [self.author_with_m2m, self.publisher],
    
  3668.             [self.author_with_m2m_blank, self.publisher],
    
  3669.         )
    
  3670.         # Right number/type of migrations?
    
  3671.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3672.         self.assertOperationTypes(changes, "testapp", 0, ["AlterField"])
    
  3673.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="publishers")
    
  3674. 
    
  3675.     def test_create_with_through_model(self):
    
  3676.         """
    
  3677.         Adding a m2m with a through model and the models that use it should be
    
  3678.         ordered correctly.
    
  3679.         """
    
  3680.         changes = self.get_changes(
    
  3681.             [], [self.author_with_m2m_through, self.publisher, self.contract]
    
  3682.         )
    
  3683.         # Right number/type of migrations?
    
  3684.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3685.         self.assertOperationTypes(
    
  3686.             changes,
    
  3687.             "testapp",
    
  3688.             0,
    
  3689.             [
    
  3690.                 "CreateModel",
    
  3691.                 "CreateModel",
    
  3692.                 "CreateModel",
    
  3693.                 "AddField",
    
  3694.             ],
    
  3695.         )
    
  3696.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  3697.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
    
  3698.         self.assertOperationAttributes(changes, "testapp", 0, 2, name="Contract")
    
  3699.         self.assertOperationAttributes(
    
  3700.             changes, "testapp", 0, 3, model_name="author", name="publishers"
    
  3701.         )
    
  3702. 
    
  3703.     def test_create_with_through_model_separate_apps(self):
    
  3704.         author_with_m2m_through = ModelState(
    
  3705.             "authors",
    
  3706.             "Author",
    
  3707.             [
    
  3708.                 ("id", models.AutoField(primary_key=True)),
    
  3709.                 (
    
  3710.                     "publishers",
    
  3711.                     models.ManyToManyField(
    
  3712.                         "testapp.Publisher", through="contract.Contract"
    
  3713.                     ),
    
  3714.                 ),
    
  3715.             ],
    
  3716.         )
    
  3717.         contract = ModelState(
    
  3718.             "contract",
    
  3719.             "Contract",
    
  3720.             [
    
  3721.                 ("id", models.AutoField(primary_key=True)),
    
  3722.                 ("author", models.ForeignKey("authors.Author", models.CASCADE)),
    
  3723.                 ("publisher", models.ForeignKey("testapp.Publisher", models.CASCADE)),
    
  3724.             ],
    
  3725.         )
    
  3726.         changes = self.get_changes(
    
  3727.             [], [author_with_m2m_through, self.publisher, contract]
    
  3728.         )
    
  3729.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3730.         self.assertNumberMigrations(changes, "contract", 1)
    
  3731.         self.assertNumberMigrations(changes, "authors", 2)
    
  3732.         self.assertMigrationDependencies(
    
  3733.             changes,
    
  3734.             "authors",
    
  3735.             1,
    
  3736.             {("authors", "auto_1"), ("contract", "auto_1"), ("testapp", "auto_1")},
    
  3737.         )
    
  3738.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  3739.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
    
  3740.         self.assertOperationTypes(changes, "contract", 0, ["CreateModel"])
    
  3741.         self.assertOperationAttributes(changes, "contract", 0, 0, name="Contract")
    
  3742.         self.assertOperationTypes(changes, "authors", 0, ["CreateModel"])
    
  3743.         self.assertOperationTypes(changes, "authors", 1, ["AddField"])
    
  3744.         self.assertOperationAttributes(changes, "authors", 0, 0, name="Author")
    
  3745.         self.assertOperationAttributes(
    
  3746.             changes, "authors", 1, 0, model_name="author", name="publishers"
    
  3747.         )
    
  3748. 
    
  3749.     def test_many_to_many_removed_before_through_model(self):
    
  3750.         """
    
  3751.         Removing a ManyToManyField and the "through" model in the same change
    
  3752.         must remove the field before the model to maintain consistency.
    
  3753.         """
    
  3754.         changes = self.get_changes(
    
  3755.             [
    
  3756.                 self.book_with_multiple_authors_through_attribution,
    
  3757.                 self.author_name,
    
  3758.                 self.attribution,
    
  3759.             ],
    
  3760.             [self.book_with_no_author, self.author_name],
    
  3761.         )
    
  3762.         # Remove both the through model and ManyToMany
    
  3763.         # Right number/type of migrations?
    
  3764.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  3765.         self.assertOperationTypes(
    
  3766.             changes, "otherapp", 0, ["RemoveField", "DeleteModel"]
    
  3767.         )
    
  3768.         self.assertOperationAttributes(
    
  3769.             changes, "otherapp", 0, 0, name="authors", model_name="book"
    
  3770.         )
    
  3771.         self.assertOperationAttributes(changes, "otherapp", 0, 1, name="Attribution")
    
  3772. 
    
  3773.     def test_many_to_many_removed_before_through_model_2(self):
    
  3774.         """
    
  3775.         Removing a model that contains a ManyToManyField and the "through" model
    
  3776.         in the same change must remove the field before the model to maintain
    
  3777.         consistency.
    
  3778.         """
    
  3779.         changes = self.get_changes(
    
  3780.             [
    
  3781.                 self.book_with_multiple_authors_through_attribution,
    
  3782.                 self.author_name,
    
  3783.                 self.attribution,
    
  3784.             ],
    
  3785.             [self.author_name],
    
  3786.         )
    
  3787.         # Remove both the through model and ManyToMany
    
  3788.         # Right number/type of migrations?
    
  3789.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  3790.         self.assertOperationTypes(
    
  3791.             changes, "otherapp", 0, ["RemoveField", "DeleteModel", "DeleteModel"]
    
  3792.         )
    
  3793.         self.assertOperationAttributes(
    
  3794.             changes, "otherapp", 0, 0, name="authors", model_name="book"
    
  3795.         )
    
  3796.         self.assertOperationAttributes(changes, "otherapp", 0, 1, name="Attribution")
    
  3797.         self.assertOperationAttributes(changes, "otherapp", 0, 2, name="Book")
    
  3798. 
    
  3799.     def test_m2m_w_through_multistep_remove(self):
    
  3800.         """
    
  3801.         A model with a m2m field that specifies a "through" model cannot be
    
  3802.         removed in the same migration as that through model as the schema will
    
  3803.         pass through an inconsistent state. The autodetector should produce two
    
  3804.         migrations to avoid this issue.
    
  3805.         """
    
  3806.         changes = self.get_changes(
    
  3807.             [self.author_with_m2m_through, self.publisher, self.contract],
    
  3808.             [self.publisher],
    
  3809.         )
    
  3810.         # Right number/type of migrations?
    
  3811.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3812.         self.assertOperationTypes(
    
  3813.             changes,
    
  3814.             "testapp",
    
  3815.             0,
    
  3816.             ["RemoveField", "RemoveField", "DeleteModel", "DeleteModel"],
    
  3817.         )
    
  3818.         self.assertOperationAttributes(
    
  3819.             changes, "testapp", 0, 0, name="author", model_name="contract"
    
  3820.         )
    
  3821.         self.assertOperationAttributes(
    
  3822.             changes, "testapp", 0, 1, name="publisher", model_name="contract"
    
  3823.         )
    
  3824.         self.assertOperationAttributes(changes, "testapp", 0, 2, name="Author")
    
  3825.         self.assertOperationAttributes(changes, "testapp", 0, 3, name="Contract")
    
  3826. 
    
  3827.     def test_concrete_field_changed_to_many_to_many(self):
    
  3828.         """
    
  3829.         #23938 - Changing a concrete field into a ManyToManyField
    
  3830.         first removes the concrete field and then adds the m2m field.
    
  3831.         """
    
  3832.         changes = self.get_changes(
    
  3833.             [self.author_with_former_m2m], [self.author_with_m2m, self.publisher]
    
  3834.         )
    
  3835.         # Right number/type of migrations?
    
  3836.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3837.         self.assertOperationTypes(
    
  3838.             changes, "testapp", 0, ["CreateModel", "RemoveField", "AddField"]
    
  3839.         )
    
  3840.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher")
    
  3841.         self.assertOperationAttributes(
    
  3842.             changes, "testapp", 0, 1, name="publishers", model_name="author"
    
  3843.         )
    
  3844.         self.assertOperationAttributes(
    
  3845.             changes, "testapp", 0, 2, name="publishers", model_name="author"
    
  3846.         )
    
  3847. 
    
  3848.     def test_many_to_many_changed_to_concrete_field(self):
    
  3849.         """
    
  3850.         #23938 - Changing a ManyToManyField into a concrete field
    
  3851.         first removes the m2m field and then adds the concrete field.
    
  3852.         """
    
  3853.         changes = self.get_changes(
    
  3854.             [self.author_with_m2m, self.publisher], [self.author_with_former_m2m]
    
  3855.         )
    
  3856.         # Right number/type of migrations?
    
  3857.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3858.         self.assertOperationTypes(
    
  3859.             changes, "testapp", 0, ["RemoveField", "DeleteModel", "AddField"]
    
  3860.         )
    
  3861.         self.assertOperationAttributes(
    
  3862.             changes, "testapp", 0, 0, name="publishers", model_name="author"
    
  3863.         )
    
  3864.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
    
  3865.         self.assertOperationAttributes(
    
  3866.             changes, "testapp", 0, 2, name="publishers", model_name="author"
    
  3867.         )
    
  3868.         self.assertOperationFieldAttributes(changes, "testapp", 0, 2, max_length=100)
    
  3869. 
    
  3870.     def test_non_circular_foreignkey_dependency_removal(self):
    
  3871.         """
    
  3872.         If two models with a ForeignKey from one to the other are removed at the
    
  3873.         same time, the autodetector should remove them in the correct order.
    
  3874.         """
    
  3875.         changes = self.get_changes(
    
  3876.             [self.author_with_publisher, self.publisher_with_author], []
    
  3877.         )
    
  3878.         # Right number/type of migrations?
    
  3879.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3880.         self.assertOperationTypes(
    
  3881.             changes, "testapp", 0, ["RemoveField", "DeleteModel", "DeleteModel"]
    
  3882.         )
    
  3883.         self.assertOperationAttributes(
    
  3884.             changes, "testapp", 0, 0, name="author", model_name="publisher"
    
  3885.         )
    
  3886.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Author")
    
  3887.         self.assertOperationAttributes(changes, "testapp", 0, 2, name="Publisher")
    
  3888. 
    
  3889.     def test_alter_model_options(self):
    
  3890.         """Changing a model's options should make a change."""
    
  3891.         changes = self.get_changes([self.author_empty], [self.author_with_options])
    
  3892.         # Right number/type of migrations?
    
  3893.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3894.         self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
    
  3895.         self.assertOperationAttributes(
    
  3896.             changes,
    
  3897.             "testapp",
    
  3898.             0,
    
  3899.             0,
    
  3900.             options={
    
  3901.                 "permissions": [("can_hire", "Can hire")],
    
  3902.                 "verbose_name": "Authi",
    
  3903.             },
    
  3904.         )
    
  3905. 
    
  3906.         # Changing them back to empty should also make a change
    
  3907.         changes = self.get_changes([self.author_with_options], [self.author_empty])
    
  3908.         # Right number/type of migrations?
    
  3909.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3910.         self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
    
  3911.         self.assertOperationAttributes(
    
  3912.             changes, "testapp", 0, 0, name="author", options={}
    
  3913.         )
    
  3914. 
    
  3915.     def test_alter_model_options_proxy(self):
    
  3916.         """Changing a proxy model's options should also make a change."""
    
  3917.         changes = self.get_changes(
    
  3918.             [self.author_proxy, self.author_empty],
    
  3919.             [self.author_proxy_options, self.author_empty],
    
  3920.         )
    
  3921.         # Right number/type of migrations?
    
  3922.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3923.         self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
    
  3924.         self.assertOperationAttributes(
    
  3925.             changes,
    
  3926.             "testapp",
    
  3927.             0,
    
  3928.             0,
    
  3929.             name="authorproxy",
    
  3930.             options={"verbose_name": "Super Author"},
    
  3931.         )
    
  3932. 
    
  3933.     def test_set_alter_order_with_respect_to(self):
    
  3934.         """Setting order_with_respect_to adds a field."""
    
  3935.         changes = self.get_changes(
    
  3936.             [self.book, self.author_with_book],
    
  3937.             [self.book, self.author_with_book_order_wrt],
    
  3938.         )
    
  3939.         # Right number/type of migrations?
    
  3940.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3941.         self.assertOperationTypes(changes, "testapp", 0, ["AlterOrderWithRespectTo"])
    
  3942.         self.assertOperationAttributes(
    
  3943.             changes, "testapp", 0, 0, name="author", order_with_respect_to="book"
    
  3944.         )
    
  3945. 
    
  3946.     def test_add_alter_order_with_respect_to(self):
    
  3947.         """
    
  3948.         Setting order_with_respect_to when adding the FK too does
    
  3949.         things in the right order.
    
  3950.         """
    
  3951.         changes = self.get_changes(
    
  3952.             [self.author_name], [self.book, self.author_with_book_order_wrt]
    
  3953.         )
    
  3954.         # Right number/type of migrations?
    
  3955.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3956.         self.assertOperationTypes(
    
  3957.             changes, "testapp", 0, ["AddField", "AlterOrderWithRespectTo"]
    
  3958.         )
    
  3959.         self.assertOperationAttributes(
    
  3960.             changes, "testapp", 0, 0, model_name="author", name="book"
    
  3961.         )
    
  3962.         self.assertOperationAttributes(
    
  3963.             changes, "testapp", 0, 1, name="author", order_with_respect_to="book"
    
  3964.         )
    
  3965. 
    
  3966.     def test_remove_alter_order_with_respect_to(self):
    
  3967.         """
    
  3968.         Removing order_with_respect_to when removing the FK too does
    
  3969.         things in the right order.
    
  3970.         """
    
  3971.         changes = self.get_changes(
    
  3972.             [self.book, self.author_with_book_order_wrt], [self.author_name]
    
  3973.         )
    
  3974.         # Right number/type of migrations?
    
  3975.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3976.         self.assertOperationTypes(
    
  3977.             changes, "testapp", 0, ["AlterOrderWithRespectTo", "RemoveField"]
    
  3978.         )
    
  3979.         self.assertOperationAttributes(
    
  3980.             changes, "testapp", 0, 0, name="author", order_with_respect_to=None
    
  3981.         )
    
  3982.         self.assertOperationAttributes(
    
  3983.             changes, "testapp", 0, 1, model_name="author", name="book"
    
  3984.         )
    
  3985. 
    
  3986.     def test_add_model_order_with_respect_to(self):
    
  3987.         """
    
  3988.         Setting order_with_respect_to when adding the whole model
    
  3989.         does things in the right order.
    
  3990.         """
    
  3991.         changes = self.get_changes([], [self.book, self.author_with_book_order_wrt])
    
  3992.         # Right number/type of migrations?
    
  3993.         self.assertNumberMigrations(changes, "testapp", 1)
    
  3994.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  3995.         self.assertOperationAttributes(
    
  3996.             changes,
    
  3997.             "testapp",
    
  3998.             0,
    
  3999.             0,
    
  4000.             name="Author",
    
  4001.             options={"order_with_respect_to": "book"},
    
  4002.         )
    
  4003.         self.assertNotIn(
    
  4004.             "_order",
    
  4005.             [name for name, field in changes["testapp"][0].operations[0].fields],
    
  4006.         )
    
  4007. 
    
  4008.     def test_add_model_order_with_respect_to_index_foo_together(self):
    
  4009.         changes = self.get_changes(
    
  4010.             [],
    
  4011.             [
    
  4012.                 self.book,
    
  4013.                 ModelState(
    
  4014.                     "testapp",
    
  4015.                     "Author",
    
  4016.                     [
    
  4017.                         ("id", models.AutoField(primary_key=True)),
    
  4018.                         ("name", models.CharField(max_length=200)),
    
  4019.                         ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  4020.                     ],
    
  4021.                     options={
    
  4022.                         "order_with_respect_to": "book",
    
  4023.                         "index_together": {("name", "_order")},
    
  4024.                         "unique_together": {("id", "_order")},
    
  4025.                     },
    
  4026.                 ),
    
  4027.             ],
    
  4028.         )
    
  4029.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4030.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  4031.         self.assertOperationAttributes(
    
  4032.             changes,
    
  4033.             "testapp",
    
  4034.             0,
    
  4035.             0,
    
  4036.             name="Author",
    
  4037.             options={
    
  4038.                 "order_with_respect_to": "book",
    
  4039.                 "index_together": {("name", "_order")},
    
  4040.                 "unique_together": {("id", "_order")},
    
  4041.             },
    
  4042.         )
    
  4043. 
    
  4044.     def test_add_model_order_with_respect_to_index_constraint(self):
    
  4045.         tests = [
    
  4046.             (
    
  4047.                 "AddIndex",
    
  4048.                 {
    
  4049.                     "indexes": [
    
  4050.                         models.Index(fields=["_order"], name="book_order_idx"),
    
  4051.                     ]
    
  4052.                 },
    
  4053.             ),
    
  4054.             (
    
  4055.                 "AddConstraint",
    
  4056.                 {
    
  4057.                     "constraints": [
    
  4058.                         models.CheckConstraint(
    
  4059.                             check=models.Q(_order__gt=1),
    
  4060.                             name="book_order_gt_1",
    
  4061.                         ),
    
  4062.                     ]
    
  4063.                 },
    
  4064.             ),
    
  4065.         ]
    
  4066.         for operation, extra_option in tests:
    
  4067.             with self.subTest(operation=operation):
    
  4068.                 after = ModelState(
    
  4069.                     "testapp",
    
  4070.                     "Author",
    
  4071.                     [
    
  4072.                         ("id", models.AutoField(primary_key=True)),
    
  4073.                         ("name", models.CharField(max_length=200)),
    
  4074.                         ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  4075.                     ],
    
  4076.                     options={
    
  4077.                         "order_with_respect_to": "book",
    
  4078.                         **extra_option,
    
  4079.                     },
    
  4080.                 )
    
  4081.                 changes = self.get_changes([], [self.book, after])
    
  4082.                 self.assertNumberMigrations(changes, "testapp", 1)
    
  4083.                 self.assertOperationTypes(
    
  4084.                     changes,
    
  4085.                     "testapp",
    
  4086.                     0,
    
  4087.                     [
    
  4088.                         "CreateModel",
    
  4089.                         operation,
    
  4090.                     ],
    
  4091.                 )
    
  4092.                 self.assertOperationAttributes(
    
  4093.                     changes,
    
  4094.                     "testapp",
    
  4095.                     0,
    
  4096.                     0,
    
  4097.                     name="Author",
    
  4098.                     options={"order_with_respect_to": "book"},
    
  4099.                 )
    
  4100. 
    
  4101.     def test_set_alter_order_with_respect_to_index_constraint_foo_together(self):
    
  4102.         tests = [
    
  4103.             (
    
  4104.                 "AddIndex",
    
  4105.                 {
    
  4106.                     "indexes": [
    
  4107.                         models.Index(fields=["_order"], name="book_order_idx"),
    
  4108.                     ]
    
  4109.                 },
    
  4110.             ),
    
  4111.             (
    
  4112.                 "AddConstraint",
    
  4113.                 {
    
  4114.                     "constraints": [
    
  4115.                         models.CheckConstraint(
    
  4116.                             check=models.Q(_order__gt=1),
    
  4117.                             name="book_order_gt_1",
    
  4118.                         ),
    
  4119.                     ]
    
  4120.                 },
    
  4121.             ),
    
  4122.             ("AlterIndexTogether", {"index_together": {("name", "_order")}}),
    
  4123.             ("AlterUniqueTogether", {"unique_together": {("id", "_order")}}),
    
  4124.         ]
    
  4125.         for operation, extra_option in tests:
    
  4126.             with self.subTest(operation=operation):
    
  4127.                 after = ModelState(
    
  4128.                     "testapp",
    
  4129.                     "Author",
    
  4130.                     [
    
  4131.                         ("id", models.AutoField(primary_key=True)),
    
  4132.                         ("name", models.CharField(max_length=200)),
    
  4133.                         ("book", models.ForeignKey("otherapp.Book", models.CASCADE)),
    
  4134.                     ],
    
  4135.                     options={
    
  4136.                         "order_with_respect_to": "book",
    
  4137.                         **extra_option,
    
  4138.                     },
    
  4139.                 )
    
  4140.                 changes = self.get_changes(
    
  4141.                     [self.book, self.author_with_book],
    
  4142.                     [self.book, after],
    
  4143.                 )
    
  4144.                 self.assertNumberMigrations(changes, "testapp", 1)
    
  4145.                 self.assertOperationTypes(
    
  4146.                     changes,
    
  4147.                     "testapp",
    
  4148.                     0,
    
  4149.                     [
    
  4150.                         "AlterOrderWithRespectTo",
    
  4151.                         operation,
    
  4152.                     ],
    
  4153.                 )
    
  4154. 
    
  4155.     def test_alter_model_managers(self):
    
  4156.         """
    
  4157.         Changing the model managers adds a new operation.
    
  4158.         """
    
  4159.         changes = self.get_changes([self.other_pony], [self.other_pony_food])
    
  4160.         # Right number/type of migrations?
    
  4161.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  4162.         self.assertOperationTypes(changes, "otherapp", 0, ["AlterModelManagers"])
    
  4163.         self.assertOperationAttributes(changes, "otherapp", 0, 0, name="pony")
    
  4164.         self.assertEqual(
    
  4165.             [name for name, mgr in changes["otherapp"][0].operations[0].managers],
    
  4166.             ["food_qs", "food_mgr", "food_mgr_kwargs"],
    
  4167.         )
    
  4168.         self.assertEqual(
    
  4169.             changes["otherapp"][0].operations[0].managers[1][1].args, ("a", "b", 1, 2)
    
  4170.         )
    
  4171.         self.assertEqual(
    
  4172.             changes["otherapp"][0].operations[0].managers[2][1].args, ("x", "y", 3, 4)
    
  4173.         )
    
  4174. 
    
  4175.     def test_swappable_first_inheritance(self):
    
  4176.         """Swappable models get their CreateModel first."""
    
  4177.         changes = self.get_changes([], [self.custom_user, self.aardvark])
    
  4178.         # Right number/type of migrations?
    
  4179.         self.assertNumberMigrations(changes, "thirdapp", 1)
    
  4180.         self.assertOperationTypes(
    
  4181.             changes, "thirdapp", 0, ["CreateModel", "CreateModel"]
    
  4182.         )
    
  4183.         self.assertOperationAttributes(changes, "thirdapp", 0, 0, name="CustomUser")
    
  4184.         self.assertOperationAttributes(changes, "thirdapp", 0, 1, name="Aardvark")
    
  4185. 
    
  4186.     def test_default_related_name_option(self):
    
  4187.         model_state = ModelState(
    
  4188.             "app",
    
  4189.             "model",
    
  4190.             [
    
  4191.                 ("id", models.AutoField(primary_key=True)),
    
  4192.             ],
    
  4193.             options={"default_related_name": "related_name"},
    
  4194.         )
    
  4195.         changes = self.get_changes([], [model_state])
    
  4196.         self.assertNumberMigrations(changes, "app", 1)
    
  4197.         self.assertOperationTypes(changes, "app", 0, ["CreateModel"])
    
  4198.         self.assertOperationAttributes(
    
  4199.             changes,
    
  4200.             "app",
    
  4201.             0,
    
  4202.             0,
    
  4203.             name="model",
    
  4204.             options={"default_related_name": "related_name"},
    
  4205.         )
    
  4206.         altered_model_state = ModelState(
    
  4207.             "app",
    
  4208.             "Model",
    
  4209.             [
    
  4210.                 ("id", models.AutoField(primary_key=True)),
    
  4211.             ],
    
  4212.         )
    
  4213.         changes = self.get_changes([model_state], [altered_model_state])
    
  4214.         self.assertNumberMigrations(changes, "app", 1)
    
  4215.         self.assertOperationTypes(changes, "app", 0, ["AlterModelOptions"])
    
  4216.         self.assertOperationAttributes(changes, "app", 0, 0, name="model", options={})
    
  4217. 
    
  4218.     @override_settings(AUTH_USER_MODEL="thirdapp.CustomUser")
    
  4219.     def test_swappable_first_setting(self):
    
  4220.         """Swappable models get their CreateModel first."""
    
  4221.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  4222.             changes = self.get_changes([], [self.custom_user_no_inherit, self.aardvark])
    
  4223.         # Right number/type of migrations?
    
  4224.         self.assertNumberMigrations(changes, "thirdapp", 1)
    
  4225.         self.assertOperationTypes(
    
  4226.             changes, "thirdapp", 0, ["CreateModel", "CreateModel"]
    
  4227.         )
    
  4228.         self.assertOperationAttributes(changes, "thirdapp", 0, 0, name="CustomUser")
    
  4229.         self.assertOperationAttributes(changes, "thirdapp", 0, 1, name="Aardvark")
    
  4230. 
    
  4231.     def test_bases_first(self):
    
  4232.         """Bases of other models come first."""
    
  4233.         changes = self.get_changes(
    
  4234.             [], [self.aardvark_based_on_author, self.author_name]
    
  4235.         )
    
  4236.         # Right number/type of migrations?
    
  4237.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4238.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel"])
    
  4239.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  4240.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Aardvark")
    
  4241. 
    
  4242.     def test_bases_first_mixed_case_app_label(self):
    
  4243.         app_label = "MiXedCaseApp"
    
  4244.         changes = self.get_changes(
    
  4245.             [],
    
  4246.             [
    
  4247.                 ModelState(
    
  4248.                     app_label,
    
  4249.                     "owner",
    
  4250.                     [
    
  4251.                         ("id", models.AutoField(primary_key=True)),
    
  4252.                     ],
    
  4253.                 ),
    
  4254.                 ModelState(
    
  4255.                     app_label,
    
  4256.                     "place",
    
  4257.                     [
    
  4258.                         ("id", models.AutoField(primary_key=True)),
    
  4259.                         (
    
  4260.                             "owner",
    
  4261.                             models.ForeignKey("MiXedCaseApp.owner", models.CASCADE),
    
  4262.                         ),
    
  4263.                     ],
    
  4264.                 ),
    
  4265.                 ModelState(app_label, "restaurant", [], bases=("MiXedCaseApp.place",)),
    
  4266.             ],
    
  4267.         )
    
  4268.         self.assertNumberMigrations(changes, app_label, 1)
    
  4269.         self.assertOperationTypes(
    
  4270.             changes,
    
  4271.             app_label,
    
  4272.             0,
    
  4273.             [
    
  4274.                 "CreateModel",
    
  4275.                 "CreateModel",
    
  4276.                 "CreateModel",
    
  4277.             ],
    
  4278.         )
    
  4279.         self.assertOperationAttributes(changes, app_label, 0, 0, name="owner")
    
  4280.         self.assertOperationAttributes(changes, app_label, 0, 1, name="place")
    
  4281.         self.assertOperationAttributes(changes, app_label, 0, 2, name="restaurant")
    
  4282. 
    
  4283.     def test_multiple_bases(self):
    
  4284.         """
    
  4285.         Inheriting models doesn't move *_ptr fields into AddField operations.
    
  4286.         """
    
  4287.         A = ModelState("app", "A", [("a_id", models.AutoField(primary_key=True))])
    
  4288.         B = ModelState("app", "B", [("b_id", models.AutoField(primary_key=True))])
    
  4289.         C = ModelState("app", "C", [], bases=("app.A", "app.B"))
    
  4290.         D = ModelState("app", "D", [], bases=("app.A", "app.B"))
    
  4291.         E = ModelState("app", "E", [], bases=("app.A", "app.B"))
    
  4292.         changes = self.get_changes([], [A, B, C, D, E])
    
  4293.         # Right number/type of migrations?
    
  4294.         self.assertNumberMigrations(changes, "app", 1)
    
  4295.         self.assertOperationTypes(
    
  4296.             changes,
    
  4297.             "app",
    
  4298.             0,
    
  4299.             ["CreateModel", "CreateModel", "CreateModel", "CreateModel", "CreateModel"],
    
  4300.         )
    
  4301.         self.assertOperationAttributes(changes, "app", 0, 0, name="A")
    
  4302.         self.assertOperationAttributes(changes, "app", 0, 1, name="B")
    
  4303.         self.assertOperationAttributes(changes, "app", 0, 2, name="C")
    
  4304.         self.assertOperationAttributes(changes, "app", 0, 3, name="D")
    
  4305.         self.assertOperationAttributes(changes, "app", 0, 4, name="E")
    
  4306. 
    
  4307.     def test_proxy_bases_first(self):
    
  4308.         """Bases of proxies come first."""
    
  4309.         changes = self.get_changes(
    
  4310.             [], [self.author_empty, self.author_proxy, self.author_proxy_proxy]
    
  4311.         )
    
  4312.         # Right number/type of migrations?
    
  4313.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4314.         self.assertOperationTypes(
    
  4315.             changes, "testapp", 0, ["CreateModel", "CreateModel", "CreateModel"]
    
  4316.         )
    
  4317.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  4318.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="AuthorProxy")
    
  4319.         self.assertOperationAttributes(
    
  4320.             changes, "testapp", 0, 2, name="AAuthorProxyProxy"
    
  4321.         )
    
  4322. 
    
  4323.     def test_pk_fk_included(self):
    
  4324.         """
    
  4325.         A relation used as the primary key is kept as part of CreateModel.
    
  4326.         """
    
  4327.         changes = self.get_changes([], [self.aardvark_pk_fk_author, self.author_name])
    
  4328.         # Right number/type of migrations?
    
  4329.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4330.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel"])
    
  4331.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
    
  4332.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="Aardvark")
    
  4333. 
    
  4334.     def test_first_dependency(self):
    
  4335.         """
    
  4336.         A dependency to an app with no migrations uses __first__.
    
  4337.         """
    
  4338.         # Load graph
    
  4339.         loader = MigrationLoader(connection)
    
  4340.         before = self.make_project_state([])
    
  4341.         after = self.make_project_state([self.book_migrations_fk])
    
  4342.         after.real_apps = {"migrations"}
    
  4343.         autodetector = MigrationAutodetector(before, after)
    
  4344.         changes = autodetector._detect_changes(graph=loader.graph)
    
  4345.         # Right number/type of migrations?
    
  4346.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  4347.         self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
    
  4348.         self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Book")
    
  4349.         self.assertMigrationDependencies(
    
  4350.             changes, "otherapp", 0, [("migrations", "__first__")]
    
  4351.         )
    
  4352. 
    
  4353.     @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
    
  4354.     def test_last_dependency(self):
    
  4355.         """
    
  4356.         A dependency to an app with existing migrations uses the
    
  4357.         last migration of that app.
    
  4358.         """
    
  4359.         # Load graph
    
  4360.         loader = MigrationLoader(connection)
    
  4361.         before = self.make_project_state([])
    
  4362.         after = self.make_project_state([self.book_migrations_fk])
    
  4363.         after.real_apps = {"migrations"}
    
  4364.         autodetector = MigrationAutodetector(before, after)
    
  4365.         changes = autodetector._detect_changes(graph=loader.graph)
    
  4366.         # Right number/type of migrations?
    
  4367.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  4368.         self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"])
    
  4369.         self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Book")
    
  4370.         self.assertMigrationDependencies(
    
  4371.             changes, "otherapp", 0, [("migrations", "0002_second")]
    
  4372.         )
    
  4373. 
    
  4374.     def test_alter_fk_before_model_deletion(self):
    
  4375.         """
    
  4376.         ForeignKeys are altered _before_ the model they used to
    
  4377.         refer to are deleted.
    
  4378.         """
    
  4379.         changes = self.get_changes(
    
  4380.             [self.author_name, self.publisher_with_author],
    
  4381.             [self.aardvark_testapp, self.publisher_with_aardvark_author],
    
  4382.         )
    
  4383.         # Right number/type of migrations?
    
  4384.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4385.         self.assertOperationTypes(
    
  4386.             changes, "testapp", 0, ["CreateModel", "AlterField", "DeleteModel"]
    
  4387.         )
    
  4388.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Aardvark")
    
  4389.         self.assertOperationAttributes(changes, "testapp", 0, 1, name="author")
    
  4390.         self.assertOperationAttributes(changes, "testapp", 0, 2, name="Author")
    
  4391. 
    
  4392.     def test_fk_dependency_other_app(self):
    
  4393.         """
    
  4394.         #23100 - ForeignKeys correctly depend on other apps' models.
    
  4395.         """
    
  4396.         changes = self.get_changes(
    
  4397.             [self.author_name, self.book], [self.author_with_book, self.book]
    
  4398.         )
    
  4399.         # Right number/type of migrations?
    
  4400.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4401.         self.assertOperationTypes(changes, "testapp", 0, ["AddField"])
    
  4402.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="book")
    
  4403.         self.assertMigrationDependencies(
    
  4404.             changes, "testapp", 0, [("otherapp", "__first__")]
    
  4405.         )
    
  4406. 
    
  4407.     def test_alter_unique_together_fk_to_m2m(self):
    
  4408.         changes = self.get_changes(
    
  4409.             [self.author_name, self.book_unique_together],
    
  4410.             [
    
  4411.                 self.author_name,
    
  4412.                 ModelState(
    
  4413.                     "otherapp",
    
  4414.                     "Book",
    
  4415.                     [
    
  4416.                         ("id", models.AutoField(primary_key=True)),
    
  4417.                         ("author", models.ManyToManyField("testapp.Author")),
    
  4418.                         ("title", models.CharField(max_length=200)),
    
  4419.                     ],
    
  4420.                 ),
    
  4421.             ],
    
  4422.         )
    
  4423.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  4424.         self.assertOperationTypes(
    
  4425.             changes, "otherapp", 0, ["AlterUniqueTogether", "RemoveField", "AddField"]
    
  4426.         )
    
  4427.         self.assertOperationAttributes(
    
  4428.             changes, "otherapp", 0, 0, name="book", unique_together=set()
    
  4429.         )
    
  4430.         self.assertOperationAttributes(
    
  4431.             changes, "otherapp", 0, 1, model_name="book", name="author"
    
  4432.         )
    
  4433.         self.assertOperationAttributes(
    
  4434.             changes, "otherapp", 0, 2, model_name="book", name="author"
    
  4435.         )
    
  4436. 
    
  4437.     def test_alter_field_to_fk_dependency_other_app(self):
    
  4438.         changes = self.get_changes(
    
  4439.             [self.author_empty, self.book_with_no_author_fk],
    
  4440.             [self.author_empty, self.book],
    
  4441.         )
    
  4442.         self.assertNumberMigrations(changes, "otherapp", 1)
    
  4443.         self.assertOperationTypes(changes, "otherapp", 0, ["AlterField"])
    
  4444.         self.assertMigrationDependencies(
    
  4445.             changes, "otherapp", 0, [("testapp", "__first__")]
    
  4446.         )
    
  4447. 
    
  4448.     def test_circular_dependency_mixed_addcreate(self):
    
  4449.         """
    
  4450.         #23315 - The dependency resolver knows to put all CreateModel
    
  4451.         before AddField and not become unsolvable.
    
  4452.         """
    
  4453.         address = ModelState(
    
  4454.             "a",
    
  4455.             "Address",
    
  4456.             [
    
  4457.                 ("id", models.AutoField(primary_key=True)),
    
  4458.                 ("country", models.ForeignKey("b.DeliveryCountry", models.CASCADE)),
    
  4459.             ],
    
  4460.         )
    
  4461.         person = ModelState(
    
  4462.             "a",
    
  4463.             "Person",
    
  4464.             [
    
  4465.                 ("id", models.AutoField(primary_key=True)),
    
  4466.             ],
    
  4467.         )
    
  4468.         apackage = ModelState(
    
  4469.             "b",
    
  4470.             "APackage",
    
  4471.             [
    
  4472.                 ("id", models.AutoField(primary_key=True)),
    
  4473.                 ("person", models.ForeignKey("a.Person", models.CASCADE)),
    
  4474.             ],
    
  4475.         )
    
  4476.         country = ModelState(
    
  4477.             "b",
    
  4478.             "DeliveryCountry",
    
  4479.             [
    
  4480.                 ("id", models.AutoField(primary_key=True)),
    
  4481.             ],
    
  4482.         )
    
  4483.         changes = self.get_changes([], [address, person, apackage, country])
    
  4484.         # Right number/type of migrations?
    
  4485.         self.assertNumberMigrations(changes, "a", 2)
    
  4486.         self.assertNumberMigrations(changes, "b", 1)
    
  4487.         self.assertOperationTypes(changes, "a", 0, ["CreateModel", "CreateModel"])
    
  4488.         self.assertOperationTypes(changes, "a", 1, ["AddField"])
    
  4489.         self.assertOperationTypes(changes, "b", 0, ["CreateModel", "CreateModel"])
    
  4490. 
    
  4491.     @override_settings(AUTH_USER_MODEL="a.Tenant")
    
  4492.     def test_circular_dependency_swappable(self):
    
  4493.         """
    
  4494.         #23322 - The dependency resolver knows to explicitly resolve
    
  4495.         swappable models.
    
  4496.         """
    
  4497.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  4498.             tenant = ModelState(
    
  4499.                 "a",
    
  4500.                 "Tenant",
    
  4501.                 [
    
  4502.                     ("id", models.AutoField(primary_key=True)),
    
  4503.                     ("primary_address", models.ForeignKey("b.Address", models.CASCADE)),
    
  4504.                 ],
    
  4505.                 bases=(AbstractBaseUser,),
    
  4506.             )
    
  4507.             address = ModelState(
    
  4508.                 "b",
    
  4509.                 "Address",
    
  4510.                 [
    
  4511.                     ("id", models.AutoField(primary_key=True)),
    
  4512.                     (
    
  4513.                         "tenant",
    
  4514.                         models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE),
    
  4515.                     ),
    
  4516.                 ],
    
  4517.             )
    
  4518.             changes = self.get_changes([], [address, tenant])
    
  4519. 
    
  4520.         # Right number/type of migrations?
    
  4521.         self.assertNumberMigrations(changes, "a", 2)
    
  4522.         self.assertOperationTypes(changes, "a", 0, ["CreateModel"])
    
  4523.         self.assertOperationTypes(changes, "a", 1, ["AddField"])
    
  4524.         self.assertMigrationDependencies(changes, "a", 0, [])
    
  4525.         self.assertMigrationDependencies(
    
  4526.             changes, "a", 1, [("a", "auto_1"), ("b", "auto_1")]
    
  4527.         )
    
  4528.         # Right number/type of migrations?
    
  4529.         self.assertNumberMigrations(changes, "b", 1)
    
  4530.         self.assertOperationTypes(changes, "b", 0, ["CreateModel"])
    
  4531.         self.assertMigrationDependencies(
    
  4532.             changes, "b", 0, [("__setting__", "AUTH_USER_MODEL")]
    
  4533.         )
    
  4534. 
    
  4535.     @override_settings(AUTH_USER_MODEL="b.Tenant")
    
  4536.     def test_circular_dependency_swappable2(self):
    
  4537.         """
    
  4538.         #23322 - The dependency resolver knows to explicitly resolve
    
  4539.         swappable models but with the swappable not being the first migrated
    
  4540.         model.
    
  4541.         """
    
  4542.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  4543.             address = ModelState(
    
  4544.                 "a",
    
  4545.                 "Address",
    
  4546.                 [
    
  4547.                     ("id", models.AutoField(primary_key=True)),
    
  4548.                     (
    
  4549.                         "tenant",
    
  4550.                         models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE),
    
  4551.                     ),
    
  4552.                 ],
    
  4553.             )
    
  4554.             tenant = ModelState(
    
  4555.                 "b",
    
  4556.                 "Tenant",
    
  4557.                 [
    
  4558.                     ("id", models.AutoField(primary_key=True)),
    
  4559.                     ("primary_address", models.ForeignKey("a.Address", models.CASCADE)),
    
  4560.                 ],
    
  4561.                 bases=(AbstractBaseUser,),
    
  4562.             )
    
  4563.             changes = self.get_changes([], [address, tenant])
    
  4564.         # Right number/type of migrations?
    
  4565.         self.assertNumberMigrations(changes, "a", 2)
    
  4566.         self.assertOperationTypes(changes, "a", 0, ["CreateModel"])
    
  4567.         self.assertOperationTypes(changes, "a", 1, ["AddField"])
    
  4568.         self.assertMigrationDependencies(changes, "a", 0, [])
    
  4569.         self.assertMigrationDependencies(
    
  4570.             changes, "a", 1, [("__setting__", "AUTH_USER_MODEL"), ("a", "auto_1")]
    
  4571.         )
    
  4572.         # Right number/type of migrations?
    
  4573.         self.assertNumberMigrations(changes, "b", 1)
    
  4574.         self.assertOperationTypes(changes, "b", 0, ["CreateModel"])
    
  4575.         self.assertMigrationDependencies(changes, "b", 0, [("a", "auto_1")])
    
  4576. 
    
  4577.     @override_settings(AUTH_USER_MODEL="a.Person")
    
  4578.     def test_circular_dependency_swappable_self(self):
    
  4579.         """
    
  4580.         #23322 - The dependency resolver knows to explicitly resolve
    
  4581.         swappable models.
    
  4582.         """
    
  4583.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  4584.             person = ModelState(
    
  4585.                 "a",
    
  4586.                 "Person",
    
  4587.                 [
    
  4588.                     ("id", models.AutoField(primary_key=True)),
    
  4589.                     (
    
  4590.                         "parent1",
    
  4591.                         models.ForeignKey(
    
  4592.                             settings.AUTH_USER_MODEL,
    
  4593.                             models.CASCADE,
    
  4594.                             related_name="children",
    
  4595.                         ),
    
  4596.                     ),
    
  4597.                 ],
    
  4598.             )
    
  4599.             changes = self.get_changes([], [person])
    
  4600.         # Right number/type of migrations?
    
  4601.         self.assertNumberMigrations(changes, "a", 1)
    
  4602.         self.assertOperationTypes(changes, "a", 0, ["CreateModel"])
    
  4603.         self.assertMigrationDependencies(changes, "a", 0, [])
    
  4604. 
    
  4605.     @override_settings(AUTH_USER_MODEL="a.User")
    
  4606.     def test_swappable_circular_multi_mti(self):
    
  4607.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  4608.             parent = ModelState(
    
  4609.                 "a",
    
  4610.                 "Parent",
    
  4611.                 [("user", models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE))],
    
  4612.             )
    
  4613.             child = ModelState("a", "Child", [], bases=("a.Parent",))
    
  4614.             user = ModelState("a", "User", [], bases=(AbstractBaseUser, "a.Child"))
    
  4615.             changes = self.get_changes([], [parent, child, user])
    
  4616.         self.assertNumberMigrations(changes, "a", 1)
    
  4617.         self.assertOperationTypes(
    
  4618.             changes, "a", 0, ["CreateModel", "CreateModel", "CreateModel", "AddField"]
    
  4619.         )
    
  4620. 
    
  4621.     @mock.patch(
    
  4622.         "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition",
    
  4623.         side_effect=AssertionError("Should not have prompted for not null addition"),
    
  4624.     )
    
  4625.     def test_add_blank_textfield_and_charfield(self, mocked_ask_method):
    
  4626.         """
    
  4627.         #23405 - Adding a NOT NULL and blank `CharField` or `TextField`
    
  4628.         without default should not prompt for a default.
    
  4629.         """
    
  4630.         changes = self.get_changes(
    
  4631.             [self.author_empty], [self.author_with_biography_blank]
    
  4632.         )
    
  4633.         # Right number/type of migrations?
    
  4634.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4635.         self.assertOperationTypes(changes, "testapp", 0, ["AddField", "AddField"])
    
  4636.         self.assertOperationAttributes(changes, "testapp", 0, 0)
    
  4637. 
    
  4638.     @mock.patch(
    
  4639.         "django.db.migrations.questioner.MigrationQuestioner.ask_not_null_addition"
    
  4640.     )
    
  4641.     def test_add_non_blank_textfield_and_charfield(self, mocked_ask_method):
    
  4642.         """
    
  4643.         #23405 - Adding a NOT NULL and non-blank `CharField` or `TextField`
    
  4644.         without default should prompt for a default.
    
  4645.         """
    
  4646.         changes = self.get_changes(
    
  4647.             [self.author_empty], [self.author_with_biography_non_blank]
    
  4648.         )
    
  4649.         self.assertEqual(mocked_ask_method.call_count, 2)
    
  4650.         # Right number/type of migrations?
    
  4651.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4652.         self.assertOperationTypes(changes, "testapp", 0, ["AddField", "AddField"])
    
  4653.         self.assertOperationAttributes(changes, "testapp", 0, 0)
    
  4654. 
    
  4655.     def test_mti_inheritance_model_removal(self):
    
  4656.         Animal = ModelState(
    
  4657.             "app",
    
  4658.             "Animal",
    
  4659.             [
    
  4660.                 ("id", models.AutoField(primary_key=True)),
    
  4661.             ],
    
  4662.         )
    
  4663.         Dog = ModelState("app", "Dog", [], bases=("app.Animal",))
    
  4664.         changes = self.get_changes([Animal, Dog], [Animal])
    
  4665.         self.assertNumberMigrations(changes, "app", 1)
    
  4666.         self.assertOperationTypes(changes, "app", 0, ["DeleteModel"])
    
  4667.         self.assertOperationAttributes(changes, "app", 0, 0, name="Dog")
    
  4668. 
    
  4669.     def test_add_model_with_field_removed_from_base_model(self):
    
  4670.         """
    
  4671.         Removing a base field takes place before adding a new inherited model
    
  4672.         that has a field with the same name.
    
  4673.         """
    
  4674.         before = [
    
  4675.             ModelState(
    
  4676.                 "app",
    
  4677.                 "readable",
    
  4678.                 [
    
  4679.                     ("id", models.AutoField(primary_key=True)),
    
  4680.                     ("title", models.CharField(max_length=200)),
    
  4681.                 ],
    
  4682.             ),
    
  4683.         ]
    
  4684.         after = [
    
  4685.             ModelState(
    
  4686.                 "app",
    
  4687.                 "readable",
    
  4688.                 [
    
  4689.                     ("id", models.AutoField(primary_key=True)),
    
  4690.                 ],
    
  4691.             ),
    
  4692.             ModelState(
    
  4693.                 "app",
    
  4694.                 "book",
    
  4695.                 [
    
  4696.                     ("title", models.CharField(max_length=200)),
    
  4697.                 ],
    
  4698.                 bases=("app.readable",),
    
  4699.             ),
    
  4700.         ]
    
  4701.         changes = self.get_changes(before, after)
    
  4702.         self.assertNumberMigrations(changes, "app", 1)
    
  4703.         self.assertOperationTypes(changes, "app", 0, ["RemoveField", "CreateModel"])
    
  4704.         self.assertOperationAttributes(
    
  4705.             changes, "app", 0, 0, name="title", model_name="readable"
    
  4706.         )
    
  4707.         self.assertOperationAttributes(changes, "app", 0, 1, name="book")
    
  4708. 
    
  4709.     def test_parse_number(self):
    
  4710.         tests = [
    
  4711.             ("no_number", None),
    
  4712.             ("0001_initial", 1),
    
  4713.             ("0002_model3", 2),
    
  4714.             ("0002_auto_20380101_1112", 2),
    
  4715.             ("0002_squashed_0003", 3),
    
  4716.             ("0002_model2_squashed_0003_other4", 3),
    
  4717.             ("0002_squashed_0003_squashed_0004", 4),
    
  4718.             ("0002_model2_squashed_0003_other4_squashed_0005_other6", 5),
    
  4719.             ("0002_custom_name_20380101_1112_squashed_0003_model", 3),
    
  4720.             ("2_squashed_4", 4),
    
  4721.         ]
    
  4722.         for migration_name, expected_number in tests:
    
  4723.             with self.subTest(migration_name=migration_name):
    
  4724.                 self.assertEqual(
    
  4725.                     MigrationAutodetector.parse_number(migration_name),
    
  4726.                     expected_number,
    
  4727.                 )
    
  4728. 
    
  4729.     def test_add_custom_fk_with_hardcoded_to(self):
    
  4730.         class HardcodedForeignKey(models.ForeignKey):
    
  4731.             def __init__(self, *args, **kwargs):
    
  4732.                 kwargs["to"] = "testapp.Author"
    
  4733.                 super().__init__(*args, **kwargs)
    
  4734. 
    
  4735.             def deconstruct(self):
    
  4736.                 name, path, args, kwargs = super().deconstruct()
    
  4737.                 del kwargs["to"]
    
  4738.                 return name, path, args, kwargs
    
  4739. 
    
  4740.         book_hardcoded_fk_to = ModelState(
    
  4741.             "testapp",
    
  4742.             "Book",
    
  4743.             [
    
  4744.                 ("author", HardcodedForeignKey(on_delete=models.CASCADE)),
    
  4745.             ],
    
  4746.         )
    
  4747.         changes = self.get_changes(
    
  4748.             [self.author_empty],
    
  4749.             [self.author_empty, book_hardcoded_fk_to],
    
  4750.         )
    
  4751.         self.assertNumberMigrations(changes, "testapp", 1)
    
  4752.         self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
    
  4753.         self.assertOperationAttributes(changes, "testapp", 0, 0, name="Book")
    
  4754. 
    
  4755. 
    
  4756. class MigrationSuggestNameTests(SimpleTestCase):
    
  4757.     def test_no_operations(self):
    
  4758.         class Migration(migrations.Migration):
    
  4759.             operations = []
    
  4760. 
    
  4761.         migration = Migration("some_migration", "test_app")
    
  4762.         self.assertIs(migration.suggest_name().startswith("auto_"), True)
    
  4763. 
    
  4764.     def test_no_operations_initial(self):
    
  4765.         class Migration(migrations.Migration):
    
  4766.             initial = True
    
  4767.             operations = []
    
  4768. 
    
  4769.         migration = Migration("some_migration", "test_app")
    
  4770.         self.assertEqual(migration.suggest_name(), "initial")
    
  4771. 
    
  4772.     def test_single_operation(self):
    
  4773.         class Migration(migrations.Migration):
    
  4774.             operations = [migrations.CreateModel("Person", fields=[])]
    
  4775. 
    
  4776.         migration = Migration("0001_initial", "test_app")
    
  4777.         self.assertEqual(migration.suggest_name(), "person")
    
  4778. 
    
  4779.         class Migration(migrations.Migration):
    
  4780.             operations = [migrations.DeleteModel("Person")]
    
  4781. 
    
  4782.         migration = Migration("0002_initial", "test_app")
    
  4783.         self.assertEqual(migration.suggest_name(), "delete_person")
    
  4784. 
    
  4785.     def test_single_operation_long_name(self):
    
  4786.         class Migration(migrations.Migration):
    
  4787.             operations = [migrations.CreateModel("A" * 53, fields=[])]
    
  4788. 
    
  4789.         migration = Migration("some_migration", "test_app")
    
  4790.         self.assertEqual(migration.suggest_name(), "a" * 53)
    
  4791. 
    
  4792.     def test_two_operations(self):
    
  4793.         class Migration(migrations.Migration):
    
  4794.             operations = [
    
  4795.                 migrations.CreateModel("Person", fields=[]),
    
  4796.                 migrations.DeleteModel("Animal"),
    
  4797.             ]
    
  4798. 
    
  4799.         migration = Migration("some_migration", "test_app")
    
  4800.         self.assertEqual(migration.suggest_name(), "person_delete_animal")
    
  4801. 
    
  4802.     def test_two_create_models(self):
    
  4803.         class Migration(migrations.Migration):
    
  4804.             operations = [
    
  4805.                 migrations.CreateModel("Person", fields=[]),
    
  4806.                 migrations.CreateModel("Animal", fields=[]),
    
  4807.             ]
    
  4808. 
    
  4809.         migration = Migration("0001_initial", "test_app")
    
  4810.         self.assertEqual(migration.suggest_name(), "person_animal")
    
  4811. 
    
  4812.     def test_two_create_models_with_initial_true(self):
    
  4813.         class Migration(migrations.Migration):
    
  4814.             initial = True
    
  4815.             operations = [
    
  4816.                 migrations.CreateModel("Person", fields=[]),
    
  4817.                 migrations.CreateModel("Animal", fields=[]),
    
  4818.             ]
    
  4819. 
    
  4820.         migration = Migration("0001_initial", "test_app")
    
  4821.         self.assertEqual(migration.suggest_name(), "initial")
    
  4822. 
    
  4823.     def test_many_operations_suffix(self):
    
  4824.         class Migration(migrations.Migration):
    
  4825.             operations = [
    
  4826.                 migrations.CreateModel("Person1", fields=[]),
    
  4827.                 migrations.CreateModel("Person2", fields=[]),
    
  4828.                 migrations.CreateModel("Person3", fields=[]),
    
  4829.                 migrations.DeleteModel("Person4"),
    
  4830.                 migrations.DeleteModel("Person5"),
    
  4831.             ]
    
  4832. 
    
  4833.         migration = Migration("some_migration", "test_app")
    
  4834.         self.assertEqual(
    
  4835.             migration.suggest_name(),
    
  4836.             "person1_person2_person3_delete_person4_and_more",
    
  4837.         )
    
  4838. 
    
  4839.     def test_operation_with_no_suggested_name(self):
    
  4840.         class Migration(migrations.Migration):
    
  4841.             operations = [
    
  4842.                 migrations.CreateModel("Person", fields=[]),
    
  4843.                 migrations.RunSQL("SELECT 1 FROM person;"),
    
  4844.             ]
    
  4845. 
    
  4846.         migration = Migration("some_migration", "test_app")
    
  4847.         self.assertIs(migration.suggest_name().startswith("auto_"), True)
    
  4848. 
    
  4849.     def test_none_name(self):
    
  4850.         class Migration(migrations.Migration):
    
  4851.             operations = [migrations.RunSQL("SELECT 1 FROM person;")]
    
  4852. 
    
  4853.         migration = Migration("0001_initial", "test_app")
    
  4854.         suggest_name = migration.suggest_name()
    
  4855.         self.assertIs(suggest_name.startswith("auto_"), True)
    
  4856. 
    
  4857.     def test_none_name_with_initial_true(self):
    
  4858.         class Migration(migrations.Migration):
    
  4859.             initial = True
    
  4860.             operations = [migrations.RunSQL("SELECT 1 FROM person;")]
    
  4861. 
    
  4862.         migration = Migration("0001_initial", "test_app")
    
  4863.         self.assertEqual(migration.suggest_name(), "initial")
    
  4864. 
    
  4865.     def test_auto(self):
    
  4866.         migration = migrations.Migration("0001_initial", "test_app")
    
  4867.         suggest_name = migration.suggest_name()
    
  4868.         self.assertIs(suggest_name.startswith("auto_"), True)