Skip to content

Commit 45119e5

Browse files
run bump-pydantic
1 parent 956c3b7 commit 45119e5

Some content is hidden

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

58 files changed

+497
-515
lines changed

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

Lines changed: 8 additions & 7 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, ValidationInfo, field_validator
66

77

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

21-
@validator("end")
21+
@field_validator("end")
2222
@classmethod
23-
def check_start_before_end(cls, v, values):
24-
if start := values.get("start"):
23+
def check_start_before_end(cls, v, info: ValidationInfo):
24+
if start := info.data.get("start"):
2525
end = v
2626
if end <= start:
2727
msg = f"end={end!r} is not before start={start!r}"
@@ -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/application_settings.py

Lines changed: 77 additions & 47 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
@@ -83,13 +91,13 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
8391
SIMCORE_VCS_RELEASE_TAG: str | None = Field(
8492
default=None,
8593
description="Name of the tag that marks this release, or None if undefined",
86-
example="ResistanceIsFutile10",
94+
examples=["ResistanceIsFutile10"],
8795
)
8896

8997
SIMCORE_VCS_RELEASE_URL: AnyHttpUrl | None = Field(
9098
default=None,
9199
description="URL to release notes",
92-
example="https://github.com/ITISFoundation/osparc-simcore/releases/tag/staging_ResistanceIsFutile10",
100+
examples=["https://github.com/ITISFoundation/osparc-simcore/releases/tag/staging_ResistanceIsFutile10"],
93101
)
94102

95103
SWARM_STACK_NAME: str | None = Field(
@@ -105,13 +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
)
111-
112119
WEBSERVER_LOG_FORMAT_LOCAL_DEV_ENABLED: bool = Field(
113120
default=False,
114-
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+
),
115124
description="Enables local development log format. WARNING: make sure it is disabled if you want to have structured logs!",
116125
)
117126
# TODO: find a better name!?
@@ -120,100 +129,117 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
120129
description="host name to serve within the container."
121130
"NOTE that this different from WEBSERVER_HOST env which is the host seen outside the container",
122131
)
123-
WEBSERVER_HOST: str | None = Field(None, env=["WEBSERVER_HOST", "HOST", "HOSTNAME"])
124-
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)
125136

126137
WEBSERVER_FRONTEND: FrontEndAppSettings | None = Field(
127-
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",
128140
)
129141

130142
# PLUGINS ----------------
131143

132144
WEBSERVER_ACTIVITY: PrometheusSettings | None = Field(
133-
auto_default_from_env=True,
145+
json_schema_extra={"auto_default_from_env": True},
134146
description="activity plugin",
135147
)
136148
WEBSERVER_CATALOG: CatalogSettings | None = Field(
137-
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",
138151
)
139152
# TODO: Shall be required
140153
WEBSERVER_DB: PostgresSettings | None = Field(
141-
auto_default_from_env=True, description="database plugin"
154+
json_schema_extra={"auto_default_from_env": True}, description="database plugin"
142155
)
143156
WEBSERVER_DIAGNOSTICS: DiagnosticsSettings | None = Field(
144-
auto_default_from_env=True, description="diagnostics plugin"
157+
json_schema_extra={"auto_default_from_env": True},
158+
description="diagnostics plugin",
145159
)
146160
WEBSERVER_DIRECTOR_V2: DirectorV2Settings | None = Field(
147-
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",
148163
)
149164
WEBSERVER_EMAIL: SMTPSettings | None = Field(
150-
auto_default_from_env=True, description="email plugin"
165+
json_schema_extra={"auto_default_from_env": True}, description="email plugin"
151166
)
152167
WEBSERVER_EXPORTER: ExporterSettings | None = Field(
153-
auto_default_from_env=True, description="exporter plugin"
168+
json_schema_extra={"auto_default_from_env": True}, description="exporter plugin"
154169
)
155170
WEBSERVER_GARBAGE_COLLECTOR: GarbageCollectorSettings | None = Field(
156-
auto_default_from_env=True, description="garbage collector plugin"
171+
json_schema_extra={"auto_default_from_env": True},
172+
description="garbage collector plugin",
157173
)
158174

159175
WEBSERVER_INVITATIONS: InvitationsSettings | None = Field(
160-
auto_default_from_env=True, description="invitations plugin"
176+
json_schema_extra={"auto_default_from_env": True},
177+
description="invitations plugin",
161178
)
162179

163180
WEBSERVER_LOGIN: LoginSettings | None = Field(
164-
auto_default_from_env=True, description="login plugin"
181+
json_schema_extra={"auto_default_from_env": True}, description="login plugin"
165182
)
166183

167184
WEBSERVER_PAYMENTS: PaymentsSettings | None = Field(
168-
auto_default_from_env=True, description="payments plugin settings"
185+
json_schema_extra={"auto_default_from_env": True},
186+
description="payments plugin settings",
169187
)
170188

171189
WEBSERVER_DYNAMIC_SCHEDULER: DynamicSchedulerSettings | None = Field(
172-
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},
173192
)
174193

175-
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+
)
176197

177198
WEBSERVER_REST: RestSettings | None = Field(
178-
auto_default_from_env=True, description="rest api plugin"
199+
description="rest api plugin", json_schema_extra={"auto_default_from_env": True}
179200
)
180201

