Skip to content

Commit a00d55f

Browse files
GitHKAndrei Neagu
andauthored
pydantic2 making ported services green (#6701)
Co-authored-by: Andrei Neagu <[email protected]>
1 parent f07afbf commit a00d55f

File tree

64 files changed

+334
-241
lines changed

Some content is hidden

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

64 files changed

+334
-241
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1+
import contextlib
12
from datetime import timedelta
23
from typing import Any
34

4-
from pydantic import BaseModel, SecretStr
5+
from pydantic import BaseModel, SecretStr, TypeAdapter, ValidationError
56
from pydantic_core import Url
67

7-
from .pydantic_fields_extension import get_type
8-
98

109
def model_dump_with_secrets(
1110
settings_obj: BaseModel, *, show_secrets: bool, **pydantic_export_options
@@ -31,10 +30,11 @@ def model_dump_with_secrets(
3130
data[field_name] = str(field_data)
3231

3332
elif isinstance(field_data, dict):
34-
field_type = get_type(settings_obj.model_fields[field_name])
35-
if issubclass(field_type, BaseModel):
33+
possible_pydantic_model = settings_obj.model_fields[field_name].annotation
34+
# NOTE: data could be a dict which does not represent a pydantic model or a union of models
35+
with contextlib.suppress(AttributeError, ValidationError):
3636
data[field_name] = model_dump_with_secrets(
37-
field_type.model_validate(field_data),
37+
TypeAdapter(possible_pydantic_model).validate_python(field_data),
3838
show_secrets=show_secrets,
3939
**pydantic_export_options,
4040
)

packages/models-library/src/models_library/api_schemas_clusters_keeper/clusters.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import datetime
22
from enum import auto
33

4-
from pydantic import AnyUrl, BaseModel
4+
from pydantic import AnyUrl, BaseModel, Field
55

66
from ..clusters import ClusterAuthentication
77
from ..users import UserID
@@ -17,7 +17,7 @@ class ClusterState(StrAutoEnum):
1717

1818
class OnDemandCluster(BaseModel):
1919
endpoint: AnyUrl
20-
authentication: ClusterAuthentication
20+
authentication: ClusterAuthentication = Field(discriminator="type")
2121
state: ClusterState
2222
user_id: UserID
2323
wallet_id: WalletID | None

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class ClusterDetailsGet(ClusterDetails):
114114

115115
class ClusterCreate(BaseCluster):
116116
owner: GroupID | None = None # type: ignore[assignment]
117-
authentication: ExternalClusterAuthentication
117+
authentication: ExternalClusterAuthentication = Field(discriminator="type")
118118
access_rights: dict[GroupID, ClusterAccessRights] = Field(
119119
alias="accessRights", default_factory=dict
120120
)
@@ -144,9 +144,9 @@ class ClusterCreate(BaseCluster):
144144
"password": "somepassword",
145145
},
146146
"accessRights": {
147-
154: CLUSTER_ADMIN_RIGHTS, # type: ignore[dict-item]
148-
12: CLUSTER_MANAGER_RIGHTS, # type: ignore[dict-item]
149-
7899: CLUSTER_USER_RIGHTS, # type: ignore[dict-item]
147+
154: CLUSTER_ADMIN_RIGHTS.model_dump(), # type:ignore[dict-item]
148+
12: CLUSTER_MANAGER_RIGHTS.model_dump(), # type:ignore[dict-item]
149+
7899: CLUSTER_USER_RIGHTS.model_dump(), # type:ignore[dict-item]
150150
},
151151
},
152152
]
@@ -174,7 +174,7 @@ class ClusterPatch(BaseCluster):
174174
owner: GroupID | None = None # type: ignore[assignment]
175175
thumbnail: HttpUrl | None = None
176176
endpoint: AnyUrl | None = None # type: ignore[assignment]
177-
authentication: ExternalClusterAuthentication | None = None # type: ignore[assignment]
177+
authentication: ExternalClusterAuthentication | None = Field(None, discriminator="type") # type: ignore[assignment]
178178
access_rights: dict[GroupID, ClusterAccessRights] | None = Field( # type: ignore[assignment]
179179
default=None, alias="accessRights"
180180
)
@@ -190,9 +190,9 @@ class ClusterPatch(BaseCluster):
190190
},
191191
{
192192
"accessRights": {
193-
154: CLUSTER_ADMIN_RIGHTS, # type: ignore[dict-item]
194-
12: CLUSTER_MANAGER_RIGHTS, # type: ignore[dict-item]
195-
7899: CLUSTER_USER_RIGHTS, # type: ignore[dict-item]
193+
154: CLUSTER_ADMIN_RIGHTS.model_dump(), # type:ignore[dict-item]
194+
12: CLUSTER_MANAGER_RIGHTS.model_dump(), # type:ignore[dict-item]
195+
7899: CLUSTER_USER_RIGHTS.model_dump(), # type:ignore[dict-item]
196196
},
197197
},
198198
]
@@ -203,5 +203,7 @@ class ClusterPatch(BaseCluster):
203203
class ClusterPing(BaseModel):
204204
endpoint: AnyHttpUrl
205205
authentication: ClusterAuthentication = Field(
206-
..., description="Dask gateway authentication"
206+
...,
207+
description="Dask gateway authentication",
208+
discriminator="type",
207209
)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class BaseCluster(BaseModel):
140140
)
141141
endpoint: AnyUrl
142142
authentication: ClusterAuthentication = Field(
143-
..., description="Dask gateway authentication"
143+
..., description="Dask gateway authentication", discriminator="type"
144144
)
145145
access_rights: dict[GroupID, ClusterAccessRights] = Field(default_factory=dict)
146146

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from datetime import datetime
66
from enum import Enum
7-
from typing import Any, Final, TypeAlias
7+
from typing import Annotated, Any, Final, TypeAlias
88
from uuid import UUID
99

