From 9d1ea2f5d0e1019f0e4667b6777cec793aed7dce Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Tue, 1 Aug 2023 07:07:18 -0500 Subject: [PATCH 1/5] REF: Use Pydantic v1 API from v2 --- .github/workflows/ci.yaml | 5 +++++ .../_tests/unit_tests/components/test_interchange.py | 6 +++++- .../interchange/_tests/unit_tests/smirnoff/test_valence.py | 6 +++++- openff/interchange/common/_nonbonded.py | 6 +++++- openff/interchange/common/_valence.py | 6 +++++- openff/interchange/components/_base.py | 6 +++++- openff/interchange/components/interchange.py | 6 +++++- openff/interchange/components/mdconfig.py | 6 +++++- openff/interchange/components/potentials.py | 6 +++++- openff/interchange/drivers/report.py | 6 +++++- openff/interchange/foyer/_nonbonded.py | 6 +++++- openff/interchange/foyer/_valence.py | 6 +++++- openff/interchange/interop/gromacs/models/models.py | 6 +++++- openff/interchange/models.py | 6 +++++- openff/interchange/smirnoff/_nonbonded.py | 6 +++++- openff/interchange/smirnoff/_virtual_sites.py | 6 +++++- 16 files changed, 80 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 22cdd847b..e7413d13c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,6 +19,7 @@ defaults: jobs: test: + name: Test on ${{ matrix.os }}, Python ${{ matrix.python-version }}, OpenMM ${{ matrix.openmm }}, Pydantic ${{ matrix.pydantic-version }}, OpenEye ${{ matrix.openeye }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -30,6 +31,9 @@ jobs: - "3.9" - "3.10" - "3.11" + pydantic-version: + - "1" + - "2" openeye: - true - false @@ -50,6 +54,7 @@ jobs: environment-file: devtools/conda-envs/test_env.yaml create-args: >- python=${{ matrix.python-version }} + pydantic=${{ matrix.pydantic-version }} - name: Install package run: | diff --git a/openff/interchange/_tests/unit_tests/components/test_interchange.py b/openff/interchange/_tests/unit_tests/components/test_interchange.py index c4daa429c..267c97f96 100644 --- a/openff/interchange/_tests/unit_tests/components/test_interchange.py +++ b/openff/interchange/_tests/unit_tests/components/test_interchange.py @@ -10,7 +10,6 @@ ) from openff.units import unit from openff.utilities.testing import skip_if_missing -from pydantic import ValidationError from openff.interchange import Interchange from openff.interchange._tests import ( @@ -30,6 +29,11 @@ SMIRNOFFHandlersNotImplementedError, ) +try: + from pydantic.v1 import ValidationError +except ImportError: + from pydantic import ValidationError + @pytest.mark.slow() class TestInterchange(_BaseTest): diff --git a/openff/interchange/_tests/unit_tests/smirnoff/test_valence.py b/openff/interchange/_tests/unit_tests/smirnoff/test_valence.py index 4e6e14393..fad0a072d 100644 --- a/openff/interchange/_tests/unit_tests/smirnoff/test_valence.py +++ b/openff/interchange/_tests/unit_tests/smirnoff/test_valence.py @@ -15,7 +15,6 @@ ImproperTorsionHandler, ) from openff.units import unit -from pydantic import ValidationError from openff.interchange import Interchange from openff.interchange._tests import _BaseTest @@ -31,6 +30,11 @@ _check_molecule_uniqueness, ) +try: + from pydantic.v1 import ValidationError +except ImportError: + from pydantic import ValidationError + class TestSMIRNOFFValenceCollections(_BaseTest): def test_bond_collection(self, water): diff --git a/openff/interchange/common/_nonbonded.py b/openff/interchange/common/_nonbonded.py index 510bb88f9..42926c619 100644 --- a/openff/interchange/common/_nonbonded.py +++ b/openff/interchange/common/_nonbonded.py @@ -5,12 +5,16 @@ from openff.models.types import FloatQuantity from openff.units import Quantity, unit -from pydantic import Field, PrivateAttr from openff.interchange.components.potentials import Collection from openff.interchange.constants import _PME from openff.interchange.models import LibraryChargeTopologyKey, TopologyKey +try: + from pydantic.v1 import Field, PrivateAttr +except ImportError: + from pydantic import Field, PrivateAttr + class _NonbondedCollection(Collection, abc.ABC): # noqa type: str = "nonbonded" diff --git a/openff/interchange/common/_valence.py b/openff/interchange/common/_valence.py index a6ee15f82..fd8965572 100644 --- a/openff/interchange/common/_valence.py +++ b/openff/interchange/common/_valence.py @@ -2,10 +2,14 @@ from typing import Literal from openff.toolkit.topology.molecule import Atom -from pydantic import Field from openff.interchange.components.potentials import Collection +try: + from pydantic.v1 import Field +except ImportError: + from pydantic import Field + class ConstraintCollection(Collection): """Collection storing constraint potentials as produced by a SMIRNOFF force field.""" diff --git a/openff/interchange/components/_base.py b/openff/interchange/components/_base.py index d74c72f0e..bbe690cef 100644 --- a/openff/interchange/components/_base.py +++ b/openff/interchange/components/_base.py @@ -5,10 +5,14 @@ from openff.models.types import FloatQuantity from openff.units import unit -from pydantic import Field from openff.interchange.components.potentials import Collection +try: + from pydantic.v1 import Field +except ImportError: + from pydantic import Field + class BaseBondHandler(Collection): """Base handler for storing generic bond interactions.""" diff --git a/openff/interchange/components/interchange.py b/openff/interchange/components/interchange.py index 460638e72..75dbf4974 100644 --- a/openff/interchange/components/interchange.py +++ b/openff/interchange/components/interchange.py @@ -11,7 +11,6 @@ from openff.toolkit import ForceField, Molecule, Topology from openff.units import unit from openff.utilities.utilities import has_package, requires_package -from pydantic import Field, validator from openff.interchange._experimental import experimental from openff.interchange.common._nonbonded import ElectrostaticsCollection, vdWCollection @@ -35,6 +34,11 @@ from openff.interchange.smirnoff._virtual_sites import SMIRNOFFVirtualSiteCollection from openff.interchange.warnings import InterchangeDeprecationWarning +try: + from pydantic.v1 import Field, validator +except ImportError: + from pydantic import Field, validator + if has_package("foyer"): from foyer.forcefield import Forcefield as FoyerForcefield if has_package("nglview"): diff --git a/openff/interchange/components/mdconfig.py b/openff/interchange/components/mdconfig.py index bf8959f73..94603b04c 100644 --- a/openff/interchange/components/mdconfig.py +++ b/openff/interchange/components/mdconfig.py @@ -4,7 +4,6 @@ from openff.models.models import DefaultModel from openff.models.types import FloatQuantity from openff.units import unit -from pydantic import Field from openff.interchange.constants import _PME from openff.interchange.exceptions import ( @@ -12,6 +11,11 @@ UnsupportedExportError, ) +try: + from pydantic.v1 import Field +except ImportError: + from pydantic import Field + if TYPE_CHECKING: from openff.interchange import Interchange diff --git a/openff/interchange/components/potentials.py b/openff/interchange/components/potentials.py index 697433980..a8d39a0ea 100644 --- a/openff/interchange/components/potentials.py +++ b/openff/interchange/components/potentials.py @@ -9,7 +9,6 @@ from openff.models.types import ArrayQuantity, FloatQuantity from openff.units import unit from openff.utilities.utilities import has_package, requires_package -from pydantic import Field, PrivateAttr, validator from openff.interchange.exceptions import MissingParametersError from openff.interchange.models import ( @@ -19,6 +18,11 @@ ) from openff.interchange.warnings import InterchangeDeprecationWarning +try: + from pydantic.v1 import Field, PrivateAttr, validator +except ImportError: + from pydantic import Field, PrivateAttr, validator + if has_package("jax"): from jax import numpy as jax_numpy diff --git a/openff/interchange/drivers/report.py b/openff/interchange/drivers/report.py index 6fa00000e..9efa9ccca 100644 --- a/openff/interchange/drivers/report.py +++ b/openff/interchange/drivers/report.py @@ -5,7 +5,6 @@ from openff.models.models import DefaultModel from openff.models.types import FloatQuantity from openff.units import unit -from pydantic import validator from openff.interchange.constants import kj_mol from openff.interchange.exceptions import ( @@ -14,6 +13,11 @@ InvalidEnergyError, ) +try: + from pydantic.v1 import validator +except ImportError: + from pydantic import validator + _KNOWN_ENERGY_TERMS: set[str] = { "Bond", "Angle", diff --git a/openff/interchange/foyer/_nonbonded.py b/openff/interchange/foyer/_nonbonded.py index 42f336fd6..983288590 100644 --- a/openff/interchange/foyer/_nonbonded.py +++ b/openff/interchange/foyer/_nonbonded.py @@ -4,13 +4,17 @@ from openff.toolkit.topology import Topology from openff.units import Quantity, unit from openff.utilities.utilities import has_package -from pydantic import Field, PrivateAttr from openff.interchange.common._nonbonded import ElectrostaticsCollection, vdWCollection from openff.interchange.components.potentials import Potential from openff.interchange.foyer._base import _copy_params from openff.interchange.models import PotentialKey, TopologyKey +try: + from pydantic.v1 import Field, PrivateAttr +except ImportError: + from pydantic import Field, PrivateAttr + if has_package("foyer"): from foyer.forcefield import Forcefield diff --git a/openff/interchange/foyer/_valence.py b/openff/interchange/foyer/_valence.py index a5dcaa3c4..32ff6a9c5 100644 --- a/openff/interchange/foyer/_valence.py +++ b/openff/interchange/foyer/_valence.py @@ -1,6 +1,5 @@ from openff.toolkit.topology import Topology from openff.units import unit -from pydantic import Field from openff.interchange.common._valence import ( AngleCollection, @@ -16,6 +15,11 @@ ) from openff.interchange.models import PotentialKey, TopologyKey +try: + from pydantic.v1 import Field +except ImportError: + from pydantic import Field + class FoyerHarmonicBondHandler(FoyerConnectedAtomsHandler, BondCollection): """Handler storing bond potentials as produced by a Foyer force field.""" diff --git a/openff/interchange/interop/gromacs/models/models.py b/openff/interchange/interop/gromacs/models/models.py index d1283faa3..59cbbb13b 100644 --- a/openff/interchange/interop/gromacs/models/models.py +++ b/openff/interchange/interop/gromacs/models/models.py @@ -4,7 +4,11 @@ from openff.models.models import DefaultModel from openff.models.types import ArrayQuantity, FloatQuantity from openff.units import unit -from pydantic import Field, PositiveInt, PrivateAttr + +try: + from pydantic.v1 import Field, PositiveInt, PrivateAttr +except ImportError: + from pydantic import Field, PositiveInt, PrivateAttr class GROMACSAtomType(DefaultModel): diff --git a/openff/interchange/models.py b/openff/interchange/models.py index 99080c43a..e3fd6daa1 100644 --- a/openff/interchange/models.py +++ b/openff/interchange/models.py @@ -3,7 +3,11 @@ from typing import Literal, Optional from openff.models.models import DefaultModel -from pydantic import Field + +try: + from pydantic.v1 import Field +except ImportError: + from pydantic import Field class TopologyKey(DefaultModel, abc.ABC): diff --git a/openff/interchange/smirnoff/_nonbonded.py b/openff/interchange/smirnoff/_nonbonded.py index b69b5bdee..cb0a1278f 100644 --- a/openff/interchange/smirnoff/_nonbonded.py +++ b/openff/interchange/smirnoff/_nonbonded.py @@ -13,7 +13,6 @@ vdWHandler, ) from openff.units import Quantity, unit -from pydantic import Field from openff.interchange.common._nonbonded import ( ElectrostaticsCollection, @@ -39,6 +38,11 @@ ) from openff.interchange.smirnoff._base import SMIRNOFFCollection, T +try: + from pydantic.v1 import Field +except ImportError: + from pydantic import Field + ElectrostaticsHandlerType = Union[ ElectrostaticsHandler, ToolkitAM1BCCHandler, diff --git a/openff/interchange/smirnoff/_virtual_sites.py b/openff/interchange/smirnoff/_virtual_sites.py index 4b4755d07..9bc54ffbe 100644 --- a/openff/interchange/smirnoff/_virtual_sites.py +++ b/openff/interchange/smirnoff/_virtual_sites.py @@ -7,7 +7,6 @@ VirtualSiteHandler, ) from openff.units import unit -from pydantic import Field from openff.interchange.components.potentials import Potential from openff.interchange.components.toolkit import _validated_list_to_array @@ -18,6 +17,11 @@ SMIRNOFFvdWCollection, ) +try: + from pydantic.v1 import Field +except ImportError: + from pydantic import Field + # The use of `type` as a field name conflicts with the built-in `type()` when used with PEP 585 _ListOfHandlerTypes = list[type[ParameterHandler]] From 4b1a0f0039ac239e1dcd03af354147010e86f168 Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Tue, 1 Aug 2023 07:16:39 -0500 Subject: [PATCH 2/5] MAINT: Relax Pydantic constraint in environments --- devtools/conda-envs/beta_env.yaml | 2 +- devtools/conda-envs/dev_env.yaml | 2 +- devtools/conda-envs/examples_env.yaml | 2 +- devtools/conda-envs/minimal_env.yaml | 2 +- devtools/conda-envs/test_env.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/devtools/conda-envs/beta_env.yaml b/devtools/conda-envs/beta_env.yaml index 26266d95a..08d0997ef 100644 --- a/devtools/conda-envs/beta_env.yaml +++ b/devtools/conda-envs/beta_env.yaml @@ -9,7 +9,7 @@ dependencies: - python - pip - numpy >=1.21 - - pydantic >=1.10.8,<2.0.0a0 + - pydantic - openmm >=7.6 # OpenFF stack - openff-toolkit >=0.14 diff --git a/devtools/conda-envs/dev_env.yaml b/devtools/conda-envs/dev_env.yaml index bb9d7c5e5..2a94e4cf2 100644 --- a/devtools/conda-envs/dev_env.yaml +++ b/devtools/conda-envs/dev_env.yaml @@ -8,7 +8,7 @@ dependencies: - python - pip - numpy >=1.21 - - pydantic >=1.10.8,<2.0.0a0 + - pydantic - openmm # OpenFF stack - openff-toolkit >=0.14 diff --git a/devtools/conda-envs/examples_env.yaml b/devtools/conda-envs/examples_env.yaml index 9fd2b9f72..35765e7ac 100644 --- a/devtools/conda-envs/examples_env.yaml +++ b/devtools/conda-envs/examples_env.yaml @@ -8,7 +8,7 @@ dependencies: - python - pip - numpy >=1.21 - - pydantic >=1.10.8,<2.0.0a0 + - pydantic - openmm >=7.6 # OpenFF stack - openff-toolkit >=0.14 diff --git a/devtools/conda-envs/minimal_env.yaml b/devtools/conda-envs/minimal_env.yaml index 8fca5a264..ac8fc23d5 100644 --- a/devtools/conda-envs/minimal_env.yaml +++ b/devtools/conda-envs/minimal_env.yaml @@ -6,7 +6,7 @@ dependencies: # Core - python - pip - - pydantic >=1.10.8,<2.0.0a0 + - pydantic # OpenFF stack - openff-toolkit >=0.14 - openff-models >=0.0.4 diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index ac059e2b5..c9b0d4394 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -7,7 +7,7 @@ dependencies: - python - pip - numpy >=1.21 - - pydantic <2.0.0a0 + - pydantic - openmm >=7.6 # OpenFF stack - openff-toolkit >=0.14 From 469cdfb1f832e4b75b56e19206040b1fcbfc3ea5 Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Tue, 1 Aug 2023 07:47:12 -0500 Subject: [PATCH 3/5] MAINT: Use `openff-models=0.1.0beta0` --- devtools/conda-envs/beta_env.yaml | 3 ++- devtools/conda-envs/dev_env.yaml | 2 +- devtools/conda-envs/minimal_env.yaml | 2 +- devtools/conda-envs/test_env.yaml | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/devtools/conda-envs/beta_env.yaml b/devtools/conda-envs/beta_env.yaml index 08d0997ef..e77f7a5a7 100644 --- a/devtools/conda-envs/beta_env.yaml +++ b/devtools/conda-envs/beta_env.yaml @@ -2,6 +2,7 @@ name: beta-env channels: - jaimergp/label/unsupported-cudatoolkit-shim - conda-forge/label/openmm_rc + - conda-forge/label/openff-models_rc - conda-forge - openeye dependencies: @@ -13,7 +14,7 @@ dependencies: - openmm >=7.6 # OpenFF stack - openff-toolkit >=0.14 - - openff-models >=0.0.4 + - openff-models - openff-nagl - openff-nagl-models # Optional features diff --git a/devtools/conda-envs/dev_env.yaml b/devtools/conda-envs/dev_env.yaml index 2a94e4cf2..cbbbef47d 100644 --- a/devtools/conda-envs/dev_env.yaml +++ b/devtools/conda-envs/dev_env.yaml @@ -12,7 +12,7 @@ dependencies: - openmm # OpenFF stack - openff-toolkit >=0.14 - - openff-models >=0.0.4 + - openff-models - openff-nagl - openff-nagl-models # Optional features diff --git a/devtools/conda-envs/minimal_env.yaml b/devtools/conda-envs/minimal_env.yaml index ac8fc23d5..f66d486ad 100644 --- a/devtools/conda-envs/minimal_env.yaml +++ b/devtools/conda-envs/minimal_env.yaml @@ -9,7 +9,7 @@ dependencies: - pydantic # OpenFF stack - openff-toolkit >=0.14 - - openff-models >=0.0.4 + - openff-models # Testing - pytest - pytest-xdist diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index c9b0d4394..d7ea3a23f 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -1,6 +1,8 @@ name: openff-interchange-env channels: - jaimergp/label/unsupported-cudatoolkit-shim + - conda-forge/label/openff-models_rc + - conda-forge/label/openff-interchange_rc - conda-forge dependencies: # Core From 1d672f53f9d5d4c68a37a1a2ceff4c1f66fc2db5 Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Tue, 1 Aug 2023 12:12:02 -0500 Subject: [PATCH 4/5] MAINT: Drop Foyer until Pydantic v2 support --- devtools/conda-envs/test_env.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index d7ea3a23f..dae95c0c8 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -18,7 +18,8 @@ dependencies: # Optional features - unyt - mbuild - - foyer >=0.11.3 + # GMSO does not support Pydantic 2 + # foyer >=0.11.3 # Testing - mdtraj - intermol From 45839c7f3c6da3ba9a08013d5145f2ccd28325e7 Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Tue, 1 Aug 2023 12:34:50 -0500 Subject: [PATCH 5/5] TST: Skip Foyer test --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e7413d13c..47c4d7a73 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -85,7 +85,7 @@ jobs: - name: Run tests if: always() run: | - python -m pytest -r fE -nauto --durations=10 $COV openff/interchange/ -m "slow or not slow" + python -m pytest -r fE -nauto --durations=10 $COV openff/interchange/ -m "slow or not slow" --ignore=openff/interchange/_tests/energy_tests/test_energies.py - name: Run small molecule regression tests if: ${{ matrix.python-version == 3.9 && matrix.openeye == true }}