Skip to content

Commit aa269bb

Browse files
authored
Merge branch 'master' into enh/responsive-login-page
2 parents 8ddac2b + c37d45b commit aa269bb

File tree

11 files changed

+76
-63
lines changed

11 files changed

+76
-63
lines changed

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

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -98,30 +98,20 @@ def to_db(self) -> dict:
9898

9999
@classmethod
100100
def update_preference_default_value(cls, new_default: Any) -> None:
101-
expected_type = get_type(
102-
cls.model_fields["value"] # pylint: disable=unsubscriptable-object
103-
)
101+
# pylint: disable=unsubscriptable-object
102+
expected_type = get_type(cls.model_fields["value"])
104103
detected_type = type(new_default)
105104
if expected_type != detected_type:
106105
msg = (
107106
f"Error, {cls.__name__} {expected_type=} differs from {detected_type=}"
108107
)
109108
raise TypeError(msg)
110109

111-
if (
112-
cls.model_fields["value"].default # pylint: disable=unsubscriptable-object
113-
is None
114-
):
115-
cls.model_fields[ # pylint: disable=unsubscriptable-object
116-
"value"
117-
].default_factory = lambda: new_default
110+
if cls.model_fields["value"].default is None:
111+
cls.model_fields["value"].default_factory = lambda: new_default
118112
else:
119-
cls.model_fields[ # pylint: disable=unsubscriptable-object
120-
"value"
121-
].default = new_default
122-
cls.model_fields[ # pylint: disable=unsubscriptable-object
123-
"value"
124-
].default_factory = None
113+
cls.model_fields["value"].default = new_default
114+
cls.model_fields["value"].default_factory = None
125115

126116
cls.model_rebuild(force=True)
127117

packages/models-library/src/models_library/utils/labels_annotations.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from common_library.json_serialization import json_dumps
1212

13-
LabelsAnnotationsDict: TypeAlias = dict[str, str]
13+
LabelsAnnotationsDict: TypeAlias = dict[str, str | float | bool | None]
1414

1515
# SEE https://docs.docker.com/config/labels-custom-metadata/#label-keys-and-values
1616
# "Authors of third-party tools should prefix each label key with the reverse DNS notation of a
@@ -28,7 +28,7 @@ def to_labels(
2828
"""converts config into labels annotations"""
2929

3030
# FIXME: null is loaded as 'null' string value? is that correct? json -> None upon deserialization?
31-
labels = {}
31+
labels: LabelsAnnotationsDict = {}
3232
for key, value in config.items():
3333
if trim_key_head:
3434
if isinstance(value, str):
@@ -57,7 +57,7 @@ def from_labels(
5757
for key, label in labels.items():
5858
if key.startswith(f"{prefix_key}."):
5959
try:
60-
value = json.loads(label)
60+
value = json.loads(label) # type: ignore
6161
except JSONDecodeError:
6262
value = label
6363

packages/service-integration/requirements/prod.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# installs base + tests requirements
1010
--requirement _base.txt
1111

12+
simcore-common-library @ ../common-library/
1213
simcore-models-library @ ../models-library
1314

1415
# current module

packages/service-integration/src/service_integration/cli/_compose_spec.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import rich
77
import typer
88
import yaml
9-
from models_library.utils.labels_annotations import to_labels
9+
from models_library.utils.labels_annotations import LabelsAnnotationsDict, to_labels
1010
from rich.console import Console
1111
from yarl import URL
1212

@@ -93,7 +93,7 @@ def create_docker_compose_image_spec(
9393
rich.print("No runtime config found (optional), using default.")
9494

9595
# OCI annotations (optional)
96-
extra_labels = {}
96+
extra_labels: LabelsAnnotationsDict = {}
9797
try:
9898
oci_spec = yaml.safe_load(
9999
(config_basedir / f"{OCI_LABEL_PREFIX}.yml").read_text()

packages/service-integration/src/service_integration/cli/_config.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import rich
66
import typer
77
import yaml
8+
from models_library.utils.labels_annotations import LabelsAnnotationsDict
89
from pydantic import BaseModel
910

1011
from ..compose_spec_model import ComposeSpecification
@@ -20,7 +21,7 @@
2021
)
2122

2223

23-
def _get_labels_or_raise(build_labels) -> dict[str, str]:
24+
def _get_labels_or_raise(build_labels) -> LabelsAnnotationsDict:
2425
if isinstance(build_labels, list):
2526
return dict(item.strip().split("=") for item in build_labels)
2627
if isinstance(build_labels, dict):
@@ -56,7 +57,9 @@ def _save(service_name: str, filename: Path, model: BaseModel):
5657
rich.print(f"Creating {output_path} ...", end="")
5758

5859
with output_path.open("wt") as fh:
59-
data = json.loads(model.model_dump_json(by_alias=True, exclude_none=True))
60+
data = json.loads(
61+
model.model_dump_json(by_alias=True, exclude_none=True)
62+
)
6063
yaml.safe_dump(data, fh, sort_keys=False)
6164

6265
rich.print("DONE")
@@ -68,7 +71,7 @@ def _save(service_name: str, filename: Path, model: BaseModel):
6871
service_name
6972
].build.labels: # AttributeError if build is str
7073

71-
labels: dict[str, str] = _get_labels_or_raise(build_labels)
74+
labels = _get_labels_or_raise(build_labels)
7275
meta_cfg = MetadataConfig.from_labels_annotations(labels)
7376
_save(service_name, metadata_path, meta_cfg)
7477

@@ -86,11 +89,7 @@ def _save(service_name: str, filename: Path, model: BaseModel):
8689
runtime_cfg = RuntimeConfig.from_labels_annotations(labels)
8790
_save(service_name, service_specs_path, runtime_cfg)
8891

89-
except ( # noqa: PERF203
90-
AttributeError,
91-
TypeError,
92-
ValueError,
93-
) as err:
92+
except (AttributeError, TypeError, ValueError) as err:
9493
rich.print(
9594
f"WARNING: failure producing specs for {service_name}: {err}"
9695
)

packages/service-integration/src/service_integration/compose_spec_model.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from ._compose_spec_model_autogenerated import ( # type:ignore
1111
BuildItem,
1212
ComposeSpecification,
13+
ListOrDict,
1314
Service,
1415
Volume1,
1516
)
@@ -23,6 +24,7 @@
2324
__all__: tuple[str, ...] = (
2425
"BuildItem",
2526
"ComposeSpecification",
27+
"ListOrDict",
2628
"SCHEMA_VERSION",
2729
"Service",
2830
"ServiceVolume",

packages/service-integration/src/service_integration/oci_image_spec.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
from typing import Annotated, Any
1111

1212
from models_library.basic_types import SHA1Str, VersionStr
13-
from models_library.utils.labels_annotations import from_labels, to_labels
13+
from models_library.utils.labels_annotations import (
14+
LabelsAnnotationsDict,
15+
from_labels,
16+
to_labels,
17+
)
1418
from pydantic import BaseModel, ConfigDict, Field
1519
from pydantic.networks import AnyUrl
1620

@@ -132,17 +136,16 @@ class OciImageSpecAnnotations(BaseModel):
132136

133137
@classmethod
134138
def from_labels_annotations(
135-
cls, labels: dict[str, str]
139+
cls, labels: LabelsAnnotationsDict
136140
) -> "OciImageSpecAnnotations":
137141
data = from_labels(labels, prefix_key=OCI_LABEL_PREFIX, trim_key_head=False)
138142
return cls.model_validate(data)
139143

140-
def to_labels_annotations(self) -> dict[str, str]:
141-
labels: dict[str, str] = to_labels(
144+
def to_labels_annotations(self) -> LabelsAnnotationsDict:
145+
return to_labels(
142146
self.model_dump(exclude_unset=True, by_alias=True, exclude_none=True),
143147
prefix_key=OCI_LABEL_PREFIX,
144148
)
145-
return labels
146149

147150

148151
class LabelSchemaAnnotations(BaseModel):
@@ -164,7 +167,7 @@ class LabelSchemaAnnotations(BaseModel):
164167
@classmethod
165168
def create_from_env(cls) -> "LabelSchemaAnnotations":
166169
data = {}
167-
for field_name in cls.model_fields.keys():
170+
for field_name in cls.model_fields.keys(): # noqa: SIM118
168171
if value := os.environ.get(field_name.upper()):
169172
data[field_name] = value
170173
return cls.model_validate(data)

packages/service-integration/src/service_integration/osparc_config.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,14 @@
3434
from models_library.services_types import ServiceKey
3535
from models_library.utils.labels_annotations import (
3636
OSPARC_LABEL_PREFIXES,
37+
LabelsAnnotationsDict,
3738
from_labels,
3839
to_labels,
3940
)
4041
from pydantic import (
4142
ConfigDict,
4243
NonNegativeInt,
44+
TypeAdapter,
4345
ValidationError,
4446
ValidationInfo,
4547
field_validator,
@@ -121,24 +123,21 @@ def _check_contact_in_authors(cls, v, info: ValidationInfo):
121123
def from_yaml(cls, path: Path) -> "MetadataConfig":
122124
with path.open() as fh:
123125
data = yaml_safe_load(fh)
124-
model: "MetadataConfig" = cls.model_validate(data)
125-
return model
126+
return cls.model_validate(data)
126127

127128
@classmethod
128-
def from_labels_annotations(cls, labels: dict[str, str]) -> "MetadataConfig":
129+
def from_labels_annotations(cls, labels: LabelsAnnotationsDict) -> "MetadataConfig":
129130
data = from_labels(
130131
labels, prefix_key=OSPARC_LABEL_PREFIXES[0], trim_key_head=False
131132
)
132-
model: "MetadataConfig" = cls.model_validate(data)
133-
return model
133+
return cls.model_validate(data)
134134

135-
def to_labels_annotations(self) -> dict[str, str]:
136-
labels: dict[str, str] = to_labels(
135+
def to_labels_annotations(self) -> LabelsAnnotationsDict:
136+
return to_labels(
137137
self.model_dump(exclude_unset=True, by_alias=True, exclude_none=True),
138138
prefix_key=OSPARC_LABEL_PREFIXES[0],
139139
trim_key_head=False,
140140
)
141-
return labels
142141

143142
def service_name(self) -> str:
144143
"""name used as key in the compose-spec services map"""
@@ -151,7 +150,9 @@ def image_name(self, settings: AppSettings, registry="local") -> str:
151150
if registry in "dockerhub":
152151
# dockerhub allows only one-level names -> dot it
153152
# TODO: check thisname is compatible with REGEX
154-
service_path = ServiceKey(service_path.replace("/", "."))
153+
service_path = TypeAdapter(ServiceKey).validate_python(
154+
service_path.replace("/", ".")
155+
)
155156

156157
service_version = self.version
157158
return f"{registry_prefix}{service_path}:{service_version}"
@@ -264,13 +265,12 @@ def from_yaml(cls, path: Path) -> "RuntimeConfig":
264265
return cls.model_validate(data)
265266

266267
@classmethod
267-
def from_labels_annotations(cls, labels: dict[str, str]) -> "RuntimeConfig":
268+
def from_labels_annotations(cls, labels: LabelsAnnotationsDict) -> "RuntimeConfig":
268269
data = from_labels(labels, prefix_key=OSPARC_LABEL_PREFIXES[1])
269270
return cls.model_validate(data)
270271

271-
def to_labels_annotations(self) -> dict[str, str]:
272-
labels: dict[str, str] = to_labels(
272+
def to_labels_annotations(self) -> LabelsAnnotationsDict:
273+
return to_labels(
273274
self.model_dump(exclude_unset=True, by_alias=True, exclude_none=True),
274275
prefix_key=OSPARC_LABEL_PREFIXES[1],
275276
)
276-
return labels

packages/service-integration/src/service_integration/osparc_image_specs.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
33
"""
44

5+
from typing import Any
56

7+
from models_library.utils.labels_annotations import LabelsAnnotationsDict
68
from service_integration.compose_spec_model import (
79
BuildItem,
810
ComposeSpecification,
11+
ListOrDict,
912
Service,
1013
)
1114

@@ -19,14 +22,14 @@ def create_image_spec(
1922
docker_compose_overwrite_cfg: DockerComposeOverwriteConfig,
2023
runtime_cfg: RuntimeConfig | None = None,
2124
*,
22-
extra_labels: dict[str, str] | None = None,
25+
extra_labels: LabelsAnnotationsDict | None = None,
2326
**_context
2427
) -> ComposeSpecification:
2528
"""Creates the image-spec provided the osparc-config and a given context (e.g. development)
2629
2730
- the image-spec simplifies building an image to ``docker compose build``
2831
"""
29-
labels = {**meta_cfg.to_labels_annotations()}
32+
labels = meta_cfg.to_labels_annotations()
3033
if extra_labels:
3134
labels.update(extra_labels)
3235
if runtime_cfg:
@@ -36,19 +39,26 @@ def create_image_spec(
3639

3740
assert docker_compose_overwrite_cfg.services # nosec
3841

39-
if not docker_compose_overwrite_cfg.services[service_name].build.context:
40-
docker_compose_overwrite_cfg.services[service_name].build.context = "./"
42+
build = docker_compose_overwrite_cfg.services[service_name].build
43+
assert isinstance(build, BuildItem) # nosec
44+
if not build.context:
45+
build.context = "./"
4146

42-
docker_compose_overwrite_cfg.services[service_name].build.labels = labels
47+
build.labels = ListOrDict(root=labels)
4348

44-
overwrite_options = docker_compose_overwrite_cfg.services[
45-
service_name
46-
].build.model_dump(exclude_none=True, serialize_as_any=True)
49+
overwrite_options = build.model_dump(exclude_none=True, serialize_as_any=True)
4750
build_spec = BuildItem(**overwrite_options)
4851

52+
service_kwargs: dict[str, Any] = {
53+
"image": meta_cfg.image_name(settings),
54+
"build": build_spec,
55+
}
56+
if docker_compose_overwrite_cfg.services[service_name].depends_on:
57+
service_kwargs["depends_on"] = docker_compose_overwrite_cfg.services[
58+
service_name
59+
].depends_on
60+
4961
return ComposeSpecification(
5062
version=settings.COMPOSE_VERSION,
51-
services={
52-
service_name: Service(image=meta_cfg.image_name(settings), build=build_spec)
53-
},
63+
services={service_name: Service(**service_kwargs)},
5464
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
services:
22
osparc-python-runner:
3+
depends_on:
4+
- another-service
35
build:
46
dockerfile: Dockerfile

0 commit comments

Comments
 (0)