Skip to content

Commit bdfd51e

Browse files
Merge pull request #1 from GitHK/upgrade-dynamic-sceduler
Adding fixes for dynamic-scheduler
2 parents 6e76143 + a83e3ff commit bdfd51e

File tree

26 files changed

+157
-55
lines changed

26 files changed

+157
-55
lines changed

packages/common-library/requirements/_test.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
coverage
1212
faker
13+
pydantic-settings
1314
pytest
1415
pytest-asyncio
1516
pytest-cov

packages/common-library/requirements/_test.txt

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
annotated-types==0.7.0
2+
# via
3+
# -c requirements/_base.txt
4+
# pydantic
15
coverage==7.6.1
26
# via
37
# -r requirements/_test.in
48
# pytest-cov
5-
faker==30.1.0
9+
faker==30.3.0
610
# via -r requirements/_test.in
711
icdiff==2.0.7
812
# via pytest-icdiff
@@ -16,6 +20,17 @@ pluggy==1.5.0
1620
# via pytest
1721
pprintpp==0.4.0
1822
# via pytest-icdiff
23+
pydantic==2.9.2
24+
# via
25+
# -c requirements/../../../requirements/constraints.txt
26+
# -c requirements/_base.txt
27+
# pydantic-settings
28+
pydantic-core==2.23.4
29+
# via
30+
# -c requirements/_base.txt
31+
# pydantic
32+
pydantic-settings==2.5.2
33+
# via -r requirements/_test.in
1934
pytest==8.3.3
2035
# via
2136
# -r requirements/_test.in
@@ -44,7 +59,9 @@ pytest-sugar==1.0.0
4459
python-dateutil==2.9.0.post0
4560
# via faker
4661
python-dotenv==1.0.1
47-
# via -r requirements/_test.in
62+
# via
63+
# -r requirements/_test.in
64+
# pydantic-settings
4865
six==1.16.0
4966
# via python-dateutil
5067
termcolor==2.5.0
@@ -53,3 +70,5 @@ typing-extensions==4.12.2
5370
# via
5471
# -c requirements/_base.txt
5572
# faker
73+
# pydantic
74+
# pydantic-core

packages/common-library/requirements/_tools.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
astroid==3.3.5
22
# via pylint
3-
black==24.8.0
3+
black==24.10.0
44
# via -r requirements/../../../requirements/devenv.txt
55
build==1.2.2.post1
66
# via pip-tools
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
from typing import Annotated, TypeAlias
2+
23
from pydantic import AfterValidator, AnyHttpUrl
34

45

5-
AnyHttpUrlLegacy: TypeAlias = Annotated[str, AnyHttpUrl, AfterValidator(lambda u: u.rstrip("/"))]
6+
def _strip_last_slash(url: str) -> str:
7+
return url.rstrip("/")
8+
9+
10+
AnyHttpUrlLegacy: TypeAlias = Annotated[
11+
str, AnyHttpUrl, AfterValidator(_strip_last_slash)
12+
]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import datetime
2+
3+
from pydantic import field_validator
4+
5+
6+
def _get_float_string_as_seconds(
7+
v: datetime.timedelta | str | float,
8+
) -> datetime.timedelta | float | str:
9+
if isinstance(v, str):
10+
try:
11+
return float(v)
12+
except ValueError:
13+
# returns format like "1:00:00"
14+
return v
15+
return v
16+
17+
18+
def validate_timedelta_in_legacy_mode(field: str):
19+
"""Transforms a float/int number into a valid datetime as it used to work in the past"""
20+
return field_validator(field, mode="before")(_get_float_string_as_seconds)

packages/common-library/src/common_library/serialization.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from datetime import timedelta
12
from typing import Any
23

34
from common_library.pydantic_fields_extension import get_type
@@ -15,6 +16,9 @@ def model_dump_with_secrets(
1516

1617
field_data = data[field_name]
1718

19+
if isinstance(field_data, timedelta):
20+
data[field_name] = field_data.total_seconds()
21+
1822
if isinstance(field_data, SecretStr):
1923
if show_secrets:
2024
data[field_name] = field_data.get_secret_value()

packages/common-library/tests/test_errors_classes.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ class B12(B1, ValueError):
3838

3939
def test_error_codes_and_msg_template():
4040
class MyBaseError(OsparcErrorMixin, Exception):
41-
def __init__(self, **ctx: Any) -> None:
42-
super().__init__(**ctx) # Do not forget this for base exceptions!
41+
pass
4342

4443
class MyValueError(MyBaseError, ValueError):
4544
msg_template = "Wrong value {value}"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from datetime import timedelta
2+
3+
import pytest
4+
from common_library.pydantic_settings_validators import (
5+
validate_timedelta_in_legacy_mode,
6+
)
7+
from faker import Faker
8+
from pydantic import Field
9+
from pydantic_settings import BaseSettings, SettingsConfigDict
10+
from pytest_simcore.helpers.monkeypatch_envs import setenvs_from_dict
11+
12+
13+
def test_validate_timedelta_in_legacy_mode(
14+
monkeypatch: pytest.MonkeyPatch, faker: Faker
15+
):
16+
class Settings(BaseSettings):
17+
APP_NAME: str
18+
REQUEST_TIMEOUT: timedelta = Field(default=timedelta(seconds=40))
19+
20+
_legacy_parsing_request_timeout = validate_timedelta_in_legacy_mode(
21+
"REQUEST_TIMEOUT"
22+
)
23+
24+
model_config = SettingsConfigDict()
25+
26+
app_name = faker.pystr()
27+
env_vars: dict[str, str | bool] = {"APP_NAME": app_name}
28+
29+
# without timedelta
30+
setenvs_from_dict(monkeypatch, env_vars)
31+
settings = Settings()
32+
print(settings.model_dump())
33+
assert app_name == settings.APP_NAME
34+
assert timedelta(seconds=40) == settings.REQUEST_TIMEOUT
35+
36+
# with timedelta in seconds
37+
env_vars["REQUEST_TIMEOUT"] = "5555"
38+
setenvs_from_dict(monkeypatch, env_vars)
39+
settings = Settings()
40+
print(settings.model_dump())
41+
assert app_name == settings.APP_NAME
42+
assert timedelta(seconds=5555) == settings.REQUEST_TIMEOUT

packages/models-library/src/models_library/api_schemas_directorv2/dynamic_services_service.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class CommonServiceDetails(BaseModel):
3333

3434

3535
class ServiceDetails(CommonServiceDetails):
36-
basepath: Path = Field(
36+
basepath: Path | None = Field(
3737
default=None,
3838
description="predefined path where the dynamic service should be served. If empty, the service shall use the root endpoint.",
3939
alias="service_basepath",
@@ -68,7 +68,7 @@ class RunningDynamicServiceDetails(ServiceDetails):
6868
internal_port: PortInt = Field(
6969
..., description="the service swarm internal port", alias="service_port"
7070
)
71-
published_port: PortInt = Field(
71+
published_port: PortInt | None = Field(
7272
default=None,
7373
description="the service swarm published port if any",
7474
deprecated=True,

packages/models-library/src/models_library/api_schemas_webserver/projects_nodes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class NodeGet(OutputSchema):
103103
"service_basepath": "/x/E1O2E-LAH",
104104
"service_state": "pending",
105105
"service_message": "no suitable node (insufficient resources on 1 node)",
106-
"user_id": 123,
106+
"user_id": "123",
107107
}
108108
}
109109
)

0 commit comments

Comments
 (0)