mirror of
https://github.com/p2p-ld/nwb-linkml.git
synced 2024-11-14 10:44:28 +00:00
test named slot, add skeletons for basemodel methods
This commit is contained in:
parent
016b81a5c5
commit
198ed3bcea
5 changed files with 84 additions and 4 deletions
|
@ -25,7 +25,7 @@ from linkml_runtime.utils.schemaview import SchemaView
|
||||||
|
|
||||||
from nwb_linkml.includes.base import (
|
from nwb_linkml.includes.base import (
|
||||||
BASEMODEL_CAST_WITH_VALUE,
|
BASEMODEL_CAST_WITH_VALUE,
|
||||||
BASEMODEL_COERCE_CHILD,
|
BASEMODEL_COERCE_SUBCLASS,
|
||||||
BASEMODEL_COERCE_VALUE,
|
BASEMODEL_COERCE_VALUE,
|
||||||
BASEMODEL_EXTRA_TO_VALUE,
|
BASEMODEL_EXTRA_TO_VALUE,
|
||||||
BASEMODEL_GETITEM,
|
BASEMODEL_GETITEM,
|
||||||
|
@ -56,7 +56,7 @@ class NWBPydanticGenerator(PydanticGenerator):
|
||||||
BASEMODEL_GETITEM,
|
BASEMODEL_GETITEM,
|
||||||
BASEMODEL_COERCE_VALUE,
|
BASEMODEL_COERCE_VALUE,
|
||||||
BASEMODEL_CAST_WITH_VALUE,
|
BASEMODEL_CAST_WITH_VALUE,
|
||||||
BASEMODEL_COERCE_CHILD,
|
BASEMODEL_COERCE_SUBCLASS,
|
||||||
BASEMODEL_EXTRA_TO_VALUE,
|
BASEMODEL_EXTRA_TO_VALUE,
|
||||||
)
|
)
|
||||||
split: bool = True
|
split: bool = True
|
||||||
|
|
|
@ -44,7 +44,7 @@ BASEMODEL_CAST_WITH_VALUE = """
|
||||||
raise e1
|
raise e1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
BASEMODEL_COERCE_CHILD = """
|
BASEMODEL_COERCE_SUBCLASS = """
|
||||||
@field_validator("*", mode="before")
|
@field_validator("*", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def coerce_subclass(cls, v: Any, info) -> Any:
|
def coerce_subclass(cls, v: Any, info) -> Any:
|
||||||
|
|
9
nwb_linkml/tests/fixtures/schema.py
vendored
9
nwb_linkml/tests/fixtures/schema.py
vendored
|
@ -101,6 +101,15 @@ def linkml_schema_bare() -> TestSchemas:
|
||||||
inlined_as_list=False,
|
inlined_as_list=False,
|
||||||
any_of=[{"range": "OtherClass"}, {"range": "StillAnotherClass"}],
|
any_of=[{"range": "OtherClass"}, {"range": "StillAnotherClass"}],
|
||||||
),
|
),
|
||||||
|
SlotDefinition(
|
||||||
|
name="named_slot",
|
||||||
|
description=(
|
||||||
|
"A slot that should use the Named[] generic to set the name param"
|
||||||
|
),
|
||||||
|
annotations=[{"named": True}],
|
||||||
|
range="OtherClass",
|
||||||
|
inlined=True,
|
||||||
|
),
|
||||||
SlotDefinition(
|
SlotDefinition(
|
||||||
name="value",
|
name="value",
|
||||||
description="Main class's array",
|
description="Main class's array",
|
||||||
|
|
|
@ -17,6 +17,7 @@ import pytest
|
||||||
from linkml_runtime.utils.compile_python import compile_python
|
from linkml_runtime.utils.compile_python import compile_python
|
||||||
from numpydantic.dtype import Float
|
from numpydantic.dtype import Float
|
||||||
from numpydantic.ndarray import NDArrayMeta
|
from numpydantic.ndarray import NDArrayMeta
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
from nwb_linkml.generators.pydantic import NWBPydanticGenerator
|
from nwb_linkml.generators.pydantic import NWBPydanticGenerator
|
||||||
|
|
||||||
|
@ -86,7 +87,9 @@ def imported_schema(linkml_schema, request) -> TestModules:
|
||||||
|
|
||||||
def test_array(imported_schema):
|
def test_array(imported_schema):
|
||||||
"""
|
"""
|
||||||
Arraylike classes are converted to slots that specify nptyping arrays
|
Arraylike classes are converted to slots that specify nptyping arrays.
|
||||||
|
|
||||||
|
Test that we can use any_of with the array slot (unlike the upstream generator, currently)
|
||||||
|
|
||||||
array: Optional[Union[
|
array: Optional[Union[
|
||||||
NDArray[Shape["* x, * y"], Number],
|
NDArray[Shape["* x, * y"], Number],
|
||||||
|
@ -155,3 +158,26 @@ def test_get_item(imported_schema):
|
||||||
"""We can get without explicitly addressing array"""
|
"""We can get without explicitly addressing array"""
|
||||||
cls = imported_schema["core"].MainTopLevel(value=np.array([[1, 2, 3], [4, 5, 6]], dtype=float))
|
cls = imported_schema["core"].MainTopLevel(value=np.array([[1, 2, 3], [4, 5, 6]], dtype=float))
|
||||||
assert np.array_equal(cls[0], np.array([1, 2, 3], dtype=float))
|
assert np.array_equal(cls[0], np.array([1, 2, 3], dtype=float))
|
||||||
|
|
||||||
|
|
||||||
|
def test_named_slot(imported_schema):
|
||||||
|
"""
|
||||||
|
Slots that have a ``named`` annotation should get their ``name`` attribute set automatically
|
||||||
|
"""
|
||||||
|
OtherClass = imported_schema["core"].OtherClass
|
||||||
|
MainClass = imported_schema["core"].MainTopLevel
|
||||||
|
|
||||||
|
# We did in fact get the outer annotation
|
||||||
|
# this is a wild ass way to get the function name but hey
|
||||||
|
annotation = MainClass.model_fields["named_slot"].annotation.__args__[0]
|
||||||
|
validation_fn_name = annotation.__metadata__[0].func.__name__
|
||||||
|
assert validation_fn_name == "_get_name"
|
||||||
|
|
||||||
|
# we can't instantiate OtherClass without the ``name``
|
||||||
|
with pytest.raises(ValidationError, match=".*name.*"):
|
||||||
|
_ = OtherClass()
|
||||||
|
|
||||||
|
# but when we instantiate MainClass the name gets set automatically
|
||||||
|
instance = MainClass(named_slot={})
|
||||||
|
assert isinstance(instance.named_slot, OtherClass)
|
||||||
|
assert instance.named_slot.name == "named_slot"
|
||||||
|
|
45
nwb_linkml/tests/test_includes/test_base.py
Normal file
45
nwb_linkml/tests/test_includes/test_base.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
"""
|
||||||
|
Base includes
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip
|
||||||
|
def test_basemodel_getitem(imported_schema):
|
||||||
|
"""
|
||||||
|
We can get a value from ``value`` if we have it
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip
|
||||||
|
def test_basemodel_coerce_value(imported_schema):
|
||||||
|
"""
|
||||||
|
We can instantiate something by trying to grab it's "value" item
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip
|
||||||
|
def test_basemodel_cast_with_value(imported_schema):
|
||||||
|
"""
|
||||||
|
Opposite of above, we try to cast **into** the ``value`` field
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip
|
||||||
|
def test_basemodel_coerce_subclass(imported_schema):
|
||||||
|
"""
|
||||||
|
We try to rescue by coercing to a child class if possible
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip
|
||||||
|
def test_basemodel_extra_to_value(imported_schema):
|
||||||
|
"""
|
||||||
|
We gather extra fields and put them into a value dict when it's present
|
||||||
|
"""
|
||||||
|
pass
|
Loading…
Reference in a new issue