fixes to handle wonky yaml files

config_dataclasses
Andrew Mirsky 2025-07-13 16:38:08 -04:00
rodzic 0aabfa7e78
commit fdd7c7c5c6
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: A98E67635CDF2C39
1 zmienionych plików z 18 dodań i 7 usunięć

Wyświetl plik

@ -80,6 +80,15 @@ class Dictable:
"""Return a copy of the dataclass.""" """Return a copy of the dataclass."""
return replace(self) # type: ignore[type-var] return replace(self) # type: ignore[type-var]
@staticmethod
def _coerce_lists(value: list[Any] | dict[str, Any] | Any) -> list[dict[str, Any]]:
if isinstance(value, list):
return value # It's already a list of dicts
if isinstance(value, dict):
return [value] # Promote single dict to a list
msg = "Could not convert 'list' to 'list[dict[str, Any]]'"
raise ValueError(msg)
@dataclass @dataclass
class ListenerConfig(Dictable): class ListenerConfig(Dictable):
@ -160,10 +169,11 @@ class BrokerConfig(Dictable):
"""Deprecated field used to config EntryPoint-loaded plugins. See """Deprecated field used to config EntryPoint-loaded plugins. See
[`TopicTabooPlugin`](#taboo-topic-plugin) and [`TopicTabooPlugin`](#taboo-topic-plugin) and
[`TopicACLPlugin`](#acl-topic-plugin) for more information.*""" [`TopicACLPlugin`](#acl-topic-plugin) for more information.*"""
plugins: dict[str, Any] | list[dict[str,Any]] | None = field(default_factory=default_broker_plugins) plugins: dict[str, Any] | list[str | dict[str,Any]] | None = field(default_factory=default_broker_plugins)
"""The dictionary has a key of the dotted-module path of a class derived from `BasePlugin`, `BaseAuthPlugin` """The dictionary has a key of the dotted-module path of a class derived from `BasePlugin`, `BaseAuthPlugin`
or `BaseTopicPlugin`; the value is a dictionary of configuration options for that plugin. See or `BaseTopicPlugin`; the value is a dictionary of configuration options for that plugin. See
[Plugins](http://localhost:8000/custom_plugins/) for more information.""" [Plugins](http://localhost:8000/custom_plugins/) for more information. `list[str | dict[str,Any]]` is not
recommended but available to support legacy use cases."""
def __post_init__(self) -> None: def __post_init__(self) -> None:
"""Check config for errors and transform fields for easier use.""" """Check config for errors and transform fields for easier use."""
@ -182,9 +192,9 @@ class BrokerConfig(Dictable):
if isinstance(self.plugins, list): if isinstance(self.plugins, list):
_plugins: dict[str, Any] = {} _plugins: dict[str, Any] = {}
for plugin in self.plugins: for plugin in self.plugins:
# in case a plugin in a yaml file is listed without config # in case a plugin in a yaml file is listed without config map
if isinstance(plugin, str): # type: ignore[unreachable] if isinstance(plugin, str):
_plugins |= {plugin:{}} # type: ignore[unreachable] _plugins |= {plugin:{}}
continue continue
_plugins |= plugin _plugins |= plugin
self.plugins = _plugins self.plugins = _plugins
@ -208,8 +218,9 @@ class BrokerConfig(Dictable):
data=d, data=d,
config=DaciteConfig( config=DaciteConfig(
cast=[StrEnum, ListenerType], cast=[StrEnum, ListenerType],
strict=True) strict=True,
) type_hooks={list[dict[str, Any]]: cls._coerce_lists}
))
@dataclass @dataclass