From ce4c679d93599be2d9ed540cd43274936ed4f0ff Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Tue, 30 Jun 2026 10:49:49 -0700 Subject: [PATCH 1/4] update env for upstream openff pydantic fixes --- environment.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/environment.yml b/environment.yml index fffb4b14..4dd6c1ea 100644 --- a/environment.yml +++ b/environment.yml @@ -22,3 +22,7 @@ dependencies: - typing-extensions - ipywidgets # opt - zstandard + - pip: + - git+https://github.com/openforcefield/openff-units/@define-pydantic-schema + - git+https://github.com/openforcefield/openff-interchange/@fix-pydantic + - pydantic==2.13.* From d155955e4ef03722f0e06e83b3201b5b808e37ba Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Tue, 30 Jun 2026 11:19:21 -0700 Subject: [PATCH 2/4] update expected serialization schema --- src/gufe/tests/test_models.py | 12 ++++++++---- src/gufe/vendor/openff/interchange/pydantic.py | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/gufe/tests/test_models.py b/src/gufe/tests/test_models.py index ee613e03..f6d71077 100644 --- a/src/gufe/tests/test_models.py +++ b/src/gufe/tests/test_models.py @@ -80,7 +80,7 @@ def test_settings_schema(): def test_openmmffsettings_schema(): - expected_schema = { + expected_val_schema = { "additionalProperties": False, "description": "Parameters to set up the force field with OpenMM ForceFields\n\n.. note::\n Currently, this stores what is needed for the\n :class:`openmmforcefields.system_generators.SystemGenerator` signature.\n See the `OpenMMForceField SystemGenerator documentation`_ for more details.\n\n\n.. _`OpenMMForceField SystemGenerator documentation`:\n https://github.com/openmm/openmmforcefields#automating-force-field-management-with-systemgenerator", "properties": { @@ -118,10 +118,14 @@ def test_openmmffsettings_schema(): "title": "OpenMMSystemGeneratorFFSettings", "type": "object", } - ser_schema = OpenMMSystemGeneratorFFSettings.model_json_schema(mode="serialization") + val_schema = OpenMMSystemGeneratorFFSettings.model_json_schema(mode="validation") - assert ser_schema == expected_schema - assert val_schema == expected_schema + assert val_schema == expected_val_schema + + ser_schema = OpenMMSystemGeneratorFFSettings.model_json_schema(mode="serialization") + expected_ser_schema = expected_val_schema.copy() + expected_ser_schema["properties"]["nonbonded_cutoff"]["default"] = {"val": 0.9, "unit": "nanometer"} + assert ser_schema == expected_ser_schema def test_default_settings(): diff --git a/src/gufe/vendor/openff/interchange/pydantic.py b/src/gufe/vendor/openff/interchange/pydantic.py index 88853fd8..52d70f89 100644 --- a/src/gufe/vendor/openff/interchange/pydantic.py +++ b/src/gufe/vendor/openff/interchange/pydantic.py @@ -15,7 +15,7 @@ class _BaseModel(BaseModel): ) def model_dump(self, **kwargs) -> dict[str, Any]: - return super().model_dump(serialize_as_any=True, **kwargs) + return super().model_dump(**kwargs) def model_dump_json(self, **kwargs) -> str: - return super().model_dump_json(serialize_as_any=True, **kwargs) + return super().model_dump_json(**kwargs) From 95249f9ffe6e43fe6dfd768f56d03bc83a3c6d21 Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Tue, 30 Jun 2026 11:36:56 -0700 Subject: [PATCH 3/4] temporary fix for new polymorphic_seralization --- src/gufe/settings/models.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gufe/settings/models.py b/src/gufe/settings/models.py index 7627bc17..d7e85889 100644 --- a/src/gufe/settings/models.py +++ b/src/gufe/settings/models.py @@ -96,9 +96,11 @@ def __eq__(self, other: Any) -> bool: # which results in frozen/unfrozen objects not being equal # https://github.com/pydantic/pydantic/blob/2486e068e85c51728c9f2d344cfee2f7e11d555c/pydantic/v1/main.py#L911 if isinstance(other, _BaseModel): - return self.model_dump() == other.model_dump() + return self.model_dump(polymorphic_serialization=True) == other.model_dump(polymorphic_serialization=True) + # TODO: as of pydantic 3.13, polymorphic_serialization is required, or else the default(?) will be used instead? + # https://pydantic.dev/docs/validation/latest/concepts/serialization#polymorphic-serialization else: - return self.model_dump() == other + return self.model_dump(polymorphic_serialization=True) == other class ThermoSettings(SettingsBaseModel): From f56747f73a015f9486c0767beb4cb6d0c4814c87 Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Tue, 30 Jun 2026 11:51:51 -0700 Subject: [PATCH 4/4] update validation schema --- environment.yml | 2 +- src/gufe/tests/test_models.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index 4dd6c1ea..6a8e6810 100644 --- a/environment.yml +++ b/environment.yml @@ -8,7 +8,7 @@ dependencies: - networkx - numpy - openff-toolkit-base >=0.15.1 - - openff-units >=0.3.1 + - openff-units >=0.3.2 - openmm - pint - pip diff --git a/src/gufe/tests/test_models.py b/src/gufe/tests/test_models.py index f6d71077..302dd376 100644 --- a/src/gufe/tests/test_models.py +++ b/src/gufe/tests/test_models.py @@ -110,6 +110,7 @@ def test_openmmffsettings_schema(): }, "nonbonded_method": {"default": "PME", "title": "Nonbonded Method", "type": "string"}, "nonbonded_cutoff": { + "default": '{"magnitude": 0.9, "units": "nanometer"}', "description": "Cutoff value for short range nonbonded interactions in nm. Compatible units will be converted to nm.", "title": "Nonbonded Cutoff", "type": "number",