Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⬆️ Upgrade Web Server service (Pydantic v2) #6584

Merged
Show file tree
Hide file tree
Changes from 154 commits
Commits
Show all changes
172 commits
Select commit Hold shift + click to select a range
956c3b7
upgrade reqs
giancarloromeo Oct 23, 2024
45119e5
run bump-pydantic
giancarloromeo Oct 23, 2024
9979a3f
add common-library dependency
giancarloromeo Oct 23, 2024
29ab6c2
fix import
giancarloromeo Oct 23, 2024
a75e832
fix import
giancarloromeo Oct 23, 2024
dc1f60d
continue fixing
giancarloromeo Oct 23, 2024
fdb7238
fix arbitrary type field
giancarloromeo Oct 23, 2024
c1db89a
continue fixing
giancarloromeo Oct 23, 2024
9586ea8
continue fixing
giancarloromeo Oct 23, 2024
e7ba88a
continue fixing
giancarloromeo Oct 24, 2024
c5dd024
fix settings validator
giancarloromeo Oct 24, 2024
1e97ead
continue fixing
giancarloromeo Oct 24, 2024
82ba4bd
remove deprecated
giancarloromeo Oct 24, 2024
be74c41
fix model_config attr
giancarloromeo Oct 24, 2024
8015258
remove deprecated
giancarloromeo Oct 24, 2024
44d97de
continue fixing
giancarloromeo Oct 24, 2024
cf01290
continue fixing
giancarloromeo Oct 24, 2024
2b12826
continue fixing
giancarloromeo Oct 24, 2024
a50f41a
fix deprecated dict()
giancarloromeo Oct 24, 2024
6b9d7fa
fix deprecated json()
giancarloromeo Oct 24, 2024
557f51d
Merge branch 'pydantic_v2_migration_do_not_squash_updates' into is448…
giancarloromeo Oct 24, 2024
335ff84
fix type
giancarloromeo Oct 24, 2024
c7958b0
Merge branch 'is4481/upgrade-web-server-service' of github.com:gianca…
giancarloromeo Oct 24, 2024
e0db4a9
fix validation
giancarloromeo Oct 24, 2024
a135e42
continue fixing
giancarloromeo Oct 24, 2024
0c639bf
continue fixing
giancarloromeo Oct 24, 2024
48b6c26
no sort_keys anymore
giancarloromeo Oct 24, 2024
5a6a7d1
fix rootmodel
giancarloromeo Oct 24, 2024
1d0e14d
fix validate_call
giancarloromeo Oct 24, 2024
f7cdf05
fix mypy
giancarloromeo Oct 24, 2024
39b9898
remove deprecated from_orm
giancarloromeo Oct 25, 2024
1cb84d6
fix frozen settings
giancarloromeo Oct 25, 2024
6eba301
change thumbnail field type
giancarloromeo Oct 25, 2024
efefd0a
upgrade deprecated
giancarloromeo Oct 25, 2024
b323706
fix auto_default_from_env prop
giancarloromeo Oct 25, 2024
a605f2f
fix envs
giancarloromeo Oct 25, 2024
32043a4
fix sleep
giancarloromeo Oct 25, 2024
2c062e3
fix first elem get
giancarloromeo Oct 25, 2024
b9a4f88
fix import
giancarloromeo Oct 25, 2024
a2e1af6
fix envvar
giancarloromeo Oct 25, 2024
8421102
fix test
giancarloromeo Oct 25, 2024
fe53763
revert time
giancarloromeo Oct 25, 2024
00970e3
fix diagnostic settings mock
giancarloromeo Oct 25, 2024
2e6fc93
fix usernotfound error
giancarloromeo Oct 25, 2024
28f6d1a
continue fixing
giancarloromeo Oct 25, 2024
d11850d
fix Url
giancarloromeo Oct 25, 2024
5b2fd38
fix mypy
giancarloromeo Oct 25, 2024
820592c
fix url
giancarloromeo Oct 25, 2024
f1d4df5
fix mypy
giancarloromeo Oct 28, 2024
faf684d
Merge branch 'pydantic_v2_migration_do_not_squash_updates' into is448…
giancarloromeo Oct 28, 2024
893d0dc
fix test
giancarloromeo Oct 28, 2024
bb36b72
continue fixing
giancarloromeo Oct 28, 2024
2100adc
fix test
giancarloromeo Oct 28, 2024
b500cd6
continue fixing
giancarloromeo Oct 28, 2024
f1a2f46
fix
giancarloromeo Oct 28, 2024
8a7bc17
continue fixing
giancarloromeo Oct 28, 2024
9a3b124
silent sonar
giancarloromeo Oct 28, 2024
dcf7d83
fix test
giancarloromeo Oct 28, 2024
76e52b3
fix
giancarloromeo Oct 28, 2024
0aae043
fix test
giancarloromeo Oct 28, 2024
6b46049
fix test
giancarloromeo Oct 28, 2024
eec18e0
fix typecheck
giancarloromeo Oct 28, 2024
4409fa2
fix bytesize validation
giancarloromeo Oct 28, 2024
dd17474
fix extra
giancarloromeo Oct 29, 2024
65d0f7c
continue fixing
giancarloromeo Oct 29, 2024
1c056e5
Merge branch 'pydantic_v2_migration_do_not_squash_updates' into is448…
giancarloromeo Oct 29, 2024
5ab5d99
upgrade new code
giancarloromeo Oct 29, 2024
cc4b2cd
continue fixing
giancarloromeo Oct 29, 2024
3d916b2
continue fixing
giancarloromeo Oct 29, 2024
5aa6da7
fix
giancarloromeo Oct 29, 2024
4781498
fix
giancarloromeo Oct 29, 2024
744e366
update strategies
giancarloromeo Oct 29, 2024
d0e1f4b
fix import
giancarloromeo Oct 29, 2024
fa50fac
fix typecheck
giancarloromeo Oct 29, 2024
60ee4c8
fix urls
giancarloromeo Oct 29, 2024
1e29d7b
fix test
giancarloromeo Oct 29, 2024
7f76165
fix
giancarloromeo Oct 29, 2024
aca5dcd
fix
giancarloromeo Oct 29, 2024
c4784bb
fix test
giancarloromeo Oct 29, 2024
0402d82
fix bytesize
giancarloromeo Oct 29, 2024
44add09
fix env vars
giancarloromeo Oct 30, 2024
f634ec4
fix env vars
giancarloromeo Oct 30, 2024
976acf7
fix env vars
giancarloromeo Oct 30, 2024
e6d1d71
fix
giancarloromeo Oct 30, 2024
4432e00
continue fixing
giancarloromeo Oct 30, 2024
b685088
fix validation field
giancarloromeo Oct 30, 2024
f6f5908
fix validation
giancarloromeo Oct 30, 2024
ecd48d2
fix dump
giancarloromeo Oct 30, 2024
f948082
remove deprecated
giancarloromeo Oct 30, 2024
7604a40
continue fixing
giancarloromeo Oct 30, 2024
d1cc36b
fix date
giancarloromeo Oct 30, 2024
574a80a
continue fixing
giancarloromeo Oct 30, 2024
b0d44b6
fix
giancarloromeo Oct 30, 2024
a2bf2f3
fix
giancarloromeo Oct 30, 2024
723ca36
fix field
giancarloromeo Oct 30, 2024
48cac88
Merge branch 'pydantic_v2_migration_do_not_squash_updates' into is448…
giancarloromeo Oct 30, 2024
b44186a
add env vars
giancarloromeo Oct 30, 2024
8df92e8
remove unused ignore
giancarloromeo Oct 30, 2024
17a2049
add env vars
giancarloromeo Oct 30, 2024
c3d76a2
fix message
giancarloromeo Oct 30, 2024
ef0fc2f
fix msg
giancarloromeo Oct 30, 2024
c7fd828
fix invitations
giancarloromeo Oct 30, 2024
a83a7a6
fix sessionsettings
giancarloromeo Oct 30, 2024
19f787a
revert msg
giancarloromeo Oct 30, 2024
9404441
continue fixing
giancarloromeo Oct 30, 2024
7592d97
fix
giancarloromeo Oct 30, 2024
b865a76
fix mypy
giancarloromeo Oct 30, 2024
b810b5e
fix
giancarloromeo Oct 30, 2024
c9ab39f
fix
giancarloromeo Oct 30, 2024
fc5de11
fixing
giancarloromeo Oct 31, 2024
45e9a08
fix fields
giancarloromeo Oct 31, 2024
35e8c9d
fix tests
giancarloromeo Oct 31, 2024
83635d2
fix dynamic scheduler settings
giancarloromeo Oct 31, 2024
af87df5
fix import
giancarloromeo Oct 31, 2024
d3d9b71
remove env vars
giancarloromeo Oct 31, 2024
dba3ce2
remove env vars
giancarloromeo Oct 31, 2024
9001bd5
fix urls
giancarloromeo Oct 31, 2024
42bea1e
fix optional
giancarloromeo Oct 31, 2024
5119159
fix projects
giancarloromeo Oct 31, 2024
e1e182b
continue fixing
giancarloromeo Oct 31, 2024
b5b8495
coerce num to str
giancarloromeo Oct 31, 2024
c63bb66
revert for now
giancarloromeo Nov 1, 2024
5298ad9
fix test
giancarloromeo Nov 1, 2024
34be411
fix nullable
giancarloromeo Nov 1, 2024
10ed6a0
fix nullable
giancarloromeo Nov 1, 2024
fb633f2
fix url
giancarloromeo Nov 1, 2024
83a34e5
fix nullable
giancarloromeo Nov 1, 2024
cf0a1ca
fix rootmodel
giancarloromeo Nov 1, 2024
8b9f93f
pin pydantic-settins version
giancarloromeo Nov 1, 2024
871ecea
continue fixing
giancarloromeo Nov 1, 2024
7e00d51
fix error_msg
giancarloromeo Nov 1, 2024
e377829
fix error_code
giancarloromeo Nov 1, 2024
3c1dee5
fix datetime
giancarloromeo Nov 1, 2024
9641b16
fix
giancarloromeo Nov 1, 2024
22ea2f7
fix
giancarloromeo Nov 1, 2024
99127a4
fix typecheck
giancarloromeo Nov 1, 2024
ddf210e
fix message
giancarloromeo Nov 1, 2024
5ccfac9
Merge branch 'pydantic_v2_migration_do_not_squash_updates' into is448…
giancarloromeo Nov 1, 2024
958d4dd
fix typecheck
giancarloromeo Nov 1, 2024
d6c71c6
continue fixing
giancarloromeo Nov 1, 2024
ce882a5
continue fixing
giancarloromeo Nov 1, 2024
abecfa5
Merge branch 'pydantic_v2_migration_do_not_squash_updates' into is448…
giancarloromeo Nov 1, 2024
1b3128f
fix error
giancarloromeo Nov 1, 2024
d672a77
fix pagination
giancarloromeo Nov 1, 2024
0332dec
fix error msg
giancarloromeo Nov 1, 2024
e695d8e
fix sql
giancarloromeo Nov 1, 2024
05d515c
fix datetime
giancarloromeo Nov 4, 2024
a66f145
fix gid
giancarloromeo Nov 4, 2024
f934a6a
fix validation
giancarloromeo Nov 4, 2024
f1ba05f
fix date timezone
giancarloromeo Nov 4, 2024
59b423e
fix required
giancarloromeo Nov 4, 2024
4905f4c
fix user prefs
giancarloromeo Nov 4, 2024
3c6cc75
fix query
giancarloromeo Nov 4, 2024
cf63244
fix column check
giancarloromeo Nov 4, 2024
ded3b25
Update packages/models-library/src/models_library/api_schemas_directo…
giancarloromeo Nov 5, 2024
bbe8ea2
remove pattern
giancarloromeo Nov 5, 2024
509a7ac
revert nullable
giancarloromeo Nov 5, 2024
f6e2128
remove constraint
giancarloromeo Nov 5, 2024
0034952
fix model_dump_json option
giancarloromeo Nov 5, 2024
9db58f7
fix fields
giancarloromeo Nov 5, 2024
d292788
fix
giancarloromeo Nov 5, 2024
59a64dc
remove frozen
giancarloromeo Nov 5, 2024
9a1bc00
fix jsondump
giancarloromeo Nov 5, 2024
f24cd19
minor fix
giancarloromeo Nov 5, 2024
4634acb
fix comments
giancarloromeo Nov 5, 2024
c74b2b2
fix nullable
giancarloromeo Nov 5, 2024
7b7d020
fix enum
giancarloromeo Nov 5, 2024
274e2cb
fix schema
giancarloromeo Nov 6, 2024
8aac73d
revert none
giancarloromeo Nov 6, 2024
399abc8
remove ignore
giancarloromeo Nov 6, 2024
e1b8401
revert gid cast
giancarloromeo Nov 6, 2024
c7d5f0c
fix comment
giancarloromeo Nov 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,35 @@
import datetime
import re
import warnings
from datetime import timedelta

