Skip to content

Commit 8d07aff

Browse files
committed
fixes nullable and is_literal
1 parent 868227d commit 8d07aff

File tree

3 files changed

+41
-11
lines changed

3 files changed

+41
-11
lines changed
Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
from types import UnionType
2-
from typing import Any, Literal, get_args, get_origin
2+
from typing import Annotated, Any, Literal, Union, get_args, get_origin
33

44
from pydantic.fields import FieldInfo
55

6+
NoneType: type = type(None)
7+
68

79
def get_type(info: FieldInfo) -> Any:
810
field_type = info.annotation
911
if args := get_args(info.annotation):
10-
field_type = next(a for a in args if a is not type(None))
12+
field_type = next(a for a in args if a is not NoneType)
1113
return field_type
1214

1315

16+
def _unwrap_annotation(ann):
17+
"""Peel off Annotated wrappers until reaching the core type."""
18+
while get_origin(ann) is Annotated:
19+
ann = get_args(ann)[0]
20+
return ann
21+
22+
1423
def is_literal(info: FieldInfo) -> bool:
15-
return get_origin(info.annotation) is Literal
24+
ann = _unwrap_annotation(info.annotation)
25+
return get_origin(ann) is Literal
1626

1727

1828
def is_nullable(info: FieldInfo) -> bool:
19-
origin = get_origin(info.annotation) # X | None or Optional[X] will return Union
20-
if origin is UnionType:
21-
return any(x in get_args(info.annotation) for x in (type(None), Any))
22-
return False
29+
"""Checks whether a field allows None as a value."""
30+
ann = _unwrap_annotation(info.annotation)
31+
origin = get_origin(ann) # X | None or Optional[X] will return Union
32+
33+
if origin in (Union, UnionType):
34+
return any(arg is NoneType or arg is Any for arg in get_args(ann))
35+
36+
return ann is NoneType or ann is Any

packages/common-library/tests/test_pydantic_fields_extension.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from collections.abc import Callable
2-
from typing import Any, Literal
2+
from typing import Annotated, Any, Literal
33

44
import pytest
55
from common_library.pydantic_fields_extension import get_type, is_literal, is_nullable
6-
from pydantic import BaseModel
6+
from pydantic import BaseModel, PositiveInt
77

88

99
class MyModel(BaseModel):
@@ -12,6 +12,11 @@ class MyModel(BaseModel):
1212
c: str = "bla"
1313
d: bool | None = None
1414
e: Literal["bla"]
15+
f: Annotated[
16+
PositiveInt | None,
17+
"nullable inside Annotated (PositiveInt = Annotated[int, ...])",
18+
]
19+
g: Annotated[Literal["foo", "bar"], "literal inside Annotated"]
1520

1621

1722
@pytest.mark.parametrize(
@@ -50,6 +55,8 @@ class MyModel(BaseModel):
5055
),
5156
(is_literal, False, "d"),
5257
(is_literal, True, "e"),
58+
(is_literal, False, "f"),
59+
(is_literal, True, "g"),
5360
(
5461
is_nullable,
5562
False,
@@ -67,6 +74,11 @@ class MyModel(BaseModel):
6774
),
6875
(is_nullable, True, "d"),
6976
(is_nullable, False, "e"),
77+
(
78+
is_nullable,
79+
True,
80+
"f",
81+
),
7082
],
7183
)
7284
def test_field_fn(fn: Callable[[Any], Any], expected: Any, name: str):

services/web/server/src/simcore_service_webserver/users/_accounts_repository.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,17 +381,21 @@ async def search_merged_pre_and_registered_users(
381381
users_pre_registration_details.c.state,
382382
users_pre_registration_details.c.postal_code,
383383
users_pre_registration_details.c.country,
384-
users_pre_registration_details.c.user_id, # user_id from pre-registration
384+
users_pre_registration_details.c.user_id.label(
385+
"pre_reg_user_id"
386+
), # "copy" of user_id from pre-registration
385387
users_pre_registration_details.c.extras,
386388
users_pre_registration_details.c.account_request_status,
387389
users_pre_registration_details.c.account_request_reviewed_by,
388390
users_pre_registration_details.c.account_request_reviewed_at,
389-
users.c.status,
390391
invited_by,
391392
account_request_reviewed_by_username, # account_request_reviewed_by converted to username
392393
users_pre_registration_details.c.created,
394+
# NOTE: some users have no pre-registration details (e.g. s4l-lite)
395+
users.c.id.label("user_id"), # real user_id from users table
393396
users.c.name.label("user_name"),
394397
users.c.primary_gid.label("user_primary_group_id"),
398+
users.c.status,
395399
)
396400

397401
left_outer_join = _build_left_outer_join_query(

0 commit comments

Comments
 (0)