huge refactor of the entire codebase, with the goal of improving maintainability, readability, and extensibility. This commit includes changes to almost every file in the project, including:
This commit is contained in:
@@ -1,10 +1,4 @@
|
||||
"""Provider registry for ResultTable API (breaking, strict API).
|
||||
|
||||
Providers register themselves here with an adapter and optional column factory
|
||||
and selection function. Consumers (cmdlets) can look up providers by name and
|
||||
obtain the columns and selection behavior for building tables and for selection
|
||||
args used by subsequent cmdlets.
|
||||
"""
|
||||
"""Plugin registry for the strict ResultTable API."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
@@ -18,7 +12,7 @@ SelectionFn = Callable[[ResultModel], List[str]]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Provider:
|
||||
class Plugin:
|
||||
name: str
|
||||
adapter: ProviderAdapter
|
||||
# columns can be a static list or a factory that derives columns from sample rows
|
||||
@@ -28,7 +22,7 @@ class Provider:
|
||||
|
||||
def get_columns(self, rows: Optional[Iterable[ResultModel]] = None) -> List[ColumnSpec]:
|
||||
if self.columns is None:
|
||||
raise ValueError(f"provider '{self.name}' must define columns")
|
||||
raise ValueError(f"plugin '{self.name}' must define columns")
|
||||
|
||||
if callable(self.columns):
|
||||
rows_list = list(rows) if rows is not None else []
|
||||
@@ -37,13 +31,13 @@ class Provider:
|
||||
cols = list(self.columns)
|
||||
|
||||
if not cols:
|
||||
raise ValueError(f"provider '{self.name}' produced no columns")
|
||||
raise ValueError(f"plugin '{self.name}' produced no columns")
|
||||
|
||||
return cols
|
||||
|
||||
def selection_args(self, row: ResultModel) -> List[str]:
|
||||
if not callable(self.selection_fn):
|
||||
raise ValueError(f"provider '{self.name}' must define a selection function")
|
||||
raise ValueError(f"plugin '{self.name}' must define a selection function")
|
||||
|
||||
sel = list(self.selection_fn(ensure_result_model(row)))
|
||||
return sel
|
||||
@@ -54,7 +48,7 @@ class Provider:
|
||||
try:
|
||||
rows = [ensure_result_model(r) for r in self.adapter(items)]
|
||||
except Exception as exc:
|
||||
raise RuntimeError(f"provider '{self.name}' adapter failed") from exc
|
||||
raise RuntimeError(f"plugin '{self.name}' adapter failed") from exc
|
||||
|
||||
cols = self.get_columns(rows)
|
||||
return ResultTable(provider=self.name, rows=rows, columns=cols, meta=self.metadata or {})
|
||||
@@ -82,37 +76,37 @@ class Provider:
|
||||
return [self.serialize_row(r) for r in rows]
|
||||
|
||||
|
||||
_PROVIDERS: Dict[str, Provider] = {}
|
||||
_PLUGINS: Dict[str, Plugin] = {}
|
||||
|
||||
|
||||
def register_provider(
|
||||
def register_plugin(
|
||||
name: str,
|
||||
adapter: ProviderAdapter,
|
||||
*,
|
||||
columns: Union[List[ColumnSpec], ColumnFactory],
|
||||
selection_fn: SelectionFn,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> Provider:
|
||||
) -> Plugin:
|
||||
name = str(name or "").strip().lower()
|
||||
if not name:
|
||||
raise ValueError("provider name required")
|
||||
if name in _PROVIDERS:
|
||||
raise ValueError(f"provider already registered: {name}")
|
||||
raise ValueError("plugin name required")
|
||||
if name in _PLUGINS:
|
||||
raise ValueError(f"plugin already registered: {name}")
|
||||
if columns is None:
|
||||
raise ValueError("provider registration requires columns")
|
||||
raise ValueError("plugin registration requires columns")
|
||||
if selection_fn is None:
|
||||
raise ValueError("provider registration requires selection_fn")
|
||||
p = Provider(name=name, adapter=adapter, columns=columns, selection_fn=selection_fn, metadata=metadata)
|
||||
_PROVIDERS[name] = p
|
||||
return p
|
||||
raise ValueError("plugin registration requires selection_fn")
|
||||
plugin = Plugin(name=name, adapter=adapter, columns=columns, selection_fn=selection_fn, metadata=metadata)
|
||||
_PLUGINS[name] = plugin
|
||||
return plugin
|
||||
|
||||
|
||||
def get_provider(name: str) -> Provider:
|
||||
def get_plugin(name: str) -> Plugin:
|
||||
normalized = str(name or "").lower()
|
||||
if normalized not in _PROVIDERS:
|
||||
raise KeyError(f"provider not registered: {name}")
|
||||
return _PROVIDERS[normalized]
|
||||
if normalized not in _PLUGINS:
|
||||
raise KeyError(f"plugin not registered: {name}")
|
||||
return _PLUGINS[normalized]
|
||||
|
||||
|
||||
def list_providers() -> List[str]:
|
||||
return list(_PROVIDERS.keys())
|
||||
def list_plugins() -> List[str]:
|
||||
return list(_PLUGINS.keys())
|
||||
|
||||
Reference in New Issue
Block a user