-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
67 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
"""Python toolbox of Ambient Digital containing an abundance of useful tools and gadgets.""" | ||
|
||
__version__ = "11.5.5" | ||
__version__ = "11.6.0" |
24 changes: 24 additions & 0 deletions
24
ambient_toolbox/management/commands/detect_ghost_tables.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import sys | ||
|
||
from django.core.management.base import BaseCommand | ||
from django.db import connection | ||
|
||
|
||
class Command(BaseCommand): | ||
""" | ||
Script to detect ghost tables. | ||
Ghost tables are tables which were probably created by Django, | ||
removed in the codebase but never removed in the database. | ||
""" | ||
|
||
def handle(self, *args, **options): | ||
table_names = set(connection.introspection.table_names()) | ||
django_table_names = set(connection.introspection.django_table_names()) | ||
possible_matches = table_names - django_table_names - {"django_migrations"} | ||
|
||
if len(possible_matches) == 0: | ||
return | ||
|
||
sys.stdout.write("The following tables might be left-overs and can be deleted:\n") | ||
for table in possible_matches: | ||
sys.stdout.write(f"* {table}\n") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Clean-up | ||
|
||
## Detect "forgotten" tables | ||
|
||
Forgotten or ghost tables are tables which were created by Django migrations but then removed in the code. Django will | ||
not necessarily remove tables when deleting models. Adam Johnson wrote | ||
a [neat snippet](https://adamj.eu/tech/2024/11/21/django-tables-without-models/) to detect such tables. | ||
|
||
This package provides a management command to neatly list those tables in the command-line. | ||
|
||
```shell | ||
python ./manage.py detect_ghost_tables | ||
|
||
> The following tables might be left-overs and can be deleted: | ||
> * invalid_table | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import sys | ||
from unittest import mock | ||
|
||
from django.core.management import call_command | ||
from django.db import connection | ||
from django.test import SimpleTestCase | ||
|
||
|
||
class DetectGhostTableCommandTest(SimpleTestCase): | ||
@mock.patch.object(connection.introspection, "table_names", return_value=["invalid_table"]) | ||
def test_management_command_match_found(self, *args): | ||
with mock.patch.object(sys.stdout, "write") as mocked_write: | ||
call_command("detect_ghost_tables") | ||
|
||
mocked_write.assert_called_with("* invalid_table\n") | ||
|
||
@mock.patch.object(connection.introspection, "table_names", return_value=[]) | ||
def test_management_no_match_found(self, *args): | ||
with mock.patch.object(sys.stdout, "write") as mocked_write: | ||
call_command("detect_ghost_tables") | ||
|
||
mocked_write.assert_not_called() |
Empty file.