1 """Provide a base class for registries that use a normalized name index."""
3 from dataclasses
import dataclass, field
4 from datetime
import datetime
5 from functools
import lru_cache
9 from .registry
import BaseRegistryItems
12 @dataclass(slots=True, frozen=True, kw_only=True)
14 """Normalized Name Base Registry Entry."""
17 normalized_name: str = field(init=
False)
18 created_at: datetime = field(default_factory=dt_util.utcnow)
19 modified_at: datetime = field(default_factory=dt_util.utcnow)
23 object.__setattr__(self,
"normalized_name",
normalize_name(self.name))
26 @lru_cache(maxsize=1024)
28 """Normalize a name by removing whitespace and case folding."""
29 return name.casefold().replace(
" ",
"")
33 BaseRegistryItems[_VT]
35 """Base container for normalized name registry items, maps key -> entry.
37 Maintains an additional index:
38 - normalized name -> entry
42 """Initialize the container."""
44 self._normalized_names: dict[str, _VT] = {}
46 def _unindex_entry(self, key: str, replacement_entry: _VT |
None =
None) ->
None:
47 old_entry = self.data[key]
49 replacement_entry
is not None
50 and (normalized_name := replacement_entry.normalized_name)
51 != old_entry.normalized_name
52 and normalized_name
in self._normalized_names
55 f
"The name {replacement_entry.name} ({normalized_name}) is already in use"
57 del self._normalized_names[old_entry.normalized_name]
60 self._normalized_names[entry.normalized_name] = entry
63 """Get entry by name."""
67 """Generate ID from name."""
68 suggestion = suggestion_base =
slugify(name)
70 while suggestion
in self:
72 suggestion = f
"{suggestion_base}_{tries}"
web.Response get(self, web.Request request, str config_key)
str normalize_name(str name)
None _index_entry(self, str key, _VT entry)
None _unindex_entry(self, str key, _VT|None replacement_entry=None)
_VT|None get_by_name(self, str name)
str generate_id_from_name(self, str name)