1010
from models_library.basic_types import ConstrainedStr
@@ -77,7 +77,7 @@ class BaseProjectModel(BaseModel):
7777
last_change_date: datetime = Field(...)
7878

7979
# Pipeline of nodes (SEE projects_nodes.py)
80-
workbench: NodesDict = Field(..., description="Project's pipeline")
80+
workbench: Annotated[NodesDict, Field(..., description="Project's pipeline")]
8181

8282
# validators
8383
_empty_thumbnail_is_none = field_validator("thumbnail", mode="before")(

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
from enum import Enum, unique
6+
from typing import Annotated
67

78
from pydantic import (
89
BaseModel,
@@ -126,7 +127,7 @@ class ProjectRunningState(BaseModel):
126127

127128

128129
class ProjectState(BaseModel):
129-
locked: ProjectLocked = Field(..., description="The project lock state")
130+
locked: Annotated[ProjectLocked, Field(..., description="The project lock state")]
130131
state: ProjectRunningState = Field(..., description="The project running state")
131132

132133
model_config = ConfigDict(extra="forbid")

packages/pytest-simcore/src/pytest_simcore/helpers/httpx_calls_capture_parameters.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import Literal
1+
from typing import Annotated, Literal
22

3-
from pydantic import field_validator, model_validator, ConfigDict, BaseModel, Field
3+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
44

55
from .httpx_calls_capture_errors import OpenApiSpecError
66

@@ -94,7 +94,7 @@ class CapturedParameter(BaseModel):
9494
in_: Literal["path", "header", "query"] = Field(..., alias="in")
9595
name: str
9696
required: bool
97-
schema_: CapturedParameterSchema = Field(..., alias="schema")
97+
schema_: Annotated[CapturedParameterSchema, Field(..., alias="schema")]
9898
response_value: str | None = (
9999
None # attribute for storing the params value in a concrete response
100100
)

packages/service-library/src/servicelib/aiohttp/tracing.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@
3131
except ImportError:
3232
HAS_BOTOCORE = False
3333
try:
34-
from opentelemetry.instrumentation.aiopg import ( # type: ignore[import-not-found]
35-
AiopgInstrumentor,
36-
)
34+
from opentelemetry.instrumentation.aiopg import AiopgInstrumentor
3735

3836
HAS_AIOPG = True
3937
except ImportError:

packages/service-library/src/servicelib/fastapi/tracing.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828
HAS_ASYNCPG = False
2929

3030
try:
31-
from opentelemetry.instrumentation.aiopg import ( # type: ignore[import-not-found]
32-
AiopgInstrumentor,
33-
)
31+
from opentelemetry.instrumentation.aiopg import AiopgInstrumentor
3432

3533
HAS_AIOPG = True
3634
except ImportError:

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from functools import cached_property
2+
from typing import Annotated
23

34
from models_library.basic_types import BootModeEnum, LogLevel
45
from pydantic import (
@@ -87,9 +88,10 @@ class ApplicationSettings(BasicSettings):
8788
# DOCKER BOOT
8889
SC_BOOT_MODE: BootModeEnum | None = None
8990

90-
API_SERVER_POSTGRES: PostgresSettings | None = Field(
91-
json_schema_extra={"auto_default_from_env": True}
92-
)
91+
API_SERVER_POSTGRES: Annotated[
92+
PostgresSettings | None,
93+
Field(json_schema_extra={"auto_default_from_env": True}),
94+
]
9395

9496
API_SERVER_RABBITMQ: RabbitSettings | None = Field(
9597
json_schema_extra={"auto_default_from_env": True},

0 commit comments

Comments
 (0)