Skip to content

Commit ec161bf

Browse files
Merge pull request #55 from biosimulations/simple-sedml-endpoint
Simple sedml endpoint
2 parents b017a63 + bdf52ee commit ec161bf

30 files changed

Lines changed: 4719 additions & 297 deletions

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.12
1+
3.13

Dockerfile-api

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ARG APP_UID=16997
66

77
RUN apt-get update && \
88
apt-get install -y --no-install-recommends \
9-
openssh-client && \
9+
openssh-client libexpat1 && \
1010
rm -rf /var/lib/apt/lists/*
1111

1212
# Set environment variables

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ install: ## Install the virtual environment and install the pre-commit hooks
44
@uv sync
55
@uv run pre-commit install
66

7+
.PHONY: run
8+
run: ##
9+
@echo "🚀 Run local server."
10+
@uvicorn compose_api.api.main:app --host 0.0.0.0 --port 8000 --reload
11+
712
.PHONY: check
813
check: ## Run code quality tools.
914
@echo "🚀 Checking lock file consistency with 'pyproject.toml'"
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
from http import HTTPStatus
2+
from typing import Any, Optional, Union, cast
3+
4+
import httpx
5+
6+
from ...client import AuthenticatedClient, Client
7+
from ...types import Response, UNSET
8+
from ... import errors
9+
10+
from ...models.body_execute_sedml import BodyExecuteSedml
11+
from ...models.http_validation_error import HTTPValidationError
12+
from ...models.simulation_experiment import SimulationExperiment
13+
from ...models.tool_suites import ToolSuites
14+
from typing import cast
15+
16+
17+
def _get_kwargs(
18+
*,
19+
body: BodyExecuteSedml,
20+
tool_suite: ToolSuites,
21+
) -> dict[str, Any]:
22+
headers: dict[str, Any] = {}
23+
24+
params: dict[str, Any] = {}
25+
26+
json_tool_suite = tool_suite.value
27+
params["tool_suite"] = json_tool_suite
28+
29+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
30+
31+
_kwargs: dict[str, Any] = {
32+
"method": "post",
33+
"url": "/core/simulation/execute/sedml",
34+
"params": params,
35+
}
36+
37+
_kwargs["files"] = body.to_multipart()
38+
39+
_kwargs["headers"] = headers
40+
return _kwargs
41+
42+
43+
def _parse_response(
44+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
45+
) -> Optional[Union[HTTPValidationError, SimulationExperiment]]:
46+
if response.status_code == 200:
47+
response_200 = SimulationExperiment.from_dict(response.json())
48+
49+
return response_200
50+
if response.status_code == 422:
51+
response_422 = HTTPValidationError.from_dict(response.json())
52+
53+
return response_422
54+
if client.raise_on_unexpected_status:
55+
raise errors.UnexpectedStatus(response.status_code, response.content)
56+
else:
57+
return None
58+
59+
60+
def _build_response(
61+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
62+
) -> Response[Union[HTTPValidationError, SimulationExperiment]]:
63+
return Response(
64+
status_code=HTTPStatus(response.status_code),
65+
content=response.content,
66+
headers=response.headers,
67+
parsed=_parse_response(client=client, response=response),
68+
)
69+
70+
71+
def sync_detailed(
72+
*,
73+
client: Union[AuthenticatedClient, Client],
74+
body: BodyExecuteSedml,
75+
tool_suite: ToolSuites,
76+
) -> Response[Union[HTTPValidationError, SimulationExperiment]]:
77+
"""Execute sedml
78+
79+
Args:
80+
tool_suite (ToolSuites):
81+
body (BodyExecuteSedml):
82+
83+
Raises:
84+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
85+
httpx.TimeoutException: If the request takes longer than Client.timeout.
86+
87+
Returns:
88+
Response[Union[HTTPValidationError, SimulationExperiment]]
89+
"""
90+
91+
kwargs = _get_kwargs(
92+
body=body,
93+
tool_suite=tool_suite,
94+
)
95+
96+
response = client.get_httpx_client().request(
97+
**kwargs,
98+
)
99+
100+
return _build_response(client=client, response=response)
101+
102+
103+
def sync(
104+
*,
105+
client: Union[AuthenticatedClient, Client],
106+
body: BodyExecuteSedml,
107+
tool_suite: ToolSuites,
108+
) -> Optional[Union[HTTPValidationError, SimulationExperiment]]:
109+
"""Execute sedml
110+
111+
Args:
112+
tool_suite (ToolSuites):
113+
body (BodyExecuteSedml):
114+
115+
Raises:
116+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
117+
httpx.TimeoutException: If the request takes longer than Client.timeout.
118+
119+
Returns:
120+
Union[HTTPValidationError, SimulationExperiment]
121+
"""
122+
123+
return sync_detailed(
124+
client=client,
125+
body=body,
126+
tool_suite=tool_suite,
127+
).parsed
128+
129+
130+
async def asyncio_detailed(
131+
*,
132+
client: Union[AuthenticatedClient, Client],
133+
body: BodyExecuteSedml,
134+
tool_suite: ToolSuites,
135+
) -> Response[Union[HTTPValidationError, SimulationExperiment]]:
136+
"""Execute sedml
137+
138+
Args:
139+
tool_suite (ToolSuites):
140+
body (BodyExecuteSedml):
141+
142+
Raises:
143+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
144+
httpx.TimeoutException: If the request takes longer than Client.timeout.
145+
146+
Returns:
147+
Response[Union[HTTPValidationError, SimulationExperiment]]
148+
"""
149+
150+
kwargs = _get_kwargs(
151+
body=body,
152+
tool_suite=tool_suite,
153+
)
154+
155+
response = await client.get_async_httpx_client().request(**kwargs)
156+
157+
return _build_response(client=client, response=response)
158+
159+
160+
async def asyncio(
161+
*,
162+
client: Union[AuthenticatedClient, Client],
163+
body: BodyExecuteSedml,
164+
tool_suite: ToolSuites,
165+
) -> Optional[Union[HTTPValidationError, SimulationExperiment]]:
166+
"""Execute sedml
167+
168+
Args:
169+
tool_suite (ToolSuites):
170+
body (BodyExecuteSedml):
171+
172+
Raises:
173+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
174+
httpx.TimeoutException: If the request takes longer than Client.timeout.
175+
176+
Returns:
177+
Union[HTTPValidationError, SimulationExperiment]
178+
"""
179+
180+
return (
181+
await asyncio_detailed(
182+
client=client,
183+
body=body,
184+
tool_suite=tool_suite,
185+
)
186+
).parsed

compose_api/api/client/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .bi_graph_process import BiGraphProcess
55
from .bi_graph_step import BiGraphStep
66
from .body_analyze_simulation_omex import BodyAnalyzeSimulationOmex
7+
from .body_execute_sedml import BodyExecuteSedml
78
from .body_run_copasi import BodyRunCopasi
89
from .body_run_simulation import BodyRunSimulation
910
from .body_run_tellurium import BodyRunTellurium
@@ -19,13 +20,15 @@
1920
from .simulation_experiment import SimulationExperiment
2021
from .simulation_experiment_metadata import SimulationExperimentMetadata
2122
from .simulator_version import SimulatorVersion
23+
from .tool_suites import ToolSuites
2224
from .validation_error import ValidationError
2325

2426
__all__ = (
2527
"BiGraphComputeType",
2628
"BiGraphProcess",
2729
"BiGraphStep",
2830
"BodyAnalyzeSimulationOmex",
31+
"BodyExecuteSedml",
2932
"BodyRunCopasi",
3033
"BodyRunSimulation",
3134
"BodyRunTellurium",
@@ -41,5 +44,6 @@
4144
"SimulationExperiment",
4245
"SimulationExperimentMetadata",
4346
"SimulatorVersion",
47+
"ToolSuites",
4448
"ValidationError",
4549
)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from collections.abc import Mapping
2+
from typing import Any, TypeVar, Optional, BinaryIO, TextIO, TYPE_CHECKING, Generator
3+
4+
from attrs import define as _attrs_define
5+
from attrs import field as _attrs_field
6+
import json
7+
from .. import types
8+
9+
from ..types import UNSET, Unset
10+
11+
from ..types import File, FileTypes
12+
from io import BytesIO
13+
14+
15+
T = TypeVar("T", bound="BodyExecuteSedml")
16+
17+
18+
@_attrs_define
19+
class BodyExecuteSedml:
20+
"""
21+
Attributes:
22+
uploaded_file (File):
23+
"""
24+
25+
uploaded_file: File
26+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
27+
28+
def to_dict(self) -> dict[str, Any]:
29+
uploaded_file = self.uploaded_file.to_tuple()
30+
31+
field_dict: dict[str, Any] = {}
32+
field_dict.update(self.additional_properties)
33+
field_dict.update({
34+
"uploaded_file": uploaded_file,
35+
})
36+
37+
return field_dict
38+
39+
def to_multipart(self) -> types.RequestFiles:
40+
files: types.RequestFiles = []
41+
42+
files.append(("uploaded_file", self.uploaded_file.to_tuple()))
43+
44+
for prop_name, prop in self.additional_properties.items():
45+
files.append((prop_name, (None, str(prop).encode(), "text/plain")))
46+
47+
return files
48+
49+
@classmethod
50+
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
51+
d = dict(src_dict)
52+
uploaded_file = File(payload=BytesIO(d.pop("uploaded_file")))
53+
54+
body_execute_sedml = cls(
55+
uploaded_file=uploaded_file,
56+
)
57+
58+
body_execute_sedml.additional_properties = d
59+
return body_execute_sedml
60+
61+
@property
62+
def additional_keys(self) -> list[str]:
63+
return list(self.additional_properties.keys())
64+
65+
def __getitem__(self, key: str) -> Any:
66+
return self.additional_properties[key]
67+
68+
def __setitem__(self, key: str, value: Any) -> None:
69+
self.additional_properties[key] = value
70+
71+
def __delitem__(self, key: str) -> None:
72+
del self.additional_properties[key]
73+
74+
def __contains__(self, key: str) -> bool:
75+
return key in self.additional_properties

compose_api/api/client/models/registered_package.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
from typing import cast
1111

1212
if TYPE_CHECKING:
13-
from ..models.bi_graph_step import BiGraphStep
1413
from ..models.bi_graph_process import BiGraphProcess
14+
from ..models.bi_graph_step import BiGraphStep
1515

1616

1717
T = TypeVar("T", bound="RegisteredPackage")
@@ -36,8 +36,8 @@ class RegisteredPackage:
3636
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
3737

3838
def to_dict(self) -> dict[str, Any]:
39-
from ..models.bi_graph_step import BiGraphStep
4039
from ..models.bi_graph_process import BiGraphProcess
40+
from ..models.bi_graph_step import BiGraphStep
4141

4242
database_id = self.database_id
4343

@@ -69,8 +69,8 @@ def to_dict(self) -> dict[str, Any]:
6969

7070
@classmethod
7171
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
72-
from ..models.bi_graph_step import BiGraphStep
7372
from ..models.bi_graph_process import BiGraphProcess
73+
from ..models.bi_graph_step import BiGraphStep
7474

7575
d = dict(src_dict)
7676
database_id = d.pop("database_id")

compose_api/api/client/models/simulator_version.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
import datetime
1515

1616
if TYPE_CHECKING:
17-
from ..models.containerization_file_repr import ContainerizationFileRepr
1817
from ..models.registered_package import RegisteredPackage
18+
from ..models.containerization_file_repr import ContainerizationFileRepr
1919

2020

2121
T = TypeVar("T", bound="SimulatorVersion")
@@ -40,8 +40,8 @@ class SimulatorVersion:
4040
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
4141

4242
def to_dict(self) -> dict[str, Any]:
43-
from ..models.containerization_file_repr import ContainerizationFileRepr
4443
from ..models.registered_package import RegisteredPackage
44+
from ..models.containerization_file_repr import ContainerizationFileRepr
4545

4646
singularity_def = self.singularity_def.to_dict()
4747

@@ -82,8 +82,8 @@ def to_dict(self) -> dict[str, Any]:
8282

8383
@classmethod
8484
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
85-
from ..models.containerization_file_repr import ContainerizationFileRepr
8685
from ..models.registered_package import RegisteredPackage
86+
from ..models.containerization_file_repr import ContainerizationFileRepr
8787

8888
d = dict(src_dict)
8989
singularity_def = ContainerizationFileRepr.from_dict(d.pop("singularity_def"))
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from enum import Enum
2+
3+
4+
class ToolSuites(str, Enum):
5+
BASICO = "basico"
6+
TELLURIUM = "tellurium"
7+
8+
def __str__(self) -> str:
9+
return str(self.value)

0 commit comments

Comments
 (0)