Skip to content

Commit

Permalink
Add support for django-settings-holder 0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
MrThearMan committed Oct 31, 2024
1 parent 33d1a92 commit cfe2bed
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 131 deletions.
2 changes: 1 addition & 1 deletion admin_data_views/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def get_admin_data_urls(self: admin.AdminSite) -> list[URLResolver | URLPattern]
name=item["name"],
)
)
if item["items"] is not None:
if item.get("items") is not None:
custom_paths.append(
path(
route=f"{baseroute}/{item['route']}/{item['items']['route']}/",
Expand Down
60 changes: 36 additions & 24 deletions admin_data_views/settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from django.test.signals import setting_changed
from settings_holder import holder, reload_settings
from settings_holder import SettingsHolder, reload_settings

from .typing import Any, NamedTuple, URLConfig

Expand All @@ -24,46 +24,58 @@ class AdminDataViewsSettings(NamedTuple):

DEFAULTS: dict[str, Any] = AdminDataViewsSettings()._asdict()

IMPORT_STRINGS: set[bytes | str] = {"URLS"}

IMPORT_STRINGS: set[bytes | str] = {
"URLS.0.view",
"URLS.0.items.view",
}

REMOVED_SETTINGS: set[str] = set()


class SettingsHolder(holder.SettingsHolder):
def perform_import(self, val: str, setting: str) -> Any:
if setting == "URLS":
val: list[URLConfig]
for i, item in enumerate(val):
missing = {"route", "view", "name"}.difference(item.keys())
if missing:
msg = f"Missing keys in ADMIN_DATA_VIEWS[{i}]: {missing}"
raise RuntimeError(msg)
def urls_validator(val: Any) -> None:
if not isinstance(val, list): # pragma: no cover
msg = "URLS must be a list"
raise TypeError(msg)

for i, item in enumerate(val):
if not isinstance(item, dict): # pragma: no cover
msg = f"URLS[{i}] must be a dict"
raise TypeError(msg)

missing = {"route", "view", "name"}.difference(item.keys())
if missing:
msg = f"Missing keys in URLS[{i}]: {missing}"
raise TypeError(msg)

item["route"] = item["route"].rstrip("/").lstrip("/")
item["view"] = self.import_from_string(item["view"], setting)
item["route"] = item["route"].rstrip("/").lstrip("/")

if item.get("items") is None:
item["items"] = None
continue
items = item.get("items")
if items is None:
continue

missing = {"route", "view", "name"}.difference(item["items"].keys())
if missing:
msg = f"Missing keys in ADMIN_DATA_VIEWS[{i}]['items']: {missing}"
raise RuntimeError(msg)
if not isinstance(items, dict): # pragma: no cover
msg = f"URLS[{i}]['items'] must be a dict"
raise TypeError(msg)

item["items"]["route"] = item["items"]["route"].rstrip("/").lstrip("/")
item["items"]["view"] = self.import_from_string(item["items"]["view"], setting)
missing = {"route", "view", "name"}.difference(items.keys())
if missing:
msg = f"Missing keys in URLS[{i}]['items']: {missing}"
raise TypeError(msg)

return val
items["route"] = items["route"].rstrip("/").lstrip("/")

return super().perform_import(val, setting) # pragma: no cover

VALIDATORS: dict[str, Any] = {
"URLS": urls_validator,
}

admin_data_settings = SettingsHolder(
setting_name=SETTING_NAME,
defaults=DEFAULTS,
import_strings=IMPORT_STRINGS,
removed_settings=REMOVED_SETTINGS,
validators=VALIDATORS,
)

reload_admin_data_settings = reload_settings(SETTING_NAME, admin_data_settings)
Expand Down
8 changes: 7 additions & 1 deletion admin_data_views/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

from typing import Any, Callable, ItemsView, NamedTuple, TypedDict, Union

try:
from typing import NotRequired
except ImportError:
from typing_extensions import NotRequired

__all__ = [
"Any",
"AppDict",
Expand All @@ -13,6 +18,7 @@
"ItemsView",
"NamedTuple",
"NestedDict",
"NotRequired",
"SectionData",
"TableContext",
"TableViewContext",
Expand Down Expand Up @@ -110,4 +116,4 @@ class URLConfig(TypedDict):
route: str
view: str
name: str
items: ItemConfig | None
items: NotRequired[ItemConfig]
4 changes: 2 additions & 2 deletions admin_data_views/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def wrapper(*args: Any, **kwargs: Any) -> TemplateResponse:
# This way the table is easier to render in the template.
for header in context["table"]:
for row_no, cell in enumerate(context["table"][header]):
if item["items"] is not None and isinstance(cell, ItemLink):
if item.get("items") is not None and isinstance(cell, ItemLink):
cell = format_html( # noqa: PLW2901
'<a href="{}">{}</a>',
reverse(
Expand Down Expand Up @@ -110,7 +110,7 @@ def wrapper(*args: Any, **kwargs: Any) -> TemplateResponse:
item_context["slug"] = item["route"]
break # Stop searching once view is found

if item["items"] is None:
if item.get("items") is None:
continue

# Item view inside table view definition
Expand Down
Loading

0 comments on commit cfe2bed

Please sign in to comment.