Skip to content

Commit

Permalink
add example of object ref with createmodel
Browse files Browse the repository at this point in the history
  • Loading branch information
gilesknap committed Jul 17, 2023
1 parent 90ee451 commit 003f6b2
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
75 changes: 75 additions & 0 deletions examples/test_refs2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from __future__ import annotations

from typing import Dict, List, Optional

from pydantic import (
BaseModel,
ConfigDict,
Field,
create_model,
field_validator,
model_validator,
)

id_to_entity: Dict[str, Entity] = {}


class Entity(BaseModel):
name: str = Field(..., description="The name of this entity")
value: str = Field(..., description="The value of this entity")
ref: Optional[str] = Field(
default=None, description="Reference another Entity name"
)
model_config = ConfigDict(extra="forbid")

@model_validator(mode="after") # type: ignore
def add_ibek_attributes(cls, entity: Entity):
id_to_entity[entity.name] = entity

return entity


@field_validator("ref", mode="after")
def lookup_instance(cls, id):
try:
return id_to_entity[id]
except KeyError:
raise KeyError(f"object {id} not found in {list(id_to_entity)}")


validators = {"Entity": lookup_instance}

# add validator to the Entity class using create model
Entity2 = create_model(
"Entity",
__validators__=validators,
__base__=Entity,
) # type: ignore

args = {"entities": (List[Entity2], None)}
Entities = create_model(
"Entities", **args, __config__=ConfigDict(extra="forbid")
) # type: ignore


model1 = Entities(
**{
"entities": [
{"name": "one", "value": "OneValue"},
{"name": "two", "value": "TwoValue", "ref": "one"},
]
}
)

# demonstrate that entity one has a reference to entity two
assert model1.entities[1].ref.value == "OneValue"

# this should throw an error because entity one has illegal arguments
model2 = Entities(
**{
"entities": [
{"name": "one", "value": "OneValue", "illegal": "bad argument"},
{"name": "two", "value": "TwoValue", "ref": "one"},
]
}
)
1 change: 0 additions & 1 deletion src/ibek/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class BaseSettings(BaseModel):
"""A Base class for setting consistent Pydantic model configuration"""

model_config = ConfigDict(
arbitrary_types_allowed=True,
extra="forbid",
)

Expand Down
2 changes: 1 addition & 1 deletion tests/samples/pydantic/test.ibek.ioc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ entities:

- type: pydantic_test.AnAsynPort
name: AsynPort2
IP: 10.0.0.2
IPpp: 10.0.0.2

- type: pydantic_test.Consumer
name: A Consumer
Expand Down

0 comments on commit 003f6b2

Please sign in to comment.