37 lines
1.5 KiB
Python
37 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from backend.data.contracts import DataSource, DataUsage
|
|
|
|
|
|
class DataPolicyError(RuntimeError):
|
|
pass
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class DataSourcePolicy:
|
|
calculation_sources: frozenset[DataSource] = frozenset(
|
|
{DataSource.TUSHARE, DataSource.IFIND, DataSource.LOCAL}
|
|
)
|
|
display_sources: frozenset[DataSource] = frozenset(DataSource)
|
|
|
|
def assert_allowed(self, source: DataSource, usage: DataUsage) -> None:
|
|
allowed = (
|
|
self.calculation_sources if usage is DataUsage.CALCULATION else self.display_sources
|
|
)
|
|
if source not in allowed:
|
|
raise DataPolicyError(f"{source.value} cannot be used for {usage.value}")
|
|
|
|
def candidates(self, dataset: str, usage: DataUsage) -> tuple[DataSource, ...]:
|
|
routes = {
|
|
("calendar", DataUsage.CALCULATION): (DataSource.TUSHARE,),
|
|
("entities", DataUsage.CALCULATION): (DataSource.TUSHARE,),
|
|
("daily_chart", DataUsage.DISPLAY): (DataSource.IFIND, DataSource.TUSHARE),
|
|
("minute_chart", DataUsage.DISPLAY): (DataSource.IFIND, DataSource.EASTMONEY),
|
|
("realtime_quote", DataUsage.CALCULATION): (DataSource.IFIND, DataSource.TUSHARE),
|
|
("market_insight", DataUsage.CALCULATION): (DataSource.TUSHARE,),
|
|
("dynamic_auction", DataUsage.CALCULATION): (DataSource.IFIND,),
|
|
}
|
|
return routes.get((dataset, usage), ())
|