from pydantic import TypeAdapter, field_validator


def _validate_legacy_timedelta_str(time_str: str | timedelta) -> str | timedelta:
if not isinstance(time_str, str):
return time_str

# Match the format [-][DD ][HH:MM]SS[.ffffff]
match = re.match(
r"^(?P<sign>-)?(?:(?P<days>\d+)\s)?(?:(?P<hours>\d+):)?(?:(?P<minutes>\d+):)?(?P<seconds>\d+)(?P<fraction>\.\d+)?$",
time_str,
)
if not match:
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
return time_str

# Extract components with defaults if not present
sign = match.group("sign") or ""
days = match.group("days") or "0"
hours = match.group("hours") or "0"
minutes = match.group("minutes") or "0"
seconds = match.group("seconds")
fraction = match.group("fraction") or ""

# Convert to the format [-][DD]D[,][HH:MM:]SS[.ffffff]
return f"{sign}{int(days)}D,{int(hours):02}:{int(minutes):02}:{seconds}{fraction}"
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved


def validate_numeric_string_as_timedelta(field: str):
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
"""Transforms a float/int number into a valid datetime as it used to work in the past"""

Expand All @@ -29,7 +54,7 @@ def _numeric_string_as_timedelta(
return converted_value
except ValueError:
# returns format like "1:00:00"
return v
return _validate_legacy_timedelta_str(v)
return v

return field_validator(field, mode="before")(_numeric_string_as_timedelta)
36 changes: 34 additions & 2 deletions packages/common-library/tests/test_pydantic_validators.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,45 @@
from datetime import timedelta
from typing import Annotated

import pytest
from common_library.pydantic_validators import validate_numeric_string_as_timedelta
from common_library.pydantic_validators import (
validate_legacy_timedelta_str,
validate_numeric_string_as_timedelta,
)
from faker import Faker
from pydantic import Field
from pydantic import BeforeValidator, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
from pytest_simcore.helpers.monkeypatch_envs import setenvs_from_dict


def test_validate_legacy_timedelta(monkeypatch: pytest.MonkeyPatch, faker: Faker):
class Settings(BaseSettings):
APP_NAME: str
REQUEST_TIMEOUT: Annotated[
timedelta, BeforeValidator(validate_legacy_timedelta_str)
] = Field(default=timedelta(hours=1))

model_config = SettingsConfigDict()

app_name = faker.pystr()
env_vars: dict[str, str | bool] = {"APP_NAME": app_name}

# without timedelta
setenvs_from_dict(monkeypatch, env_vars)
settings = Settings()
print(settings.model_dump())
assert app_name == settings.APP_NAME
assert timedelta(hours=1) == settings.REQUEST_TIMEOUT

# with timedelta in seconds
env_vars["REQUEST_TIMEOUT"] = "2 1:10:00"
setenvs_from_dict(monkeypatch, env_vars)
settings = Settings()
print(settings.model_dump())
assert app_name == settings.APP_NAME
assert timedelta(days=2, hours=1, minutes=10) == settings.REQUEST_TIMEOUT


def test_validate_timedelta_in_legacy_mode(
monkeypatch: pytest.MonkeyPatch, faker: Faker
):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Field,
HttpUrl,
NonNegativeFloat,
ValidationInfo,
field_validator,
model_validator,
)
Expand Down Expand Up @@ -96,7 +97,7 @@ class ClusterGet(Cluster):
alias="accessRights", default_factory=dict
)

