Fixed #35724 -- Tested migration commands handling of distributed namespace packages.

Also increased coverage of module_loading.py.
This commit is contained in:
Jacob Walls 2024-06-01 19:34:30 -04:00 committed by Sarah Boyce
parent c6a4f853c7
commit 4082a8886e
5 changed files with 46 additions and 2 deletions

View File

@ -4,6 +4,7 @@ import io
import os import os
import shutil import shutil
import sys import sys
from pathlib import Path
from unittest import mock from unittest import mock
from django.apps import apps from django.apps import apps
@ -21,7 +22,7 @@ from django.db.backends.utils import truncate_name
from django.db.migrations.exceptions import InconsistentMigrationHistory from django.db.migrations.exceptions import InconsistentMigrationHistory
from django.db.migrations.recorder import MigrationRecorder from django.db.migrations.recorder import MigrationRecorder
from django.test import TestCase, override_settings, skipUnlessDBFeature from django.test import TestCase, override_settings, skipUnlessDBFeature
from django.test.utils import captured_stdout from django.test.utils import captured_stdout, extend_sys_path
from django.utils import timezone from django.utils import timezone
from django.utils.version import get_docs_version from django.utils.version import get_docs_version
@ -1729,6 +1730,25 @@ class MakeMigrationsTests(MigrationTestBase):
call_command("makemigrations", stdout=out) call_command("makemigrations", stdout=out)
self.assertIn("0001_initial.py", out.getvalue()) self.assertIn("0001_initial.py", out.getvalue())
def test_makemigrations_no_init_ambiguous(self):
"""
Migration directories without an __init__.py file are not allowed if
there are multiple namespace search paths that resolve to them.
"""
out = io.StringIO()
with self.temporary_migration_module(
module="migrations.test_migrations_no_init"
) as migration_dir:
# Copy the project directory into another place under sys.path.
app_dir = Path(migration_dir).parent
os.remove(app_dir / "__init__.py")
project_dir = app_dir.parent
dest = project_dir.parent / "other_dir_in_path"
shutil.copytree(project_dir, dest)
with extend_sys_path(str(dest)):
call_command("makemigrations", stdout=out)
self.assertEqual("No changes detected\n", out.getvalue())
def test_makemigrations_migrations_announce(self): def test_makemigrations_migrations_announce(self):
""" """
makemigrations announces the migration at the default verbosity level. makemigrations announces the migration at the default verbosity level.

View File

@ -22,7 +22,8 @@ from django.core.validators import EmailValidator, RegexValidator
from django.db import migrations, models from django.db import migrations, models
from django.db.migrations.serializer import BaseSerializer from django.db.migrations.serializer import BaseSerializer
from django.db.migrations.writer import MigrationWriter, OperationWriter from django.db.migrations.writer import MigrationWriter, OperationWriter
from django.test import SimpleTestCase from django.test import SimpleTestCase, override_settings
from django.test.utils import extend_sys_path
from django.utils.deconstruct import deconstructible from django.utils.deconstruct import deconstructible
from django.utils.functional import SimpleLazyObject from django.utils.functional import SimpleLazyObject
from django.utils.timezone import get_default_timezone, get_fixed_timezone from django.utils.timezone import get_default_timezone, get_fixed_timezone
@ -954,6 +955,29 @@ class WriterTests(SimpleTestCase):
writer = MigrationWriter(migration) writer = MigrationWriter(migration)
self.assertEqual(writer.path, expected_path) self.assertEqual(writer.path, expected_path)
@override_settings(
MIGRATION_MODULES={"namespace_app": "namespace_app.migrations"},
INSTALLED_APPS=[
"migrations.migrations_test_apps.distributed_app_location_2.namespace_app"
],
)
def test_migration_path_distributed_namespace(self):
base_dir = os.path.dirname(os.path.dirname(__file__))
test_apps_dir = os.path.join(base_dir, "migrations", "migrations_test_apps")
expected_msg = (
"Could not locate an appropriate location to create "
"migrations package namespace_app.migrations. Make sure the toplevel "
"package exists and can be imported."
)
with extend_sys_path(
os.path.join(test_apps_dir, "distributed_app_location_1"),
os.path.join(test_apps_dir, "distributed_app_location_2"),
):
migration = migrations.Migration("0001_initial", "namespace_app")
writer = MigrationWriter(migration)
with self.assertRaisesMessage(ValueError, expected_msg):
writer.path
def test_custom_operation(self): def test_custom_operation(self):
migration = type( migration = type(
"Migration", "Migration",