diff --git a/README.md b/README.md index 7374b7e..5bdc9d4 100644 --- a/README.md +++ b/README.md @@ -84,4 +84,5 @@ You can customize name and location of the fixture, but you will need to include ``` ## Upgrading from v1 -As `pytest-interface-tester` v2 is using `pydantic` v2 that introduces breaking changes to their API, you might need to adjust your tested charm to also support v2. See [migration guide](https://docs.pydantic.dev/latest/migration/) for more information. \ No newline at end of file +`pytest-interface-tester` supports both pydantic v1 and v2, but using v2 is recommended. +You might need to adjust your tested charm to also support v2. See [migration guide](https://docs.pydantic.dev/latest/migration/) for more information. \ No newline at end of file diff --git a/interface_tester/interface_test.py b/interface_tester/interface_test.py index b9d1f5b..86144c2 100644 --- a/interface_tester/interface_test.py +++ b/interface_tester/interface_test.py @@ -10,6 +10,7 @@ from enum import Enum from typing import Any, Callable, List, Literal, Optional, Union +import pydantic from ops.testing import CharmType from pydantic import ValidationError from scenario import Context, Event, Relation, State @@ -28,6 +29,14 @@ logger = logging.getLogger(__name__) +_has_pydantic_v1 = pydantic.version.VERSION.split(".") <= ["2"] + + +def _validate(model: pydantic.BaseModel, obj: dict): + if _has_pydantic_v1: + return model.validate(obj) + return model.model_validate(obj) + class InvalidTestCase(RuntimeError): """Raised if a function decorated with interface_test_case is invalid.""" @@ -283,7 +292,8 @@ def assert_schema_valid(self, schema: Optional["DataBagSchema"] = None): errors = [] for relation in self._relations: try: - databag_schema.model_validate( + _validate( + databag_schema, { "unit": relation.local_unit_data, "app": relation.local_app_data, @@ -441,7 +451,7 @@ def _get_endpoint(supported_endpoints: dict, role: Role, interface_name: str): return endpoints_for_interface[0] def _generate_relations_state( - self, state_template: State, input_state: State, supported_endpoints, role: Role + self, state_template: State, input_state: State, supported_endpoints, role: Role ) -> List[Relation]: """Merge the relations from the input state and the state template into one. diff --git a/tests/unit/test_collect_schemas.py b/tests/unit/test_collect_schemas.py index 9500021..5e97a1d 100644 --- a/tests/unit/test_collect_schemas.py +++ b/tests/unit/test_collect_schemas.py @@ -3,6 +3,7 @@ import pytest +from interface_tester.interface_test import _has_pydantic_v1 from interface_tester.collector import ( collect_tests, get_schema_from_module, @@ -70,8 +71,13 @@ class RequirerSchema(DataBagSchema): ) tests = collect_tests(root) - assert tests["mytestinterfacea"]["v0"]["requirer"]["schema"].model_fields["foo"].default == 1 - assert tests["mytestinterfaceb"]["v0"]["requirer"]["schema"].model_fields["foo"].default == 2 + if _has_pydantic_v1: + assert tests["mytestinterfacea"]["v0"]["requirer"]["schema"].__fields__["foo"].default == 1 + assert tests["mytestinterfaceb"]["v0"]["requirer"]["schema"].__fields__["foo"].default == 2 + + else: + assert tests["mytestinterfacea"]["v0"]["requirer"]["schema"].model_fields["foo"].default == 1 + assert tests["mytestinterfaceb"]["v0"]["requirer"]["schema"].model_fields["foo"].default == 2 def test_collect_invalid_schemas(tmp_path):