35 lines
1.3 KiB
Python
35 lines
1.3 KiB
Python
from __future__ import annotations
|
|
import importlib
|
|
from typing import Any, Type, cast
|
|
|
|
from DistributionCost import DistributionCostBase
|
|
|
|
def create(name: str, /, **kwargs: Any) -> DistributionCostBase:
|
|
"""
|
|
Instantiate provider by name using a simple convention:
|
|
module: DistributionProvider.<Name>Provider
|
|
class: <Name>Provider
|
|
Example: create("TauronG13", rates=...)
|
|
-> DistributionCostProvider.TauronG13Provider.TauronG13Provider(...)
|
|
"""
|
|
safe = "".join(ch for ch in name if ch.isalnum() or ch == "_")
|
|
module_name = f"DistributionCostProvider.{safe}Provider"
|
|
class_name = f"{safe}Provider"
|
|
|
|
try:
|
|
mod = importlib.import_module(module_name)
|
|
except ModuleNotFoundError as e:
|
|
raise ValueError(f"Provider module '{module_name}' not found for name '{name}'.") from e
|
|
|
|
try:
|
|
cls: Type = getattr(mod, class_name)
|
|
except AttributeError as e:
|
|
raise ValueError(f"Provider class '{class_name}' not found in '{module_name}'.") from e
|
|
|
|
# be sure that this is a subclass of DistributionCostBase
|
|
if not issubclass(cls, DistributionCostBase):
|
|
raise TypeError(f"{class_name} does not derive from DistributionCostBase")
|
|
|
|
ProviderCls = cast(type[DistributionCostBase], cls)
|
|
return ProviderCls(**kwargs) # type: ignore[call-arg]
|