Skip to content

Commit 2486b38

Browse files
authored
♻️Pydantic V2 migration: various fixes (#6647)
1 parent 01769ac commit 2486b38

File tree

27 files changed

+199
-116
lines changed

27 files changed

+199
-116
lines changed

packages/aws-library/tests/test_s3_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ async def test_create_single_presigned_download_link(
696696

697697
dest_file = tmp_path / faker.file_name()
698698
async with ClientSession() as session:
699-
response = await session.get(download_url)
699+
response = await session.get(f"{download_url}")
700700
response.raise_for_status()
701701
with dest_file.open("wb") as fp:
702702
fp.write(await response.read())

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def to_simcore_runtime_docker_label_key(key: str) -> DockerLabelKey:
7575
class StandardSimcoreDockerLabels(BaseModel):
7676
"""
7777
Represents the standard label on oSparc created containers (not yet services)
78-
In order to create this object in code, please use construct() method!
78+
In order to create this object in code, please use model_construct() method!
7979
"""
8080

8181
user_id: UserID = Field(..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}user-id") # type: ignore[literal-required]

packages/postgres-database/tests/test_utils_projects.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from aiopg.sa.connection import SAConnection
1313
from aiopg.sa.result import RowProxy
1414
from faker import Faker
15-
from pydantic import parse_obj_as
15+
from pydantic import TypeAdapter
1616
from simcore_postgres_database.models.projects import projects
1717
from simcore_postgres_database.utils_projects import (
1818
DBProjectNotFoundError,
@@ -69,7 +69,7 @@ async def test_get_project_trashed_at_column_can_be_converted_to_datetime(
6969

7070
row = result.fetchone()
7171

72-
trashed_at = parse_obj_as(datetime | None, row.trashed_at)
72+
trashed_at = TypeAdapter(datetime | None).validate_python(row.trashed_at)
7373
assert trashed_at == expected
7474

7575

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/agent/volumes.py

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

55
from models_library.projects_nodes_io import NodeID
66
from models_library.rabbitmq_basic_types import RPCMethodName, RPCNamespace
7-
from pydantic import NonNegativeInt, parse_obj_as
7+
from pydantic import NonNegativeInt, TypeAdapter
88
from servicelib.logging_utils import log_decorator
99
from servicelib.rabbitmq import RabbitMQRPCClient
1010

@@ -29,7 +29,9 @@ async def remove_volumes_without_backup_for_service(
2929
"swarm_stack_name": swarm_stack_name,
3030
}
3131
),
32-
parse_obj_as(RPCMethodName, "remove_volumes_without_backup_for_service"),
32+
TypeAdapter(RPCMethodName).validate_python(
33+
"remove_volumes_without_backup_for_service"
34+
),
3335
node_id=node_id,
3436
timeout_s=_REQUEST_TIMEOUT,
3537
)
@@ -51,7 +53,9 @@ async def backup_and_remove_volumes_for_all_services(
5153
"swarm_stack_name": swarm_stack_name,
5254
}
5355
),
54-
parse_obj_as(RPCMethodName, "backup_and_remove_volumes_for_all_services"),
56+
TypeAdapter(RPCMethodName).validate_python(
57+
"backup_and_remove_volumes_for_all_services"
58+
),
5559
timeout_s=_REQUEST_TIMEOUT,
5660
)
5761
assert result is None # nosec

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/dynamic_sidecar/disk_usage.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import logging
2+
from typing import Final
23

34
from models_library.api_schemas_dynamic_sidecar.telemetry import DiskUsage
45
from models_library.projects_nodes_io import NodeID
56
from models_library.rabbitmq_basic_types import RPCMethodName, RPCNamespace
6-
from pydantic import parse_obj_as
7-
from servicelib.logging_utils import log_decorator
8-
from servicelib.rabbitmq import RabbitMQRPCClient
7+
from pydantic import TypeAdapter
8+
9+
from ....logging_utils import log_decorator
10+
from ... import RabbitMQRPCClient
911

1012
_logger = logging.getLogger(__name__)
1113

14+
_UPDATE_DISK_USAGE: Final[RPCMethodName] = TypeAdapter(RPCMethodName).validate_python(
15+
"update_disk_usage"
16+
)
17+
1218

