Skip to content

Commit

Permalink
✨ Is686/apiserver api 0.4.2: studies ports (#3623)
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov authored Dec 1, 2022
1 parent c1d30ff commit 51d6df3
Show file tree
Hide file tree
Showing 16 changed files with 293 additions and 29 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

<!-- NOTE: when branched replace `master` in urls -->
[![Code style: black]](https://github.com/psf/black)
[![Requires.io]](https://requires.io/github/ITISFoundation/osparc-simcore/requirements/?branch=master "State of third party python dependencies")
[![CI](https://github.com/ITISFoundation/osparc-simcore/actions/workflows/ci-testing-deploy.yml/badge.svg)](https://github.com/ITISFoundation/osparc-simcore/actions/workflows/ci-testing-deploy.yml)
[![codecov](https://codecov.io/gh/ITISFoundation/osparc-simcore/branch/master/graph/badge.svg?token=h1rOE8q7ic)](https://codecov.io/gh/ITISFoundation/osparc-simcore)
[![github.io]](https://itisfoundation.github.io/)
Expand All @@ -17,7 +16,6 @@

<!-- ADD HERE ALL BADGE URLS. Use https://shields.io/ -->
[Code style: black]:https://img.shields.io/badge/code%20style-black-000000.svg
[Requires.io]:https://requires.io/github/ITISFoundation/osparc-simcore/requirements.svg?branch=master
[github.io]:https://img.shields.io/website-up-down-green-red/https/itisfoundation.github.io.svg?label=documentation
[itis.dockerhub]:https://img.shields.io/website/https/hub.docker.com/u/itisfoundation.svg?down_color=red&label=dockerhub%20repos&up_color=green
[license]:https://img.shields.io/github/license/ITISFoundation/osparc-simcore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from typing import Any, Final

# Web-server API responses of /projects/{project_id}/metadata/ports
# as reponses in this mock. SEE services/web/server/tests/unit/with_dbs/02/test_projects_ports_handlers.py
# NOTE: this could be added as examples in the OAS but for the moment we want to avoid overloading openapi.yml
# in the web-server.
PROJECTS_METADATA_PORTS_RESPONSE_BODY_DATA: Final[list[dict[str, Any]]] = [
{
"key": "38a0d401-af4b-4ea7-ab4c-5005c712a546",
"kind": "input",
"content_schema": {
"description": "Parameter of type integer",
"title": "X",
"type": "integer",
},
},
{
"key": "fc48252a-9dbb-4e07-bf9a-7af65a18f612",
"kind": "input",
"content_schema": {
"description": "Parameter of type integer",
"title": "Z",
"type": "integer",
},
},
{
"key": "7bf0741f-bae4-410b-b662-fc34b47c27c9",
"kind": "input",
"content_schema": {
"description": "Parameter of type boolean",
"title": "on",
"type": "boolean",
},
},
{
"key": "09fd512e-0768-44ca-81fa-0cecab74ec1a",
"kind": "output",
"content_schema": {
"default": 0,
"description": "Captures integer values attached to it",
"title": "Random sleep interval_2",
"type": "integer",
},
},
{
"key": "76f607b4-8761-4f96-824d-cab670bc45f5",
"kind": "output",
"content_schema": {
"default": 0,
"description": "Captures integer values attached to it",
"title": "Random sleep interval",
"type": "integer",
},
},
]
2 changes: 1 addition & 1 deletion services/api-server/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.1
0.4.2
2 changes: 1 addition & 1 deletion services/api-server/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "osparc.io web API",
"description": "osparc-simcore public web API specifications",
"version": "0.4.1",
"version": "0.4.2",
"x-logo": {
"url": "https://raw.githubusercontent.com/ITISFoundation/osparc-manual/b809d93619512eb60c827b7e769c6145758378d0/_media/osparc-logo.svg",
"altText": "osparc-simcore logo"
Expand Down
2 changes: 1 addition & 1 deletion services/api-server/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.4.1
current_version = 0.4.2
commit = True
message = services/api-server version: {current_version} → {new_version}
tag = False
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from fastapi import APIRouter

from ..core.settings import ApplicationSettings
from .routes import files, health, meta, solvers, solvers_jobs, users
from .routes import files, health, meta, solvers, solvers_jobs, studies, users


def create_router(settings: ApplicationSettings):
Expand All @@ -17,6 +17,7 @@ def create_router(settings: ApplicationSettings):
router.include_router(files.router, tags=["files"], prefix="/files")
router.include_router(solvers.router, tags=["solvers"], prefix="/solvers")
router.include_router(solvers_jobs.router, tags=["solvers"], prefix="/solvers")
router.include_router(studies.router, tags=["studies"], prefix="/studies")

# NOTE: multiple-files upload is currently disabled
# Web form to upload files at http://localhost:8000/v0/upload-form-view
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import logging
from typing import Any

from fastapi import APIRouter, Depends

from ...core.settings import BasicSettings
from ...models.schemas.studies import StudyID, StudyPort
from ..dependencies.webserver import AuthSession, get_webserver_session

logger = logging.getLogger(__name__)
router = APIRouter()
settings = BasicSettings.create_from_envs()


@router.get(
"/{study_id}/ports",
response_model=list[StudyPort],
include_in_schema=settings.API_SERVER_DEV_FEATURES_ENABLED,
)
async def list_study_ports(
study_id: StudyID,
webserver_api: AuthSession = Depends(get_webserver_session),
):
"""Lists metadata on ports of a given study
New in *version 0.5.0* (only with API_SERVER_DEV_FEATURES_ENABLED=1)
"""
project_ports: list[
dict[str, Any]
] = await webserver_api.get_project_metadata_ports(project_id=study_id)
return project_ports
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from models_library.projects import ProjectID
from models_library.projects_nodes_io import NodeID
from pydantic import Field

from .solvers import SolverPort

StudyID = ProjectID


class StudyPort(SolverPort):
key: NodeID = Field(
...,
description="port identifier name."
"Correponds to the UUID of the parameter/probe node in the study",
title="Key name",
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
from collections import deque
from contextlib import suppress
from dataclasses import dataclass
from typing import Optional
from typing import Any, Optional
from uuid import UUID

from cryptography import fernet
from fastapi import FastAPI, HTTPException
from httpx import AsyncClient, Response
from models_library.projects import ProjectID
from pydantic import ValidationError
from servicelib.aiohttp.long_running_tasks.server import TaskStatus
from starlette import status
Expand All @@ -22,7 +23,7 @@

from ..core.settings import WebServerSettings
from ..models.domain.projects import NewProjectIn, Project
from ..models.raw_data import JSON, ListAnyDict
from ..models.types import JSON, ListAnyDict
from ..utils.client_base import BaseServiceClientApi, setup_client_instance

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -53,7 +54,7 @@ def create(cls, app: FastAPI, session_cookies: dict):
)

@classmethod
def _process(cls, resp: Response) -> Optional[JSON]:
def _postprocess(cls, resp: Response) -> Optional[JSON]:
# enveloped answer
data, error = None, None

Expand Down Expand Up @@ -97,7 +98,7 @@ async def get(self, path: str) -> Optional[JSON]:
logger.exception("Failed to get %s", url)
raise HTTPException(status.HTTP_503_SERVICE_UNAVAILABLE) from err

return self._process(resp)
return self._postprocess(resp)

async def put(self, path: str, body: dict) -> Optional[JSON]:
url = path.lstrip("/")
Expand All @@ -107,7 +108,7 @@ async def put(self, path: str, body: dict) -> Optional[JSON]:
logger.exception("Failed to put %s", url)
raise HTTPException(status.HTTP_503_SERVICE_UNAVAILABLE) from err

return self._process(resp)
return self._postprocess(resp)

# PROJECTS resource ---
# TODO: error handling!
Expand All @@ -122,7 +123,7 @@ async def create_project(self, project: NewProjectIn):
), ## FIXME: REEAAAALY HACKY!
cookies=self.session_cookies,
)
data: Optional[JSON] = self._process(resp)
data: Optional[JSON] = self._postprocess(resp)
assert data # nosec
assert isinstance(data, dict) # nosec
# NOTE: /v0 is already included in the http client base_url
Expand Down Expand Up @@ -155,7 +156,7 @@ async def get_project(self, project_id: UUID) -> Project:
f"/projects/{project_id}", cookies=self.session_cookies
)

data: Optional[JSON] = self._process(resp)
data: Optional[JSON] = self._postprocess(resp)
return Project.parse_obj(data)

async def list_projects(self, solver_name: str) -> list[Project]:
Expand All @@ -166,7 +167,7 @@ async def list_projects(self, solver_name: str) -> list[Project]:
cookies=self.session_cookies,
)

data: ListAnyDict = self._process(resp) or []
data: ListAnyDict = self._postprocess(resp) or []

# FIXME: move filter to webserver API (next PR)
projects: deque[Project] = deque()
Expand All @@ -182,6 +183,22 @@ async def list_projects(self, solver_name: str) -> list[Project]:

return list(projects)

async def get_project_metadata_ports(
self, project_id: ProjectID
) -> list[dict[str, Any]]:
"""
maps GET "/projects/{study_id}/metadata/ports", unenvelopes
and returns data
"""
resp = await self.client.get(
f"/projects/{project_id}/metadata/ports",
cookies=self.session_cookies,
)
data = self._postprocess(resp)
assert data
assert isinstance(data, list)
return data


def _get_secret_key(settings: WebServerSettings):
secret_key_bytes = settings.WEBSERVER_SESSION_SECRET_KEY.get_secret_value().encode(
Expand Down Expand Up @@ -211,7 +228,7 @@ class WebserverApi(BaseServiceClientApi):

def setup(app: FastAPI, settings: Optional[WebServerSettings] = None) -> None:
if not settings:
settings = WebServerSettings()
settings = WebServerSettings.create_from_envs()

assert settings is not None # nosec

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
wait_fixed,
)

from ..models.raw_data import JSON
from ..models.types import JSON


def handle_retry(logger: logging.Logger):
Expand Down
10 changes: 5 additions & 5 deletions services/api-server/tests/unit/api_solvers/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import pytest
import respx
from fastapi import FastAPI
from pytest_simcore.helpers import catalog_data_fakers
from pytest_simcore.helpers import faker_catalog
from respx import MockRouter
from simcore_service_api_server.core.settings import ApplicationSettings

Expand Down Expand Up @@ -50,14 +50,14 @@ def mocked_catalog_service_api(
200,
json=[
# one solver
catalog_data_fakers.create_service_out(
faker_catalog.create_service_out(
key="simcore/services/comp/Foo", name="Foo"
),
# two version of the same solver
catalog_data_fakers.create_service_out(version="0.0.1"),
catalog_data_fakers.create_service_out(version="1.0.1"),
faker_catalog.create_service_out(version="0.0.1"),
faker_catalog.create_service_out(version="1.0.1"),
# not a solver
catalog_data_fakers.create_service_out(type="dynamic"),
faker_catalog.create_service_out(type="dynamic"),
],
)

Expand Down
Loading

0 comments on commit 51d6df3

Please sign in to comment.