""" Provides the building stones for adding analytics to a site.
An analytics provider can provide both user- and application-facing
configuration
"""
from __future__ import annotations
from abc import abstractmethod, ABCMeta
from typing import Any, ClassVar, Self, TypeAlias, TYPE_CHECKING
if TYPE_CHECKING:
from markupsafe import Markup
from .types import RenderData
[docs]
AnyRequest: TypeAlias = Any
[docs]
class AnalyticsProvider(metaclass=ABCMeta):
""" Base class and registry for analytics providers. """
[docs]
__slots__ = ('configuration',)
if TYPE_CHECKING:
# forward declare for type checking
title: ClassVar[str]
def __init__(self, **configuration: Any) -> None:
[docs]
self.configuration = configuration
@property
[docs]
def display_name(self) -> str:
return self.title
[docs]
def url(self, request: AnyRequest) -> str | None:
return None
@property
@abstractmethod
[docs]
def template(self) -> Markup:
raise NotImplementedError()
@classmethod
@abstractmethod
[docs]
def template_variables(
self,
request: AnyRequest
) -> RenderData | None:
""" Returns the necessary variables for formatting the template
or ``None`` if the analytics can't be rendered. """
[docs]
def code(self, request: AnyRequest) -> Markup | None:
""" This function gets called for every request where this provider
is active and returns the necessary html embed. """
variables = self.template_variables(request)
if variables is None:
return None
return self.template.format(**variables)