model_config = ConfigDict(populate_by_name=True)
model_config = ConfigDict(extra="allow", populate_by_name=True)
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved

@model_validator(mode="before")
@classmethod
Expand All @@ -112,7 +113,7 @@ class ClusterDetailsGet(ClusterDetails):


class ClusterCreate(BaseCluster):
owner: GroupID | None # type: ignore[assignment]
owner: GroupID | None
authentication: ExternalClusterAuthentication
access_rights: dict[GroupID, ClusterAccessRights] = Field(
alias="accessRights", default_factory=dict
Expand Down Expand Up @@ -154,9 +155,9 @@ class ClusterCreate(BaseCluster):

@field_validator("thumbnail", mode="before")
@classmethod
def set_default_thumbnail_if_empty(cls, v, values):
def set_default_thumbnail_if_empty(cls, v, info: ValidationInfo):
if v is None:
cluster_type = values["type"]
cluster_type = info.data["type"]
default_thumbnails = {
ClusterTypeInModel.AWS.value: "https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/250px-Amazon_Web_Services_Logo.svg.png",
ClusterTypeInModel.ON_PREMISE.value: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Crystal_Clear_app_network_local.png/120px-Crystal_Clear_app_network_local.png",
Expand All @@ -167,15 +168,15 @@ def set_default_thumbnail_if_empty(cls, v, values):


class ClusterPatch(BaseCluster):
name: str | None # type: ignore[assignment]
description: str | None
type: ClusterTypeInModel | None # type: ignore[assignment]
owner: GroupID | None # type: ignore[assignment]
thumbnail: HttpUrl | None
endpoint: AnyUrl | None # type: ignore[assignment]
authentication: ExternalClusterAuthentication | None # type: ignore[assignment]
name: str | None = None # type: ignore[assignment]
description: str | None = None
type: ClusterTypeInModel | None = None # type: ignore[assignment]
owner: GroupID | None = None # type: ignore[assignment]
thumbnail: HttpUrl | None = None
endpoint: AnyUrl | None = None # type: ignore[assignment]
authentication: ExternalClusterAuthentication | None = None # type: ignore[assignment]
access_rights: dict[GroupID, ClusterAccessRights] | None = Field( # type: ignore[assignment]
alias="accessRights"
None, alias="accessRights"
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
)

model_config = ConfigDict(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ class ApiKeyGet(BaseModel):
api_secret: str

model_config = ConfigDict(
from_attributes=True,
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
json_schema_extra={
"examples": [
{"display_name": "myapi", "api_key": "key", "api_secret": "secret"},
]
}
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
class ClusterPathParams(BaseModel):
cluster_id: ClusterID
model_config = ConfigDict(
populate_by_name=True,
populate_by_name=True,
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
extra="forbid",
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class CreateFolderBodyParams(InputSchema):

class PutFolderBodyParams(InputSchema):
name: IDStr
parent_folder_id: FolderID | None
parent_folder_id: FolderID | None = None
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
model_config = ConfigDict(extra="forbid")

_null_or_none_str_to_none_validator = field_validator(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from contextlib import suppress

from pydantic import (
AnyHttpUrl,
AnyUrl,
BaseModel,
ConfigDict,
Expand Down Expand Up @@ -90,7 +91,7 @@ def _sanitize_legacy_data(cls, v):
if v:
# Enforces null if thumbnail is not valid URL or empty
with suppress(ValidationError):
return TypeAdapter(AnyUrl).validate_python(v)
return TypeAdapter(AnyHttpUrl).validate_python(v)
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
return None


Expand Down Expand Up @@ -143,12 +144,14 @@ class AllUsersGroups(BaseModel):


class GroupUserGet(BaseModel):
id: str | None = Field(None, description="the user id")
id: str | None = Field(None, description="the user id", coerce_numbers_to_str=True)
login: LowerCaseEmailStr | None = Field(None, description="the user login email")
first_name: str | None = Field(None, description="the user first name")
last_name: str | None = Field(None, description="the user last name")
gravatar_id: str | None = Field(None, description="the user gravatar id hash")
gid: str | None = Field(None, description="the user primary gid")
gid: str | None = Field(
None, description="the user primary gid", coerce_numbers_to_str=True
)
access_rights: GroupAccessRights = Field(..., alias="accessRights")

model_config = ConfigDict(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
"""

from datetime import datetime
from typing import Any, Literal, TypeAlias
from typing import Annotated, Any, Literal, TypeAlias

from pydantic import ConfigDict, Field, HttpUrl, field_validator
from models_library.folders import FolderID
from models_library.workspaces import WorkspaceID
from pydantic import BeforeValidator, ConfigDict, Field, HttpUrl, field_validator

from ..api_schemas_long_running_tasks.tasks import TaskGet
from ..basic_types import LongTruncatedStr, ShortTruncatedStr
Expand Down Expand Up @@ -105,7 +107,7 @@ class ProjectReplace(InputSchema):
uuid: ProjectID
name: ShortTruncatedStr
description: LongTruncatedStr
thumbnail: HttpUrl | None
thumbnail: Annotated[HttpUrl | None, BeforeValidator(empty_str_to_none_pre_validator)] = Field(default=None)
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
creation_date: DateTimeStr
last_change_date: DateTimeStr
workbench: NodesDict
Expand All @@ -121,25 +123,17 @@ class ProjectReplace(InputSchema):
default_factory=dict, json_schema_extra={"default": {}}
)

_empty_is_none = field_validator("thumbnail", mode="before")(
empty_str_to_none_pre_validator
)


class ProjectPatch(InputSchema):
name: ShortTruncatedStr | None = Field(default=None)
description: LongTruncatedStr | None = Field(default=None)
thumbnail: HttpUrl | None = Field(default=None)
thumbnail: Annotated[HttpUrl | None, BeforeValidator(empty_str_to_none_pre_validator)] = Field(default=None)
access_rights: dict[GroupIDStr, AccessRights] | None = Field(default=None)
classifiers: list[ClassifierID] | None = Field(default=None)
dev: dict | None = Field(default=None)
ui: StudyUI | None = Field(default=None)
quality: dict[str, Any] | None = Field(default=None)

_empty_is_none = field_validator("thumbnail", mode="before")(
empty_str_to_none_pre_validator
)



__all__: tuple[str, ...] = (
"EmptyModel",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
class NodeCreate(InputSchemaWithoutCamelCase):
service_key: ServiceKey
service_version: ServiceVersion
service_id: str | None
service_id: str | None = Field(default=None)
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved


BootOptions: TypeAlias = dict
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import datetime
from decimal import Decimal

from pydantic import BaseModel, ConfigDict
from pydantic import BaseModel, ConfigDict, Field

from ..projects import ProjectID
from ..projects_nodes_io import NodeID
Expand Down Expand Up @@ -48,7 +48,7 @@ class ServiceRunGet(
class PricingUnitGet(OutputSchema):
pricing_unit_id: PricingUnitId
unit_name: str
unit_extra_info: dict
unit_extra_info: UnitExtraInfo
current_cost_per_unit: Decimal
default: bool

Expand Down Expand Up @@ -131,7 +131,7 @@ class UpdatePricingUnitBodyParams(InputSchema):
unit_extra_info: UnitExtraInfo
default: bool
specific_info: SpecificInfo
pricing_unit_cost_update: PricingUnitCostUpdate | None
pricing_unit_cost_update: PricingUnitCostUpdate | None = Field(default=None)
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved

model_config = ConfigDict(
str_strip_whitespace=True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from decimal import Decimal
from typing import Annotated, Literal, TypeAlias

from pydantic import ConfigDict, Field, HttpUrl, PlainSerializer, field_validator
from pydantic import ConfigDict, Field, HttpUrl, PlainSerializer, ValidationInfo, field_validator

from ..basic_types import AmountDecimal, IDStr, NonNegativeDecimal
from ..users import GroupID
Expand All @@ -20,7 +20,10 @@ class WalletGet(OutputSchema):
created: datetime
modified: datetime

model_config = ConfigDict(frozen=False)
model_config = ConfigDict(
from_attributes=True,
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
frozen=False
)


class WalletGetWithAvailableCredits(WalletGet):
Expand Down Expand Up @@ -139,6 +142,7 @@ class PaymentMethodGet(OutputSchema):
)

model_config = ConfigDict(
frozen=False,
json_schema_extra={
"examples": [
{
Expand Down Expand Up @@ -200,8 +204,8 @@ class ReplaceWalletAutoRecharge(InputSchema):

@field_validator("monthly_limit_in_usd")
@classmethod
def _monthly_limit_greater_than_top_up(cls, v, values):
top_up = values["top_up_amount_in_usd"]
def _monthly_limit_greater_than_top_up(cls, v, info: ValidationInfo):
top_up = info.data["top_up_amount_in_usd"]
if v is not None and v < top_up:
msg = "Monthly limit ({v} USD) should be greater than top up amount ({top_up} USD)"
raise ValueError(msg)
Expand Down
3 changes: 2 additions & 1 deletion packages/models-library/src/models_library/clusters.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class Cluster(BaseCluster):
id: ClusterID = Field(..., description="The cluster ID")

model_config = ConfigDict(
extra="allow",
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved
json_schema_extra={
"examples": [
{
Expand Down Expand Up @@ -217,7 +218,7 @@ class Cluster(BaseCluster):
},
},
]
}
},
)

@model_validator(mode="before")
Expand Down
2 changes: 1 addition & 1 deletion packages/models-library/src/models_library/projects_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class StudyUI(BaseModel):
current_node_id: NodeID | None = Field(default=None, alias="currentNodeId")
annotations: dict[NodeIDStr, Annotation] | None = None

model_config = ConfigDict(extra="allow")
model_config = ConfigDict(extra="allow", populate_by_name=True)

_empty_is_none = field_validator("*", mode="before")(
empty_str_to_none_pre_validator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ class PricingUnitWithCostUpdate(BaseModel):
unit_extra_info: UnitExtraInfo
default: bool
specific_info: SpecificInfo
pricing_unit_cost_update: None | PricingUnitCostUpdate
pricing_unit_cost_update: None | PricingUnitCostUpdate = Field(default=None)
giancarloromeo marked this conversation as resolved.
Show resolved Hide resolved

model_config = ConfigDict(
json_schema_extra={
Expand Down
Loading
Loading