From dd7236f5c4225cb8cb7d885dda944ab378734497 Mon Sep 17 00:00:00 2001 From: "george.robertson1" <50412379+georgeRobertson@users.noreply.github.com> Date: Mon, 22 Jun 2026 13:17:40 +0100 Subject: [PATCH 1/2] fix: adjusted the `is_type_complex` function to work with subclasses of 'simple' types added some more tests around is complex and stringify model to ensure functionality is working --- src/dve/core_engine/backends/utilities.py | 8 ++- .../test_backends/test_utilities.py | 63 ++++++++++++++++++- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/dve/core_engine/backends/utilities.py b/src/dve/core_engine/backends/utilities.py index 6b8c5bc..f221212 100644 --- a/src/dve/core_engine/backends/utilities.py +++ b/src/dve/core_engine/backends/utilities.py @@ -1,5 +1,6 @@ """Necessary, otherwise uncategorised backend functionality.""" +import inspect import sys from dataclasses import is_dataclass from datetime import date, datetime, time @@ -41,10 +42,11 @@ def is_type_complex(type_: Any) -> bool: """Check whether a type is a complex type or not.""" - if type_ in (str, int, float, bool, bytes): - return False + _simple_types = (str, int, float, bool, bytes, date, datetime, time, Decimal) - if type_ in (date, datetime, time, Decimal): + if type_ in _simple_types or ( + inspect.isclass(type_) and any(issubclass(type_, st) for st in _simple_types) + ): return False return True diff --git a/tests/test_core_engine/test_backends/test_utilities.py b/tests/test_core_engine/test_backends/test_utilities.py index 839d9b7..1c9121f 100644 --- a/tests/test_core_engine/test_backends/test_utilities.py +++ b/tests/test_core_engine/test_backends/test_utilities.py @@ -1,10 +1,29 @@ -from datetime import date +""" +Test backend utility functions +""" + +# pylint: disable=C0115,C0116 + +from datetime import date, datetime +from decimal import Decimal from typing import Any import pytest from pydantic import BaseModel -from dve.core_engine.backends.utilities import is_field_complex +from dve.core_engine.backends.utilities import is_field_complex, stringify_model +from dve.metadata_parser.domain_types import FormattedDatetime + + +def model_to_schema(mdl: BaseModel) -> dict[str, Any]: + schema = {} + for field_name, field_md in mdl.model_fields.items(): + if issubclass(field_md.annotation, BaseModel): + schema[field_name] = model_to_schema(field_md.annotation) + else: + schema[field_name] = field_md.annotation + + return schema class AnotherTestModel(BaseModel): @@ -21,6 +40,23 @@ class TestModel(BaseModel): simple_tuple: tuple[int, str] another_model: AnotherTestModel date_example: date + test_fdatetime: FormattedDatetime + + +class ChildMultiTypeModel(BaseModel): + child_test_int: int + + +class MultiTypeModel(BaseModel): + test_str: str + test_int: int + test_dict: dict[str, int] + test_list: list[int] + test_decimal: Decimal + test_date: date + test_datetime: datetime + test_fdatetime: FormattedDatetime + test_child_model: ChildMultiTypeModel TEST_MODEL = TestModel( @@ -32,7 +68,8 @@ class TestModel(BaseModel): simple_set={"a", "b", "c"}, simple_tuple=(1, "wow"), another_model=AnotherTestModel(test_field="lemon"), - date_example=date(2026,1,1) + date_example=date(2026,1,1), + test_fdatetime="2026-01-01T12:30:10", ) @@ -47,9 +84,29 @@ class TestModel(BaseModel): ("simple_set", True), ("simple_tuple", True), ("another_model", True), + ("test_fdatetime", False), ] ) def test_is_field_complex(field_name: str, expected: bool): _field = TEST_MODEL.model_fields[field_name] _res = is_field_complex(_field) assert _res == expected, f"Expected {expected}. Got {_res}." + + +def test_stringify_model(): + expected_dict = { + "test_str": str, + "test_int": str, + "test_dict": dict[str, str], + "test_list": list[str], + "test_decimal": str, + "test_date": str, + "test_datetime": str, + "test_fdatetime": str, + "test_child_model": { + "child_test_int": str + }, + } + serialised_model_result = model_to_schema(stringify_model(MultiTypeModel)) + + assert expected_dict == serialised_model_result From 4d6b0825f9a2ed81c743a16e083e9104faee841e Mon Sep 17 00:00:00 2001 From: "george.robertson1" <50412379+georgeRobertson@users.noreply.github.com> Date: Mon, 22 Jun 2026 17:33:48 +0100 Subject: [PATCH 2/2] fix: inherit is_mandatory with get_type_and_validators This was causing custom type objects in the dischema to become unmandatory despite being lists in the mandatory_fields section --- src/dve/metadata_parser/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dve/metadata_parser/models.py b/src/dve/metadata_parser/models.py index fd8ed6f..49e2386 100644 --- a/src/dve/metadata_parser/models.py +++ b/src/dve/metadata_parser/models.py @@ -231,7 +231,7 @@ def get_type_and_validators( elif hasattr(possible_python_type, "get_type_and_validators"): possible_python_type: "FieldSpecification" # type: ignore nested_vals = possible_python_type.get_type_and_validators( # type: ignore - field_name, *type_mappings, schemas=schemas, is_mandatory=False + field_name, *type_mappings, schemas=schemas, is_mandatory=is_mandatory ) python_type, nested_default, nested_validators = nested_vals # type: ignore