diff --git a/CHANGELOG.md b/CHANGELOG.md index a1b5213..300fe00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.1.1 (unreleased) + +- Fixed `RunPython` model import check when using a `through` object like `MyModel.many_to_many.through.objects.filter(...)` (issue #218) + ## 4.1.0 - Allow configuring logging for `makemigrations` command and unify behaviour with `lintmigrations` (issue #207) diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index f4b1695..99e72f9 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -531,7 +531,7 @@ class MigrationLinter(object): @staticmethod def get_runpython_model_import_issues(code): - model_object_regex = re.compile(r"[^a-zA-Z]?([a-zA-Z0-9]+?)\.objects") + model_object_regex = re.compile(r"[^a-zA-Z0-9._]?([a-zA-Z0-9._]+?)\.objects") function_name = code.__name__ source_code = inspect.getsource(code) @@ -539,6 +539,7 @@ class MigrationLinter(object): called_models = model_object_regex.findall(source_code) issues = [] for model in called_models: + model = model.split(".", 1)[0] has_get_model_call = ( re.search( r"{}.*= +\w+\.get_model\(".format(model), diff --git a/tests/functional/test_data_migrations.py b/tests/functional/test_data_migrations.py index 5478eff..2bb039c 100644 --- a/tests/functional/test_data_migrations.py +++ b/tests/functional/test_data_migrations.py @@ -137,7 +137,7 @@ class DataMigrationModelImportTestCase(unittest.TestCase): def test_not_overlapping_model_name(self): """ - Correct for the import error, but should raise a warning + Correct for the import error, but should raise a warning. """ def forward_method(apps, schema_editor): @@ -159,7 +159,7 @@ class DataMigrationModelImportTestCase(unittest.TestCase): def test_not_overlapping_one_param(self): """ - Not an error, but should raise a warning + Not an error, but should raise a warning. """ def forward_method(apps, schema_editor): @@ -170,6 +170,24 @@ class DataMigrationModelImportTestCase(unittest.TestCase): issues = MigrationLinter.get_runpython_model_import_issues(forward_method) self.assertEqual(0, len(issues)) + def test_m2m_through_orm_usage(self): + def forward_method(apps, schema_editor): + MyModel = apps.get_model("myapp", "MyModel") + + MyModel.many_to_many.through.objects.filter(id=1).first() + + issues = MigrationLinter.get_runpython_model_import_issues(forward_method) + self.assertEqual(0, len(issues)) + + def test_missing_m2m_through_orm(self): + def forward_method(apps, schema_editor): + from tests.test_project.app_data_migrations.models import MyModel + + MyModel.many_to_many.through.objects.filter(id=1).first() + + issues = MigrationLinter.get_runpython_model_import_issues(forward_method) + self.assertEqual(1, len(issues)) + class DataMigrationModelVariableNamingTestCase(unittest.TestCase): def test_same_variable_name(self):