Source code for platzky.db.db
"""Abstract base classes for database implementations."""
from abc import ABC, abstractmethod
from collections.abc import Callable
from functools import partial
from typing import Any
from pydantic import BaseModel, Field
from platzky.models import MenuItem, Page, Post
from platzky.plugin.plugin_config import PluginConfigBase
[docs]
class DB(ABC):
"""Abstract base class for all database implementations."""
db_name: str = "DB"
module_name: str = "db"
config_type: type
def __init_subclass__(cls, *args, **kw):
"""Check that all methods defined in the subclass exist in the superclasses.
This is to prevent subclasses from splitting up DB interface.
"""
super().__init_subclass__(*args, **kw)
for name in cls.__dict__:
if name.startswith("_"):
continue
for superclass in cls.__mro__[1:]:
if name in dir(superclass):
break
else:
raise TypeError(
f"Method {name} defined in {cls.__name__} does not exist in superclasses"
)
[docs]
def extend(self, function_name: str, function: Callable[..., Any]) -> None:
"""
Add a function to the DB object. The function must take the DB object as first parameter.
Parameters:
function_name (str): The name of the function to add.
function (Callable): The function to add to the DB object.
"""
if not callable(function):
raise ValueError(f"The provided func for '{function_name}' is not callable.")
try:
bound_function = partial(function, self)
setattr(self, function_name, bound_function)
except Exception as e:
raise ValueError(f"Failed to extend DB with function {function_name}: {e}")
[docs]
@abstractmethod
def get_app_description(self, lang: str) -> str:
"""Retrieve the application description for a specific language.
Args:
lang: Language code (e.g., 'en', 'pl')
"""
pass
[docs]
@abstractmethod
def get_all_posts(self, lang: str) -> list[Post]:
"""Retrieve all posts for a specific language.
Args:
lang: Language code (e.g., 'en', 'pl')
"""
pass
[docs]
@abstractmethod
def get_post(self, slug: str) -> Post:
"""Retrieve a single post by its slug.
Args:
slug: URL-friendly identifier for the post
"""
pass
[docs]
@abstractmethod
def get_page(self, slug: str) -> Page:
"""Retrieve a page by its slug.
Args:
slug: URL-friendly identifier for the page
"""
pass
[docs]
@abstractmethod
def get_posts_by_tag(self, tag: str, lang: str) -> list[Post]:
"""Retrieve posts filtered by tag and language.
Args:
tag: Tag name to filter by
lang: Language code (e.g., 'en', 'pl')
"""
pass
[docs]
@abstractmethod
def get_logo_url(self) -> str: # TODO: Provide alternative text along with the URL of logo
"""Retrieve the URL of the application logo."""
pass
[docs]
@abstractmethod
def get_favicon_url(self) -> str:
"""Retrieve the URL of the application favicon."""
pass
[docs]
@abstractmethod
def get_primary_color(self) -> str:
"""Retrieve the primary color for the application theme."""
pass
[docs]
@abstractmethod
def get_secondary_color(self) -> str:
"""Retrieve the secondary color for the application theme."""
pass
[docs]
@abstractmethod
def get_plugins_data(self) -> list[PluginConfigBase]:
"""Retrieve configuration data for all plugins."""
pass
[docs]
@abstractmethod
def get_font(self) -> str:
"""Get the font configuration for the application."""
pass
[docs]
@abstractmethod
def health_check(self) -> None:
"""Perform a health check on the database.
Should raise an exception if the database is not healthy.
This should be a lightweight operation suitable for health checks.
"""
pass
[docs]
class DBConfig(BaseModel):
"""Base configuration class for database connections."""
type: str = Field(alias="TYPE")