from typing import ClassVar, Optional, Type
from datetime import datetime
from pydantic import BaseModel, Extra
from todays_paper_web.widgets import registerDataSource
[docs]
class DataSourceParams(BaseModel):
"""Base ``Params`` for every data source. Unlike ``ViewParams``, there's no field common to
every data source - a data source has no parent/child relationship for something else to read
a value off it generically the way a widget's `x`/`y`/`align`/`valign` are - so this exists
only to carry the shared `extra=ignore` config."""
class Config:
extra = Extra.ignore
[docs]
class DataSource:
#: See `View.Params` - same opt-in typed-attribute mechanism, for a data
#: source's `params:` config block instead of a widget's XML attributes.
#: Unlike `View.Params`, left as `None` by default: nothing reads a data
#: source's params except its own `fetch()`, so there's no requirement
#: that every source (registered or not) have a working one.
Params: ClassVar[Optional[Type[DataSourceParams]]] = None
def __init__(self, params):
self._params = params
self._parsedParams: Optional[DataSourceParams] = None
self._timestamp: datetime = datetime.today()
[docs]
def fetch(self):
return {}
@property
def params(self) -> DataSourceParams:
if self._parsedParams is None:
if self.Params is None:
raise AttributeError(f"{type(self).__name__} has no declared Params")
self._parsedParams = self.Params.parse_obj(self._params)
return self._parsedParams
@property
def timestamp(self) -> datetime:
return self._timestamp
@timestamp.setter
def timestamp(self, timestamp: datetime) -> None:
self._timestamp = timestamp
[docs]
@staticmethod
def get(name, params):
# pylint: disable=invalid-name
DataSourceCls = registerDataSource.get(name, DataSource)
source = DataSourceCls(params)
return source