Skip to content

Commit f5a7c40

Browse files
committed
updates listing
1 parent d2f8ec9 commit f5a7c40

File tree

5 files changed

+69
-45
lines changed

5 files changed

+69
-45
lines changed

packages/models-library/src/models_library/api_schemas_catalog/services.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
171171
)
172172

173173

174-
class ServiceGetV2Base(CatalogOutputSchema):
174+
class _BaseServiceGetV2(CatalogOutputSchema):
175175
# Model used in catalog's rpc and rest interfaces
176176
key: ServiceKey
177177
version: ServiceVersion
@@ -205,8 +205,14 @@ class ServiceGetV2Base(CatalogOutputSchema):
205205
classifiers: list[str] | None = []
206206
quality: dict[str, Any] = {}
207207

208+
model_config = ConfigDict(
209+
extra="forbid",
210+
populate_by_name=True,
211+
alias_generator=snake_to_camel,
212+
)
208213

209-
class ServiceGetV2(ServiceGetV2Base):
214+
215+
class ServiceGetV2(_BaseServiceGetV2):
210216
# Model used in catalog's rpc and rest interfaces
211217
history: Annotated[
212218
list[ServiceRelease],
@@ -278,14 +284,11 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
278284
)
279285

280286
model_config = ConfigDict(
281-
extra="forbid",
282-
populate_by_name=True,
283-
alias_generator=snake_to_camel,
284287
json_schema_extra=_update_json_schema_extra,
285288
)
286289

287290

