diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0a536621..ec194638 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,7 +18,7 @@ jobs: test: - name: 💻 ${{ matrix.os }}, 🐍 ${{ matrix.python-version }}, 👀 ${{ matrix.openeye }}, pymbar ${{ matrix.pymbar-version }}, OpenMM ${{ matrix.openmm-version }} + name: 💻 ${{ matrix.os }}, 🐍 ${{ matrix.python-version }}, 👀 ${{ matrix.openeye }}, pymbar ${{ matrix.pymbar-version }}, Pydantic ${{ matrix.pydantic-version }}, OpenMM ${{ matrix.openmm-version }} runs-on: ${{ matrix.os }} env: @@ -35,6 +35,9 @@ jobs: - "3.10" pymbar-version: - "3.1" + pydantic-version: + - "1" + - "2" openmm-version: - "7" - "8" @@ -55,9 +58,8 @@ jobs: create-args: >- python=${{ matrix.python-version }} pymbar=${{ matrix.pymbar-version }} + pydantic=${{ matrix.pydantic-version }} openmm=${{ matrix.openmm-version }} - jax>=0.3 - jaxlib>=0.3 - name: Install OpenEye if: matrix.openeye @@ -69,6 +71,11 @@ jobs: env: SECRET_OE_LICENSE: ${{ secrets.OE_LICENSE }} + - name: Install Foyer + if: ${{ matrix.pydantic-version == 1 }} + shell: bash -l {0} + run: micromamba install foyer -c conda-forge + - name: Install PASCAL Compiler (MacOS) if: startsWith(matrix.os, 'macOS') run: brew install fpc @@ -88,20 +95,19 @@ jobs: - name: Install Package and test plugins run: python -m pip install . utilities/test_plugins/ - - name: Conda Environment Information - run: conda info && conda list - - name: Run tests run: python -m pytest -v --cov=openff openff/evaluator/_tests/ --cov-report=xml --color=yes - name: Run (non-GPU) tutorials - if: ${{ matrix.pymbar-version == 3 }} + if: ${{ matrix.pymbar-version == 3.1 }} run: | # ForceBalance requires pymbar 3, so don't run these tests if we are using pymbar 4, # even though we're not running the fitting tutorial # https://github.com/conda-forge/forcebalance-feedstock/blob/9793b0205489f8ec7826d301a3c82cfb96997c57/recipe/meta.yaml#L29 micromamba install "forcebalance >=1.9.5" -c conda-forge -yq - python -m pytest --nbval-lax docs/tutorials/tutorial01.ipynb docs/tutorials/tutorial03.ipynb + python -m pytest --nbval-lax --dist loadscope -nauto -p no:randomly \ + docs/tutorials/tutorial01.ipynb \ + docs/tutorials/tutorial03.ipynb - name: Code coverage uses: codecov/codecov-action@v3 diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index cc4f8cbc..113dc0e7 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -15,7 +15,8 @@ dependencies: - nbval - requests-mock # For testing http requests. # smirnoff-plugins =0.0.3 - - foyer + # Add back when MoSDeF supports pydantic v2 + # foyer # Shims - pint =0.20.1 @@ -32,7 +33,7 @@ dependencies: - pyyaml - requests - python-dateutil - - pydantic <2.0.0a0 + - pydantic - paprika - taproom - dataclasses diff --git a/openff/evaluator/_pydantic.py b/openff/evaluator/_pydantic.py new file mode 100644 index 00000000..ff625be9 --- /dev/null +++ b/openff/evaluator/_pydantic.py @@ -0,0 +1,32 @@ +try: + from pydantic.v1 import ( + BaseModel, + Field, + HttpUrl, + PositiveFloat, + PositiveInt, + ValidationError, + confloat, + conint, + conlist, + constr, + root_validator, + validator, + ) + from pydantic.v1.validators import dict_validator +except ModuleNotFoundError: + from pydantic import ( + BaseModel, + Field, + HttpUrl, + PositiveFloat, + PositiveInt, + ValidationError, + confloat, + conint, + conlist, + constr, + root_validator, + validator, + ) + from pydantic.validators import dict_validator diff --git a/openff/evaluator/_tests/test_datasets/test_curation/test_filtering.py b/openff/evaluator/_tests/test_datasets/test_curation/test_filtering.py index fed328c6..09be395c 100644 --- a/openff/evaluator/_tests/test_datasets/test_curation/test_filtering.py +++ b/openff/evaluator/_tests/test_datasets/test_curation/test_filtering.py @@ -4,8 +4,8 @@ import pandas import pytest from openff.units import unit -from pydantic import ValidationError +from openff.evaluator._pydantic import ValidationError from openff.evaluator.datasets import ( MeasurementSource, PhysicalPropertyDataSet, diff --git a/openff/evaluator/_tests/test_protocols/test_forcefield.py b/openff/evaluator/_tests/test_protocols/test_forcefield.py index 1b3d7bd5..b1937161 100644 --- a/openff/evaluator/_tests/test_protocols/test_forcefield.py +++ b/openff/evaluator/_tests/test_protocols/test_forcefield.py @@ -8,6 +8,7 @@ from openff.toolkit.topology import Molecule from openff.toolkit.utils.rdkit_wrapper import RDKitToolkitWrapper from openff.units import unit +from openff.utilities import skip_if_missing from openff.evaluator._tests.utils import build_tip3p_smirnoff_force_field from openff.evaluator.backends import ComputeResources @@ -168,6 +169,7 @@ def download_callback(_, context): assert path.isfile(assign_parameters.parameterized_system.system_path) +@skip_if_missing("foyer") def test_build_foyer_oplsaa_system(): force_field_source = FoyerForceFieldSource("oplsaa") substance = Substance.from_components("C", "CC", "c1ccccc1", "CC(=O)O") @@ -202,6 +204,7 @@ def test_build_foyer_oplsaa_system(): assert path.isfile(energy_minimisation.output_coordinate_file) +@skip_if_missing("foyer") def test_build_foyer_xml_system(): with tempfile.TemporaryDirectory() as directory: force_field_source_path = path.join(directory, "ff.json") diff --git a/openff/evaluator/datasets/curation/components/components.py b/openff/evaluator/datasets/curation/components/components.py index d6589435..289c4d30 100644 --- a/openff/evaluator/datasets/curation/components/components.py +++ b/openff/evaluator/datasets/curation/components/components.py @@ -3,8 +3,8 @@ from typing import overload import pandas -from pydantic import BaseModel +from openff.evaluator._pydantic import BaseModel from openff.evaluator.datasets import PhysicalPropertyDataSet logger = logging.getLogger(__name__) diff --git a/openff/evaluator/datasets/curation/components/conversion.py b/openff/evaluator/datasets/curation/components/conversion.py index f3f7387a..cffed9e3 100644 --- a/openff/evaluator/datasets/curation/components/conversion.py +++ b/openff/evaluator/datasets/curation/components/conversion.py @@ -5,9 +5,9 @@ from typing import TYPE_CHECKING, Union import pandas -from pydantic import Field from typing_extensions import Literal +from openff.evaluator._pydantic import Field from openff.evaluator.datasets.curation.components import ( CurationComponent, CurationComponentSchema, @@ -19,7 +19,7 @@ PositiveFloat = float else: - from pydantic import conint + from openff.evaluator._pydantic import conint logger = logging.getLogger(__name__) diff --git a/openff/evaluator/datasets/curation/components/filtering.py b/openff/evaluator/datasets/curation/components/filtering.py index f0eb297c..34c425b1 100644 --- a/openff/evaluator/datasets/curation/components/filtering.py +++ b/openff/evaluator/datasets/curation/components/filtering.py @@ -7,10 +7,10 @@ import numpy import pandas from openff.units import unit -from pydantic import Field, root_validator, validator from scipy.optimize import linear_sum_assignment from typing_extensions import Literal +from openff.evaluator._pydantic import Field, root_validator, validator from openff.evaluator.datasets.curation.components import ( CurationComponent, CurationComponentSchema, @@ -31,7 +31,13 @@ PositiveFloat = float else: - from pydantic import PositiveFloat, PositiveInt, confloat, conint, constr + from openff.evaluator._pydantic import ( + PositiveFloat, + PositiveInt, + confloat, + conint, + constr, + ) logger = logging.getLogger(__name__) diff --git a/openff/evaluator/datasets/curation/components/selection.py b/openff/evaluator/datasets/curation/components/selection.py index fd07c651..5edb74c2 100644 --- a/openff/evaluator/datasets/curation/components/selection.py +++ b/openff/evaluator/datasets/curation/components/selection.py @@ -5,9 +5,9 @@ import numpy import pandas -from pydantic import BaseModel, Field, conlist, validator from typing_extensions import Literal +from openff.evaluator._pydantic import BaseModel, Field, conlist, validator from openff.evaluator.datasets.curation.components import ( CurationComponent, CurationComponentSchema, @@ -36,7 +36,7 @@ OEFingerPrint = None else: - from pydantic import PositiveInt + from openff.evaluator._pydantic import PositiveInt class State(BaseModel): diff --git a/openff/evaluator/datasets/curation/components/thermoml.py b/openff/evaluator/datasets/curation/components/thermoml.py index 6cf85a9d..9f2c31f0 100644 --- a/openff/evaluator/datasets/curation/components/thermoml.py +++ b/openff/evaluator/datasets/curation/components/thermoml.py @@ -8,9 +8,9 @@ import pandas import requests -from pydantic import Field, HttpUrl from typing_extensions import Literal +from openff.evaluator._pydantic import Field, HttpUrl from openff.evaluator.datasets.curation.components import ( CurationComponent, CurationComponentSchema, diff --git a/openff/evaluator/datasets/curation/workflow.py b/openff/evaluator/datasets/curation/workflow.py index 11375e38..b1521a50 100644 --- a/openff/evaluator/datasets/curation/workflow.py +++ b/openff/evaluator/datasets/curation/workflow.py @@ -3,8 +3,8 @@ import numpy import pandas -from pydantic import BaseModel, Field +from openff.evaluator._pydantic import BaseModel, Field from openff.evaluator.datasets import PhysicalPropertyDataSet from openff.evaluator.datasets.curation.components import CurationComponent from openff.evaluator.datasets.curation.components.conversion import ( diff --git a/setup.cfg b/setup.cfg index 2bdf6fac..1a1cbc08 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,6 +13,7 @@ ignore = E203, E266, E501, W503 select = B,C,E,F,W,T4,B9 per-file-ignores = openff/evaluator/__init__.py:F401 + openff/evaluator/_pydantic.py:F401 [isort] multi_line_output=3