Skip to content

Commit 3c9f726

Browse files
remove workbenc from data model
1 parent dcf0efe commit 3c9f726

File tree

4 files changed

+140
-70
lines changed

4 files changed

+140
-70
lines changed

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

Lines changed: 94 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Models a study's project document
2+
Models a study's project document
33
"""
44

55
from datetime import datetime
@@ -11,7 +11,14 @@
1111
from models_library.basic_types import ConstrainedStr
1212
from models_library.folders import FolderID
1313
from models_library.workspaces import WorkspaceID
14-
from pydantic import BaseModel, ConfigDict, Field, HttpUrl, field_validator
14+
from pydantic import (
15+
BaseModel,
16+
BeforeValidator,
17+
ConfigDict,
18+
Field,
19+
HttpUrl,
20+
field_validator,
21+
)
1522

1623
from .basic_regex import DATE_RE, UUID_RE_BASE
1724
from .emails import LowerCaseEmailStr
@@ -54,56 +61,103 @@ class ProjectType(str, Enum):
5461

5562
class BaseProjectModel(BaseModel):
5663
# Description of the project
57-
uuid: ProjectID = Field(
58-
...,
59-
description="project unique identifier",
60-
examples=[
61-
"07640335-a91f-468c-ab69-a374fa82078d",
62-
"9bcf8feb-c1b1-41b6-b201-639cd6ccdba8",
63-
],
64-
)
65-
name: str = Field(
66-
..., description="project name", examples=["Temporal Distortion Simulator"]
67-
)
68-
description: str = Field(
69-
...,
70-
description="longer one-line description about the project",
71-
examples=["Dabbling in temporal transitions ..."],
72-
)
73-
thumbnail: HttpUrl | None = Field(
74-
...,
75-
description="url of the project thumbnail",
76-
examples=["https://placeimg.com/171/96/tech/grayscale/?0.jpg"],
77-
)
64+
uuid: Annotated[
65+
ProjectID,
66+
Field(
67+
...,
68+
description="project unique identifier",
69+
examples=[
70+
"07640335-a91f-468c-ab69-a374fa82078d",
71+
"9bcf8feb-c1b1-41b6-b201-639cd6ccdba8",
72+
],
73+
),
74+
]
75+
name: Annotated[
76+
str,
77+
Field(
78+
..., description="project name", examples=["Temporal Distortion Simulator"]
79+
),
80+
]
81+
description: Annotated[
82+
str,
83+
BeforeValidator(none_to_empty_str_pre_validator),
84+
Field(
85+
...,
86+
description="longer one-line description about the project",
87+
examples=["Dabbling in temporal transitions ..."],
88+
),
89+
]
90+
thumbnail: Annotated[
91+
HttpUrl | None,
92+
BeforeValidator(empty_str_to_none_pre_validator),
93+
Field(
94+
...,
95+
description="url of the project thumbnail",
96+
examples=["https://placeimg.com/171/96/tech/grayscale/?0.jpg"],
97+
),
98+
]
7899

79-
creation_date: datetime = Field(...)
80-
last_change_date: datetime = Field(...)
100+
creation_date: datetime
101+
last_change_date: datetime
81102

82103
# Pipeline of nodes (SEE projects_nodes.py)
83104
workbench: Annotated[NodesDict, Field(..., description="Project's pipeline")]
84105

85-
# validators
86-
_empty_thumbnail_is_none = field_validator("thumbnail", mode="before")(
87-
empty_str_to_none_pre_validator
88-
)
89106

90-
_none_description_is_empty = field_validator("description", mode="before")(
91-
none_to_empty_str_pre_validator
92-
)
107+
class ProjectAtDB(BaseModel):
108+
# Model used to READ from database (will be removed)
93109

110+
uuid: Annotated[
111+
ProjectID,
112+
Field(
113+
...,
114+
description="project unique identifier",
115+
examples=[
116+
"07640335-a91f-468c-ab69-a374fa82078d",
117+
"9bcf8feb-c1b1-41b6-b201-639cd6ccdba8",
118+
],
119+
),
120+
]
121+
name: Annotated[
122+
str,
123+
Field(
124+
..., description="project name", examples=["Temporal Distortion Simulator"]
125+
),
126+
]
127+
description: Annotated[
128+
str,
129+
BeforeValidator(none_to_empty_str_pre_validator),
130+
Field(
131+
...,
132+
description="longer one-line description about the project",
133+
examples=["Dabbling in temporal transitions ..."],
134+
),
135+
]
136+
thumbnail: Annotated[
137+
HttpUrl | None,
138+
BeforeValidator(empty_str_to_none_pre_validator),
139+
Field(
140+
...,
141+
description="url of the project thumbnail",
142+
examples=["https://placeimg.com/171/96/tech/grayscale/?0.jpg"],
143+
),
144+
]
94145

95-
class ProjectAtDB(BaseProjectModel):
96-
# Model used to READ from database
146+
creation_date: datetime
147+
last_change_date: datetime
97148

98-
id: int = Field(..., description="The table primary index")
149+
id: Annotated[int, Field(..., description="The table primary index")]
99150

100-
project_type: ProjectType = Field(..., alias="type", description="The project type")
151+
project_type: Annotated[
152+
ProjectType, Field(..., alias="type", description="The project type")
153+
]
101154

102-
prj_owner: int | None = Field(..., description="The project owner id")
155+
prj_owner: Annotated[int | None, Field(..., description="The project owner id")]
103156

104-
published: bool | None = Field(
105-
default=False, description="Defines if a study is available publicly"
106-
)
157+
published: Annotated[
158+
bool | None,
159+
Field(default=False, description="Defines if a study is available publicly"),
160+
]
107161

108162
@field_validator("project_type", mode="before")
109163
@classmethod

packages/pytest-simcore/src/pytest_simcore/db_entries_mocks.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,10 @@ async def project(
6767
) -> AsyncIterator[Callable[..., Awaitable[ProjectAtDB]]]:
6868
created_project_ids: list[str] = []
6969

70-
async def creator(
70+
async def _(
7171
user: dict[str, Any],
7272
*,
73+
workbench: dict[str, Any] | None = None,
7374
project_nodes_overrides: dict[str, Any] | None = None,
7475
**project_overrides,
7576
) -> ProjectAtDB:
@@ -83,7 +84,6 @@ async def creator(
8384
"prj_owner": user["id"],
8485
"access_rights": {"1": {"read": True, "write": True, "delete": True}},
8586
"thumbnail": "",
86-
"workbench": {},
8787
}
8888
project_config.update(**project_overrides)
8989
async with aiopg_engine.acquire() as con, con.begin():
@@ -94,23 +94,31 @@ async def creator(
9494
)
9595

9696
inserted_project = ProjectAtDB.model_validate(await result.first())
97-
project_nodes_repo = ProjectNodesRepo(project_uuid=project_uuid)
98-
# NOTE: currently no resources is passed until it becomes necessary
99-
default_node_config = {"required_resources": {}, "key": faker.pystr(), "version": faker.pystr(), "label": faker.pystr()}
100-
if project_nodes_overrides:
101-
default_node_config.update(project_nodes_overrides)
102-
await project_nodes_repo.add(
103-
con,
104-
nodes=[
105-
ProjectNodeCreate(node_id=NodeID(node_id), **default_node_config)
106-
for node_id in inserted_project.workbench
107-
],
108-
)
97+
if workbench:
98+
project_nodes_repo = ProjectNodesRepo(project_uuid=project_uuid)
99+
# NOTE: currently no resources is passed until it becomes necessary
100+
default_node_config = {
101+
"required_resources": {},
102+
"key": faker.pystr(),
103+
"version": faker.pystr(),
104+
"label": faker.pystr(),
105+
}
106+
if project_nodes_overrides:
107+
default_node_config.update(project_nodes_overrides)
108+
await project_nodes_repo.add(
109+
con,
110+
nodes=[
111+
ProjectNodeCreate(
112+
node_id=NodeID(node_id), **default_node_config | node_data
113+
)
114+
for node_id, node_data in workbench.items()
115+
],
116+
)
109117
print(f"--> created {inserted_project=}")
110118
created_project_ids.append(f"{inserted_project.uuid}")
111119
return inserted_project
112120

113-
yield creator
121+
yield _
114122

115123
# cleanup
116124
async with aiopg_engine.acquire() as con:

services/director-v2/tests/unit/with_dbs/comp_scheduler/test_api_route_computations.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,9 @@ async def test_get_computation_from_not_started_computation_task(
877877
assert response.status_code == status.HTTP_409_CONFLICT, response.text
878878

879879
# now create the expected tasks and the state is good again
880-
comp_tasks = await create_tasks(user=user, project=proj)
880+
comp_tasks = await create_tasks(
881+
user=user, project=proj, workbench=fake_workbench_without_outputs
882+
)
881883
response = await async_client.get(get_computation_url)
882884
assert response.status_code == status.HTTP_200_OK, response.text
883885
returned_computation = ComputationGet.model_validate(response.json())

services/director-v2/tests/unit/with_dbs/conftest.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,13 @@ async def create_tasks(
7777
created_task_ids: list[int] = []
7878

7979
async def _(
80-
user: dict[str, Any], project: ProjectAtDB, **overrides_kwargs
80+
user: dict[str, Any],
81+
project: ProjectAtDB,
82+
workbench: dict[str, Any],
83+
**overrides_kwargs,
8184
) -> list[CompTaskAtDB]:
8285
created_tasks: list[CompTaskAtDB] = []
83-
for internal_id, (node_id, node_data) in enumerate(project.workbench.items()):
86+
for internal_id, (node_id, node_data) in enumerate(workbench.items(), start=1):
8487
task_config = {
8588
"project_id": f"{project.uuid}",
8689
"node_id": f"{node_id}",
@@ -94,9 +97,9 @@ async def _(
9497
if isinstance(value, BaseModel)
9598
else value
9699
)
97-
for key, value in node_data.inputs.items()
100+
for key, value in node_data["inputs"].items()
98101
}
99-
if node_data.inputs
102+
if "inputs" in node_data
100103
else {}
101104
),
102105
"outputs": (
@@ -108,19 +111,19 @@ async def _(
108111
if isinstance(value, BaseModel)
109112
else value
110113
)
111-
for key, value in node_data.outputs.items()
114+
for key, value in node_data["outputs"].items()
112115
}
113-
if node_data.outputs
116+
if "outputs" in node_data
114117
else {}
115118
),
116-
"image": Image(name=node_data.key, tag=node_data.version).model_dump(
117-
by_alias=True, exclude_unset=True
118-
),
119-
"node_class": to_node_class(node_data.key),
120-
"internal_id": internal_id + 1,
119+
"image": Image(
120+
name=node_data["key"], tag=node_data["version"]
121+
).model_dump(by_alias=True, exclude_unset=True),
122+
"node_class": to_node_class(node_data["key"]),
123+
"internal_id": internal_id,
121124
"job_id": generate_dask_job_id(
122-
service_key=node_data.key,
123-
service_version=node_data.version,
125+
service_key=node_data["key"],
126+
service_version=node_data["version"],
124127
user_id=user["id"],
125128
project_id=project.uuid,
126129
node_id=NodeID(node_id),
@@ -238,7 +241,10 @@ async def _() -> PublishedProject:
238241
dag_adjacency_list=fake_workbench_adjacency,
239242
),
240243
tasks=await create_tasks(
241-
user=user, project=created_project, state=StateType.PUBLISHED
244+
user=user,
245+
project=created_project,
246+
workbench=fake_workbench_without_outputs,
247+
state=StateType.PUBLISHED,
242248
),
243249
)
244250

0 commit comments

Comments
 (0)