Skip to content

Commit de7fc15

Browse files
committed
drafts catalog service
1 parent a6d85cc commit de7fc15

File tree

3 files changed

+158
-11
lines changed

3 files changed

+158
-11
lines changed

services/api-server/src/simcore_service_api_server/services_http/catalog.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
from fastapi import FastAPI, status
1111
from models_library.emails import LowerCaseEmailStr
12+
from models_library.products import ProductName
1213
from models_library.services import ServiceMetaDataPublished, ServiceType
14+
from models_library.users import UserID
1315
from pydantic import ConfigDict, TypeAdapter, ValidationError
1416
from settings_library.catalog import CatalogSettings
1517
from settings_library.tracing import TracingSettings
@@ -70,9 +72,9 @@ def to_solver(self) -> Solver:
7072

7173
_exception_mapper = partial(service_exception_mapper, service_name="Catalog")
7274

73-
TruncatedCatalogServiceOutAdapter: Final[
74-
TypeAdapter[TruncatedCatalogServiceOut]
75-
] = TypeAdapter(TruncatedCatalogServiceOut)
75+
TruncatedCatalogServiceOutAdapter: Final[TypeAdapter[TruncatedCatalogServiceOut]] = (
76+
TypeAdapter(TruncatedCatalogServiceOut)
77+
)
7678
TruncatedCatalogServiceOutListAdapter: Final[
7779
TypeAdapter[list[TruncatedCatalogServiceOut]]
7880
] = TypeAdapter(list[TruncatedCatalogServiceOut])
@@ -97,8 +99,8 @@ class CatalogApi(BaseServiceClientApi):
9799
async def list_solvers(
98100
self,
99101
*,
100-
user_id: int,
101-
product_name: str,
102+
user_id: UserID,
103+
product_name: ProductName,
102104
predicate: Callable[[Solver], bool] | None = None,
103105
) -> list[Solver]:
104106

@@ -140,7 +142,12 @@ async def list_solvers(
140142
http_status_map={status.HTTP_404_NOT_FOUND: SolverOrStudyNotFoundError}
141143
)
142144
async def get_service(
143-
self, *, user_id: int, name: SolverKeyId, version: VersionStr, product_name: str
145+
self,
146+
*,
147+
user_id: UserID,
148+
name: SolverKeyId,
149+
version: VersionStr,
150+
product_name: ProductName,
144151
) -> Solver:
145152

146153
assert version != LATEST_VERSION # nosec
@@ -171,8 +178,13 @@ async def get_service(
171178
http_status_map={status.HTTP_404_NOT_FOUND: SolverOrStudyNotFoundError}
172179
)
173180
async def get_service_ports(
174-
self, *, user_id: int, name: SolverKeyId, version: VersionStr, product_name: str
175-
):
181+
self,
182+
*,
183+
user_id: UserID,
184+
name: SolverKeyId,
185+
version: VersionStr,
186+
product_name: ProductName,
187+
) -> list[SolverPort]:
176188

177189
assert version != LATEST_VERSION # nosec
178190

