File size: 2,288 Bytes
b4f2238 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | """Business logic services."""
from __future__ import annotations
from collections.abc import Callable, Iterable
from dataclasses import dataclass
from typing import Any, TypeVar, cast
@dataclass(frozen=True)
class CodePlaceholderDefinition:
key: str
source: str
category: str
display_name: str = ""
description: str = ""
example_value: str = ""
class CodePlaceholderRegistry:
_instance: CodePlaceholderRegistry | None = None
_definitions: dict[str, CodePlaceholderDefinition]
def __new__(cls) -> CodePlaceholderRegistry:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._definitions = {}
return cls._instance
def register(self, definitions: Iterable[CodePlaceholderDefinition]) -> None:
for definition in definitions:
self._definitions.setdefault(definition.key, definition)
def upsert(self, definitions: Iterable[CodePlaceholderDefinition]) -> None:
for definition in definitions:
self._definitions[definition.key] = definition
def list_definitions(self) -> list[CodePlaceholderDefinition]:
return sorted(self._definitions.values(), key=lambda d: d.key)
def clear(self) -> None:
self._definitions.clear()
T = TypeVar("T")
def expose_placeholders(
*,
keys: list[str],
source: str,
category: str,
metadata: dict[str, dict[str, Any]] | None = None,
description: str = "",
) -> Callable[[T], T]:
def decorator(target: T) -> T:
defs: list[CodePlaceholderDefinition] = []
per_key = metadata or {}
for key in keys:
key_meta = per_key.get(key, {}) or {}
defs.append(
CodePlaceholderDefinition(
key=key,
source=source,
category=category,
display_name=key_meta.get("display_name") or "",
description=key_meta.get("description") or description or "",
example_value=key_meta.get("example_value") or "",
)
)
cast(Any, target).__code_placeholder_definitions__ = defs
CodePlaceholderRegistry().register(defs)
return target
return decorator
|