Skip to content

Commit

Permalink
fix some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gilesknap committed Jul 14, 2023
1 parent 0ba40e0 commit 3ab0625
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 33 deletions.
2 changes: 1 addition & 1 deletion src/ibek/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class BaseSettings(BaseModel):

def render_with_utils(context: Dict, template_text: str) -> str:
"""
Render a Jinja template with the global __utils__ object available
Render a Jinja template with the global __utils__ object in the context
"""
jinja_template = Template(template_text)
return jinja_template.render(context, __utils__=UTILS)
5 changes: 2 additions & 3 deletions src/ibek/ioc.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class Entity(BaseSettings):
deserialize entry point.
"""

# All entities have these two fields, others are added by make_entity_model
type: str = Field(description="The type of this entity")
entity_enabled: bool = Field(
description="enable or disable this entity instance", default=True
Expand All @@ -33,7 +32,7 @@ class Entity(BaseSettings):
def add_ibek_attributes(cls, entity: Entity):
"""Whole Entity model validation"""

# find any id fields in this Entity
# find the id field in this Entity if it has one
ids = set(a.name for a in entity.__definition__.args if isinstance(a, IdArg))

entity_dict = entity.model_dump()
Expand Down Expand Up @@ -71,7 +70,7 @@ def add_arg(name, typ, description, default):

if isinstance(arg, ObjectArg):

@field_validator(arg.name)
@field_validator(arg.name, mode="after")
def lookup_instance(cls, id):
try:
return id_to_entity[id]
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def get_support(samples: Path, yaml_file: str) -> Support:
# load from file
d = YAML(typ="safe").load(samples / f"{yaml_file}")
# create a support object from that dict
support = Support.deserialize(d)
support = Support(**d)
return support


Expand Down
32 changes: 19 additions & 13 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from ibek import __version__
from ibek.__main__ import cli
from ibek.ioc import clear_entity_model_ids, make_entity_models
from ibek.ioc import clear_entity_model_ids, make_entity_models, make_ioc_model
from ibek.support import Support

runner = CliRunner()
Expand Down Expand Up @@ -205,20 +205,26 @@ def test_build_startup_env_vars_and_post_ioc_init(

def test_loading_module_twice(tmp_path: Path, samples: Path, ibek_defs: Path):
"""
regression test to demonstrate that clear_entity_classes works and
allows us to call make_entity_classes more than once
Now that we use pydantic it is OK to create the same entity twice
Verify this.
"""

clear_entity_model_ids()
# When we deserialize the same yaml twice as we do in the full test suite
# we may get clashes in the namespace of generated Entity classes.
# This tests that we get a sensible error when we do
definition_file = ibek_defs / "pmac" / "pmac.ibek.support.yaml"
support = Support.deserialize(YAML(typ="safe").load(definition_file))
make_entity_models(support)
with pytest.raises(AssertionError) as ctx:
make_entity_models(support)
assert str(ctx.value) == "Entity classes already created for pmac"
definition_file = samples / "pydantic" / "test.ibek.support.yaml"
instance_file = samples / "pydantic" / "test.ibek.ioc.yaml"

support = Support(**YAML(typ="safe").load(definition_file))
entities1 = make_entity_models(support)
entities2 = make_entity_models(support)

generic_ioc1 = make_ioc_model(entities1)
generic_ioc2 = make_ioc_model(entities2)

instance = YAML(typ="safe").load(instance_file)
ioc1 = generic_ioc1(**instance)
ioc2 = generic_ioc2(**instance)

assert ioc1.model_dump() == ioc2.model_dump()


def test_bad_counter(tmp_path: Path, samples: Path):
Expand Down
45 changes: 31 additions & 14 deletions tests/test_conversions.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
from ibek.ioc import IOC, clear_entity_model_ids, id_to_entity, make_entity_models
from ibek.ioc import (
clear_entity_model_ids,
id_to_entity,
make_entity_models,
make_ioc_model,
)
from ibek.support import Definition, IdArg, ObjectArg, Support


def test_conversion_classes():
clear_entity_model_ids()

support = Support(
"mymodule",
[
Definition("port", "A port", [IdArg("name", "the name", "id")]),
Definition("device", "a device", [ObjectArg("port", "the port", "object")]),
module="mymodule",
defs=[
Definition(
name="port",
description="a port",
args=[IdArg(name="name", description="an id")],
),
Definition(
name="device",
description="a device",
args=[ObjectArg(name="port", description="the port")],
),
],
)
namespace = make_entity_models(support)
assert {"device", "port"}.issubset(dir(namespace))
assert namespace.port.__definition__ == support.defs[0]
assert namespace.device.__definition__ == support.defs[1]

entities = make_entity_models(support)
ioc_model = make_ioc_model(entities)
assert entities[0].__definition__ == support.defs[0]
assert entities[1].__definition__ == support.defs[1]

d = dict(
ioc_name="",
description="",
Expand All @@ -24,9 +40,10 @@ def test_conversion_classes():
],
generic_ioc_image="",
)
ioc = IOC.deserialize(d)
ioc = ioc_model(**d)
port, device = ioc.entities
assert port.type == "mymodule.port"
assert id_to_entity == {"PORT": port}
assert device.type == "mymodule.device"
assert device.port is port
# TODO try to get rid of the need for '.root'
assert port.root.type == "mymodule.port"
assert device.root.type == "mymodule.device"
assert device.root.port is port.root
assert id_to_entity == {"PORT": port.root}
13 changes: 12 additions & 1 deletion tests/test_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@
Tests for the rendering of scripts and database entries from generated
Entity classes
"""
from typing import Literal
from unittest.mock import Mock

from ibek.ioc import IOC
from ibek.render import Render


def test_pmac_asyn_ip_port_script(pmac_classes):
generated_class = pmac_classes.PmacAsynIPPort
for entity_class in pmac_classes:
# TODO is this the easiest way to find the entity class?
if (
entity_class.model_fields["type"].annotation
== Literal["pmac.PmacAsynIPPort"]
):
generated_class = entity_class
break
else:
raise ValueError("PmacAsynIPPort not found in pmac_classes")

pmac_asyn_ip = generated_class(name="my_pmac_instance", IP="111.111.111.111")

render = Render()
Expand Down

0 comments on commit 3ab0625

Please sign in to comment.