1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
from datetime import datetime
from typing import Optional
import pytest
import odmantic
from odmantic.field import Field
from odmantic.model import EmbeddedModel, Model
from odmantic.reference import Reference
def test_field_defined_as_primary_key_and_custom_name():
with pytest.raises(
ValueError, match="cannot specify a primary field with a custom key_name"
):
Field(primary_field=True, key_name="not _id")
def test_field_defined_as_primary_key_default_name():
f = Field(primary_field=True)
assert f.key_name == "_id"
def test_field_define_key_as__id_without_setting_as_primary():
with pytest.raises(
ValueError,
match="cannot specify key_name='_id' without defining the field as primary",
):
Field(key_name="_id")
def test_pos_key_name():
class M(Model):
field: int = Field(key_name="alternate_name")
assert +M.field == "alternate_name"
assert ++M.field == "$alternate_name"
def test_unknown_attr_embedded_model():
class E(EmbeddedModel): ...
class M(Model):
field: E
with pytest.raises(AttributeError):
M.field.unknown_attr # type: ignore
@pytest.mark.parametrize("operator_name", ("lt", "lte", "gt", "gte", "match"))
def test_reference_field_operator_not_allowed(operator_name: str):
class E(Model): ...
class M(Model):
field: E = Reference()
with pytest.raises(
AttributeError,
match=f"operator {operator_name} not allowed for ODMReference fields",
):
getattr(M.field, operator_name)
def test_field_required_in_doc_without_default():
class M(Model):
field: str
assert M.__odm_fields__["field"].is_required_in_doc()
def test_field_required_in_doc_with_default():
class M(Model):
field: str = Field("hi")
assert not M.__odm_fields__["field"].is_required_in_doc()
def test_field_required_in_doc_default_factory_disabled():
class M(Model):
field: str = Field(default_factory=lambda: "hi") # pragma: no cover
assert M.__odm_fields__["field"].is_required_in_doc()
def test_field_required_in_doc_default_factory_enabled():
class M(Model):
field: str = Field(default_factory=lambda: "hi") # pragma: no cover
model_config = {
"parse_doc_with_default_factories": True,
}
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]
)
instance = M(field="Hi")
# This should work and never throw a value error
instance.optionalBoolField = True
|