Skip to content

Commit 1bef5ad

Browse files
fix code
1 parent d91dd1b commit 1bef5ad

File tree

142 files changed

+917
-816
lines changed

Some content is hidden

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

142 files changed

+917
-816
lines changed

services/web/server/src/simcore_service_webserver/announcements/_models.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from datetime import datetime
2-
from typing import Any, ClassVar, Literal
2+
from typing import Literal
33

44
import arrow
5-
from pydantic import BaseModel, validator
5+
from pydantic import BaseModel, ConfigDict, field_validator
66

77

88
# NOTE: this model is used for BOTH
@@ -18,7 +18,7 @@ class Announcement(BaseModel):
1818
link: str
1919
widgets: list[Literal["login", "ribbon", "user-menu"]]
2020

21-
@validator("end")
21+
@field_validator("end")
2222
@classmethod
2323
def check_start_before_end(cls, v, values):
2424
if start := values.get("start"):
@@ -31,8 +31,8 @@ def check_start_before_end(cls, v, values):
3131
def expired(self) -> bool:
3232
return self.end <= arrow.utcnow().datetime
3333

34-
class Config:
35-
schema_extra: ClassVar[dict[str, Any]] = {
34+
model_config = ConfigDict(
35+
json_schema_extra={
3636
"examples": [
3737
{
3838
"id": "Student_Competition_2023",
@@ -56,3 +56,4 @@ class Config:
5656
},
5757
]
5858
}
59+
)

services/web/server/src/simcore_service_webserver/api_keys/_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ async def get_api_key(
7070
) -> ApiKeyGet | None:
7171
repo = ApiKeyRepo.create_from_app(app)
7272
row = await repo.get(display_name=name, user_id=user_id, product_name=product_name)
73-
return ApiKeyGet.parse_obj(row) if row else None
73+
return ApiKeyGet.model_validate(row) if row else None
7474

7575

7676
async def get_or_create_api_key(

services/web/server/src/simcore_service_webserver/api_keys/_handlers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class _RequestContext(RequestParams):
3131
@login_required
3232
@permission_required("user.apikey.*")
3333
async def list_api_keys(request: web.Request):
34-
req_ctx = _RequestContext.parse_obj(request)
34+
req_ctx = _RequestContext.model_validate(request)
3535
api_keys_names = await _api.list_api_keys(
3636
request.app,
3737
user_id=req_ctx.user_id,
@@ -44,7 +44,7 @@ async def list_api_keys(request: web.Request):
4444
@login_required
4545
@permission_required("user.apikey.*")
4646
async def create_api_key(request: web.Request):
47-
req_ctx = _RequestContext.parse_obj(request)
47+
req_ctx = _RequestContext.model_validate(request)
4848
new = await parse_request_body_as(ApiKeyCreate, request)
4949
try:
5050
data = await _api.create_api_key(
@@ -66,7 +66,7 @@ async def create_api_key(request: web.Request):
6666
@login_required
6767
@permission_required("user.apikey.*")
6868
async def delete_api_key(request: web.Request):
69-
req_ctx = _RequestContext.parse_obj(request)
69+
req_ctx = _RequestContext.model_validate(request)
7070

7171
# NOTE: SEE https://github.com/ITISFoundation/osparc-simcore/issues/4920
7272
body = await request.json()

services/web/server/src/simcore_service_webserver/application_settings.py

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import Any, Final
44

55
from aiohttp import web
6+
from common_library.pydantic_fields_extension import is_nullable
67
from models_library.basic_types import (
78
BootModeEnum,
89
BuildTargetEnum,
@@ -11,8 +12,15 @@
1112
VersionTag,
1213
)
1314
from models_library.utils.change_case import snake_to_camel
14-
from pydantic import AnyHttpUrl, parse_obj_as, root_validator, validator
15-
from pydantic.fields import Field, ModelField
15+
from pydantic import (
16+
AliasChoices,
17+
AnyHttpUrl,
18+
TypeAdapter,
19+
ValidationInfo,
20+
field_validator,
21+
model_validator,
22+
)
23+
from pydantic.fields import Field
1624
from pydantic.types import PositiveInt
1725
from settings_library.base import BaseCustomSettings
1826
from settings_library.email import SMTPSettings
@@ -53,7 +61,7 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
5361
# CODE STATICS ---------------------------------------------------------
5462
API_VERSION: str = API_VERSION
5563
APP_NAME: str = APP_NAME
56-
API_VTAG: VersionTag = parse_obj_as(VersionTag, API_VTAG)
64+
API_VTAG: VersionTag = TypeAdapter(VersionTag).validate_python(API_VTAG)
5765

5866
# IMAGE BUILDTIME ------------------------------------------------------
5967
# @Makefile
@@ -105,12 +113,14 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
105113
)
106114
WEBSERVER_LOGLEVEL: LogLevel = Field(
107115
default=LogLevel.WARNING.value,
108-
env=["WEBSERVER_LOGLEVEL", "LOG_LEVEL", "LOGLEVEL"],
116+
validation_alias=AliasChoices("WEBSERVER_LOGLEVEL", "LOG_LEVEL", "LOGLEVEL"),
109117
# NOTE: suffix '_LOGLEVEL' is used overall
110118
)
111119
WEBSERVER_LOG_FORMAT_LOCAL_DEV_ENABLED: bool = Field(
112120
default=False,
113-
env=["WEBSERVER_LOG_FORMAT_LOCAL_DEV_ENABLED", "LOG_FORMAT_LOCAL_DEV_ENABLED"],
121+
validation_alias=AliasChoices(
122+
"WEBSERVER_LOG_FORMAT_LOCAL_DEV_ENABLED", "LOG_FORMAT_LOCAL_DEV_ENABLED"
123+
),
114124
description="Enables local development log format. WARNING: make sure it is disabled if you want to have structured logs!",
115125
)
116126
# TODO: find a better name!?
@@ -119,100 +129,117 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
119129
description="host name to serve within the container."
120130
"NOTE that this different from WEBSERVER_HOST env which is the host seen outside the container",
121131
)
122-
WEBSERVER_HOST: str | None = Field(None, env=["WEBSERVER_HOST", "HOST", "HOSTNAME"])
123-
WEBSERVER_PORT: PortInt = parse_obj_as(PortInt, DEFAULT_AIOHTTP_PORT)
132+
WEBSERVER_HOST: str | None = Field(
133+
None, validation_alias=AliasChoices("WEBSERVER_HOST", "HOST", "HOSTNAME")
134+
)
135+
WEBSERVER_PORT: PortInt = TypeAdapter(PortInt).validate_python(DEFAULT_AIOHTTP_PORT)
124136

125137
WEBSERVER_FRONTEND: FrontEndAppSettings | None = Field(
126-
auto_default_from_env=True, description="front-end static settings"
138+
json_schema_extra={"auto_default_from_env": True},
139+
description="front-end static settings",
127140
)
128141

129142
# PLUGINS ----------------
130143

131144
WEBSERVER_ACTIVITY: PrometheusSettings | None = Field(
132-
auto_default_from_env=True,
145+
json_schema_extra={"auto_default_from_env": True},
133146
description="activity plugin",
134147
)
135148
WEBSERVER_CATALOG: CatalogSettings | None = Field(
136-
auto_default_from_env=True, description="catalog service client's plugin"
149+
json_schema_extra={"auto_default_from_env": True},
150+
description="catalog service client's plugin",
137151
)
138152
# TODO: Shall be required
139153
WEBSERVER_DB: PostgresSettings | None = Field(
140-
auto_default_from_env=True, description="database plugin"
154+
json_schema_extra={"auto_default_from_env": True}, description="database plugin"
141155
)
142156
WEBSERVER_DIAGNOSTICS: DiagnosticsSettings | None = Field(
143-
auto_default_from_env=True, description="diagnostics plugin"
157+
json_schema_extra={"auto_default_from_env": True},
158+
description="diagnostics plugin",
144159
)
145160
WEBSERVER_DIRECTOR_V2: DirectorV2Settings | None = Field(
146-
auto_default_from_env=True, description="director-v2 service client's plugin"
161+
json_schema_extra={"auto_default_from_env": True},
162+
description="director-v2 service client's plugin",
147163
)
148164
WEBSERVER_EMAIL: SMTPSettings | None = Field(
149-
auto_default_from_env=True, description="email plugin"
165+
json_schema_extra={"auto_default_from_env": True}, description="email plugin"
150166
)
151167
WEBSERVER_EXPORTER: ExporterSettings | None = Field(
152-
auto_default_from_env=True, description="exporter plugin"
168+
json_schema_extra={"auto_default_from_env": True}, description="exporter plugin"
153169
)
154170
WEBSERVER_GARBAGE_COLLECTOR: GarbageCollectorSettings | None = Field(
155-
auto_default_from_env=True, description="garbage collector plugin"
171+
json_schema_extra={"auto_default_from_env": True},
172+
description="garbage collector plugin",
156173
)
157174

158175
WEBSERVER_INVITATIONS: InvitationsSettings | None = Field(
159-
auto_default_from_env=True, description="invitations plugin"
176+
json_schema_extra={"auto_default_from_env": True},
177+
description="invitations plugin",
160178
)
161179

162180
WEBSERVER_LOGIN: LoginSettings | None = Field(
163-
auto_default_from_env=True, description="login plugin"
181+
json_schema_extra={"auto_default_from_env": True}, description="login plugin"
164182
)
165183

166184
WEBSERVER_PAYMENTS: PaymentsSettings | None = Field(
167-
auto_default_from_env=True, description="payments plugin settings"
185+
json_schema_extra={"auto_default_from_env": True},
186+
description="payments plugin settings",
168187
)
169188

170189
WEBSERVER_DYNAMIC_SCHEDULER: DynamicSchedulerSettings | None = Field(
171-
auto_default_from_env=True, description="dynamic-scheduler plugin settings"
190+
description="dynamic-scheduler plugin settings",
191+
json_schema_extra={"auto_default_from_env": True},
172192
)
173193

174-
WEBSERVER_REDIS: RedisSettings | None = Field(auto_default_from_env=True)
194+
WEBSERVER_REDIS: RedisSettings | None = Field(
195+
json_schema_extra={"auto_default_from_env": True}
196+
)
175197

176198
WEBSERVER_REST: RestSettings | None = Field(
177-
auto_default_from_env=True, description="rest api plugin"
199+
description="rest api plugin", json_schema_extra={"auto_default_from_env": True}
178200
)
179201

180202
WEBSERVER_RESOURCE_MANAGER: ResourceManagerSettings = Field(
181-
auto_default_from_env=True, description="resource_manager plugin"
203+
description="resource_manager plugin",
204+
json_schema_extra={"auto_default_from_env": True},
182205
)
183206
WEBSERVER_RESOURCE_USAGE_TRACKER: ResourceUsageTrackerSettings | None = Field(
184-
auto_default_from_env=True,
185207
description="resource usage tracker service client's plugin",
208+
json_schema_extra={"auto_default_from_env": True},
186209
)
187210
WEBSERVER_SCICRUNCH: SciCrunchSettings | None = Field(
188-
auto_default_from_env=True, description="scicrunch plugin"
211+
description="scicrunch plugin",
212+
json_schema_extra={"auto_default_from_env": True},
189213
)
190214
WEBSERVER_SESSION: SessionSettings = Field(
191-
auto_default_from_env=True, description="session plugin"
215+
description="session plugin", json_schema_extra={"auto_default_from_env": True}
192216
)
193217

194218
WEBSERVER_STATICWEB: StaticWebserverModuleSettings | None = Field(
195-
auto_default_from_env=True, description="static-webserver service plugin"
219+
description="static-webserver service plugin",
220+
json_schema_extra={"auto_default_from_env": True},
196221
)
197222
WEBSERVER_STORAGE: StorageSettings | None = Field(
198-
auto_default_from_env=True, description="storage service client's plugin"
223+
description="storage service client's plugin",
224+
json_schema_extra={"auto_default_from_env": True},
199225
)
200226
WEBSERVER_STUDIES_DISPATCHER: StudiesDispatcherSettings | None = Field(
201-
auto_default_from_env=True, description="studies dispatcher plugin"
227+
description="studies dispatcher plugin",
228+
json_schema_extra={"auto_default_from_env": True},
202229
)
203230

204231
WEBSERVER_TRACING: TracingSettings | None = Field(
205-
auto_default_from_env=True, description="tracing plugin"
232+
description="tracing plugin", json_schema_extra={"auto_default_from_env": True}
206233
)
207234

208235
WEBSERVER_PROJECTS: ProjectsSettings | None = Field(
209-
auto_default_from_env=True, description="projects plugin"
236+
description="projects plugin", json_schema_extra={"auto_default_from_env": True}
210237
)
211238
WEBSERVER_RABBITMQ: RabbitSettings | None = Field(
212-
auto_default_from_env=True, description="rabbitmq plugin"
239+
description="rabbitmq plugin", json_schema_extra={"auto_default_from_env": True}
213240
)
214241
WEBSERVER_USERS: UsersSettings | None = Field(
215-
auto_default_from_env=True, description="users plugin"
242+
description="users plugin", json_schema_extra={"auto_default_from_env": True}
216243
)
217244

218245
# These plugins only require (for the moment) an entry to toggle between enabled/disabled
@@ -241,7 +268,7 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
241268
"Currently this is a system plugin and cannot be disabled",
242269
)
243270

244-
@root_validator()
271+
@model_validator(mode="after")
245272
@classmethod
246273
def build_vcs_release_url_if_unset(cls, values):
247274
release_url = values.get("SIMCORE_VCS_RELEASE_URL")
@@ -259,39 +286,43 @@ def build_vcs_release_url_if_unset(cls, values):
259286

260287
return values
261288

262-
@validator(
289+
@field_validator(
263290
# List of plugins under-development (keep up-to-date)
264291
# TODO: consider mark as dev-feature in field extras of Config attr.
265292
# Then they can be automtically advertised
266293
"WEBSERVER_META_MODELING",
267294
"WEBSERVER_VERSION_CONTROL",
268-
pre=True,
269-
always=True,
295+
mode="before",
270296
)
271297
@classmethod
272-
def enable_only_if_dev_features_allowed(cls, v, values, field: ModelField):
298+
def enable_only_if_dev_features_allowed(cls, v, info: ValidationInfo):
273299
"""Ensures that plugins 'under development' get programatically
274300
disabled if WEBSERVER_DEV_FEATURES_ENABLED=False
275301
"""
276-
if values["WEBSERVER_DEV_FEATURES_ENABLED"]:
302+
if info.data["WEBSERVER_DEV_FEATURES_ENABLED"]:
277303
return v
278304
if v:
279305
_logger.warning(
280-
"%s still under development and will be disabled.", field.name
306+
"%s still under development and will be disabled.", info.field_name
281307
)
282-
return None if field.allow_none else False
308+
309+
return (
310+
None
311+
if info.field_name and is_nullable(cls.model_fields[info.field_name])
312+
else False
313+
)
283314

284315
@cached_property
285316
def log_level(self) -> int:
286317
level: int = getattr(logging, self.WEBSERVER_LOGLEVEL.upper())
287318
return level
288319

289-
@validator("WEBSERVER_LOGLEVEL")
320+
@field_validator("WEBSERVER_LOGLEVEL")
290321
@classmethod
291322
def valid_log_level(cls, value):
292323
return cls.validate_log_level(value)
293324

294-
@validator("SC_HEALTHCHECK_TIMEOUT", pre=True)
325+
@field_validator("SC_HEALTHCHECK_TIMEOUT", mode="before")
295326
@classmethod
296327
def get_healthcheck_timeout_in_seconds(cls, v):
297328
# Ex. HEALTHCHECK --interval=5m --timeout=3s

services/web/server/src/simcore_service_webserver/catalog/_api.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from models_library.users import UserID
2424
from models_library.utils.fastapi_encoders import jsonable_encoder
2525
from pint import UnitRegistry
26-
from pydantic import BaseModel
26+
from pydantic import BaseModel, ConfigDict
2727
from servicelib.aiohttp.requests_validation import handle_validation_as_http_error
2828
from servicelib.rabbitmq.rpc_interfaces.catalog import services as catalog_rpc
2929
from servicelib.rest_constants import RESPONSE_MODEL_POLICY
@@ -42,9 +42,7 @@ class CatalogRequestContext(BaseModel):
4242
user_id: UserID
4343
product_name: str
4444
unit_registry: UnitRegistry
45-
46-
class Config:
47-
arbitrary_types_allowed = True
45+
model_config = ConfigDict(arbitrary_types_allowed=True)
4846

4947
@classmethod
5048
def create(cls, request: Request) -> "CatalogRequestContext":
@@ -157,7 +155,7 @@ async def update_service_v2(
157155
user_id=user_id,
158156
service_key=service_key,
159157
service_version=service_version,
160-
update=ServiceUpdateV2.parse_obj(update_data),
158+
update=ServiceUpdateV2.model_validate(update_data),
161159
)
162160

163161
data = jsonable_encoder(service, exclude_unset=True)

0 commit comments

Comments
 (0)