mirror of
https://github.com/django/django.git
synced 2025-11-17 18:48:15 +00:00
Allow migrations in namespace packages without __init__.py
Remove obsolete __file__ check to support Python 3 implicit namespace packages as valid migration modules. This enables migrations to work in directories lacking __init__.py files. Refs #29091.
This commit is contained in:
parent
5d9cf79baf
commit
2ad994f9a0
3 changed files with 44 additions and 7 deletions
|
|
@ -84,11 +84,6 @@ class MigrationLoader:
|
||||||
continue
|
continue
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
# Empty directories are namespaces.
|
|
||||||
# getattr() needed on PY36 and older (replace w/attribute access).
|
|
||||||
if getattr(module, '__file__', None) is None:
|
|
||||||
self.unmigrated_apps.add(app_config.label)
|
|
||||||
continue
|
|
||||||
# Module is not a package (e.g. migrations.py).
|
# Module is not a package (e.g. migrations.py).
|
||||||
if not hasattr(module, '__path__'):
|
if not hasattr(module, '__path__'):
|
||||||
self.unmigrated_apps.add(app_config.label)
|
self.unmigrated_apps.add(app_config.label)
|
||||||
|
|
|
||||||
|
|
@ -190,11 +190,37 @@ class LoaderTests(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_load_empty_dir(self):
|
def test_load_empty_dir(self):
|
||||||
|
"""
|
||||||
|
A namespace package (directory without __init__.py) can be a valid
|
||||||
|
migrations module even when it has no migration files. It's treated
|
||||||
|
the same as a regular package with no migrations.
|
||||||
|
"""
|
||||||
with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.namespace"}):
|
with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.namespace"}):
|
||||||
loader = MigrationLoader(connection)
|
loader = MigrationLoader(connection)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"migrations", loader.unmigrated_apps,
|
"migrations", loader.migrated_apps,
|
||||||
"App missing __init__.py in migrations module not in unmigrated apps."
|
"Namespace package should be in migrated apps even without migrations."
|
||||||
|
)
|
||||||
|
# Ensure no migrations were actually loaded
|
||||||
|
migration_count = len([
|
||||||
|
key for key in loader.disk_migrations if key[0] == "migrations"
|
||||||
|
])
|
||||||
|
self.assertEqual(migration_count, 0)
|
||||||
|
|
||||||
|
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_namespace_package"})
|
||||||
|
def test_namespace_package_with_migrations(self):
|
||||||
|
"""
|
||||||
|
Namespace packages (directories without __init__.py) can contain
|
||||||
|
migration files and should be loaded correctly.
|
||||||
|
"""
|
||||||
|
loader = MigrationLoader(connection)
|
||||||
|
self.assertIn(
|
||||||
|
"migrations", loader.migrated_apps,
|
||||||
|
"Namespace package with migrations should be in migrated apps."
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
("migrations", "0001_initial"), loader.disk_migrations,
|
||||||
|
"Migration from namespace package should be loaded."
|
||||||
)
|
)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
"Author",
|
||||||
|
[
|
||||||
|
("id", models.AutoField(primary_key=True)),
|
||||||
|
("name", models.CharField(max_length=255)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue