Skip to content

Commit 0fb353a

Browse files
fix code
1 parent 079e9d4 commit 0fb353a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+327
-274
lines changed

services/api-server/src/simcore_service_api_server/api/routes/solvers.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from httpx import HTTPStatusError
88
from models_library.api_schemas_api_server.pricing_plans import ServicePricingPlanGet
99
from pydantic import ValidationError
10-
from pydantic.errors import PydanticValueError
1110

1211
from ...exceptions.service_errors_utils import DEFAULT_BACKEND_SERVICE_STATUS_CODES
1312
from ...models.basic_types import VersionStr
@@ -230,7 +229,6 @@ async def get_solver_release(
230229
IndexError,
231230
ValidationError,
232231
HTTPStatusError,
233-
PydanticValueError,
234232
) as err:
235233
raise HTTPException(
236234
status_code=status.HTTP_404_NOT_FOUND,

services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
def _compose_job_resource_name(solver_key, solver_version, job_id) -> str:
5252
"""Creates a unique resource name for solver's jobs"""
5353
return Job.compose_resource_name(
54-
parent_name=Solver.compose_resource_name(solver_key, solver_version), # type: ignore
54+
parent_name=Solver.compose_resource_name(solver_key, solver_version),
5555
job_id=job_id,
5656
)
5757

services/api-server/src/simcore_service_api_server/core/application.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def init_app(settings: ApplicationSettings | None = None) -> FastAPI:
5353
config_all_loggers(
5454
log_format_local_dev_enabled=settings.API_SERVER_LOG_FORMAT_LOCAL_DEV_ENABLED
5555
)
56-
_logger.debug("App settings:\n%s", settings.json(indent=2))
56+
_logger.debug("App settings:\n%s", settings.model_dump_json(indent=2))
5757

5858
# Labeling
5959
title = "osparc.io public API"

services/api-server/src/simcore_service_api_server/core/settings.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
from functools import cached_property
22

33
from models_library.basic_types import BootModeEnum, LogLevel
4-
from pydantic import Field, NonNegativeInt, PositiveInt, SecretStr
5-
from pydantic.class_validators import validator
4+
from pydantic import (
5+
AliasChoices,
6+
Field,
7+
NonNegativeInt,
8+
PositiveInt,
9+
SecretStr,
10+
field_validator,
11+
)
612
from settings_library.base import BaseCustomSettings
713
from settings_library.catalog import CatalogSettings
814
from settings_library.director_v2 import DirectorV2Settings
@@ -24,11 +30,14 @@ class WebServerSettings(WebServerBaseSettings, MixinSessionSettings):
2430
description="Secret key to encrypt cookies. "
2531
'TIP: python3 -c "from cryptography.fernet import *; print(Fernet.generate_key())"',
2632
min_length=44,
27-
env=["SESSION_SECRET_KEY", "WEBSERVER_SESSION_SECRET_KEY"],
33+
validation_alias=AliasChoices(
34+
"SESSION_SECRET_KEY", "WEBSERVER_SESSION_SECRET_KEY"
35+
),
2836
)
2937
WEBSERVER_SESSION_NAME: str = DEFAULT_SESSION_COOKIE_NAME
3038

31-
@validator("WEBSERVER_SESSION_SECRET_KEY")
39+
@field_validator("WEBSERVER_SESSION_SECRET_KEY")
40+
@classmethod
3241
@classmethod
3342
def check_valid_fernet_key(cls, v):
3443
return cls.do_check_valid_fernet_key(v)
@@ -41,21 +50,25 @@ class BasicSettings(BaseCustomSettings, MixinLoggingSettings):
4150
# DEVELOPMENT
4251
API_SERVER_DEV_FEATURES_ENABLED: bool = Field(
4352
default=False,
44-
env=["API_SERVER_DEV_FEATURES_ENABLED", "FAKE_API_SERVER_ENABLED"],
53+
validation_alias=AliasChoices(
54+
"API_SERVER_DEV_FEATURES_ENABLED", "FAKE_API_SERVER_ENABLED"
55+
),
4556
)
4657

4758
# LOGGING
4859
LOG_LEVEL: LogLevel = Field(
4960
default=LogLevel.INFO.value,
50-
env=["API_SERVER_LOGLEVEL", "LOG_LEVEL", "LOGLEVEL"],
61+
validation_alias=AliasChoices("API_SERVER_LOGLEVEL", "LOG_LEVEL", "LOGLEVEL"),
5162
)
5263
API_SERVER_LOG_FORMAT_LOCAL_DEV_ENABLED: bool = Field(
5364
default=False,
54-
env=["API_SERVER_LOG_FORMAT_LOCAL_DEV_ENABLED", "LOG_FORMAT_LOCAL_DEV_ENABLED"],
65+
validation_alias=AliasChoices(
66+
"API_SERVER_LOG_FORMAT_LOCAL_DEV_ENABLED", "LOG_FORMAT_LOCAL_DEV_ENABLED"
67+
),
5568
description="Enables local development log format. WARNING: make sure it is disabled if you want to have structured logs!",
5669
)
5770

