From d75ccacaaa017a1fe3583ad00a9a48800b155dc6 Mon Sep 17 00:00:00 2001 From: Peter Dudfield Date: Thu, 2 Apr 2026 08:13:20 +0100 Subject: [PATCH 1/2] convert gsp_ids="" to None --- .../internal/service/uk_national/endpoint_types.py | 3 +++ .../internal/service/uk_national/gsp_router.py | 11 +++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/quartz_api/internal/service/uk_national/endpoint_types.py b/src/quartz_api/internal/service/uk_national/endpoint_types.py index 6c9a77f..ebdd878 100644 --- a/src/quartz_api/internal/service/uk_national/endpoint_types.py +++ b/src/quartz_api/internal/service/uk_national/endpoint_types.py @@ -41,6 +41,9 @@ def convert_list_of_gsp_ids(gsp_ids:str | None) -> list[int] | None: if gsp_ids is None: return gsp_ids + if gsp_ids == "": + return None + return [int(gsp_id) for gsp_id in gsp_ids.split(",")] class EnhancedBaseModel(BaseModel): diff --git a/src/quartz_api/internal/service/uk_national/gsp_router.py b/src/quartz_api/internal/service/uk_national/gsp_router.py index 418f30d..88bb3d4 100644 --- a/src/quartz_api/internal/service/uk_national/gsp_router.py +++ b/src/quartz_api/internal/service/uk_national/gsp_router.py @@ -310,7 +310,8 @@ async def get_all_available_forecasts( dt.datetime, Depends(limit_end_datetime_by_permissions), ], - gsp_ids: str | None = None, + gsp_ids: Annotated[list[str] | None, + AfterValidator(lambda v: convert_list_of_gsp_ids(v))] = None, compact: bool = False, ) -> list[OneDatetimeManyForecastValuesMW] | ListForecasts: """### Get all forecasts for all GSPs. @@ -365,7 +366,7 @@ async def get_all_available_forecasts( # gsp_ids path: custom query, fetch live. gsps_to_convert: dict[int, models.Location] = { k: v for k, v in gsp_id_map.items() - if k in convert_list_of_gsp_ids(gsp_ids) + if k in gsp_ids } tasks = [ db.get_predicted_generation( @@ -547,7 +548,8 @@ async def get_truths_for_all_gsps( start_datetime_utc: models.UTCDatetimeDefaultWindowStart, # TODO update to now end_datetime_utc: models.UTCDatetimeDefaultWindowEnd, regime: Annotated[str, AfterValidator(lambda v: v.replace("-", "_"))] = "in-day", - gsp_ids: str | None = None, + gsp_ids: Annotated[list[str] | None, + AfterValidator(lambda v: convert_list_of_gsp_ids(v))] = None, ) -> list[GSPYieldGroupByDatetime]: """### Get PV_Live values for all GSPs for yesterday and today. @@ -567,10 +569,7 @@ async def get_truths_for_all_gsps( - **start_datetime_utc**: optional start datetime for the query. - **end_datetime_utc**: optional end datetime for the query. """ - # Why not just make the endpoint type list[int] and let fast API do this? - gsp_ids: list[int] | None = convert_list_of_gsp_ids(gsp_ids) out: list[GSPYieldGroupByDatetime] = [] - gsp_uuid_id_map: dict[UUID, int] = {v.uuid: k for k, v in gsp_id_map.items()} if gsp_ids is None: From c9b3ee858b57b2f4ec7651d59e37528292ada313 Mon Sep 17 00:00:00 2001 From: Peter Dudfield Date: Thu, 2 Apr 2026 10:15:16 +0100 Subject: [PATCH 2/2] dont use annotated --- src/quartz_api/internal/service/uk_national/gsp_router.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quartz_api/internal/service/uk_national/gsp_router.py b/src/quartz_api/internal/service/uk_national/gsp_router.py index 88bb3d4..4fa595c 100644 --- a/src/quartz_api/internal/service/uk_national/gsp_router.py +++ b/src/quartz_api/internal/service/uk_national/gsp_router.py @@ -310,8 +310,7 @@ async def get_all_available_forecasts( dt.datetime, Depends(limit_end_datetime_by_permissions), ], - gsp_ids: Annotated[list[str] | None, - AfterValidator(lambda v: convert_list_of_gsp_ids(v))] = None, + gsp_ids: str | None = None, compact: bool = False, ) -> list[OneDatetimeManyForecastValuesMW] | ListForecasts: """### Get all forecasts for all GSPs. @@ -330,6 +329,7 @@ async def get_all_available_forecasts( """ # Default (no gsp_ids): served from warm cache only. If we're here it's a cache miss — # trigger a warm in the background and ask the client to retry. + gsp_ids = convert_list_of_gsp_ids(gsp_ids) start_datetime_utc_set = start_datetime_utc != default_now_window_start() end_datetime_utc_set = end_datetime_utc != default_window_end() @@ -548,8 +548,7 @@ async def get_truths_for_all_gsps( start_datetime_utc: models.UTCDatetimeDefaultWindowStart, # TODO update to now end_datetime_utc: models.UTCDatetimeDefaultWindowEnd, regime: Annotated[str, AfterValidator(lambda v: v.replace("-", "_"))] = "in-day", - gsp_ids: Annotated[list[str] | None, - AfterValidator(lambda v: convert_list_of_gsp_ids(v))] = None, + gsp_ids: str | None = None, ) -> list[GSPYieldGroupByDatetime]: """### Get PV_Live values for all GSPs for yesterday and today. @@ -570,6 +569,7 @@ async def get_truths_for_all_gsps( - **end_datetime_utc**: optional end datetime for the query. """ out: list[GSPYieldGroupByDatetime] = [] + gsp_ids = convert_list_of_gsp_ids(gsp_ids) gsp_uuid_id_map: dict[UUID, int] = {v.uuid: k for k, v in gsp_id_map.items()} if gsp_ids is None: