Skip to content

Commit 774c98f

Browse files
committed
save
1 parent 8f51b73 commit 774c98f

File tree

9 files changed

+117
-25
lines changed

9 files changed

+117
-25
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# pylint: disable=not-context-manager
2+
# pylint: disable=protected-access
3+
# pylint: disable=redefined-outer-name
4+
# pylint: disable=unused-argument
5+
# pylint: disable=unused-variable
6+
7+
8+
from models_library.projects import ProjectID
9+
from pydantic import TypeAdapter
10+
from servicelib.rabbitmq._client_rpc import RabbitMQRPCClient
11+
12+
13+
class WebserverRpcSideEffects:
14+
# pylint: disable=no-self-use
15+
16+
async def mark_project_as_job(
17+
self,
18+
rpc_client: RabbitMQRPCClient,
19+
*,
20+
project_uuid: ProjectID,
21+
job_parent_resource_name: str,
22+
) -> None:
23+
assert rpc_client
24+
25+
assert not job_parent_resource_name.startswith("/") # nosec
26+
assert "/" in job_parent_resource_name # nosec
27+
assert not job_parent_resource_name.endswith("/") # nosec
28+
29+
TypeAdapter(ProjectID).validate_python(project_uuid)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import logging
2+
3+
from models_library.projects import ProjectID
4+
from pydantic import TypeAdapter
5+
from servicelib.logging_utils import log_decorator
6+
from servicelib.rabbitmq import RabbitMQRPCClient
7+
8+
_logger = logging.getLogger(__name__)
9+
10+
11+
@log_decorator(_logger, level=logging.DEBUG)
12+
async def mark_project_as_job(
13+
rpc_client: RabbitMQRPCClient,
14+
*,
15+
project_uuid: ProjectID,
16+
job_parent_resource_name: str,
17+
) -> None:
18+
19+
assert rpc_client
20+
21+
assert not job_parent_resource_name.startswith("/") # nosec
22+
assert "/" in job_parent_resource_name # nosec
23+
assert not job_parent_resource_name.endswith("/") # nosec
24+
25+
TypeAdapter(ProjectID).validate_python(project_uuid)
26+
27+
raise NotImplementedError

services/api-server/src/simcore_service_api_server/models/schemas/files.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,28 @@ class ClientFile(BaseModel):
3737
filename: FileName = Field(..., description="File name")
3838
filesize: NonNegativeInt = Field(..., description="File size in bytes")
3939
sha256_checksum: SHA256Str = Field(..., description="SHA256 checksum")
40+
destination: Annotated[
41+
ProgramJobFilePath | None,
42+
Field(..., description="Destination within a program job"),
43+
]
4044

4145

4246
class File(BaseModel):
4347
"""Represents a file stored on the server side i.e. a unique reference to a file in the cloud."""
4448

45-
# WARNING: from pydantic import File as FileParam
46-
# NOTE: see https://ant.apache.org/manual/Tasks/checksum.html
47-
48-
id: UUID = Field(..., description="Resource identifier")
49-
50-
filename: str = Field(..., description="Name of the file with extension")
51-
content_type: str | None = Field(
52-
default=None,
53-
description="Guess of type content [EXPERIMENTAL]",
54-
validate_default=True,
55-
)
56-
sha256_checksum: SHA256Str | None = Field(
57-
default=None,
58-
description="SHA256 hash of the file's content",
59-
alias="checksum", # alias for backwards compatibility
60-
)
61-
e_tag: ETag | None = Field(default=None, description="S3 entity tag")
49+
id: Annotated[UUID, Field(description="Resource identifier")]
50+
filename: Annotated[str, Field(description="Name of the file with extension")]
51+
content_type: Annotated[
52+
str | None,
53+
Field(
54+
description="Guess of type content [EXPERIMENTAL]", validate_default=True
55+
),
56+
] = None
57+
sha256_checksum: Annotated[
58+
SHA256Str | None,
59+
Field(description="SHA256 hash of the file's content", alias="checksum"),
60+
] = None
61+
e_tag: Annotated[ETag | None, Field(description="S3 entity tag")] = None
6262

6363
model_config = ConfigDict(
6464
populate_by_name=True,
@@ -163,16 +163,18 @@ def quoted_storage_file_id(self) -> str:
163163

164164

165165
class UploadLinks(BaseModel):
166-
abort_upload: str
167-
complete_upload: str
166+
abort_upload: Annotated[str, Field()]
167+
complete_upload: Annotated[str, Field()]
168168

169169

170170
class FileUploadData(BaseModel):
171-
chunk_size: NonNegativeInt
172-
urls: list[Annotated[AnyHttpUrl, UriSchema()]]
173-
links: UploadLinks
171+
chunk_size: Annotated[int, Field(description="Chunk size in bytes")]
172+
urls: Annotated[list[Annotated[AnyHttpUrl, UriSchema()]], Field()]
173+
links: Annotated[UploadLinks, Field()]
174174

175175

176176
class ClientFileUploadData(BaseModel):
177-
file_id: UUID = Field(..., description="The file resource id")
178-
upload_schema: FileUploadData = Field(..., description="Schema for uploading file")
177+
file_id: Annotated[UUID, Field(description="The file resource id")]
178+
upload_schema: Annotated[
179+
FileUploadData, Field(description="Schema for uploading file")
180+
]

services/api-server/src/simcore_service_api_server/services_rpc/wb_api_server.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from servicelib.rabbitmq.rpc_interfaces.resource_usage_tracker.errors import (
2828
NotEnoughAvailableSeatsError,
2929
)
30+
from servicelib.rabbitmq.rpc_interfaces.webserver import projects as projects_rpc
3031
from servicelib.rabbitmq.rpc_interfaces.webserver.functions.functions import (
3132
ping as _ping,
3233
)
@@ -211,7 +212,11 @@ async def mark_project_as_job(
211212

212213
assert project_uuid
213214

214-
raise NotImplementedError
215+
await projects_rpc.mark_project_as_job(
216+
rpc_client=self._client,
217+
project_uuid=project_uuid,
218+
job_parent_resource_name=job_parent_resource_name,
219+
)
215220

216221

217222
def setup(app: FastAPI, rabbitmq_rmp_client: RabbitMQRPCClient):

services/api-server/tests/unit/_with_db/test_api_user.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ async def test_get_profile(
5454
client: httpx.AsyncClient,
5555
auth: httpx.BasicAuth,
5656
mocked_webserver_service_api: MockRouter,
57+
mocked_rpc_webserver_service_api: dict[str, MockType],
5758
):
5859
# needs no auth
5960
resp = await client.get(f"/{API_VTAG}/meta")
@@ -77,6 +78,7 @@ async def test_update_profile(
7778
client: httpx.AsyncClient,
7879
auth: httpx.BasicAuth,
7980
mocked_webserver_service_api: MockRouter,
81+
mocked_rpc_webserver_service_api: dict[str, MockType],
8082
):
8183
# needs auth
8284
resp = await client.put(

services/api-server/tests/unit/api_solvers/conftest.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
from fastapi import FastAPI, status
1414
from fastapi.encoders import jsonable_encoder
1515
from models_library.projects_state import RunningState
16+
from pytest_mock import MockerFixture, MockType
1617
from pytest_simcore.helpers import faker_catalog
18+
from pytest_simcore.helpers.webserver_rpc_server import WebserverRpcSideEffects
1719
from respx import MockRouter
1820
from simcore_service_api_server.core.settings import ApplicationSettings
1921
from simcore_service_api_server.services_http.director_v2 import ComputationTaskGet
@@ -43,6 +45,26 @@ def mocked_webserver_service_api(
4345
return mocked_webserver_service_api_base
4446

4547

48+
@pytest.fixture
49+
def mocked_rpc_webserver_service_api(
50+
app: FastAPI, mocker: MockerFixture
51+
) -> dict[str, MockType]:
52+
from simcore_service_api_server.services_rpc.wb_api_server import projects_rpc
53+
54+
settings: ApplicationSettings = app.state.settings
55+
assert settings.API_SERVER_WEBSERVER
56+
57+
side_effects = WebserverRpcSideEffects()
58+
59+
return {
60+
"mark_project_as_job": mocker.patch.object(
61+
projects_rpc,
62+
"mark_project_as_job",
63+
side_effects.mark_project_as_job,
64+
),
65+
}
66+
67+
4668
@pytest.fixture
4769
def mocked_catalog_service_api(
4870
app: FastAPI,

services/api-server/tests/unit/api_solvers/test_api_routers_solvers_jobs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from models_library.services import ServiceMetaDataPublished
1919
from models_library.utils.fastapi_encoders import jsonable_encoder
2020
from pydantic import AnyUrl, HttpUrl, TypeAdapter
21+
from pytest_mock import MockType
2122
from respx import MockRouter
2223
from simcore_service_api_server._meta import API_VTAG
2324
from simcore_service_api_server.core.settings import ApplicationSettings
@@ -206,6 +207,7 @@ async def test_run_solver_job(
206207
mocked_catalog_service_api: MockRouter,
207208
mocked_directorv2_service_api: MockRouter,
208209
mocked_webserver_service_api: MockRouter,
210+
mocked_rpc_webserver_service_api: dict[str, MockType],
209211
auth: httpx.BasicAuth,
210212
project_id: str,
211213
solver_key: str,

services/api-server/tests/unit/api_solvers/test_api_routers_solvers_jobs_delete.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class MockedBackendApiDict(TypedDict):
3333
@pytest.fixture
3434
def mocked_backend_services_apis_for_delete_non_existing_project(
3535
mocked_webserver_service_api: MockRouter,
36+
mocked_rpc_webserver_service_api: dict[str, MockType],
3637
project_tests_dir: Path,
3738
) -> MockedBackendApiDict:
3839
mock_name = "delete_project_not_found.json"
@@ -85,6 +86,7 @@ async def test_delete_non_existing_solver_job(
8586
@pytest.fixture
8687
def mocked_backend_services_apis_for_create_and_delete_solver_job(
8788
mocked_webserver_service_api: MockRouter,
89+
mocked_rpc_webserver_service_api: dict[str, MockType],
8890
mocked_catalog_service_api: MockRouter,
8991
project_tests_dir: Path,
9092
) -> MockedBackendApiDict:

services/api-server/tests/unit/api_solvers/test_api_routers_solvers_jobs_metadata.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def _as_path_regex(initial_path: str):
3838
@pytest.fixture
3939
def mocked_backend(
4040
mocked_webserver_service_api: MockRouter,
41+
mocked_rpc_webserver_service_api: dict[str, MockType],
4142
mocked_catalog_service_api: MockRouter,
4243
project_tests_dir: Path,
4344
) -> MockedBackendApiDict:

0 commit comments

Comments
 (0)