58-
@validator("LOG_LEVEL", pre=True)
71+
@field_validator("LOG_LEVEL", mode="before")
5972
@classmethod
6073
def _validate_loglevel(cls, value) -> str:
6174
log_level: str = cls.validate_log_level(value)
@@ -66,18 +79,27 @@ class ApplicationSettings(BasicSettings):
6679
# DOCKER BOOT
6780
SC_BOOT_MODE: BootModeEnum | None
6881

69-
API_SERVER_POSTGRES: PostgresSettings | None = Field(auto_default_from_env=True)
82+
API_SERVER_POSTGRES: PostgresSettings | None = Field(
83+
json_schema_extra={"auto_default_from_env": True}
84+
)
7085

7186
API_SERVER_RABBITMQ: RabbitSettings | None = Field(
72-
auto_default_from_env=True, description="settings for service/rabbitmq"
87+
json_schema_extra={"auto_default_from_env": True},
88+
description="settings for service/rabbitmq",
7389
)
7490

7591
# SERVICES with http API
76-
API_SERVER_WEBSERVER: WebServerSettings | None = Field(auto_default_from_env=True)
77-
API_SERVER_CATALOG: CatalogSettings | None = Field(auto_default_from_env=True)
78-
API_SERVER_STORAGE: StorageSettings | None = Field(auto_default_from_env=True)
92+
API_SERVER_WEBSERVER: WebServerSettings | None = Field(
93+
json_schema_extra={"auto_default_from_env": True}
94+
)
95+
API_SERVER_CATALOG: CatalogSettings | None = Field(
96+
json_schema_extra={"auto_default_from_env": True}
97+
)
98+
API_SERVER_STORAGE: StorageSettings | None = Field(
99+
json_schema_extra={"auto_default_from_env": True}
100+
)
79101
API_SERVER_DIRECTOR_V2: DirectorV2Settings | None = Field(
80-
auto_default_from_env=True
102+
json_schema_extra={"auto_default_from_env": True}
81103
)
82104
API_SERVER_LOG_CHECK_TIMEOUT_SECONDS: NonNegativeInt = 3 * 60
83105
API_SERVER_PROMETHEUS_INSTRUMENTATION_ENABLED: bool = True

services/api-server/src/simcore_service_api_server/exceptions/_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Any
22

3-
from models_library.errors_classes import OsparcErrorMixin
3+
from common_library.errors_classes import OsparcErrorMixin
44

55

66
class ApiServerBaseError(OsparcErrorMixin, Exception):

services/api-server/src/simcore_service_api_server/models/api_resources.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import re
22
import urllib.parse
3-
from typing import Any
3+
from typing import Annotated, Any, TypeAlias
44

5-
from pydantic import BaseModel, Field
6-
from pydantic.types import ConstrainedStr
5+
from pydantic import BaseModel, Field, TypeAdapter
6+
from pydantic.types import StringConstraints
77

88
# RESOURCE NAMES https://cloud.google.com/apis/design/resource_names
99
#
@@ -30,18 +30,16 @@
3030
_RELATIVE_RESOURCE_NAME_RE = r"^([^\s/]+/?){1,10}$"
3131

3232

33-
class RelativeResourceName(ConstrainedStr):
34-
regex = re.compile(_RELATIVE_RESOURCE_NAME_RE)
35-
36-
class Config:
37-
frozen = True
33+
RelativeResourceName: TypeAlias = Annotated[
34+
str, StringConstraints(pattern=_RELATIVE_RESOURCE_NAME_RE)
35+
]
3836

3937

4038
# NOTE: we quote parts in a single resource_name and unquote when split
4139

4240

4341
def parse_last_resource_id(resource_name: RelativeResourceName) -> str:
44-
if match := RelativeResourceName.regex.match(resource_name):
42+
if match := re.match(_RELATIVE_RESOURCE_NAME_RE, resource_name):
4543
last_quoted_part = match.group(1)
4644
return urllib.parse.unquote_plus(last_quoted_part)
4745
msg = f"Invalid '{resource_name=}' does not match RelativeResourceName"
@@ -53,7 +51,7 @@ def compose_resource_name(*collection_or_resource_ids) -> RelativeResourceName:
5351
urllib.parse.quote_plus(f"{_id}".lstrip("/"))
5452
for _id in collection_or_resource_ids
5553
]
56-
return RelativeResourceName("/".join(quoted_parts))
54+
return TypeAdapter(RelativeResourceName).validate_python("/".join(quoted_parts))
5755

5856

