Skip to content

Commit

Permalink
v11.6.0 (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
GitRon authored Nov 25, 2024
1 parent 803983e commit 93d7d2f
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

**11.6.0** (2024-11-20)
* Added `detect_ghost_tables` management command

**11.5.5** (2024-11-20)
* Moved permission check to "apps.ready()" method
* Internal updates via `ambient-package-update`
Expand Down
2 changes: 1 addition & 1 deletion ambient_toolbox/__init__.py
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 ambient_toolbox/management/commands/detect_ghost_tables.py
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")
16 changes: 16 additions & 0 deletions docs/features/cleanup.md
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
```
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The package is published at pypi under the following link: `https://pypi.org/pro

features/setup.md
features/admin.md
features/cleanup.md
features/context_manager.md
features/context_processors.md
features/database_anonymisation.md
Expand Down
Empty file added tests/management/__init__.py
Empty file.
Empty file.
22 changes: 22 additions & 0 deletions tests/management/commands/test_detect_ghost_tables.py
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.

0 comments on commit 93d7d2f

Please sign in to comment.