288-
class ServiceItemList(ServiceGetV2Base):
291+
class ServiceItemList(_BaseServiceGetV2):
289292
release: ServiceRelease
290293
history: Annotated[
291294
list[ServiceRelease],

packages/models-library/src/models_library/services_history.py

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime
2-
from typing import TypeAlias
2+
from typing import Annotated, TypeAlias
33

44
from pydantic import BaseModel, ConfigDict, Field
55

@@ -8,51 +8,50 @@
88

99

1010
class CompatibleService(BaseModel):
11-
key: ServiceKey | None = Field(
12-
default=None,
13-
description="If None, it refer to current service. Used only for inter-service compatibility",
14-
)
11+
key: Annotated[
12+
ServiceKey | None,
13+
Field(
14+
description="If None, it refer to current service. Used only for inter-service compatibility"
15+
),
16+
] = None
1517
version: ServiceVersion
1618

1719

1820
class Compatibility(BaseModel):
19-
# NOTE: as an object it is more maintainable than a list
20-
can_update_to: CompatibleService = Field(
21-
..., description="Latest compatible service at this moment"
22-
)
21+
can_update_to: Annotated[
22+
CompatibleService, Field(description="Latest compatible service at this moment")
23+
]
2324

2425
model_config = ConfigDict(alias_generator=snake_to_camel, populate_by_name=True)
2526

2627

2728
class ServiceRelease(BaseModel):
28-
# from ServiceMetaDataPublished
2929
version: ServiceVersion
30-
version_display: str | None = Field(
31-
default=None, description="If None, then display `version`"
32-
)
33-
released: datetime | None = Field(
34-
default=None, description="When provided, it indicates the release timestamp"
35-
)
36-
retired: datetime | None = Field(
37-
default=None,
38-
description="whether this service is planned to be retired. "
39-
"If None, the service is still active. "
40-
"If now<retired then the service is deprecated. "
41-
"If retired<now then the service is retired and should not be used. ",
42-
)
43-
compatibility: Compatibility | None = Field(
44-
default=None, description="Compatibility with other releases at this moment"
45-
)
30+
version_display: Annotated[
31+
str | None, Field(description="If None, then display `version`")
32+
] = None
33+
released: Annotated[
34+
datetime | None,
35+
Field(description="When provided, it indicates the release timestamp"),
36+
] = None
37+
retired: Annotated[
38+
datetime | None,
39+
Field(
40+
description="whether this service is planned to be retired. If None, the service is still active. If now<retired then the service is deprecated. If retired<now then the service is retired and should not be used."
41+
),
42+
] = None
43+
compatibility: Annotated[
44+
Compatibility | None,
45+
Field(description="Compatibility with other releases at this moment"),
46+
] = None
4647

4748
model_config = ConfigDict(
4849
alias_generator=snake_to_camel,
4950
populate_by_name=True,
5051
json_schema_extra={
5152
"examples": [
5253
# minimal
53-
{
54-
"version": "0.9.0",
55-
},
54+
{"version": "0.9.0"},
5655
# complete
5756
{
5857
"version": "0.9.1",

services/catalog/src/simcore_service_catalog/services/services_api.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from models_library.api_schemas_catalog.services import (
44
MyServiceGet,
55
ServiceGetV2,
6+
ServiceItemList,
67
ServiceUpdateV2,
78
)
89
from models_library.groups import GroupID
@@ -88,7 +89,7 @@ async def list_services_paginated(
8889
user_id: UserID,
8990
limit: PageLimitInt | None,
9091
offset: NonNegativeInt = 0,
91-
) -> tuple[NonNegativeInt, list[ServiceGetV2]]:
92+
) -> tuple[NonNegativeInt, list[ServiceItemList]]:
9293

9394
# defines the order
9495
total_count, services = await repo.list_latest_services(
@@ -120,26 +121,45 @@ async def list_services_paginated(
120121

121122
items = [
122123
_db_to_api_model(
123-
service_db=s, access_rights_db=ar, service_manifest=sm, compatibility_map=cm
124+
service_db=sc,
125+
access_rights_db=ar,
126+
service_manifest=sm,
127+
compatibility_map=cm,
124128
)
125-
for s in services
129+
for sc in services
126130
if (
127-
(ar := access_rights.get((s.key, s.version)))
128-
and (sm := service_manifest.get((s.key, s.version)))
131+
(ar := access_rights.get((sc.key, sc.version)))
132+
and (sm := service_manifest.get((sc.key, sc.version)))
129133
and (
130134
# NOTE: This operation might be resource-intensive.
131135
# It is temporarily implemented on a trial basis.
132136
cm := await evaluate_service_compatibility_map(
133137
repo,
134138
product_name=product_name,
135139
user_id=user_id,
136-
service_release_history=s.history,
140+
service_release_history=sc.history,
137141
)
138142
)
139143
)
140144
]
141145

142-
return total_count, items
146+
def _get_release(item: ServiceGetV2) -> ServiceRelease:
147+
for rs in item.history:
148+
if rs.version == item.version:
149+
return rs
150+
return ServiceRelease(
151+
version=item.version, version_display=item.version_display, released=None
152+
)
153+
154+
return total_count, [
155+
ServiceItemList.model_validate(
156+
{
157+
**it.model_dump(exclude_unset=True, by_alias=True),
158+
"release": _get_release(it),
159+
}
160+
)
161+
for it in items
162+
]
143163

144164

145165
async def get_service(

services/catalog/tests/unit/conftest.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
pytest_plugins = [
3535
"pytest_simcore.cli_runner",
3636
"pytest_simcore.docker_compose",
37-
"pytest_simcore.simcore_catalog_service",
3837
"pytest_simcore.docker_registry",
3938
"pytest_simcore.docker_swarm",
4039
"pytest_simcore.environment_configs",

services/catalog/tests/unit/with_dbs/test_services_services_api.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ async def background_sync_task_mocked(
8989
services_db_tables_injector: Callable,
9090
fake_services_data: list,
9191
) -> None:
92-
# inject db services (typically done by the sync background task)
92+
"""
93+
Emulates a sync backgroundtask that injects
94+
some services in the db
95+
"""
9396
await services_db_tables_injector(fake_services_data)
9497

9598

@@ -150,7 +153,7 @@ async def test_list_services_paginated(
150153
service_version=item.version,
151154
)
152155

153-
assert got == item
156+
assert got.model_dump() == item.model_dump(exclude={"release"})
154157

155158
# since it is cached, it should only call it `limit` times
156159
assert mocked_director_service_api["get_service"].call_count == limit

0 commit comments

Comments
 (0)