From 6931b7119ff5487467fd4e712d52d8f2d1a61f3b Mon Sep 17 00:00:00 2001 From: Bob Steers Date: Fri, 7 Jun 2024 16:05:42 +0200 Subject: [PATCH] extend timedelta parsing for pydantic fields --- brewblox_history/models.py | 20 ++++++++++++-------- brewblox_history/victoria.py | 2 +- test/conftest.py | 1 - test/test_utils.py | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/brewblox_history/models.py b/brewblox_history/models.py index cbc0c2c..9a8752d 100644 --- a/brewblox_history/models.py +++ b/brewblox_history/models.py @@ -26,6 +26,8 @@ def parse_duration(value: DurationSrc_) -> timedelta: try: value = float(value) + except TypeError: + value = None except ValueError: value = timeparse(value) or value @@ -39,7 +41,7 @@ def parse_datetime(value: DatetimeSrc_) -> datetime | None: return pydantic_datetime_validator.validate_python(value) -Duration_ = Annotated[timedelta, BeforeValidator(parse_duration)] +loose_timedelta = Annotated[timedelta, BeforeValidator(parse_duration)] def flatten(d, parent_key=''): @@ -88,11 +90,11 @@ class ServiceConfig(BaseSettings): history_topic: str = 'brewcast/history' datastore_topic: str = 'brewcast/datastore' - ranges_interval: Duration_ = timedelta(seconds=10) - metrics_interval: Duration_ = timedelta(seconds=10) - minimum_step: Duration_ = timedelta(seconds=10) + ranges_interval: loose_timedelta = timedelta(seconds=10) + metrics_interval: loose_timedelta = timedelta(seconds=10) + minimum_step: loose_timedelta = timedelta(seconds=10) - query_duration_default: Duration_ = timedelta(days=1) + query_duration_default: loose_timedelta = timedelta(days=1) query_desired_points: int = 1000 @@ -148,12 +150,14 @@ class DatastoreDeleteResponse(BaseModel): class TimeSeriesFieldsQuery(BaseModel): - duration: str = Field('1d', examples=['10m', '1d']) + duration: loose_timedelta = Field(timedelta(days=1), + examples=['10m', '1d']) class TimeSeriesMetricsQuery(BaseModel): fields: list[str] - duration: str = Field('10m', examples=['10m', '1d']) + duration: loose_timedelta = Field(timedelta(minutes=10), + examples=['10m', '1d']) class TimeSeriesMetric(BaseModel): @@ -166,7 +170,7 @@ class TimeSeriesRangesQuery(BaseModel): fields: list[str] = Field(examples=[['spark-one/sensor/value[degC]']]) start: datetime | None = Field(None, examples=['2020-01-01T20:00:00.000Z']) end: datetime | None = Field(None, examples=['2030-01-01T20:00:00.000Z']) - duration: str | None = Field(None, examples=['1d']) + duration: loose_timedelta | None = Field(None, examples=['1d']) class TimeSeriesRangeValue(NamedTuple): diff --git a/brewblox_history/victoria.py b/brewblox_history/victoria.py index 8277410..fe9d830 100644 --- a/brewblox_history/victoria.py +++ b/brewblox_history/victoria.py @@ -51,7 +51,7 @@ async def _json_query(self, query: str, url: str): return resp.json() async def fields(self, args: TimeSeriesFieldsQuery) -> list[str]: - query = f'match[]={{__name__!=""}}&start={args.duration}' + query = f'match[]={{__name__!=""}}&start={args.duration.total_seconds()}s' LOGGER.debug(query) result = await self._json_query(query, '/api/v1/series') retv = [ diff --git a/test/conftest.py b/test/conftest.py index f58f3dd..55d591a 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -61,7 +61,6 @@ def config(monkeypatch: pytest.MonkeyPatch, redis_port=docker_services.port_for('redis', 6379), victoria_host='localhost', victoria_port=docker_services.port_for('victoria', 8428), - ranges_interval='10s', ) monkeypatch.setattr(utils, 'get_config', lambda: cfg) yield cfg diff --git a/test/test_utils.py b/test/test_utils.py index 2a26f90..102ba6f 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -52,7 +52,7 @@ def test_parse_duration(): with pytest.raises(ValidationError): utils.parse_duration('') - with pytest.raises(TypeError): + with pytest.raises(ValidationError): utils.parse_duration(None)