Skip to content

Commit 8dff37f

Browse files
authored
Merge pull request #341 from dandi/serialize-any
Serialize anys values in `DandiBaseModel`
2 parents d858804 + 877eb2f commit 8dff37f

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

dandischema/models.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
EmailStr,
2727
Field,
2828
GetJsonSchemaHandler,
29+
SerializerFunctionWrapHandler,
2930
StringConstraints,
3031
TypeAdapter,
3132
ValidationInfo,
33+
field_serializer,
3234
field_validator,
3335
model_validator,
3436
)
@@ -41,6 +43,13 @@
4143
from .types import ByteSizeJsonSchema
4244
from .utils import name2title
4345

46+
try:
47+
from anys import AnyBase
48+
except ImportError:
49+
_has_anys = False
50+
else:
51+
_has_anys = True
52+
4453
# Use DJANGO_DANDI_WEB_APP_URL to point to a specific deployment.
4554
DANDI_INSTANCE_URL: Optional[str]
4655
try:
@@ -508,6 +517,14 @@ def json_dict(self) -> dict:
508517
)
509518
return self.model_dump(mode="json", exclude_none=True)
510519

520+
if _has_anys:
521+
522+
@field_serializer("*", mode="wrap")
523+
def preserve_anys_values(
524+
self, value: Any, handler: SerializerFunctionWrapHandler
525+
) -> Any:
526+
return value if isinstance(value, AnyBase) else handler(value)
527+
511528
@field_validator("schemaKey")
512529
@classmethod
513530
def ensure_schemakey(cls, val: str) -> str:

dandischema/tests/test_models.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from inspect import isclass
44
from typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union, cast
55

6+
import anys
67
import pydantic
78
from pydantic import Field, ValidationError
89
import pytest
@@ -36,6 +37,39 @@
3637
from ..utils import TransitionalGenerateJsonSchema
3738

3839

40+
@pytest.mark.parametrize(
41+
("y_type", "anys_value"),
42+
[
43+
(int, anys.ANY_INT),
44+
(str, anys.ANY_STR),
45+
(list, anys.ANY_LIST),
46+
(dict, anys.ANY_DICT),
47+
],
48+
)
49+
def test_serialize_anys_values(y_type: type, anys_value: anys.AnyBase) -> None:
50+
"""
51+
Test the serialization of invalid model instances constructed with the
52+
`model_construct` method containing `anys` values.
53+
"""
54+
55+
class NewModel(DandiBaseModel):
56+
x: int
57+
y: y_type # type: ignore[valid-type]
58+
59+
m = NewModel.model_construct(x=42, y=anys_value)
60+
61+
m_serialized = m.model_dump()
62+
x = m_serialized["x"]
63+
y = m_serialized["y"]
64+
65+
# Verify that `x` serialized as expected, as an int of value 42
66+
assert type(x) is int
67+
assert x == 42
68+
69+
# Verify that `y` serialized as itself
70+
assert y is anys_value
71+
72+
3973
def test_dandiset() -> None:
4074
assert Dandiset.model_construct() # type: ignore[call-arg]
4175

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ style =
5252
flake8
5353
pre-commit
5454
test =
55+
anys
5556
mypy
5657
pytest
5758
pytest-cov

0 commit comments

Comments
 (0)