1319
@log_decorator(_logger, level=logging.DEBUG)
1420
async def update_disk_usage(
@@ -21,6 +27,8 @@ async def update_disk_usage(
2127
{"service": "dy-sidecar", "node_id": f"{node_id}"}
2228
)
2329
result = await rabbitmq_rpc_client.request(
24-
rpc_namespace, parse_obj_as(RPCMethodName, "update_disk_usage"), usage=usage
30+
rpc_namespace,
31+
_UPDATE_DISK_USAGE,
32+
usage=usage,
2533
)
2634
assert result is None # nosec

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/resource_usage_tracker/service_runs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Final, cast
2+
from typing import Final
33

44
from models_library.api_schemas_resource_usage_tracker import (
55
RESOURCE_USAGE_TRACKER_RPC_NAMESPACE,
@@ -115,5 +115,5 @@ async def export_service_runs(
115115
filters=filters,
116116
timeout_s=_DEFAULT_TIMEOUT_S,
117117
)
118-
assert cast(AnyUrl, isinstance(result, AnyUrl)) # nosec
118+
assert isinstance(result, AnyUrl) # nosec
119119
return result

packages/simcore-sdk/src/simcore_sdk/node_ports_common/aws_s3_cli_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
import re
33

4-
from pydantic import ByteSize, parse_obj_as
4+
from pydantic import ByteSize, TypeAdapter
55
from servicelib.logging_utils import log_catch
66
from servicelib.progress_bar import ProgressBarData
77

@@ -35,5 +35,5 @@ async def __call__(self, logs: str) -> None:
3535
_logger.debug("received logs: %s", logs)
3636
with log_catch(_logger, reraise=False):
3737
if _size := _parse_size(logs):
38-
_bytes = parse_obj_as(ByteSize, _size)
38+
_bytes = TypeAdapter(ByteSize).validate_python(_size)
3939
await self.progress_bar.set_(_bytes)

packages/simcore-sdk/src/simcore_sdk/node_ports_v2/nodeports_v2.py

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
2+
import traceback
23
from abc import ABC, abstractmethod
3-
from asyncio import CancelledError
4+
from asyncio import CancelledError, Task
45
from collections.abc import Callable, Coroutine
56
from pathlib import Path
67
from typing import Any
@@ -12,6 +13,7 @@
1213
from models_library.services_types import ServicePortKey
1314
from models_library.users import UserID
1415
from pydantic import BaseModel, ConfigDict, Field, ValidationError
16+
from pydantic_core import InitErrorDetails
1517
from servicelib.progress_bar import ProgressBarData
1618
from servicelib.utils import logged_gather
1719
from settings_library.aws_s3_cli import AwsS3CliSettings
@@ -28,6 +30,28 @@
2830
log = logging.getLogger(__name__)
2931

3032

33+
# -> @GitHK this looks very dangerous, using a lot of protected stuff, just checking the number of ignores shows it's a bad idea...
34+
def _format_error(task: Task) -> str:
35+
# pylint:disable=protected-access
36+
assert task._exception # nosec # noqa: SLF001
37+
error_list = traceback.format_exception(
38+
type(task._exception), # noqa: SLF001
39+
task._exception, # noqa: SLF001
40+
task._exception.__traceback__, # noqa: SLF001
41+
)
42+
return "\n".join(error_list)
43+
44+
45+
def _get_error_details(task: Task, port_key: str) -> InitErrorDetails:
46+
# pylint:disable=protected-access
47+
return InitErrorDetails(
48+
type="value_error",
49+
loc=(f"{port_key}",),
50+
input=_format_error(task),
51+
ctx={"error": task._exception}, # noqa: SLF001
52+
)
53+
54+
3155
class OutputsCallbacks(ABC):
3256
@abstractmethod
3357
async def aborted(self, key: ServicePortKey) -> None:
@@ -72,9 +96,9 @@ def __init__(self, **data: Any):
7296

7397
# let's pass ourselves down
7498
for input_key in self.internal_inputs:
75-
self.internal_inputs[input_key]._node_ports = self
99+
self.internal_inputs[input_key]._node_ports = self # noqa: SLF001
76100
for output_key in self.internal_outputs:
77-
self.internal_outputs[output_key]._node_ports = self
101+
self.internal_outputs[output_key]._node_ports = self # noqa: SLF001
78102

79103
@property
80104
async def inputs(self) -> InputsList:
@@ -132,10 +156,11 @@ async def set(
132156

133157
async def set_file_by_keymap(self, item_value: Path) -> None:
134158
for output in (await self.outputs).values():
135-
if is_file_type(output.property_type) and output.file_to_key_map:
136-
if item_value.name in output.file_to_key_map:
137-
await output.set(item_value)
138-
return
159+
if (is_file_type(output.property_type) and output.file_to_key_map) and (
160+
item_value.name in output.file_to_key_map
161+
):
162+
await output.set(item_value)
163+
return
139164
raise PortNotFound(msg=f"output port for item {item_value} not found")
140165

141166
async def _node_ports_creator_cb(self, node_uuid: NodeIDStr) -> type["Nodeports"]:
@@ -152,9 +177,9 @@ async def _auto_update_from_db(self) -> None:
152177
# let's pass ourselves down
153178
# pylint: disable=protected-access
154179
for input_key in self.internal_inputs:
155-
self.internal_inputs[input_key]._node_ports = self
180+
self.internal_inputs[input_key]._node_ports = self # noqa: SLF001
156181
for output_key in self.internal_outputs:
157-
self.internal_outputs[output_key]._node_ports = self
182+
self.internal_outputs[output_key]._node_ports = self # noqa: SLF001
158183

159184
async def set_multiple(
160185
self,

packages/simcore-sdk/src/simcore_sdk/node_ports_v2/port_utils.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
from models_library.basic_types import IDStr, SHA256Str
99
from models_library.services_types import FileName, ServicePortKey
1010
from models_library.users import UserID
11-
from pydantic import AnyUrl, ByteSize
12-
from pydantic.tools import parse_obj_as
11+
from pydantic import AnyUrl, ByteSize, TypeAdapter
1312
from servicelib.progress_bar import ProgressBarData
1413
from settings_library.aws_s3_cli import AwsS3CliSettings
1514
from settings_library.r_clone import RCloneSettings
@@ -64,6 +63,7 @@ async def get_value_from_link(
6463
file_name = other_value.name
6564
# move the file to the right final location
6665
# if a file alias is present use it
66+
6767
if file_to_key_map:
6868
file_name = next(iter(file_to_key_map))
6969

@@ -101,7 +101,7 @@ async def get_download_link_from_storage(
101101

102102
# could raise ValidationError but will never do it since
103103
assert isinstance(link, URL) # nosec
104-
url: AnyUrl = parse_obj_as(AnyUrl, f"{link}")
104+
url: AnyUrl = TypeAdapter(AnyUrl).validate_python(f"{link}")
105105
return url
106106

107107

@@ -123,7 +123,7 @@ async def get_download_link_from_storage_overload(
123123
s3_object=s3_object,
124124
link_type=link_type,
125125
)
126-
url: AnyUrl = parse_obj_as(AnyUrl, f"{link}")
126+
url: AnyUrl = TypeAdapter(AnyUrl).validate_python(f"{link}")
127127
return url
128128

129129

packages/simcore-sdk/tests/integration/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from models_library.generics import Envelope
1818
from models_library.projects_nodes_io import LocationID, NodeIDStr, SimcoreS3FileID
1919
from models_library.users import UserID
20-
from pydantic import parse_obj_as
20+
from pydantic import TypeAdapter
2121
from pytest_simcore.helpers.faker_factories import random_project, random_user
2222
from settings_library.aws_s3_cli import AwsS3CliSettings
2323
from settings_library.r_clone import RCloneSettings, S3Provider
@@ -94,7 +94,7 @@ def create_valid_file_uuid(
9494
) -> Callable[[str, Path], SimcoreS3FileID]:
9595
def _create(key: str, file_path: Path) -> SimcoreS3FileID:
9696
clean_path = Path(f"{project_id}/{node_uuid}/{key}/{file_path.name}")
97-
return parse_obj_as(SimcoreS3FileID, f"{clean_path}")
97+
return TypeAdapter(SimcoreS3FileID).validate_python(f"{clean_path}")
9898

9999
return _create
100100

0 commit comments

Comments
 (0)