Skip to content

Commit

Permalink
Support multiple optional fields in a model by removing a hack that r…
Browse files Browse the repository at this point in the history
…esulted in all optional fields being assigned the same type
  • Loading branch information
netomi authored and art049 committed Mar 18, 2024
1 parent 5d469e8 commit 2b3dcf6
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
8 changes: 3 additions & 5 deletions odmantic/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,9 @@ def validate_type(type_: Type) -> Type:
# generics is found
# https://github.com/pydantic/pydantic/issues/8354
if type_origin is Union:
new_root = Union[
int, str
] # We don't care about int,str since they will be replaced
setattr(new_root, "__args__", new_arg_types)
type_ = new_root # type: ignore
# as new_arg_types is a tuple, we can directly create a matching Union instance,
# instead of hacking our way around it: https://stackoverflow.com/a/72884529/3784643
type_ = Union[new_arg_types] # type: ignore
else:
type_ = GenericAlias(type_origin, new_arg_types) # type: ignore
return type_
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/test_field.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from datetime import datetime
from typing import Optional

import odmantic
import pytest

from odmantic.field import Field
Expand Down Expand Up @@ -89,3 +93,19 @@ class M(Model):
}

assert not M.__odm_fields__["field"].is_required_in_doc()


def test_multiple_optional_fields():
class M(Model):
field: str = Field(default_factory=lambda: "hi") # pragma: no cover
optionalBoolField: Optional[bool] = None
optionalDatetimeField: Optional[datetime] = None

assert M.__odm_fields__["optionalBoolField"].pydantic_field.annotation == Optional[bool]
assert M.__odm_fields__["optionalDatetimeField"].pydantic_field.annotation == Optional[odmantic.bson._datetime]

try:
instance = M(field="Hi")
instance.optionalBoolField = True
except:
pytest.fail("a boolean value can not be assigned to a boolean field")

Check warning on line 111 in tests/unit/test_field.py

View check run for this annotation

Codecov / codecov/patch

tests/unit/test_field.py#L110-L111

Added lines #L110 - L111 were not covered by tests

0 comments on commit 2b3dcf6

Please sign in to comment.