181202
WEBSERVER_RESOURCE_MANAGER: ResourceManagerSettings = Field(
182-
auto_default_from_env=True, description="resource_manager plugin"
203+
description="resource_manager plugin",
204+
json_schema_extra={"auto_default_from_env": True},
183205
)
184206
WEBSERVER_RESOURCE_USAGE_TRACKER: ResourceUsageTrackerSettings | None = Field(
185-
auto_default_from_env=True,
186207
description="resource usage tracker service client's plugin",
208+
json_schema_extra={"auto_default_from_env": True},
187209
)
188210
WEBSERVER_SCICRUNCH: SciCrunchSettings | None = Field(
189-
auto_default_from_env=True, description="scicrunch plugin"
211+
description="scicrunch plugin",
212+
json_schema_extra={"auto_default_from_env": True},
190213
)
191214
WEBSERVER_SESSION: SessionSettings = Field(
192-
auto_default_from_env=True, description="session plugin"
215+
description="session plugin", json_schema_extra={"auto_default_from_env": True}
193216
)
194217

195218
WEBSERVER_STATICWEB: StaticWebserverModuleSettings | None = Field(
196-
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},
197221
)
198222
WEBSERVER_STORAGE: StorageSettings | None = Field(
199-
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},
200225
)
201226
WEBSERVER_STUDIES_DISPATCHER: StudiesDispatcherSettings | None = Field(
202-
auto_default_from_env=True, description="studies dispatcher plugin"
227+
description="studies dispatcher plugin",
228+
json_schema_extra={"auto_default_from_env": True},
203229
)
204230

205231
WEBSERVER_TRACING: TracingSettings | None = Field(
206-
auto_default_from_env=True, description="tracing plugin"
232+
description="tracing plugin", json_schema_extra={"auto_default_from_env": True}
207233
)
208234

209235
WEBSERVER_PROJECTS: ProjectsSettings | None = Field(
210-
auto_default_from_env=True, description="projects plugin"
236+
description="projects plugin", json_schema_extra={"auto_default_from_env": True}
211237
)
212238
WEBSERVER_RABBITMQ: RabbitSettings | None = Field(
213-
auto_default_from_env=True, description="rabbitmq plugin"
239+
description="rabbitmq plugin", json_schema_extra={"auto_default_from_env": True}
214240
)
215241
WEBSERVER_USERS: UsersSettings | None = Field(
216-
auto_default_from_env=True, description="users plugin"
242+
description="users plugin", json_schema_extra={"auto_default_from_env": True}
217243
)
218244

219245
# These plugins only require (for the moment) an entry to toggle between enabled/disabled
@@ -242,7 +268,7 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
242268
"Currently this is a system plugin and cannot be disabled",
243269
)
244270

245-
@root_validator()
271+
@model_validator(mode="after")
246272
@classmethod
247273
def build_vcs_release_url_if_unset(cls, values):
248274
release_url = values.get("SIMCORE_VCS_RELEASE_URL")
@@ -260,39 +286,43 @@ def build_vcs_release_url_if_unset(cls, values):
260286

261287
return values
262288

263-
@validator(
289+
@field_validator(
264290
# List of plugins under-development (keep up-to-date)
265291
# TODO: consider mark as dev-feature in field extras of Config attr.
266292
# Then they can be automtically advertised
267293
"WEBSERVER_META_MODELING",
268294
"WEBSERVER_VERSION_CONTROL",
269-
pre=True,
270-
always=True,
295+
mode="before",
271296
)
272297
@classmethod
273-
def enable_only_if_dev_features_allowed(cls, v, values, field: ModelField):
298+
def enable_only_if_dev_features_allowed(cls, v, info: ValidationInfo):
274299
"""Ensures that plugins 'under development' get programatically
275300
disabled if WEBSERVER_DEV_FEATURES_ENABLED=False
276301
"""
277-
if values["WEBSERVER_DEV_FEATURES_ENABLED"]:
302+
if info.data["WEBSERVER_DEV_FEATURES_ENABLED"]:
278303
return v
279304
if v:
280305
_logger.warning(
281-
"%s still under development and will be disabled.", field.name
306+
"%s still under development and will be disabled.", info.field_name
282307
)
283-
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+
)
284314

285315
@cached_property
286316
def log_level(self) -> int:
287317
level: int = getattr(logging, self.WEBSERVER_LOGLEVEL.upper())
288318
return level
289319

290-
@validator("WEBSERVER_LOGLEVEL", pre=True)
320+
@field_validator("WEBSERVER_LOGLEVEL")
291321
@classmethod
292-
def valid_log_level(cls, value: str) -> str:
322+
def valid_log_level(cls, value):
293323
return cls.validate_log_level(value)
294324

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

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

Lines changed: 2 additions & 4 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":

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
ServiceResourcesDict,
2727
ServiceResourcesDictHelpers,
2828
)
29-
from pydantic import BaseModel, Extra, Field, parse_obj_as, validator
29+
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, field_validator
3030
from servicelib.aiohttp.requests_validation import (
3131
parse_request_body_as,
3232
parse_request_path_parameters_as,
@@ -54,12 +54,12 @@
5454
class ServicePathParams(BaseModel):
5555
service_key: ServiceKey
5656
service_version: ServiceVersion
57+
model_config = ConfigDict(
58+
populate_by_name=True,
59+
extra="forbid",
60+
)
5761

58-
class Config:
59-
allow_population_by_field_name = True
60-
extra = Extra.forbid
61-
62-
@validator("service_key", pre=True)
62+
@field_validator("service_key", mode="before")
6363
@classmethod
6464
def ensure_unquoted(cls, v):
6565
# NOTE: this is needed as in pytest mode, the aiohttp server does not seem to unquote automatically
@@ -387,4 +387,6 @@ async def get_service_pricing_plan(request: Request):
387387
service_version=f"{path_params.service_version}",
388388
)
389389

390-
return envelope_json_response(parse_obj_as(PricingPlanGet, pricing_plan))
390+
return envelope_json_response(
391+
TypeAdapter(PricingPlanGet).validate_python(pricing_plan)
392+
)

0 commit comments

Comments
 (0)