5957
def split_resource_name(resource_name: RelativeResourceName) -> list[str]:
@@ -67,10 +65,12 @@ def split_resource_name(resource_name: RelativeResourceName) -> list[str]:
6765
# Resource IDs must be clearly documented whether they are assigned by the client, the server, or either
6866
#
6967
class BaseResource(BaseModel):
70-
name: RelativeResourceName = Field(None, example="solvers/isolve/releases/1.2.3")
71-
id: Any = Field(None, description="Resource ID", example="1.2.3") # noqa: A003
68+
name: RelativeResourceName = Field(None, examples=["solvers/isolve/releases/1.2.3"])
69+
id: Any = Field(None, description="Resource ID", examples=["1.2.3"]) # noqa: A003
7270

7371

7472
class BaseCollection(BaseModel):
75-
name: RelativeResourceName = Field(None, example="solvers/isolve/releases")
76-
id: Any = Field(None, description="Collection ID", example="releases") # noqa: A003
73+
name: RelativeResourceName = Field(None, examples=["solvers/isolve/releases"])
74+
id: Any = Field(
75+
None, description="Collection ID", examples=["releases"]
76+
) # noqa: A003

services/api-server/src/simcore_service_api_server/models/basic_types.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
import re
1+
from typing import Annotated, TypeAlias
22

33
from fastapi.responses import StreamingResponse
44
from models_library.basic_regex import SIMPLE_VERSION_RE
5-
from pydantic import ConstrainedStr
5+
from pydantic import StringConstraints
66

7+
VersionStr: TypeAlias = Annotated[
8+
str, StringConstraints(strip_whitespace=True, pattern=SIMPLE_VERSION_RE)
9+
]
710

8-
class VersionStr(ConstrainedStr):
9-
strip_whitespace = True
10-
regex = re.compile(SIMPLE_VERSION_RE)
11-
12-
13-
class FileNameStr(ConstrainedStr):
14-
strip_whitespace = True
11+
FileNameStr: TypeAlias = Annotated[str, StringConstraints(strip_whitespace=True)]
1512

1613

1714
class LogStreamingResponse(StreamingResponse):

services/api-server/src/simcore_service_api_server/models/pagination.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"""
88

99
from collections.abc import Sequence
10-
from typing import Any, ClassVar, Generic, TypeAlias, TypeVar
10+
from typing import Generic, TypeAlias, TypeVar
1111

1212
from fastapi_pagination.limit_offset import LimitOffsetParams
1313
from fastapi_pagination.links.limit_offset import (
@@ -18,8 +18,7 @@
1818
MAXIMUM_NUMBER_OF_ITEMS_PER_PAGE,
1919
)
2020
from models_library.utils.pydantic_tools_extension import FieldNotRequired
21-
from pydantic import Field, NonNegativeInt, validator
22-
from pydantic.generics import GenericModel
21+
from pydantic import BaseModel, ConfigDict, Field, NonNegativeInt, field_validator
2322

2423
T = TypeVar("T")
2524

@@ -35,7 +34,7 @@
3534
PaginationParams: TypeAlias = LimitOffsetParams
3635

3736

38-
class OnePage(GenericModel, Generic[T]):
37+
class OnePage(BaseModel, Generic[T]):
3938
"""
4039
A single page is used to envelope a small sequence that does not require
4140
pagination
@@ -47,7 +46,7 @@ class OnePage(GenericModel, Generic[T]):
4746
items: Sequence[T]
4847
total: NonNegativeInt = FieldNotRequired()
4948

50-
@validator("total", pre=True)
49+
@field_validator("total", mode="before")
5150
@classmethod
5251
def check_total(cls, v, values):
5352
items = values["items"]
@@ -60,9 +59,9 @@ def check_total(cls, v, values):
6059

6160
return v
6261

63-
class Config:
64-
frozen = True
65-
schema_extra: ClassVar[dict[str, Any]] = {
62+
model_config = ConfigDict(
63+
frozen=True,
64+
json_schema_extra={
6665
"examples": [
6766
{
6867
"total": 1,
@@ -72,7 +71,8 @@ class Config:
7271
"items": ["one"],
7372
},
7473
],
75-
}
74+
},
75+
)
7676

7777

7878
__all__: tuple[str, ...] = (
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import Any, ClassVar
1+
from typing import Any
22

3-
from pydantic import BaseModel
3+
from pydantic import BaseModel, ConfigDict
44

55

66
class ErrorGet(BaseModel):
@@ -11,12 +11,13 @@ class ErrorGet(BaseModel):
1111
# - https://github.com/ITISFoundation/osparc-simcore/issues/2446
1212
errors: list[Any]
1313

14-
class Config:
15-
schema_extra: ClassVar[dict[str, Any]] = {
14+
model_config = ConfigDict(
15+
json_schema_extra={
1616
"example": {
1717
"errors": [
1818
"some error message",
1919
"another error message",
2020
]
2121
}
2222
}
23+
)

0 commit comments

Comments
 (0)