Skip to content

Commit

Permalink
Instead of using a file search to find all the ViewSet, made use of t…
Browse files Browse the repository at this point in the history
…he django routers to identify all the ViewSets
  • Loading branch information
sasha-dresden committed Dec 16, 2024
1 parent 094451d commit edbdf09
Show file tree
Hide file tree
Showing 12 changed files with 73 additions and 95 deletions.
5 changes: 2 additions & 3 deletions django-backend/fecfiler/cash_on_hand/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from .views import CashOnHandYearlyViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"cash_on_hand", CashOnHandYearlyViewSet, basename="cash_on_hand")

# The API URLs are now determined automatically by the router.
Expand Down
91 changes: 34 additions & 57 deletions django-backend/fecfiler/committee_accounts/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
CommitteeOwnedViewMixin,
CommitteeViewSet,
)
from rest_framework.viewsets import ViewSetMixin
from fecfiler.user.models import User
from unittest.mock import Mock, patch
from fecfiler.routers import get_all_routers
import structlog

logger = structlog.get_logger(__name__)


class CommitteeMemberViewSetTest(TestCase):
Expand Down Expand Up @@ -229,66 +232,40 @@ def test_get_committee_account_data_from_redis(self):
self.assertIn("C12345678", was_called_with)
self.assertEqual(response.data["name"], "TEST")

def test_all_viewsets_include_mixin(self):
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.join(script_dir, "../..")
exclude_dirs = ["venv", "__pycache__"]

def test_viewsets_have_committee_owned_mixin(self):
exclude_list = [
"CommitteeViewSet",
"UserViewSet",
"SystemStatusViewSet",
"WebServicesViewSet",
"SummaryViewSet",
"FeedbackViewSet",
]

subclasses = find_subclasses(ViewSetMixin, project_root, exclude_dirs)
missing_mixin = [
subclass
for subclass in subclasses
if not issubclass(subclass, CommitteeOwnedViewMixin)
and subclass.__name__ not in exclude_list
]

self.assertEqual(
len(missing_mixin),
0,
f"The following subclasses of GenericViewSet "
f"do not include CommitteeOwnedViewMixin:"
f"{', '.join([f'{cls.__module__}.{cls.__name__}' for cls in missing_mixin])}",
)


def find_subclasses(base_class, project_path, exclude_dirs=None):
subclasses = []
exclude_dirs = exclude_dirs or []

for root, dirs, files in os.walk(project_path):
dirs[:] = [d for d in dirs if d not in exclude_dirs]

for file in files:
if (
file.endswith("views.py")
and not file.startswith("__init__")
and "test_views" not in file
):
module_path = os.path.join(root, file)
module_name = (
module_path.replace(project_path, "")
.replace(os.sep, ".")
.lstrip(".")
.replace(".py", "")
)
try:
module = import_module(module_name)
except (ModuleNotFoundError, ImportError):
print(f"module not found: {module_name}")
continue

for name, obj in inspect.getmembers(module, inspect.isclass):
if obj.__module__ == module.__name__:
if issubclass(obj, base_class) and obj != base_class:
subclasses.append(obj)

return subclasses
routers = get_all_routers()
missing_mixin = []

for router in routers:
for prefix, viewset, basename in router.registry:
if (
not issubclass(viewset, CommitteeOwnedViewMixin)
and viewset.__name__ not in exclude_list
):
missing_mixin.append(
{
"viewset": viewset.__name__,
"prefix": prefix,
"basename": basename,
}
)

if missing_mixin:
error_message = "\n".join(
[
f"ViewSet '{entry['viewset']}' "
f"does not inherit from CommitteeOwnedViewMixin."
for entry in missing_mixin
]
)
self.fail(
f"The following ViewSets are missing CommitteeOwnedViewMixin:\n"
f"{error_message}"
)
10 changes: 5 additions & 5 deletions django-backend/fecfiler/committee_accounts/urls.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from .views import CommitteeMembershipViewSet, CommitteeViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"committees", CommitteeViewSet, basename="committees")
router.register(r"committee-members", CommitteeMembershipViewSet,
basename="committee-members")
router.register(
r"committee-members", CommitteeMembershipViewSet, basename="committee-members"
)

# The API URLs are now determined automatically by the router.
urlpatterns = []
Expand Down
9 changes: 3 additions & 6 deletions django-backend/fecfiler/contacts/urls.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from .views import ContactViewSet, DeletedContactsViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"contacts", ContactViewSet, basename="contacts")
router.register(
r"contacts-deleted", DeletedContactsViewSet, basename="contacts-deleted"
)
router.register(r"contacts-deleted", DeletedContactsViewSet, basename="contacts-deleted")

# The API URLs are now determined automatically by the router.
urlpatterns = [
Expand Down
6 changes: 2 additions & 4 deletions django-backend/fecfiler/devops/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from fecfiler.devops.views import SystemStatusViewSet


# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"devops", SystemStatusViewSet, basename="devops")

# The API URLs are now determined automatically by the router.
Expand Down
5 changes: 2 additions & 3 deletions django-backend/fecfiler/feedback/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router

from .views import FeedbackViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"feedback", FeedbackViewSet, basename="feedback")

# The API URLs are now determined automatically by the router.
Expand Down
8 changes: 3 additions & 5 deletions django-backend/fecfiler/memo_text/urls.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from .views import MemoTextViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r"memo-text", MemoTextViewSet,
basename="memo-text")
router = register_router()
router.register(r"memo-text", MemoTextViewSet, basename="memo-text")

# The API URLs are now determined automatically by the router.
urlpatterns = [
Expand Down
5 changes: 2 additions & 3 deletions django-backend/fecfiler/reports/urls.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from django.urls import path, include
from fecfiler.reports.form_99.views import Form99ViewSet
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from .form_3x.views import Form3XViewSet
from .form_24.views import Form24ViewSet
from .form_1m.views import Form1MViewSet
from .views import ReportViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"form-3x", Form3XViewSet, basename="form-3x")
router.register(r"form-24", Form24ViewSet, basename="form-24")
router.register(r"form-99", Form99ViewSet, basename="form-99")
Expand Down
14 changes: 14 additions & 0 deletions django-backend/fecfiler/routers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from rest_framework.routers import DefaultRouter

# Global list to store all routers
_all_routers = []


def register_router():
router = DefaultRouter()
_all_routers.append(router)
return router


def get_all_routers():
return _all_routers
5 changes: 2 additions & 3 deletions django-backend/fecfiler/transactions/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from .views import TransactionViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"", TransactionViewSet, basename="transactions")

# The API URLs are now determined automatically by the router.
Expand Down
5 changes: 2 additions & 3 deletions django-backend/fecfiler/user/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from .views import UserViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"users", UserViewSet, basename="users")

# The API URLs are now determined automatically by the router.
Expand Down
5 changes: 2 additions & 3 deletions django-backend/fecfiler/web_services/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from fecfiler.routers import register_router
from .views import WebServicesViewSet
from .summary.views import SummaryViewSet

# Create a router and register our viewsets with it.
router = DefaultRouter()
router = register_router()
router.register(r"web-services", WebServicesViewSet, basename="web-services")
router.register(r"web-services/summary", SummaryViewSet, basename="summary")

Expand Down

0 comments on commit edbdf09

Please sign in to comment.