@@ -190,7 +202,7 @@ async def get_service_ports(
190202
return TypeAdapter(list[SolverPort]).validate_python(response.json())
191203

192204
async def list_latest_releases(
193-
self, *, user_id: int, product_name: str
205+
self, *, user_id: UserID, product_name: ProductName
194206
) -> list[Solver]:
195207
solvers: list[Solver] = await self.list_solvers(
196208
user_id=user_id, product_name=product_name
@@ -205,7 +217,7 @@ async def list_latest_releases(
205217
return list(latest_releases.values())
206218

207219
async def list_solver_releases(
208-
self, *, user_id: int, solver_key: SolverKeyId, product_name: str
220+
self, *, user_id: UserID, solver_key: SolverKeyId, product_name: ProductName
209221
) -> list[Solver]:
210222
def _this_solver(solver: Solver) -> bool:
211223
return solver.id == solver_key
@@ -216,7 +228,7 @@ def _this_solver(solver: Solver) -> bool:
216228
return releases
217229

218230
async def get_latest_release(
219-
self, *, user_id: int, solver_key: SolverKeyId, product_name: str
231+
self, *, user_id: UserID, solver_key: SolverKeyId, product_name: ProductName
220232
) -> Solver:
221233
releases = await self.list_solver_releases(
222234
user_id=user_id, solver_key=solver_key, product_name=product_name
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
from models_library.basic_types import VersionStr
2+
from models_library.products import ProductName
3+
from models_library.rest_pagination import (
4+
DEFAULT_NUMBER_OF_ITEMS_PER_PAGE,
5+
PageLimitInt,
6+
PageOffsetInt,
7+
)
8+
from models_library.users import UserID
9+
10+
from ..models.schemas.solvers import Solver, SolverKeyId, SolverPort
11+
12+
_FAKE: list[Solver] = [
13+
Solver.model_validate(Solver.model_json_schema()["example"]),
14+
]
15+
_FAKE2: list[SolverPort] = [
16+
SolverPort.model_validate(SolverPort.model_json_schema()["example"]),
17+
]
18+
19+
20+
async def list_latest_releases(
21+
*,
22+
product_name: ProductName,
23+
user_id: UserID,
24+
offset: PageOffsetInt = 0,
25+
limit: PageLimitInt = DEFAULT_NUMBER_OF_ITEMS_PER_PAGE,
26+
) -> list[Solver]:
27+
assert product_name # nosec
28+
assert user_id # nosec
29+
30+
return _FAKE[offset : offset + limit]
31+
32+
33+
async def list_solver_releases(
34+
*,
35+
product_name: ProductName,
36+
user_id: UserID,
37+
solver_id: SolverKeyId,
38+
offset: PageOffsetInt = 0,
39+
limit: PageLimitInt = DEFAULT_NUMBER_OF_ITEMS_PER_PAGE,
40+
) -> list[Solver]:
41+
assert product_name # nosec
42+
assert user_id # nosec
43+
return [solver for solver in _FAKE if solver.id == solver_id][
44+
offset : offset + limit
45+
]
46+
47+
48+
async def get_solver(
49+
*,
50+
product_name: ProductName,
51+
user_id: UserID,
52+
solver_id: SolverKeyId,
53+
solver_version: VersionStr,
54+
) -> Solver | None:
55+
assert product_name # nosec
56+
assert user_id # nosec
57+
58+
return next(
59+
(
60+
solver
61+
for solver in _FAKE
62+
if solver.id == solver_id and solver.version == solver_version
63+
),
64+
None,
65+
)
66+
67+
68+
async def get_solver_ports(
69+
*,
70+
product_name: ProductName,
71+
user_id: int,
72+
solver_id: SolverKeyId,
73+
solver_version: VersionStr,
74+
) -> list[SolverPort]:
75+
76+
if await get_solver(
77+
product_name=product_name,
78+
user_id=user_id,
79+
solver_id=solver_id,
80+
solver_version=solver_version,
81+
):
82+
return _FAKE2
83+
return []
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# pylint: disable=protected-access
2+
# pylint: disable=redefined-outer-name
3+
# pylint: disable=too-many-arguments
4+
# pylint: disable=unused-argument
5+
# pylint: disable=unused-variable
6+
7+
import pytest
8+
from models_library.products import ProductName
9+
from models_library.users import UserID
10+
from simcore_service_api_server.models.schemas.solvers import Solver, SolverPort
11+
from simcore_service_api_server.services_rpc import catalog as catalog_service
12+
13+
14+
@pytest.fixture
15+
def product_name() -> ProductName:
16+
return "osparc"
17+
18+
19+
async def test_catalog_service_read_solvers(product_name: ProductName, user_id: UserID):
20+
# Step 1: List latest releases in a page
21+
solver_releases_page: list[Solver] = await catalog_service.list_latest_releases(
22+
product_name=product_name, user_id=user_id
23+
)
24+
assert solver_releases_page, "Releases page should not be empty"
25+
26+
# Step 2: Select one release and list solver releases
27+
selected_release = solver_releases_page[0]
28+
solver_releases = await catalog_service.list_solver_releases(
29+
product_name=product_name,
30+
user_id=user_id,
31+
solver_id=selected_release.id,
32+
)
33+
assert solver_releases, "Solver releases should not be empty"
34+
35+
# Step 3: Take the latest solver release and get solver details
36+
latest_solver_release = solver_releases[0]
37+
solver_details: Solver | None = await catalog_service.get_solver(
38+
product_name=product_name,
39+
user_id=user_id,
40+
solver_id=latest_solver_release.id,
41+
solver_version=latest_solver_release.version,
42+
)
43+
assert solver_details, "Solver details should not be empty"
44+
45+
# Step 4: Get solver ports
46+
solver_ports: list[SolverPort] = await catalog_service.get_solver_ports(
47+
product_name=product_name,
48+
user_id=user_id,
49+
solver_id=latest_solver_release.id,
50+
solver_version=latest_solver_release.version,
51+
)
52+
assert solver_ports, "Solver ports should not be empty"

0 commit comments

Comments
 (0)