From 2e163a031f6ca013f0fdbfe51532e20797224f2d Mon Sep 17 00:00:00 2001 From: Mike Henry <11765982+mikemhenry@users.noreply.github.com> Date: Fri, 5 Jun 2026 13:43:37 -0700 Subject: [PATCH 1/7] Test Python 3.14 --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 98db567a4..a274f05bf 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -23,7 +23,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - python-version: ["3.12", "3.13"] + python-version: ["3.12", "3.13", "3.14"] rdkit: [true, false] openeye: [true, false] nagl: [true, false] From a490f276ed709d3555428a55ad9d9cb6a86064e7 Mon Sep 17 00:00:00 2001 From: Mike Henry <11765982+mikemhenry@users.noreply.github.com> Date: Thu, 11 Jun 2026 07:04:43 -0700 Subject: [PATCH 2/7] no python 3.14 builds for ambertools (yet) --- devtools/conda-envs/rdkit-examples.yaml | 1 - devtools/conda-envs/rdkit.yaml | 1 - devtools/conda-envs/test_env.yaml | 1 - 3 files changed, 3 deletions(-) diff --git a/devtools/conda-envs/rdkit-examples.yaml b/devtools/conda-envs/rdkit-examples.yaml index 6ac9bf115..19e6bbe64 100644 --- a/devtools/conda-envs/rdkit-examples.yaml +++ b/devtools/conda-envs/rdkit-examples.yaml @@ -23,7 +23,6 @@ dependencies: - typing_extensions - nglview # Toolkit-specific - - ambertools # https://github.com/rdkit/rdkit/issues/7221 and https://github.com/rdkit/rdkit/issues/7583 - rdkit =2024 # Test-only/optional/dev/typing/examples diff --git a/devtools/conda-envs/rdkit.yaml b/devtools/conda-envs/rdkit.yaml index 6f1d980ce..b2cc3d923 100644 --- a/devtools/conda-envs/rdkit.yaml +++ b/devtools/conda-envs/rdkit.yaml @@ -22,7 +22,6 @@ dependencies: - openff-nagl-models >=0.3.0 - typing_extensions # Toolkit-specific - - ambertools >=22 # https://github.com/rdkit/rdkit/issues/7221 and https://github.com/rdkit/rdkit/issues/7583 - rdkit !=2024.03.6,!=2024.03.5 # Test-only/optional/dev/typing diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index 29c16d47b..47aace469 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -23,7 +23,6 @@ dependencies: - openff-nagl-models >=0.3.0 - typing_extensions # Toolkit-specific - - ambertools >=22 # rdkit 2024.03.6 and 2024.09.1 packages fail when run natively on osx-arm64 macs # https://github.com/rdkit/rdkit/issues/7583 - rdkit !=2024.03.6,!=2024.09.1 From 6e0f39cc2afdb07c38f9ef2021bd2f089fd4f4e3 Mon Sep 17 00:00:00 2001 From: Mike Henry <11765982+mikemhenry@users.noreply.github.com> Date: Thu, 11 Jun 2026 07:13:37 -0700 Subject: [PATCH 3/7] skip python 3.14 builds with openeye --- .github/workflows/CI.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a274f05bf..d52217db9 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,6 +32,8 @@ jobs: openeye: false - openeye: true python-version: "3.13" + - openeye: true + python-version: "3.14" - rdkit: false nagl: true From abd067b3376e832634130e723fcd94e64b36ac51 Mon Sep 17 00:00:00 2001 From: Mike Henry <11765982+mikemhenry@users.noreply.github.com> Date: Thu, 11 Jun 2026 07:17:57 -0700 Subject: [PATCH 4/7] unpin numpy --- devtools/conda-envs/rdkit-examples.yaml | 2 +- devtools/conda-envs/rdkit.yaml | 2 +- devtools/conda-envs/test_env.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/devtools/conda-envs/rdkit-examples.yaml b/devtools/conda-envs/rdkit-examples.yaml index 19e6bbe64..bf943d019 100644 --- a/devtools/conda-envs/rdkit-examples.yaml +++ b/devtools/conda-envs/rdkit-examples.yaml @@ -6,7 +6,7 @@ dependencies: - python - versioningit - packaging - - numpy <2.3 + - numpy - networkx - cachetools # https://github.com/openforcefield/openff-toolkit/issues/2150 diff --git a/devtools/conda-envs/rdkit.yaml b/devtools/conda-envs/rdkit.yaml index b2cc3d923..d7270ce5d 100644 --- a/devtools/conda-envs/rdkit.yaml +++ b/devtools/conda-envs/rdkit.yaml @@ -6,7 +6,7 @@ dependencies: - python - versioningit - packaging - - numpy <2.3 + - numpy - networkx - cachetools # https://github.com/openforcefield/openff-toolkit/issues/2150 diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index 47aace469..5004795ec 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -7,7 +7,7 @@ dependencies: - python - versioningit - packaging - - numpy <2.3 + - numpy - networkx - cachetools # https://github.com/openforcefield/openff-toolkit/issues/2150 From bd89bb26580b1fc97e1dc84fbdb99f45a6bf42f0 Mon Sep 17 00:00:00 2001 From: Mike Henry <11765982+mikemhenry@users.noreply.github.com> Date: Thu, 11 Jun 2026 11:14:54 -0700 Subject: [PATCH 5/7] see if this fixes it --- devtools/scripts/build_cookiecutter_json.py | 2 + docs/conf.py | 2 + docs/conftest.py | 1 + docs/users/molecule_cookbook.ipynb | 2 + docs/users/pdb_cookbook/index.ipynb | 2 + .../QCarchive_interface.ipynb | 2 + .../SMIRNOFF_simulation/run_simulation.ipynb | 2 + .../conformer_energies.ipynb | 2 + .../conformer_energies/conformer_energies.py | 2 + examples/examples_helper.py | 1 + .../forcefield_modification.ipynb | 2 + .../inspect_assigned_parameters.ipynb | 2 + .../toolkit_showcase/toolkit_showcase.ipynb | 2 + .../export_with_interchange.ipynb | 2 + .../BRD4_inhibitor_benchmark.ipynb | 2 + examples/virtual_sites/vsite_showcase.ipynb | 2 + examples/visualization/visualization.ipynb | 2 + openff/toolkit/__init__.py | 1 + openff/toolkit/_tests/_stale_tests.py | 2 + openff/toolkit/_tests/conftest.py | 1 + openff/toolkit/_tests/create_molecules.py | 1 + openff/toolkit/_tests/mocking.py | 2 + .../_tests/molecule/test_state_enumeration.py | 2 + openff/toolkit/_tests/test_energies.py | 2 + openff/toolkit/_tests/test_examples.py | 1 + openff/toolkit/_tests/test_forcefield.py | 1 + openff/toolkit/_tests/test_interchange.py | 2 + openff/toolkit/_tests/test_io.py | 1 + openff/toolkit/_tests/test_links.py | 2 + openff/toolkit/_tests/test_mm_molecule.py | 2 + openff/toolkit/_tests/test_molecule.py | 1 + openff/toolkit/_tests/test_nagl.py | 2 + .../toolkit/_tests/test_parameter_plugins.py | 1 + openff/toolkit/_tests/test_parameters.py | 1 + openff/toolkit/_tests/test_toolkit_io.py | 1 + openff/toolkit/_tests/test_toolkits.py | 1 + openff/toolkit/_tests/test_topology.py | 1 + openff/toolkit/_tests/test_utils.py | 1 + openff/toolkit/_tests/test_utils_callback.py | 1 + .../toolkit/_tests/test_utils_collections.py | 1 + .../_tests/test_utils_serialization.py | 1 + openff/toolkit/_tests/utils.py | 1 + openff/toolkit/topology/__init__.py | 2 + openff/toolkit/topology/_mm_molecule.py | 65 ++++++++++--------- openff/toolkit/topology/molecule.py | 58 ++++++++--------- openff/toolkit/topology/topology.py | 38 +++++------ .../typing/engines/smirnoff/__init__.py | 2 + .../typing/engines/smirnoff/forcefield.py | 31 ++++----- openff/toolkit/typing/engines/smirnoff/io.py | 1 + .../typing/engines/smirnoff/parameters.py | 33 +++++----- .../typing/engines/smirnoff/plugins.py | 1 + openff/toolkit/utils/__init__.py | 2 + openff/toolkit/utils/_viz.py | 6 +- openff/toolkit/utils/ambertools_wrapper.py | 5 +- openff/toolkit/utils/base_wrapper.py | 5 +- openff/toolkit/utils/builtin_wrapper.py | 3 +- openff/toolkit/utils/callback.py | 1 + openff/toolkit/utils/collections.py | 1 + openff/toolkit/utils/constants.py | 2 + openff/toolkit/utils/exceptions.py | 6 +- openff/toolkit/utils/nagl_wrapper.py | 8 ++- openff/toolkit/utils/openeye_wrapper.py | 57 ++++++++-------- openff/toolkit/utils/rdkit_wrapper.py | 45 ++++++------- openff/toolkit/utils/serialization.py | 1 + openff/toolkit/utils/toolkit_registry.py | 1 + openff/toolkit/utils/toolkits.py | 1 + openff/toolkit/utils/utils.py | 5 +- pyproject.toml | 2 +- .../_make_chemical_substructures.py | 2 + ..._make_metadata_assignment_substructures.py | 2 + .../custom_plugins/handler_plugins.py | 2 + utilities/test_plugins/setup.py | 1 + 72 files changed, 278 insertions(+), 176 deletions(-) diff --git a/devtools/scripts/build_cookiecutter_json.py b/devtools/scripts/build_cookiecutter_json.py index 85bb7f62c..b142959c8 100644 --- a/devtools/scripts/build_cookiecutter_json.py +++ b/devtools/scripts/build_cookiecutter_json.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import sys diff --git a/docs/conf.py b/docs/conf.py index ce43d924b..19755a8a6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,6 +16,8 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # +from __future__ import annotations + import os import sys from importlib.util import find_spec as find_import_spec diff --git a/docs/conftest.py b/docs/conftest.py index 764e854c8..8cde5f186 100644 --- a/docs/conftest.py +++ b/docs/conftest.py @@ -5,6 +5,7 @@ The nbval-sanitize.cfg file is also for use with nbval. """ +from __future__ import annotations def pytest_collectstart(collector): diff --git a/docs/users/molecule_cookbook.ipynb b/docs/users/molecule_cookbook.ipynb index 2aa9d794b..7355cb076 100644 --- a/docs/users/molecule_cookbook.ipynb +++ b/docs/users/molecule_cookbook.ipynb @@ -56,6 +56,8 @@ ], "source": [ "# Workaround for https://github.com/conda-forge/qcfractal-feedstock/issues/43\n", + "from __future__ import annotations\n", + "\n", "try:\n", " import qcportal # noqa: RUF100\n", "except ImportError:\n", diff --git a/docs/users/pdb_cookbook/index.ipynb b/docs/users/pdb_cookbook/index.ipynb index 73d5531ef..fa6773d39 100644 --- a/docs/users/pdb_cookbook/index.ipynb +++ b/docs/users/pdb_cookbook/index.ipynb @@ -66,6 +66,8 @@ }, "outputs": [], "source": [ + "from __future__ import annotations\n", + "\n", "import sys\n", "import warnings\n", "\n", diff --git a/examples/QCArchive_interface/QCarchive_interface.ipynb b/examples/QCArchive_interface/QCarchive_interface.ipynb index 28b61dee1..2558c7e17 100644 --- a/examples/QCArchive_interface/QCarchive_interface.ipynb +++ b/examples/QCArchive_interface/QCarchive_interface.ipynb @@ -256,6 +256,8 @@ } ], "source": [ + "from __future__ import annotations\n", + "\n", "import qcportal\n", "\n", "from openff.toolkit import Molecule\n", diff --git a/examples/SMIRNOFF_simulation/run_simulation.ipynb b/examples/SMIRNOFF_simulation/run_simulation.ipynb index 020688f3d..0b07a7a5a 100644 --- a/examples/SMIRNOFF_simulation/run_simulation.ipynb +++ b/examples/SMIRNOFF_simulation/run_simulation.ipynb @@ -28,6 +28,8 @@ "metadata": {}, "outputs": [], "source": [ + "from __future__ import annotations\n", + "\n", "from openff.toolkit.utils import get_data_file_path" ] }, diff --git a/examples/conformer_energies/conformer_energies.ipynb b/examples/conformer_energies/conformer_energies.ipynb index 352ad7528..069aad8ad 100644 --- a/examples/conformer_energies/conformer_energies.ipynb +++ b/examples/conformer_energies/conformer_energies.ipynb @@ -23,6 +23,8 @@ }, "outputs": [], "source": [ + "from __future__ import annotations\n", + "\n", "from openff.interchange.drivers.openmm import get_openmm_energies\n", "from rdkit.Chem import rdMolAlign\n", "\n", diff --git a/examples/conformer_energies/conformer_energies.py b/examples/conformer_energies/conformer_energies.py index f1ce7c8ee..ff51f3549 100644 --- a/examples/conformer_energies/conformer_energies.py +++ b/examples/conformer_energies/conformer_energies.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import argparse from openff.interchange.drivers.openmm import get_openmm_energies diff --git a/examples/examples_helper.py b/examples/examples_helper.py index 99bc28687..32bf80d6d 100755 --- a/examples/examples_helper.py +++ b/examples/examples_helper.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Copy the openff-toolkit examples suite to a local directory""" +from __future__ import annotations import argparse from os import environ diff --git a/examples/forcefield_modification/forcefield_modification.ipynb b/examples/forcefield_modification/forcefield_modification.ipynb index 80b65b830..806e20f77 100644 --- a/examples/forcefield_modification/forcefield_modification.ipynb +++ b/examples/forcefield_modification/forcefield_modification.ipynb @@ -15,6 +15,8 @@ "metadata": {}, "outputs": [], "source": [ + "from __future__ import annotations\n", + "\n", "from copy import deepcopy\n", "\n", "from openff.units import unit\n", diff --git a/examples/inspect_assigned_parameters/inspect_assigned_parameters.ipynb b/examples/inspect_assigned_parameters/inspect_assigned_parameters.ipynb index b947e0ea8..4c039b80f 100644 --- a/examples/inspect_assigned_parameters/inspect_assigned_parameters.ipynb +++ b/examples/inspect_assigned_parameters/inspect_assigned_parameters.ipynb @@ -118,6 +118,8 @@ } ], "source": [ + "from __future__ import annotations\n", + "\n", "from openff.toolkit import ForceField, Molecule, Topology\n", "\n", "# Create a simple molecule from SMILES and turn it into a topology.\n", diff --git a/examples/toolkit_showcase/toolkit_showcase.ipynb b/examples/toolkit_showcase/toolkit_showcase.ipynb index 7eef9b1a8..663f2e4af 100644 --- a/examples/toolkit_showcase/toolkit_showcase.ipynb +++ b/examples/toolkit_showcase/toolkit_showcase.ipynb @@ -43,6 +43,8 @@ ], "source": [ "# Imports from the comp chem ecosystem\n", + "from __future__ import annotations\n", + "\n", "import mdtraj\n", "import nglview\n", "import numpy as np\n", diff --git a/examples/using_smirnoff_in_amber_or_gromacs/export_with_interchange.ipynb b/examples/using_smirnoff_in_amber_or_gromacs/export_with_interchange.ipynb index ae5ca5995..269d921a3 100644 --- a/examples/using_smirnoff_in_amber_or_gromacs/export_with_interchange.ipynb +++ b/examples/using_smirnoff_in_amber_or_gromacs/export_with_interchange.ipynb @@ -28,6 +28,8 @@ "metadata": {}, "outputs": [], "source": [ + "from __future__ import annotations\n", + "\n", "from pprint import pprint\n", "from shutil import which\n", "\n", diff --git a/examples/using_smirnoff_with_amber_protein_forcefield/BRD4_inhibitor_benchmark.ipynb b/examples/using_smirnoff_with_amber_protein_forcefield/BRD4_inhibitor_benchmark.ipynb index 4b7df39c6..b077a999b 100644 --- a/examples/using_smirnoff_with_amber_protein_forcefield/BRD4_inhibitor_benchmark.ipynb +++ b/examples/using_smirnoff_with_amber_protein_forcefield/BRD4_inhibitor_benchmark.ipynb @@ -19,6 +19,8 @@ "source": [ "# Retrieve protein and ligand files for BRD4 and a docked inhibitor from the benchmark systems GitHub repository\n", "# https://github.com/MobleyLab/benchmarksets\n", + "from __future__ import annotations\n", + "\n", "import requests\n", "\n", "repo_url = \"https://raw.githubusercontent.com/MobleyLab/benchmarksets/master/input_files/\"\n", diff --git a/examples/virtual_sites/vsite_showcase.ipynb b/examples/virtual_sites/vsite_showcase.ipynb index bb7b63cea..7729d6d39 100644 --- a/examples/virtual_sites/vsite_showcase.ipynb +++ b/examples/virtual_sites/vsite_showcase.ipynb @@ -44,6 +44,8 @@ } ], "source": [ + "from __future__ import annotations\n", + "\n", "import time\n", "\n", "import numpy\n", diff --git a/examples/visualization/visualization.ipynb b/examples/visualization/visualization.ipynb index 660560eb0..8b154e963 100644 --- a/examples/visualization/visualization.ipynb +++ b/examples/visualization/visualization.ipynb @@ -66,6 +66,8 @@ }, "outputs": [], "source": [ + "from __future__ import annotations\n", + "\n", "from openff.toolkit import Molecule, Topology\n", "from openff.toolkit.utils import get_data_file_path" ] diff --git a/openff/toolkit/__init__.py b/openff/toolkit/__init__.py index cf62c730a..b1d08db58 100644 --- a/openff/toolkit/__init__.py +++ b/openff/toolkit/__init__.py @@ -2,6 +2,7 @@ openff-toolkit A modern, extensible library for molecular mechanics force field science from the Open Force Field Consortium. """ +from __future__ import annotations import importlib from importlib.metadata import version diff --git a/openff/toolkit/_tests/_stale_tests.py b/openff/toolkit/_tests/_stale_tests.py index 221418430..4ac808d5f 100644 --- a/openff/toolkit/_tests/_stale_tests.py +++ b/openff/toolkit/_tests/_stale_tests.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from openff.toolkit import ForceField diff --git a/openff/toolkit/_tests/conftest.py b/openff/toolkit/_tests/conftest.py index fe9f735f8..f61ef1a1c 100644 --- a/openff/toolkit/_tests/conftest.py +++ b/openff/toolkit/_tests/conftest.py @@ -1,6 +1,7 @@ """ Configuration file for pytest. """ +from __future__ import annotations import logging diff --git a/openff/toolkit/_tests/create_molecules.py b/openff/toolkit/_tests/create_molecules.py index b9cfafd59..e88e98589 100644 --- a/openff/toolkit/_tests/create_molecules.py +++ b/openff/toolkit/_tests/create_molecules.py @@ -4,6 +4,7 @@ These are common to several test modules. """ +from __future__ import annotations import numpy as np diff --git a/openff/toolkit/_tests/mocking.py b/openff/toolkit/_tests/mocking.py index 9672dc805..cd8e188f6 100644 --- a/openff/toolkit/_tests/mocking.py +++ b/openff/toolkit/_tests/mocking.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy from openff.toolkit import Quantity, unit diff --git a/openff/toolkit/_tests/molecule/test_state_enumeration.py b/openff/toolkit/_tests/molecule/test_state_enumeration.py index 3ba3e6524..62d4feaf7 100644 --- a/openff/toolkit/_tests/molecule/test_state_enumeration.py +++ b/openff/toolkit/_tests/molecule/test_state_enumeration.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from openff.toolkit import Molecule diff --git a/openff/toolkit/_tests/test_energies.py b/openff/toolkit/_tests/test_energies.py index 849cb79d6..d83d9dabd 100644 --- a/openff/toolkit/_tests/test_energies.py +++ b/openff/toolkit/_tests/test_energies.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import numpy as np diff --git a/openff/toolkit/_tests/test_examples.py b/openff/toolkit/_tests/test_examples.py index 71a9124d0..3d28ea2ee 100644 --- a/openff/toolkit/_tests/test_examples.py +++ b/openff/toolkit/_tests/test_examples.py @@ -1,6 +1,7 @@ """ Test that the examples in the repo run without errors. """ +from __future__ import annotations import pathlib import re diff --git a/openff/toolkit/_tests/test_forcefield.py b/openff/toolkit/_tests/test_forcefield.py index d5fed21fb..827b07350 100644 --- a/openff/toolkit/_tests/test_forcefield.py +++ b/openff/toolkit/_tests/test_forcefield.py @@ -2,6 +2,7 @@ Tests for forcefield class """ +from __future__ import annotations import copy import itertools diff --git a/openff/toolkit/_tests/test_interchange.py b/openff/toolkit/_tests/test_interchange.py index 318608b23..8c9396ee0 100644 --- a/openff/toolkit/_tests/test_interchange.py +++ b/openff/toolkit/_tests/test_interchange.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from openff.utilities import requires_package as requires_pkg diff --git a/openff/toolkit/_tests/test_io.py b/openff/toolkit/_tests/test_io.py index e441f78ce..f6967b2bf 100644 --- a/openff/toolkit/_tests/test_io.py +++ b/openff/toolkit/_tests/test_io.py @@ -2,6 +2,7 @@ Test classes and function in module openff.toolkit.typing.engines.smirnoff.io. """ +from __future__ import annotations import pytest diff --git a/openff/toolkit/_tests/test_links.py b/openff/toolkit/_tests/test_links.py index b3d29e49e..d6a115f72 100644 --- a/openff/toolkit/_tests/test_links.py +++ b/openff/toolkit/_tests/test_links.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pathlib import re from urllib.request import Request, urlopen diff --git a/openff/toolkit/_tests/test_mm_molecule.py b/openff/toolkit/_tests/test_mm_molecule.py index 179763d4b..113f4b3da 100644 --- a/openff/toolkit/_tests/test_mm_molecule.py +++ b/openff/toolkit/_tests/test_mm_molecule.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import copy import numpy as np diff --git a/openff/toolkit/_tests/test_molecule.py b/openff/toolkit/_tests/test_molecule.py index f4950b754..5b0851684 100644 --- a/openff/toolkit/_tests/test_molecule.py +++ b/openff/toolkit/_tests/test_molecule.py @@ -12,6 +12,7 @@ serialized OFFMols. """ +from __future__ import annotations import copy import os diff --git a/openff/toolkit/_tests/test_nagl.py b/openff/toolkit/_tests/test_nagl.py index 16e32be87..9839eb698 100644 --- a/openff/toolkit/_tests/test_nagl.py +++ b/openff/toolkit/_tests/test_nagl.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pathlib import re diff --git a/openff/toolkit/_tests/test_parameter_plugins.py b/openff/toolkit/_tests/test_parameter_plugins.py index 58d9929d1..397a8c3e8 100644 --- a/openff/toolkit/_tests/test_parameter_plugins.py +++ b/openff/toolkit/_tests/test_parameter_plugins.py @@ -1,6 +1,7 @@ """ Test classes and function in module openff.toolkit.typing.engines.smirnoff.plugins """ +from __future__ import annotations import pytest diff --git a/openff/toolkit/_tests/test_parameters.py b/openff/toolkit/_tests/test_parameters.py index 8bb0b196b..7c488f8d6 100644 --- a/openff/toolkit/_tests/test_parameters.py +++ b/openff/toolkit/_tests/test_parameters.py @@ -2,6 +2,7 @@ Test classes and function in module openff.toolkit.typing.engines.smirnoff.parameters. """ +from __future__ import annotations from collections import defaultdict from inspect import isabstract, isclass diff --git a/openff/toolkit/_tests/test_toolkit_io.py b/openff/toolkit/_tests/test_toolkit_io.py index 9d911d094..5338ce114 100644 --- a/openff/toolkit/_tests/test_toolkit_io.py +++ b/openff/toolkit/_tests/test_toolkit_io.py @@ -2,6 +2,7 @@ Tests for I/O functionality of the toolkit wrappers """ +from __future__ import annotations import pathlib import sys diff --git a/openff/toolkit/_tests/test_toolkits.py b/openff/toolkit/_tests/test_toolkits.py index f48f4c68f..0be2d2969 100644 --- a/openff/toolkit/_tests/test_toolkits.py +++ b/openff/toolkit/_tests/test_toolkits.py @@ -2,6 +2,7 @@ Tests for cheminformatics toolkit wrappers """ +from __future__ import annotations import logging import os diff --git a/openff/toolkit/_tests/test_topology.py b/openff/toolkit/_tests/test_topology.py index 6b6a17d36..d652d920c 100644 --- a/openff/toolkit/_tests/test_topology.py +++ b/openff/toolkit/_tests/test_topology.py @@ -2,6 +2,7 @@ Tests for Topology """ +from __future__ import annotations import itertools import re diff --git a/openff/toolkit/_tests/test_utils.py b/openff/toolkit/_tests/test_utils.py index 7733b7505..e6f0b2b1e 100644 --- a/openff/toolkit/_tests/test_utils.py +++ b/openff/toolkit/_tests/test_utils.py @@ -2,6 +2,7 @@ Tests for utility methods """ +from __future__ import annotations import os diff --git a/openff/toolkit/_tests/test_utils_callback.py b/openff/toolkit/_tests/test_utils_callback.py index 79248d727..90b6741b3 100644 --- a/openff/toolkit/_tests/test_utils_callback.py +++ b/openff/toolkit/_tests/test_utils_callback.py @@ -2,6 +2,7 @@ Tests for callback utility classes and functions. """ +from __future__ import annotations import pytest diff --git a/openff/toolkit/_tests/test_utils_collections.py b/openff/toolkit/_tests/test_utils_collections.py index c33bfd5ac..694018073 100644 --- a/openff/toolkit/_tests/test_utils_collections.py +++ b/openff/toolkit/_tests/test_utils_collections.py @@ -2,6 +2,7 @@ Tests for custom collections classes. """ +from __future__ import annotations import copy diff --git a/openff/toolkit/_tests/test_utils_serialization.py b/openff/toolkit/_tests/test_utils_serialization.py index 71c1d7dd4..54cb24a21 100644 --- a/openff/toolkit/_tests/test_utils_serialization.py +++ b/openff/toolkit/_tests/test_utils_serialization.py @@ -2,6 +2,7 @@ Tests for utility methods for serialization """ +from __future__ import annotations import numpy as np import pytest diff --git a/openff/toolkit/_tests/utils.py b/openff/toolkit/_tests/utils.py index a0f2bcc87..9051fded4 100644 --- a/openff/toolkit/_tests/utils.py +++ b/openff/toolkit/_tests/utils.py @@ -2,6 +2,7 @@ Utilities for testing. """ +from __future__ import annotations import collections import copy diff --git a/openff/toolkit/topology/__init__.py b/openff/toolkit/topology/__init__.py index 67c96c6c3..b58e2a1cd 100644 --- a/openff/toolkit/topology/__init__.py +++ b/openff/toolkit/topology/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from openff.toolkit.topology.molecule import ( Atom, Bond, diff --git a/openff/toolkit/topology/_mm_molecule.py b/openff/toolkit/topology/_mm_molecule.py index 114e94ce8..3d4d3a2a3 100644 --- a/openff/toolkit/topology/_mm_molecule.py +++ b/openff/toolkit/topology/_mm_molecule.py @@ -9,10 +9,11 @@ deserialize a Molecule or a TypedMolecule. """ +from __future__ import annotations import functools from collections.abc import Generator, Iterable -from typing import TYPE_CHECKING, NoReturn, Union +from typing import TYPE_CHECKING, NoReturn from openff.units.elements import MASSES, SYMBOLS @@ -62,7 +63,7 @@ def add_bond(self, atom1, atom2, **kwargs): self.bonds.append(bond) @property - def conformers(self) -> list["Quantity"] | None: + def conformers(self) -> list[Quantity] | None: return self._conformers def add_conformer(self, conformer): @@ -82,13 +83,13 @@ def n_bonds(self) -> int: def n_conformers(self) -> int: return 0 if self._conformers is None else len(self._conformers) - def atom(self, index: int) -> "_SimpleAtom": + def atom(self, index: int) -> _SimpleAtom: return self.atoms[index] def atom_index(self, atom) -> int: return self.atoms.index(atom) - def bond(self, index: int) -> "_SimpleBond": + def bond(self, index: int) -> _SimpleBond: return self.bonds[index] def get_bond_between(self, atom1_index, atom2_index): @@ -104,9 +105,9 @@ def angles( self, ) -> Generator[ tuple[ - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, ], None, None, @@ -127,10 +128,10 @@ def propers( self, ) -> Generator[ tuple[ - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, ], None, None, @@ -155,10 +156,10 @@ def impropers( self, ) -> Generator[ tuple[ - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, ], None, None, @@ -181,10 +182,10 @@ def smirnoff_impropers( self, ) -> Generator[ tuple[ - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, ], None, None, @@ -198,10 +199,10 @@ def amber_impropers( self, ) -> Generator[ tuple[ - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", - "_SimpleAtom", + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, + _SimpleAtom, ], None, None, @@ -232,7 +233,7 @@ def hill_formula(self) -> str: return self.to_hill_formula() @property - def hierarchy_schemes(self) -> dict[str, "HierarchyScheme"]: + def hierarchy_schemes(self) -> dict[str, HierarchyScheme]: return self._hierarchy_schemes def to_hill_formula(self) -> str: @@ -243,7 +244,7 @@ def to_hill_formula(self) -> str: return _atom_nums_to_hill_formula(atom_nums) - def to_networkx(self) -> "nx.Graph": + def to_networkx(self) -> nx.Graph: # TODO: Custom attribtues should probably be attached to the nodes (and possibly also # the edges?). See for more: # https://github.com/openforcefield/openff-toolkit/pull/1179#discussion_r808549385 @@ -264,7 +265,7 @@ def to_networkx(self) -> "nx.Graph": return graph - def to_topology(self) -> "Topology": + def to_topology(self) -> Topology: from openff.toolkit.topology import Topology return Topology.from_molecules([self]) @@ -277,7 +278,7 @@ def nth_degree_neighbors(self, n_degrees): return _nth_degree_neighbors_from_graphlike(graphlike=self, n_degrees=n_degrees) @classmethod - def _from_subgraph(cls, subgraph: "nx.Graph"): + def _from_subgraph(cls, subgraph: nx.Graph): molecule = cls() # The subgraph stores indices that might not start at zero (i.e. topology indices) @@ -434,7 +435,7 @@ def to_molecule(self) -> NoReturn: "an OpenFF Molecule with sufficiently specified chemistry." ) - def is_isomorphic_with(self, other: Union["FrozenMolecule", "_SimpleMolecule", "nx.Graph"], **kwargs) -> bool: + def is_isomorphic_with(self, other: FrozenMolecule | _SimpleMolecule | nx.Graph, **kwargs) -> bool: """ Check for pseudo-isomorphism. @@ -454,8 +455,8 @@ def is_isomorphic_with(self, other: Union["FrozenMolecule", "_SimpleMolecule", " @staticmethod def are_isomorphic( - mol1: Union["FrozenMolecule", "_SimpleMolecule", "nx.Graph"], - mol2: Union["FrozenMolecule", "_SimpleMolecule", "nx.Graph"], + mol1: FrozenMolecule | _SimpleMolecule | nx.Graph, + mol2: FrozenMolecule | _SimpleMolecule | nx.Graph, return_atom_map: bool = False, ) -> tuple[bool, dict[int, int] | None]: import networkx @@ -521,7 +522,7 @@ def has_unique_atom_names(self) -> bool: """``True`` if the molecule has unique atom names, ``False`` otherwise.""" return _has_unique_atom_names(self) - def __getattr__(self, name: str) -> list["HierarchyElement"]: + def __getattr__(self, name: str) -> list[HierarchyElement]: """If a requested attribute is not found, check the hierarchy schemes""" try: return self.__dict__["_hierarchy_schemes"][name].hierarchy_elements @@ -583,7 +584,7 @@ def symbol(self) -> str: return SYMBOLS[self.atomic_number] @property - def mass(self) -> "Quantity": + def mass(self) -> Quantity: return MASSES[self.atomic_number] @property diff --git a/openff/toolkit/topology/molecule.py b/openff/toolkit/topology/molecule.py index fee8216df..1c85a826b 100644 --- a/openff/toolkit/topology/molecule.py +++ b/openff/toolkit/topology/molecule.py @@ -24,6 +24,7 @@ * Speed up overall import time by putting non-global imports only where they are needed """ +from __future__ import annotations import hashlib import json @@ -41,7 +42,6 @@ Literal, TextIO, TypeVar, - Union, overload, ) @@ -127,10 +127,10 @@ class Particle(Serializable): """ - _molecule: "FrozenMolecule" + _molecule: FrozenMolecule @property - def molecule(self) -> "FrozenMolecule": + def molecule(self) -> FrozenMolecule: r""" The ``Molecule`` this particle is part of. @@ -144,7 +144,7 @@ def molecule(self) -> "FrozenMolecule": return self._molecule @molecule.setter - def molecule(self, molecule: "FrozenMolecule"): + def molecule(self, molecule: FrozenMolecule): """ Set the particle's molecule pointer. Note that this will only work if the particle currently doesn't have a molecule @@ -285,7 +285,7 @@ def __init__( # TODO: We can probably avoid an explicit call and determine this dynamically # from self._molecule (maybe caching the result) to get rid of some bookkeeping. # TODO: Should stereochemistry be reset/cleared/recomputed upon addition of a bond? - def add_bond(self, bond: "Bond"): + def add_bond(self, bond: Bond): """Adds a bond that this atom is involved in .. todo :: Is this how we want to keep records? @@ -343,7 +343,7 @@ def formal_charge(self) -> Quantity: return self._formal_charge @formal_charge.setter - def formal_charge(self, other: "int | Quantity | OMMQuantity"): + def formal_charge(self, other: int | Quantity | OMMQuantity): """ Set the atom's formal charge. Accepts either ints or unit-wrapped ints with units of charge. """ @@ -503,7 +503,7 @@ def bonds(self): return self._bonds @property - def bonded_atoms(self) -> Generator["Atom", None, None]: + def bonded_atoms(self) -> Generator[Atom, None, None]: """ The list of ``Atom`` objects this atom is involved in bonds with @@ -780,7 +780,7 @@ def is_aromatic(self) -> bool: return self._is_aromatic @property - def molecule(self) -> "FrozenMolecule": + def molecule(self) -> FrozenMolecule: return self._molecule @molecule.setter @@ -1451,7 +1451,7 @@ def add_hierarchy_scheme( self, uniqueness_criteria: Iterable[str], iterator_name: str, - ) -> "HierarchyScheme": + ) -> HierarchyScheme: """ Use the molecule's metadata to facilitate iteration over its atoms. @@ -1516,7 +1516,7 @@ def add_hierarchy_scheme( return new_hier_scheme @property - def hierarchy_schemes(self) -> dict[str, "HierarchyScheme"]: + def hierarchy_schemes(self) -> dict[str, HierarchyScheme]: """ The hierarchy schemes available on the molecule. @@ -1589,7 +1589,7 @@ def update_hierarchy_schemes(self, iter_names: list[str] | None = None): hierarchy_scheme = self._hierarchy_schemes[iter_name] hierarchy_scheme.perceive_hierarchy() - def __getattr__(self, name: str) -> list["HierarchyElement"]: + def __getattr__(self, name: str) -> list[HierarchyElement]: """If a requested attribute is not found, check the hierarchy schemes""" try: return self.__dict__["_hierarchy_schemes"][name].hierarchy_elements @@ -1950,8 +1950,8 @@ def _is_exactly_the_same_as(self, other): @staticmethod def are_isomorphic( - mol1: "FrozenMolecule | _SimpleMolecule | nx.Graph[int]", - mol2: "FrozenMolecule | _SimpleMolecule | nx.Graph[int]", + mol1: FrozenMolecule | _SimpleMolecule | nx.Graph[int], + mol2: FrozenMolecule | _SimpleMolecule | nx.Graph[int], return_atom_map: bool = False, aromatic_matching: bool = True, formal_charge_matching: bool = True, @@ -2191,7 +2191,7 @@ def _to_networkx(data: FrozenMolecule | nx.Graph) -> nx.Graph: def is_isomorphic_with( self, - other: "FrozenMolecule | _SimpleMolecule | nx.Graph[int]", + other: FrozenMolecule | _SimpleMolecule | nx.Graph[int], aromatic_matching: bool = True, formal_charge_matching: bool = True, bond_order_matching: bool = True, @@ -2803,7 +2803,7 @@ def _invalidate_cached_properties(self): if "_molecule_atom_index" in atom.__dict__: del atom.__dict__["_molecule_atom_index"] - def to_networkx(self) -> "nx.Graph": + def to_networkx(self) -> nx.Graph: """Generate a NetworkX undirected graph from the molecule. Nodes are Atoms labeled with atom indices and atomic elements (via the ``element`` node atrribute). @@ -3541,7 +3541,7 @@ def to_hill_formula(self) -> str: return self._hill_formula @staticmethod - def _object_to_hill_formula(obj: Union["FrozenMolecule", "nx.Graph[int]"]) -> str: + def _object_to_hill_formula(obj: FrozenMolecule | nx.Graph[int]) -> str: """Take a Molecule or NetworkX graph and generate its Hill formula. This provides a backdoor to the old functionality of Molecule.to_hill_formula, which was a static method that duck-typed inputs of Molecule or graph objects.""" @@ -4337,7 +4337,7 @@ def to_rdkit( self, aromaticity_model=DEFAULT_AROMATICITY_MODEL, toolkit_registry=GLOBAL_TOOLKIT_REGISTRY, - ) -> "RDMol": + ) -> RDMol: """ Create an RDKit molecule @@ -4376,7 +4376,7 @@ def from_openeye( cls: type[FM], oemol, allow_undefined_stereo: bool = False, - ) -> "FrozenMolecule": + ) -> FrozenMolecule: """ Create a ``Molecule`` from an OpenEye molecule. @@ -5286,8 +5286,8 @@ def add_atom( def add_bond( self, - atom1: Union[int, "Atom"], - atom2: Union[int, "Atom"], + atom1: int | Atom, + atom2: int | Atom, bond_order: int, is_aromatic: bool, stereochemistry: Literal["E", "Z", None] = None, @@ -5364,19 +5364,19 @@ def clear_conformers(self): def visualize( self, backend: Literal["rdkit"], - ) -> "IPython.display.SVG": ... + ) -> IPython.display.SVG: ... @overload def visualize( self, backend: Literal["openeye"], - ) -> "IPython.display.Image": ... + ) -> IPython.display.Image: ... @overload def visualize( self, backend: Literal["nglview"], - ) -> "nglview.NGLWidget": ... + ) -> nglview.NGLWidget: ... def visualize( self, @@ -5384,7 +5384,7 @@ def visualize( width: int = 500, height: int = 300, show_all_hydrogens: bool = True, - ) -> Union["IPython.display.SVG", "IPython.display.Image", "nglview.NGLWidget"]: + ) -> IPython.display.SVG | IPython.display.Image | nglview.NGLWidget: """ Render a visualization of the molecule in Jupyter @@ -5634,7 +5634,7 @@ def _ipython_display_(self): # pragma: no cover pass -def _networkx_graph_to_hill_formula(graph: "nx.Graph[int]") -> str: +def _networkx_graph_to_hill_formula(graph: nx.Graph[int]) -> str: """ Convert a NetworkX graph to a Hill formula. @@ -5697,7 +5697,7 @@ def _atom_nums_to_hill_formula(atom_nums: list[int]) -> str: def _nth_degree_neighbors_from_graphlike( graphlike: MoleculeLike, n_degrees: int, -) -> Iterator[tuple[Atom, Atom] | tuple["_SimpleAtom", "_SimpleAtom"]]: +) -> Iterator[tuple[Atom, Atom] | tuple[_SimpleAtom, _SimpleAtom]]: """ Given a graph-like object, return a tuple of the nth degree neighbors of each atom. @@ -5864,7 +5864,7 @@ def add_hierarchy_element( self, identifier: tuple[str | int, ...], atom_indices: Sequence[int], - ) -> "HierarchyElement": + ) -> HierarchyElement: """ Instantiate a new HierarchyElement belonging to this HierarchyScheme. @@ -5990,7 +5990,7 @@ def n_atoms(self) -> int: return len(self.atom_indices) @property - def atoms(self) -> Iterator["Atom"]: + def atoms(self) -> Iterator[Atom]: """ Iterator over the atoms in this hierarchy element. """ @@ -6044,7 +6044,7 @@ def generate_unique_atom_names(self, suffix: str = "x"): def _has_unique_atom_names( - obj: "FrozenMolecule | _SimpleMolecule | HierarchyElement", + obj: FrozenMolecule | _SimpleMolecule | HierarchyElement, ) -> bool: """``True`` if the object has unique atom names, ``False`` otherwise.""" unique_atom_names = set([atom.name for atom in obj.atoms]) diff --git a/openff/toolkit/topology/topology.py b/openff/toolkit/topology/topology.py index 9467d350e..3124348b2 100644 --- a/openff/toolkit/topology/topology.py +++ b/openff/toolkit/topology/topology.py @@ -11,6 +11,7 @@ * Use `attrs `_ for object setter boilerplate? """ +from __future__ import annotations import re from collections import defaultdict @@ -22,7 +23,6 @@ TYPE_CHECKING, Literal, TextIO, - Union, ) import numpy as np @@ -520,7 +520,7 @@ def n_unique_molecules(self) -> int: def from_molecules( cls, molecules: MoleculeLike | Iterable[MoleculeLike], - ) -> "Topology": + ) -> Topology: """ Create a new Topology object containing one copy of each of the specified molecule(s). @@ -546,7 +546,7 @@ def from_molecules( return topology - def assert_bonded(self, atom1: Union[int, "Atom"], atom2: Union[int, "Atom"]): + def assert_bonded(self, atom1: int | Atom, atom2: int | Atom): """ Raise an exception if the specified atoms are not bonded in the topology. @@ -724,7 +724,7 @@ def n_atoms(self) -> int: return n_atoms @property - def atoms(self) -> Generator["Atom", None, None]: + def atoms(self) -> Generator[Atom, None, None]: """Returns an iterator over the atoms in this Topology. These will be in ascending order of topology index. Returns @@ -734,7 +734,7 @@ def atoms(self) -> Generator["Atom", None, None]: for molecule in self._molecules: yield from molecule.atoms - def atom_index(self, atom: "Atom") -> int: + def atom_index(self, atom: Atom) -> int: """ Returns the index of a given atom in this topology @@ -861,7 +861,7 @@ def impropers(self) -> Generator[tuple[AtomLike, AtomLike, AtomLike, AtomLike], @property def smirnoff_impropers( self, - ) -> Generator[tuple[Union["Atom", _SimpleAtom], ...], None, None]: + ) -> Generator[tuple[Atom | _SimpleAtom, ...], None, None]: """ Iterate over improper torsions in the molecule, but only those with trivalent centers, reporting the central atom second in each improper. @@ -901,7 +901,7 @@ def smirnoff_impropers( @property def amber_impropers( self, - ) -> Generator[tuple[Union["Atom", _SimpleAtom], ...], None, None]: + ) -> Generator[tuple[Atom | _SimpleAtom, ...], None, None]: """ Iterate over improper torsions in the molecule, but only those with trivalent centers, reporting the central atom first in each improper. @@ -1327,10 +1327,10 @@ def _openmm_topology_to_networkx(openmm_topology): @requires_package("openmm") def from_openmm( cls, - openmm_topology: "openmm.app.Topology", + openmm_topology: openmm.app.Topology, unique_molecules: Iterable[FrozenMolecule] | None = None, - positions: Union[None, Quantity, "OMMQuantity"] = None, - ) -> "Topology": + positions: None | Quantity | OMMQuantity = None, + ) -> Topology: """ Construct an OpenFF Topology object from an OpenMM Topology object. @@ -1771,7 +1771,7 @@ def from_pdb( def to_openmm( self, ensure_unique_atom_names: str | bool = "residues", - ) -> "openmm.app.Topology": + ) -> openmm.app.Topology: """ Create an OpenMM Topology object. @@ -1935,7 +1935,7 @@ def to_openmm( def to_file( self, file: Path | str | TextIO, - positions: Union["OMMQuantity", Quantity, NDArray] | None = None, + positions: OMMQuantity | Quantity | NDArray | None = None, file_format: Literal["PDB"] = "PDB", keep_ids: bool = False, ensure_unique_atom_names: str | bool = "residues", @@ -2122,9 +2122,9 @@ def set_positions(self, array: Quantity) -> None: @requires_package("mdtraj") def from_mdtraj( cls, - mdtraj_topology: "mdtraj.Topology", + mdtraj_topology: mdtraj.Topology, unique_molecules: Iterable[MoleculeLike] | None = None, - positions: Union[None, "OMMQuantity", Quantity] = None, + positions: None | OMMQuantity | Quantity = None, ): """ Construct an OpenFF ``Topology`` from an MDTraj ``Topology`` @@ -2192,7 +2192,7 @@ def _to_mdtraj(self): return md.Topology.from_openmm(self.to_openmm()) - def get_bond_between(self, i: Union[int, "Atom"], j: Union[int, "Atom"]) -> "Bond": + def get_bond_between(self, i: int | Atom, j: int | Atom) -> Bond: """Returns the bond between two atoms Parameters @@ -2228,7 +2228,7 @@ def get_bond_between(self, i: Union[int, "Atom"], j: Union[int, "Atom"]) -> "Bon raise NotBondedError(f"No bond between atom {i} and {j}") - def is_bonded(self, i: Union[int, "Atom"], j: Union[int, "Atom"]) -> bool: + def is_bonded(self, i: int | Atom, j: int | Atom) -> bool: """Returns True if the two atoms are bonded Parameters @@ -2248,7 +2248,7 @@ def is_bonded(self, i: Union[int, "Atom"], j: Union[int, "Atom"]) -> bool: except NotBondedError: return False - def atom(self, atom_topology_index: int) -> "Atom": + def atom(self, atom_topology_index: int) -> Atom: """ Get the Atom at a given Topology atom index. @@ -2437,7 +2437,7 @@ def is_constrained(self, iatom, jatom): return False @requires_package("nglview") - def visualize(self, ensure_correct_connectivity: bool = False) -> "NGLWidget": + def visualize(self, ensure_correct_connectivity: bool = False) -> NGLWidget: """ Visualize with NGLView. @@ -2537,7 +2537,7 @@ def hierarchy_iterator( if hasattr(molecule, iter_name): yield from getattr(molecule, iter_name) - def __getattr__(self, name: str) -> list["HierarchyElement"]: + def __getattr__(self, name: str) -> list[HierarchyElement]: """If a requested attribute is not found, check the hierarchy schemes""" # Avoid attempting to process dunder methods as hierarchy scheme iterator names if name.startswith("__"): diff --git a/openff/toolkit/typing/engines/smirnoff/__init__.py b/openff/toolkit/typing/engines/smirnoff/__init__.py index d881c950d..833e75984 100644 --- a/openff/toolkit/typing/engines/smirnoff/__init__.py +++ b/openff/toolkit/typing/engines/smirnoff/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from openff.toolkit.typing.engines.smirnoff.forcefield import ( ForceField, get_available_force_fields, diff --git a/openff/toolkit/typing/engines/smirnoff/forcefield.py b/openff/toolkit/typing/engines/smirnoff/forcefield.py index 19447e32c..e3c26ca64 100644 --- a/openff/toolkit/typing/engines/smirnoff/forcefield.py +++ b/openff/toolkit/typing/engines/smirnoff/forcefield.py @@ -10,12 +10,13 @@ * Speed up overall import time by putting non-global imports only where they are needed """ +from __future__ import annotations import logging import os import pathlib from importlib.metadata import entry_points -from typing import IO, TYPE_CHECKING, Any, Union +from typing import IO, TYPE_CHECKING, Any from packaging.version import Version @@ -1104,8 +1105,8 @@ def to_file( def combine( self, - other: "ForceField", - ) -> "ForceField": + other: ForceField, + ) -> ForceField: """ Combine this `ForceField` with another `ForceField`, returning a new `ForceField`. @@ -1128,13 +1129,13 @@ def combine( @requires_package("openmm") def create_openmm_system( self, - topology: "Topology", + topology: Topology, *, - toolkit_registry: Union["ToolkitRegistry", "ToolkitWrapper"] | None = None, - charge_from_molecules: list["Molecule"] | None = None, - partial_bond_orders_from_molecules: list["Molecule"] | None = None, + toolkit_registry: ToolkitRegistry | ToolkitWrapper | None = None, + charge_from_molecules: list[Molecule] | None = None, + partial_bond_orders_from_molecules: list[Molecule] | None = None, allow_nonintegral_charges: bool = False, - ) -> "openmm.System": + ) -> openmm.System: """Create an OpenMM System from this ForceField and a Topology. Note that most force fields specify their own partial charges, and any @@ -1174,12 +1175,12 @@ def create_openmm_system( @requires_package("openff.interchange") def create_interchange( self, - topology: "Topology", - toolkit_registry: Union["ToolkitRegistry", "ToolkitWrapper"] | None = None, - charge_from_molecules: list["Molecule"] | None = None, - partial_bond_orders_from_molecules: list["Molecule"] | None = None, + topology: Topology, + toolkit_registry: ToolkitRegistry | ToolkitWrapper | None = None, + charge_from_molecules: list[Molecule] | None = None, + partial_bond_orders_from_molecules: list[Molecule] | None = None, allow_nonintegral_charges: bool = False, - ) -> "Interchange": + ) -> Interchange: """ Create an Interchange object from a ForceField, Topology, and (optionally) box vectors. @@ -1228,7 +1229,7 @@ def create_interchange( allow_nonintegral_charges=allow_nonintegral_charges, ) - def label_molecules(self, topology: "Topology") -> list[dict[str, "ValenceDict"]]: + def label_molecules(self, topology: Topology) -> list[dict[str, ValenceDict]]: """ Return labels for a list of molecules corresponding to parameters from this force field. @@ -1313,7 +1314,7 @@ def _get_parameter_handler_class(self, tagname: str) -> type[ParameterHandler]: return ph_class @requires_package("openff.interchange") - def get_partial_charges(self, molecule: "Molecule", **kwargs: Any) -> Quantity: + def get_partial_charges(self, molecule: Molecule, **kwargs: Any) -> Quantity: """Generate the partial charges for the given molecule in this force field. Parameters diff --git a/openff/toolkit/typing/engines/smirnoff/io.py b/openff/toolkit/typing/engines/smirnoff/io.py index ba36ddc1c..ff6e13a56 100644 --- a/openff/toolkit/typing/engines/smirnoff/io.py +++ b/openff/toolkit/typing/engines/smirnoff/io.py @@ -6,6 +6,7 @@ .. codeauthor:: Peter K. Eastman """ +from __future__ import annotations __all__ = [ "ParameterIOHandler", diff --git a/openff/toolkit/typing/engines/smirnoff/parameters.py b/openff/toolkit/typing/engines/smirnoff/parameters.py index 3ae8445ae..ead8b2470 100644 --- a/openff/toolkit/typing/engines/smirnoff/parameters.py +++ b/openff/toolkit/typing/engines/smirnoff/parameters.py @@ -6,6 +6,7 @@ New pluggable handlers can be created by creating subclasses of :class:`ParameterHandler`. """ +from __future__ import annotations __all__ = [ "AngleHandler", @@ -60,7 +61,7 @@ import re from collections import defaultdict from collections.abc import Callable -from typing import Any, Literal, Union, cast, get_args +from typing import Any, Literal, cast, get_args import numpy from openff.units.units import Unit @@ -1374,7 +1375,7 @@ class ParameterList(list): def __init__( self, - input_parameter_list: list["ParameterType"] | None = None, + input_parameter_list: list[ParameterType] | None = None, ): """ Initialize a new ParameterList, optionally providing a list of ParameterType objects @@ -1489,7 +1490,7 @@ def __delitem__(self, item): index = self.index(item) super().__delitem__(index) - def __getitem__(self, item: Union[int, slice, str, "ParameterType"]): # type: ignore[override] + def __getitem__(self, item: int | slice | str | ParameterType): # type: ignore[override] """ Retrieve item by index or SMIRKS. If multiple parameters have the same SMIRKS, this returns the last one. @@ -1555,7 +1556,7 @@ def to_list(self, discard_cosmetic_attributes=True): class VirtualSiteParameterList(ParameterList): - def __getitem__(self, val: Union[int, slice, str, "ParameterType"]): # type: ignore[override] + def __getitem__(self, val: int | slice | str | ParameterType): # type: ignore[override] indexable_item: int | slice if isinstance(val, int): @@ -2273,7 +2274,7 @@ def to_dict( def _check_attributes_are_equal( self, - other: "ParameterHandler", + other: ParameterHandler, identical_attrs: tuple[str, ...] = tuple(), tolerance_attrs: tuple[str, ...] = tuple(), tolerance: float = 1e-6, @@ -2431,7 +2432,7 @@ def __init__(self, **kwargs): elif self.version == Version("0.4") and "potential" not in kwargs: self.potential = "(k/2)*(r-length)^2" - def check_handler_compatibility(self, other_handler: "BondHandler"): + def check_handler_compatibility(self, other_handler: BondHandler): """ Checks whether this ParameterHandler encodes compatible physics as another ParameterHandler. This is called if a second handler is attempted to be initialized for the same tag. @@ -2481,7 +2482,7 @@ class AngleType(ParameterType): potential = ParameterAttribute(default="harmonic") - def check_handler_compatibility(self, other_handler: "AngleHandler"): + def check_handler_compatibility(self, other_handler: AngleHandler): """ Checks whether this ParameterHandler encodes compatible physics as another ParameterHandler. This is called if a second handler is attempted to be initialized for the same tag. @@ -2529,7 +2530,7 @@ class ProperTorsionType(ParameterType): fractional_bondorder_method = ParameterAttribute(default="AM1-Wiberg") fractional_bondorder_interpolation = ParameterAttribute(default="linear", converter=_allow_only(["linear"])) - def check_handler_compatibility(self, other_handler: "ProperTorsionHandler"): + def check_handler_compatibility(self, other_handler: ProperTorsionHandler): """ Checks whether this ParameterHandler encodes compatible physics as another ParameterHandler. This is called if a second handler is attempted to be initialized for the same tag. @@ -2585,7 +2586,7 @@ class ImproperTorsionType(ParameterType): ) default_idivf = ParameterAttribute(default="auto") - def check_handler_compatibility(self, other_handler: "ImproperTorsionHandler"): + def check_handler_compatibility(self, other_handler: ImproperTorsionHandler): """ Checks whether this ParameterHandler encodes compatible physics as another ParameterHandler. This is called if a second handler is attempted to be initialized for the same tag. @@ -2772,7 +2773,7 @@ def scale15(self, attrs, new_scale15): # Tolerance when comparing float attributes for handler compatibility. _SCALETOL = 1e-5 - def check_handler_compatibility(self, other_handler: "vdWHandler"): + def check_handler_compatibility(self, other_handler: vdWHandler): """ Checks whether this ParameterHandler encodes compatible physics as another ParameterHandler. This is called if a second handler is attempted to be initialized for the same tag. @@ -2951,7 +2952,7 @@ def __init__(self, **kwargs): ) super().__init__(**kwargs) - def check_handler_compatibility(self, other_handler: "ElectrostaticsHandler"): + def check_handler_compatibility(self, other_handler: ElectrostaticsHandler): """ Checks whether this ParameterHandler encodes compatible physics as another ParameterHandler. This is called if a second handler is attempted to be initialized for the same tag. @@ -3133,7 +3134,7 @@ class NAGLChargesHandler(_NonbondedHandler): def check_handler_compatibility( self, - other_handler: "NAGLChargesHandler", + other_handler: NAGLChargesHandler, assume_missing_is_default: bool = True, ): """ @@ -3193,7 +3194,7 @@ class ToolkitAM1BCCHandler(_NonbondedHandler): def check_handler_compatibility( self, - other_handler: "ToolkitAM1BCCHandler", + other_handler: ToolkitAM1BCCHandler, assume_missing_is_default: bool = True, ): """ @@ -3255,7 +3256,7 @@ def __init__(self, **kwargs): def check_handler_compatibility( self, - other_handler: "ChargeIncrementModelHandler", + other_handler: ChargeIncrementModelHandler, assume_missing_is_default: bool = True, ): """ @@ -3335,7 +3336,7 @@ class GBSAType(ParameterType): # Tolerance when comparing float attributes for handler compatibility. _SCALETOL = 1e-5 - def check_handler_compatibility(self, other_handler: "GBSAHandler"): + def check_handler_compatibility(self, other_handler: GBSAHandler): """ Checks whether this ParameterHandler encodes compatible physics as another ParameterHandler. This is called if a second handler is attempted to be initialized for the same tag. @@ -3617,7 +3618,7 @@ def _validate_found_match( f"environment variable `OPENFF_UNSAFE_VSITES=1`." ) - def check_handler_compatibility(self, other_handler: "VirtualSiteHandler"): + def check_handler_compatibility(self, other_handler: VirtualSiteHandler): self._check_attributes_are_equal( other_handler, identical_attrs=("exclusion_policy",), diff --git a/openff/toolkit/typing/engines/smirnoff/plugins.py b/openff/toolkit/typing/engines/smirnoff/plugins.py index 49145ef86..583d5acf4 100644 --- a/openff/toolkit/typing/engines/smirnoff/plugins.py +++ b/openff/toolkit/typing/engines/smirnoff/plugins.py @@ -17,6 +17,7 @@ where in this example your package is named ``myapp`` and contains a class which inherits from ``ParameterHandler`` named ``CustomHandler``. """ +from __future__ import annotations import logging from importlib.metadata import entry_points diff --git a/openff/toolkit/utils/__init__.py b/openff/toolkit/utils/__init__.py index 5c37404b8..175731cbf 100644 --- a/openff/toolkit/utils/__init__.py +++ b/openff/toolkit/utils/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from openff.toolkit.utils.constants import ( ALLOWED_AROMATICITY_MODELS, ALLOWED_CHARGE_MODELS, diff --git a/openff/toolkit/utils/_viz.py b/openff/toolkit/utils/_viz.py index 3ff292c63..2a79d8464 100644 --- a/openff/toolkit/utils/_viz.py +++ b/openff/toolkit/utils/_viz.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import uuid from io import StringIO from typing import TYPE_CHECKING @@ -40,7 +42,7 @@ class MoleculeNGLViewTrajectory(Structure, Trajectory): def __init__( self, - molecule: "Molecule", + molecule: Molecule, ext: str = "MOL2", ): if not molecule.conformers: @@ -89,7 +91,7 @@ class TopologyNGLViewStructure(Structure): def __init__( self, - topology: "Topology", + topology: Topology, ext: str = "PDB", ): self.topology = topology diff --git a/openff/toolkit/utils/ambertools_wrapper.py b/openff/toolkit/utils/ambertools_wrapper.py index 3792b9cd5..22663a2a1 100644 --- a/openff/toolkit/utils/ambertools_wrapper.py +++ b/openff/toolkit/utils/ambertools_wrapper.py @@ -1,6 +1,7 @@ """ Wrapper class providing a minimal consistent interface to `AmberTools `_. """ +from __future__ import annotations __all__ = ("AmberToolsToolkitWrapper",) @@ -100,7 +101,7 @@ def is_available() -> bool: def assign_partial_charges( self, - molecule: "Molecule", + molecule: Molecule, partial_charge_method: str | None = None, use_conformers: list[Quantity] | None = None, strict_n_conformers: bool = False, @@ -380,7 +381,7 @@ def _get_fractional_bond_orders_from_sqm_out(self, file_path, validate_elements= def assign_fractional_bond_orders( self, - molecule: "Molecule", + molecule: Molecule, bond_order_model: str | None = None, use_conformers: list[str] | None = None, _cls=None, diff --git a/openff/toolkit/utils/base_wrapper.py b/openff/toolkit/utils/base_wrapper.py index dc4865a2d..74a836619 100644 --- a/openff/toolkit/utils/base_wrapper.py +++ b/openff/toolkit/utils/base_wrapper.py @@ -1,6 +1,7 @@ """ Base class for toolkit wrappers. Defines the public API and some shared methods """ +from __future__ import annotations __all__ = ("ToolkitWrapper",) @@ -27,7 +28,7 @@ class _ChargeSettings(TypedDict, total=False): oe_charge_method: str -def _mol_to_ctab_and_aro_key(self, molecule: "Molecule", aromaticity_model=DEFAULT_AROMATICITY_MODEL) -> str: +def _mol_to_ctab_and_aro_key(self, molecule: Molecule, aromaticity_model=DEFAULT_AROMATICITY_MODEL) -> str: return f"{molecule.ordered_connection_table_hash()}-{aromaticity_model}" @@ -186,7 +187,7 @@ def from_file_obj(self, file_obj, file_format, allow_undefined_stereo=False, _cl def _check_n_conformers( self, - molecule: "Molecule", + molecule: Molecule, partial_charge_method: str | None = None, min_confs: int | None = None, max_confs: int | None = None, diff --git a/openff/toolkit/utils/builtin_wrapper.py b/openff/toolkit/utils/builtin_wrapper.py index 9b1bdfafa..efe612db4 100644 --- a/openff/toolkit/utils/builtin_wrapper.py +++ b/openff/toolkit/utils/builtin_wrapper.py @@ -1,6 +1,7 @@ """ Built-in ToolkitWrapper for very basic functionality. Intended for testing and not much more. """ +from __future__ import annotations __all__ = ("BuiltInToolkitWrapper",) @@ -38,7 +39,7 @@ def __init__(self): def assign_partial_charges( self, - molecule: "FrozenMolecule", + molecule: FrozenMolecule, partial_charge_method: str | None = None, use_conformers: Quantity | None = None, strict_n_conformers: bool = False, diff --git a/openff/toolkit/utils/callback.py b/openff/toolkit/utils/callback.py index a86170b83..c6d29f74a 100644 --- a/openff/toolkit/utils/callback.py +++ b/openff/toolkit/utils/callback.py @@ -2,6 +2,7 @@ Utility classes and functions to create objects supporting callback registration. """ +from __future__ import annotations __all__ = [ "Callbackable", diff --git a/openff/toolkit/utils/collections.py b/openff/toolkit/utils/collections.py index b9b1dd13c..2badc4f59 100644 --- a/openff/toolkit/utils/collections.py +++ b/openff/toolkit/utils/collections.py @@ -2,6 +2,7 @@ Custom collections classes. """ +from __future__ import annotations __all__ = [ "ValidatedDict", diff --git a/openff/toolkit/utils/constants.py b/openff/toolkit/utils/constants.py index 1b368d2ed..5e6b0de06 100644 --- a/openff/toolkit/utils/constants.py +++ b/openff/toolkit/utils/constants.py @@ -1,3 +1,5 @@ +from __future__ import annotations + __all__ = ( "ALLOWED_AROMATICITY_MODELS", "ALLOWED_CHARGE_MODELS", diff --git a/openff/toolkit/utils/exceptions.py b/openff/toolkit/utils/exceptions.py index f8e69b8bf..2d1a43330 100644 --- a/openff/toolkit/utils/exceptions.py +++ b/openff/toolkit/utils/exceptions.py @@ -1,6 +1,8 @@ +from __future__ import annotations + from collections import defaultdict from collections.abc import Mapping -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING if TYPE_CHECKING: from openmm.app import Atom as OpenMMAtom @@ -429,7 +431,7 @@ def __init__( self, msg: str | None = None, substructure_library: dict[str, list[tuple]] | None = None, - omm_top: Optional["OpenMMTopology"] = None, + omm_top: OpenMMTopology | None = None, unassigned_bonds: list[tuple[int, int]] | None = None, unassigned_atoms: list[int] | None = None, matches: defaultdict[int, list[str]] | None = None, diff --git a/openff/toolkit/utils/nagl_wrapper.py b/openff/toolkit/utils/nagl_wrapper.py index 7587ce2ff..bf9d350f4 100644 --- a/openff/toolkit/utils/nagl_wrapper.py +++ b/openff/toolkit/utils/nagl_wrapper.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import importlib import pathlib import warnings @@ -60,14 +62,14 @@ def is_available(cls) -> bool: def assign_partial_charges( self, - molecule: "Molecule", + molecule: Molecule, partial_charge_method: str, - use_conformers: list["Quantity"] | None = None, + use_conformers: list[Quantity] | None = None, strict_n_conformers: bool = False, normalize_partial_charges: bool = True, doi: str | None = None, file_hash: str | None = None, - _cls: type["FrozenMolecule"] | None = None, + _cls: type[FrozenMolecule] | None = None, ): """ Compute partial charges with NAGL and store in ``self.partial_charges`` diff --git a/openff/toolkit/utils/openeye_wrapper.py b/openff/toolkit/utils/openeye_wrapper.py index 2a33c4a3e..ee21f8de1 100644 --- a/openff/toolkit/utils/openeye_wrapper.py +++ b/openff/toolkit/utils/openeye_wrapper.py @@ -2,6 +2,7 @@ Wrapper class providing a minimal consistent interface to the `OpenEye Toolkit `_ """ +from __future__ import annotations __all__ = ("OpenEyeToolkitWrapper",) @@ -277,7 +278,7 @@ def from_object( obj, allow_undefined_stereo: bool = False, _cls=None, - ) -> "FrozenMolecule": + ) -> FrozenMolecule: """ Convert an OEMol (or OEMol-derived object) into an openff.toolkit.topology.molecule @@ -325,7 +326,7 @@ def _polymer_openmm_topology_to_offmol(self, mol_class, omm_top, substructure_di def _polymer_openmm_topology_to_oemol( self, - omm_top: "openmm.app.Topology", + omm_top: openmm.app.Topology, substructure_library: dict[str, dict], ): """ @@ -460,7 +461,7 @@ def from_file( file_format: str, allow_undefined_stereo: bool = False, _cls=None, - ) -> list["FrozenMolecule"]: + ) -> list[FrozenMolecule]: """ Return an openff.toolkit.topology.Molecule from a file using this toolkit. @@ -524,7 +525,7 @@ def from_file_obj( file_format: str, allow_undefined_stereo: bool = False, _cls=None, - ) -> list["Molecule"]: + ) -> list[Molecule]: """ Return an openff.toolkit.topology.Molecule from a file-like object (an object with a ".read()" method using this toolkit. @@ -563,7 +564,7 @@ def from_file_obj( return self._read_oemolistream_molecules(ifs, allow_undefined_stereo, _cls=_cls) - def to_file_obj(self, molecule: "Molecule", file_obj, file_format: str): + def to_file_obj(self, molecule: Molecule, file_obj, file_format: str): """ Writes an OpenFF Molecule to a file-like object @@ -593,7 +594,7 @@ def to_file_obj(self, molecule: "Molecule", file_obj, file_format: str): def to_file( self, - molecule: "Molecule", + molecule: Molecule, file_path: str | pathlib.Path, file_format: str, ): @@ -807,9 +808,9 @@ def _assign_aromaticity_and_stereo_from_3d(self, offmol): def enumerate_protomers( self, - molecule: "FrozenMolecule", + molecule: FrozenMolecule, max_states: int = 0, - ) -> list["FrozenMolecule"]: + ) -> list[FrozenMolecule]: """ Enumerate the formal charges of a molecule to generate different protomers. Note that, in cases where the input molecule has an uncommon protonation state @@ -850,11 +851,11 @@ def enumerate_protomers( def enumerate_stereoisomers( self, - molecule: "FrozenMolecule", + molecule: FrozenMolecule, undefined_only: bool = False, max_isomers: int = 20, rationalise: bool = True, - ) -> list["FrozenMolecule"]: + ) -> list[FrozenMolecule]: """ Enumerate the stereocenters and bonds of the current molecule. @@ -910,7 +911,7 @@ def enumerate_stereoisomers( return molecules[:max_isomers] - def enumerate_tautomers(self, molecule: "FrozenMolecule", max_states: int = 20) -> list["FrozenMolecule"]: + def enumerate_tautomers(self, molecule: FrozenMolecule, max_states: int = 20) -> list[FrozenMolecule]: """ Enumerate the possible tautomers of the current molecule @@ -1063,7 +1064,7 @@ def from_openeye( oemol, allow_undefined_stereo: bool = False, _cls=None, - ) -> "FrozenMolecule": + ) -> FrozenMolecule: """ Create a Molecule from an OpenEye molecule. If the OpenEye molecule has implicit hydrogens, this function will make them explicit. @@ -1444,7 +1445,7 @@ def _connection_table_to_openeye(self, molecule, aromaticity_model=DEFAULT_AROMA def to_openeye( self, - molecule: "FrozenMolecule", + molecule: FrozenMolecule, aromaticity_model: str = DEFAULT_AROMATICITY_MODEL, ): r""" @@ -1606,7 +1607,7 @@ def to_openeye( return oemol - def atom_is_in_ring(self, atom: "Atom") -> bool: + def atom_is_in_ring(self, atom: Atom) -> bool: """Return whether or not an atom is in a ring. It is assumed that this atom is in molecule. @@ -1638,7 +1639,7 @@ def atom_is_in_ring(self, atom: "Atom") -> bool: return is_in_ring - def bond_is_in_ring(self, bond: "Bond") -> bool: + def bond_is_in_ring(self, bond: Bond) -> bool: """Return whether or not a bond is in a ring. It is assumed that this atom is in molecule. @@ -1696,7 +1697,7 @@ def _get_smiles_flavor(self, isomeric: bool, explicit_hydrogens: bool) -> int: def to_smiles( self, - molecule: "Molecule", + molecule: Molecule, isomeric: bool = True, explicit_hydrogens: bool = True, mapped: bool = False, @@ -1766,7 +1767,7 @@ def to_smiles( smiles = oechem.OECreateSmiString(oemol, smiles_options) return smiles - def to_inchi(self, molecule: "Molecule", fixed_hydrogens: bool = False) -> str: + def to_inchi(self, molecule: Molecule, fixed_hydrogens: bool = False) -> str: """ Create an InChI string for the molecule using the OpenEye OEChem Toolkit. InChI is a standardised representation that does not capture tautomers @@ -1813,7 +1814,7 @@ def to_inchi(self, molecule: "Molecule", fixed_hydrogens: bool = False) -> str: return inchi - def to_inchikey(self, molecule: "Molecule", fixed_hydrogens: bool = False) -> str: + def to_inchikey(self, molecule: Molecule, fixed_hydrogens: bool = False) -> str: """ Create an InChIKey for the molecule using the OpenEye OEChem Toolkit. InChIKey is a standardised representation that does not capture tautomers @@ -1858,7 +1859,7 @@ def to_inchikey(self, molecule: "Molecule", fixed_hydrogens: bool = False) -> st return inchi_key - def to_iupac(self, molecule: "Molecule") -> str: + def to_iupac(self, molecule: Molecule) -> str: """Generate IUPAC name from Molecule Parameters @@ -1888,7 +1889,7 @@ def to_iupac(self, molecule: "Molecule") -> str: return oeiupac.OECreateIUPACName(oemol) - def canonical_order_atoms(self, molecule: "FrozenMolecule") -> "FrozenMolecule": + def canonical_order_atoms(self, molecule: FrozenMolecule) -> FrozenMolecule: """ Canonical order the atoms in the molecule using the OpenEye toolkit. @@ -1938,7 +1939,7 @@ def from_smiles( allow_undefined_stereo: bool = False, _cls=None, name: str = "", - ) -> "FrozenMolecule": + ) -> FrozenMolecule: """ Create a Molecule from a SMILES string using the OpenEye toolkit. @@ -2002,7 +2003,7 @@ def from_inchi( allow_undefined_stereo: bool = False, _cls=None, name: str = "", - ) -> "FrozenMolecule": + ) -> FrozenMolecule: """ Construct a Molecule from a InChI representation @@ -2052,7 +2053,7 @@ def from_iupac( allow_undefined_stereo: bool = False, _cls=None, **kwargs, - ) -> "FrozenMolecule": + ) -> FrozenMolecule: """ Construct a Molecule from an IUPAC name @@ -2089,7 +2090,7 @@ def from_iupac( def generate_conformers( self, - molecule: "Molecule", + molecule: Molecule, n_conformers: int = 1, rms_cutoff: Quantity | None = None, clear_existing: bool = True, @@ -2161,7 +2162,7 @@ def generate_conformers( def apply_elf_conformer_selection( self, - molecule: "Molecule", + molecule: Molecule, percentage: float = 2.0, limit: int = 10, ): @@ -2256,7 +2257,7 @@ def apply_elf_conformer_selection( def assign_partial_charges( self, - molecule: "Molecule", + molecule: Molecule, partial_charge_method: str | None = None, use_conformers: list[Quantity] | None = None, strict_n_conformers: bool = False, @@ -2426,7 +2427,7 @@ def assign_partial_charges( def assign_fractional_bond_orders( self, - molecule: "Molecule", + molecule: Molecule, bond_order_model: str | None = None, use_conformers: list[Quantity] | None = None, _cls=None, @@ -2681,7 +2682,7 @@ def _find_smarts_matches( def find_smarts_matches( self, - molecule: "Molecule", + molecule: Molecule, smarts: str, aromaticity_model=DEFAULT_AROMATICITY_MODEL, unique=False, diff --git a/openff/toolkit/utils/rdkit_wrapper.py b/openff/toolkit/utils/rdkit_wrapper.py index 90d1da47a..03fc451af 100644 --- a/openff/toolkit/utils/rdkit_wrapper.py +++ b/openff/toolkit/utils/rdkit_wrapper.py @@ -2,6 +2,7 @@ """ Wrapper class providing a minimal consistent interface to the `RDKit `. """ +from __future__ import annotations __all__ = ("RDKitToolkitWrapper",) @@ -1105,7 +1106,7 @@ def from_file_obj( # TODO: TDT file support return mols - def to_file_obj(self, molecule: "Molecule", file_obj, file_format: str): + def to_file_obj(self, molecule: Molecule, file_obj, file_format: str): """ Writes an OpenFF Molecule to a file-like object @@ -1155,7 +1156,7 @@ def to_file_obj(self, molecule: "Molecule", file_obj, file_format: str): finally: writer.close() - def to_file(self, molecule: "Molecule", file_path: str, file_format: str): + def to_file(self, molecule: Molecule, file_path: str, file_format: str): """ Writes an OpenFF Molecule to a file-like object @@ -1179,11 +1180,11 @@ def to_file(self, molecule: "Molecule", file_path: str, file_format: str): def enumerate_stereoisomers( self, - molecule: "Molecule", + molecule: Molecule, undefined_only: bool = False, max_isomers: int = 20, rationalise: bool = True, - ) -> list["Molecule"]: + ) -> list[Molecule]: """ Enumerate the stereocenters and bonds of the current molecule. @@ -1240,7 +1241,7 @@ def enumerate_stereoisomers( return molecules - def enumerate_tautomers(self, molecule: "Molecule", max_states: int = 20) -> list["Molecule"]: + def enumerate_tautomers(self, molecule: Molecule, max_states: int = 20) -> list[Molecule]: """ Enumerate the possible tautomers of the current molecule. @@ -1279,7 +1280,7 @@ def enumerate_tautomers(self, molecule: "Molecule", max_states: int = 20) -> lis return molecules[:max_states] - def canonical_order_atoms(self, molecule: "Molecule") -> "Molecule": + def canonical_order_atoms(self, molecule: Molecule) -> Molecule: """ Canonical order the atoms in the molecule using the RDKit. @@ -1320,7 +1321,7 @@ def canonical_order_atoms(self, molecule: "Molecule") -> "Molecule": def to_smiles( self, - molecule: "Molecule", + molecule: Molecule, isomeric: bool = True, explicit_hydrogens: bool = True, mapped: bool = False, @@ -1560,7 +1561,7 @@ def from_inchi( def generate_conformers( self, - molecule: "Molecule", + molecule: Molecule, n_conformers: int = 1, rms_cutoff: Quantity | None = None, clear_existing: bool = True, @@ -1637,7 +1638,7 @@ def generate_conformers( def assign_partial_charges( self, - molecule: "Molecule", + molecule: Molecule, partial_charge_method: str | None = None, use_conformers: list[Quantity] | None = None, strict_n_conformers: bool = False, @@ -1713,7 +1714,7 @@ def assign_partial_charges( @classmethod def _elf_is_problematic_conformer( cls, - molecule: "Molecule", + molecule: Molecule, conformer: Quantity, ) -> tuple[bool, str | None]: """A function which checks if a particular conformer is known to be problematic @@ -1760,7 +1761,7 @@ def _elf_is_problematic_conformer( return False, None @classmethod - def _elf_prune_problematic_conformers(cls, molecule: "Molecule") -> list[Quantity]: + def _elf_prune_problematic_conformers(cls, molecule: Molecule) -> list[Quantity]: """A function which attempts to remove conformers which are known to be problematic when computing ELF partial charges. @@ -1793,7 +1794,7 @@ def _elf_prune_problematic_conformers(cls, molecule: "Molecule") -> list[Quantit @classmethod def _elf_compute_electrostatic_energy( cls, - molecule: "Molecule", + molecule: Molecule, conformer: Quantity, ) -> float: """Computes the 'electrostatic interaction energy' of a particular conformer @@ -1864,7 +1865,7 @@ def _elf_compute_electrostatic_energy( return 0.5 * interaction_energies.sum() @classmethod - def _elf_compute_rms_matrix(cls, molecule: "Molecule") -> NDArray: + def _elf_compute_rms_matrix(cls, molecule: Molecule) -> NDArray: """Computes the symmetric RMS matrix of all conformers in a molecule taking only heavy atoms into account. @@ -1906,7 +1907,7 @@ def _elf_compute_rms_matrix(cls, molecule: "Molecule") -> NDArray: @classmethod def _elf_select_diverse_conformers( cls, - molecule: "Molecule", + molecule: Molecule, ranked_conformers: list[Quantity], limit: int, rms_tolerance: Quantity, @@ -1979,7 +1980,7 @@ def _elf_select_diverse_conformers( def apply_elf_conformer_selection( self, - molecule: "Molecule", + molecule: Molecule, percentage: float = 2.0, limit: int = 10, rms_tolerance: Quantity = 0.05 * unit.angstrom, @@ -2475,7 +2476,7 @@ def _connection_table_to_rdkit(self, molecule, aromaticity_model=DEFAULT_AROMATI return rdmol - def to_rdkit(self, molecule: "Molecule", aromaticity_model: str = DEFAULT_AROMATICITY_MODEL): + def to_rdkit(self, molecule: Molecule, aromaticity_model: str = DEFAULT_AROMATICITY_MODEL): """ Create an RDKit molecule Requires the RDKit to be installed. @@ -2603,7 +2604,7 @@ def to_rdkit(self, molecule: "Molecule", aromaticity_model: str = DEFAULT_AROMAT # Return non-editable version return Chem.Mol(rdmol) - def to_inchi(self, molecule: "Molecule", fixed_hydrogens: bool = False): + def to_inchi(self, molecule: Molecule, fixed_hydrogens: bool = False): """ Create an InChI string for the molecule using the RDKit Toolkit. InChI is a standardised representation that does not capture tautomers @@ -2649,7 +2650,7 @@ def to_inchi(self, molecule: "Molecule", fixed_hydrogens: bool = False): return inchi - def to_inchikey(self, molecule: "Molecule", fixed_hydrogens: bool = False) -> str: + def to_inchikey(self, molecule: Molecule, fixed_hydrogens: bool = False) -> str: """ Create an InChIKey for the molecule using the RDKit Toolkit. InChIKey is a standardised representation that does not capture tautomers @@ -2847,7 +2848,7 @@ def _match_smarts_with_heavy_atoms_first(rdmol, qmol, match_kwargs): def find_smarts_matches( self, - molecule: "Molecule", + molecule: Molecule, smarts: str, aromaticity_model: str = "OEAroModel_MDL", unique: bool = False, @@ -2877,7 +2878,7 @@ def find_smarts_matches( unique=unique, ) - def atom_is_in_ring(self, atom: "Atom") -> bool: + def atom_is_in_ring(self, atom: Atom) -> bool: """Return whether or not an atom is in a ring. It is assumed that this atom is in molecule. @@ -2909,7 +2910,7 @@ def atom_is_in_ring(self, atom: "Atom") -> bool: return is_in_ring - def bond_is_in_ring(self, bond: "Bond") -> bool: + def bond_is_in_ring(self, bond: Bond) -> bool: """Return whether or not a bond is in a ring. It is assumed that this atom is in molecule. @@ -3135,7 +3136,7 @@ def _constrain_rank( raise NotImplementedError() @classmethod - def _assign_rdmol_bonds_stereo(cls, off_molecule: "Molecule", rd_molecule): + def _assign_rdmol_bonds_stereo(cls, off_molecule: Molecule, rd_molecule): """Copy the info about bonds stereochemistry from the OFF Molecule to RDKit Mol. The method proceeds by formulating mapping global E/Z stereo information onto local 'bond directions' as a constraint satisfaction problem (CSP). diff --git a/openff/toolkit/utils/serialization.py b/openff/toolkit/utils/serialization.py index 33ec87d1c..f3e643f84 100644 --- a/openff/toolkit/utils/serialization.py +++ b/openff/toolkit/utils/serialization.py @@ -11,6 +11,7 @@ installed? """ +from __future__ import annotations import abc from typing import TypeVar diff --git a/openff/toolkit/utils/toolkit_registry.py b/openff/toolkit/utils/toolkit_registry.py index 26bceb782..47b47112a 100644 --- a/openff/toolkit/utils/toolkit_registry.py +++ b/openff/toolkit/utils/toolkit_registry.py @@ -1,4 +1,5 @@ "Registry for ToolkitWrapper objects" +from __future__ import annotations __all__ = ("ToolkitRegistry", "toolkit_registry_manager") diff --git a/openff/toolkit/utils/toolkits.py b/openff/toolkit/utils/toolkits.py index da19d1b77..3dcfc8f17 100644 --- a/openff/toolkit/utils/toolkits.py +++ b/openff/toolkit/utils/toolkits.py @@ -19,6 +19,7 @@ * Change global variables from _INSTALLED to _AVAILABLE """ +from __future__ import annotations __all__ = ( "ALLOWED_AROMATICITY_MODELS", diff --git a/openff/toolkit/utils/utils.py b/openff/toolkit/utils/utils.py index 5cc7a6a13..5ca01c418 100644 --- a/openff/toolkit/utils/utils.py +++ b/openff/toolkit/utils/utils.py @@ -2,6 +2,7 @@ Utility subroutines """ +from __future__ import annotations __all__ = [ "all_subclasses", @@ -298,7 +299,7 @@ def convert_all_quantities_to_string( @overload def convert_all_quantities_to_string( - smirnoff_data: "Quantity", + smirnoff_data: Quantity, ) -> str | list[str] | dict[str, Any]: ... @@ -701,7 +702,7 @@ def recursive_attach_unit_strings(smirnoff_data, units_to_attach): return smirnoff_data -def get_molecule_parameterIDs(molecules: list["Molecule"], forcefield: "ForceField") -> tuple[dict, dict]: +def get_molecule_parameterIDs(molecules: list[Molecule], forcefield: ForceField) -> tuple[dict, dict]: """Process a list of molecules with a specified SMIRNOFF ffxml file and determine which parameters are used by which molecules, returning collated results. diff --git a/pyproject.toml b/pyproject.toml index eac6ca15f..a67ea2151 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ lint.isort.known-first-party = [ "openff.toolkit" ] # can't find a clean way to get Rust's globset to handle this via regex ... # https://docs.astral.sh/ruff/settings/#lint_isort_known-third-party lint.isort.known-third-party = [ "openff.interchange", "openff.utilities", "openff.units" ] - +lint.isort.required-imports = ["from __future__ import annotations"] [tool.mypy] python_version = 3.12 warn_unused_configs = true diff --git a/utilities/make_substructure_dict/_make_chemical_substructures.py b/utilities/make_substructure_dict/_make_chemical_substructures.py index 6185cd9d5..b6dae5a82 100644 --- a/utilities/make_substructure_dict/_make_chemical_substructures.py +++ b/utilities/make_substructure_dict/_make_chemical_substructures.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os from _cif_to_substructure_dict import CifSubstructures diff --git a/utilities/make_substructure_dict/_make_metadata_assignment_substructures.py b/utilities/make_substructure_dict/_make_metadata_assignment_substructures.py index e7f19be13..a26f7ea1e 100644 --- a/utilities/make_substructure_dict/_make_metadata_assignment_substructures.py +++ b/utilities/make_substructure_dict/_make_metadata_assignment_substructures.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os from _cif_to_substructure_dict import CifSubstructures diff --git a/utilities/test_plugins/custom_plugins/handler_plugins.py b/utilities/test_plugins/custom_plugins/handler_plugins.py index 8b7790613..075ab9100 100644 --- a/utilities/test_plugins/custom_plugins/handler_plugins.py +++ b/utilities/test_plugins/custom_plugins/handler_plugins.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from openff.toolkit import unit from openff.toolkit.typing.engines.smirnoff import ParameterHandler, ParameterIOHandler from openff.toolkit.typing.engines.smirnoff.parameters import ( diff --git a/utilities/test_plugins/setup.py b/utilities/test_plugins/setup.py index 6f2ae13d9..3bdfd8926 100644 --- a/utilities/test_plugins/setup.py +++ b/utilities/test_plugins/setup.py @@ -2,6 +2,7 @@ openff-test-parameter-plugins A test package used to ensure that parameterhandler plugins are handled correctly """ +from __future__ import annotations from setuptools import setup From af7b23bc416350cba1dbbf5207a7faea80ed3360 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 18:16:03 +0000 Subject: [PATCH 6/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/conftest.py | 1 + examples/examples_helper.py | 1 + openff/toolkit/__init__.py | 1 + openff/toolkit/_tests/conftest.py | 1 + openff/toolkit/_tests/create_molecules.py | 1 + openff/toolkit/_tests/test_examples.py | 1 + openff/toolkit/_tests/test_forcefield.py | 1 + openff/toolkit/_tests/test_io.py | 1 + openff/toolkit/_tests/test_molecule.py | 1 + openff/toolkit/_tests/test_parameter_plugins.py | 1 + openff/toolkit/_tests/test_parameters.py | 1 + openff/toolkit/_tests/test_toolkit_io.py | 1 + openff/toolkit/_tests/test_toolkits.py | 1 + openff/toolkit/_tests/test_topology.py | 1 + openff/toolkit/_tests/test_utils.py | 1 + openff/toolkit/_tests/test_utils_callback.py | 1 + openff/toolkit/_tests/test_utils_collections.py | 1 + openff/toolkit/_tests/test_utils_serialization.py | 1 + openff/toolkit/_tests/utils.py | 1 + openff/toolkit/topology/_mm_molecule.py | 1 + openff/toolkit/topology/molecule.py | 1 + openff/toolkit/topology/topology.py | 1 + openff/toolkit/typing/engines/smirnoff/forcefield.py | 1 + openff/toolkit/typing/engines/smirnoff/io.py | 1 + openff/toolkit/typing/engines/smirnoff/parameters.py | 1 + openff/toolkit/typing/engines/smirnoff/plugins.py | 1 + openff/toolkit/utils/ambertools_wrapper.py | 1 + openff/toolkit/utils/base_wrapper.py | 1 + openff/toolkit/utils/builtin_wrapper.py | 1 + openff/toolkit/utils/callback.py | 1 + openff/toolkit/utils/collections.py | 1 + openff/toolkit/utils/openeye_wrapper.py | 1 + openff/toolkit/utils/rdkit_wrapper.py | 1 + openff/toolkit/utils/serialization.py | 1 + openff/toolkit/utils/toolkit_registry.py | 1 + openff/toolkit/utils/toolkits.py | 1 + openff/toolkit/utils/utils.py | 1 + pyproject.toml | 3 ++- utilities/test_plugins/setup.py | 1 + 39 files changed, 40 insertions(+), 1 deletion(-) diff --git a/docs/conftest.py b/docs/conftest.py index 8cde5f186..92c9e0949 100644 --- a/docs/conftest.py +++ b/docs/conftest.py @@ -5,6 +5,7 @@ The nbval-sanitize.cfg file is also for use with nbval. """ + from __future__ import annotations diff --git a/examples/examples_helper.py b/examples/examples_helper.py index 32bf80d6d..bc2f63b59 100755 --- a/examples/examples_helper.py +++ b/examples/examples_helper.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Copy the openff-toolkit examples suite to a local directory""" + from __future__ import annotations import argparse diff --git a/openff/toolkit/__init__.py b/openff/toolkit/__init__.py index b1d08db58..830405752 100644 --- a/openff/toolkit/__init__.py +++ b/openff/toolkit/__init__.py @@ -2,6 +2,7 @@ openff-toolkit A modern, extensible library for molecular mechanics force field science from the Open Force Field Consortium. """ + from __future__ import annotations import importlib diff --git a/openff/toolkit/_tests/conftest.py b/openff/toolkit/_tests/conftest.py index f61ef1a1c..d804f040b 100644 --- a/openff/toolkit/_tests/conftest.py +++ b/openff/toolkit/_tests/conftest.py @@ -1,6 +1,7 @@ """ Configuration file for pytest. """ + from __future__ import annotations import logging diff --git a/openff/toolkit/_tests/create_molecules.py b/openff/toolkit/_tests/create_molecules.py index e88e98589..06ec9a8bd 100644 --- a/openff/toolkit/_tests/create_molecules.py +++ b/openff/toolkit/_tests/create_molecules.py @@ -4,6 +4,7 @@ These are common to several test modules. """ + from __future__ import annotations import numpy as np diff --git a/openff/toolkit/_tests/test_examples.py b/openff/toolkit/_tests/test_examples.py index 3d28ea2ee..d6919ea8f 100644 --- a/openff/toolkit/_tests/test_examples.py +++ b/openff/toolkit/_tests/test_examples.py @@ -1,6 +1,7 @@ """ Test that the examples in the repo run without errors. """ + from __future__ import annotations import pathlib diff --git a/openff/toolkit/_tests/test_forcefield.py b/openff/toolkit/_tests/test_forcefield.py index 827b07350..28f9a764a 100644 --- a/openff/toolkit/_tests/test_forcefield.py +++ b/openff/toolkit/_tests/test_forcefield.py @@ -2,6 +2,7 @@ Tests for forcefield class """ + from __future__ import annotations import copy diff --git a/openff/toolkit/_tests/test_io.py b/openff/toolkit/_tests/test_io.py index f6967b2bf..694951729 100644 --- a/openff/toolkit/_tests/test_io.py +++ b/openff/toolkit/_tests/test_io.py @@ -2,6 +2,7 @@ Test classes and function in module openff.toolkit.typing.engines.smirnoff.io. """ + from __future__ import annotations import pytest diff --git a/openff/toolkit/_tests/test_molecule.py b/openff/toolkit/_tests/test_molecule.py index 5b0851684..7a41cfc4a 100644 --- a/openff/toolkit/_tests/test_molecule.py +++ b/openff/toolkit/_tests/test_molecule.py @@ -12,6 +12,7 @@ serialized OFFMols. """ + from __future__ import annotations import copy diff --git a/openff/toolkit/_tests/test_parameter_plugins.py b/openff/toolkit/_tests/test_parameter_plugins.py index 397a8c3e8..797922419 100644 --- a/openff/toolkit/_tests/test_parameter_plugins.py +++ b/openff/toolkit/_tests/test_parameter_plugins.py @@ -1,6 +1,7 @@ """ Test classes and function in module openff.toolkit.typing.engines.smirnoff.plugins """ + from __future__ import annotations import pytest diff --git a/openff/toolkit/_tests/test_parameters.py b/openff/toolkit/_tests/test_parameters.py index 7c488f8d6..1f62befdf 100644 --- a/openff/toolkit/_tests/test_parameters.py +++ b/openff/toolkit/_tests/test_parameters.py @@ -2,6 +2,7 @@ Test classes and function in module openff.toolkit.typing.engines.smirnoff.parameters. """ + from __future__ import annotations from collections import defaultdict diff --git a/openff/toolkit/_tests/test_toolkit_io.py b/openff/toolkit/_tests/test_toolkit_io.py index 5338ce114..b86d6331f 100644 --- a/openff/toolkit/_tests/test_toolkit_io.py +++ b/openff/toolkit/_tests/test_toolkit_io.py @@ -2,6 +2,7 @@ Tests for I/O functionality of the toolkit wrappers """ + from __future__ import annotations import pathlib diff --git a/openff/toolkit/_tests/test_toolkits.py b/openff/toolkit/_tests/test_toolkits.py index 0be2d2969..1c8f8f12d 100644 --- a/openff/toolkit/_tests/test_toolkits.py +++ b/openff/toolkit/_tests/test_toolkits.py @@ -2,6 +2,7 @@ Tests for cheminformatics toolkit wrappers """ + from __future__ import annotations import logging diff --git a/openff/toolkit/_tests/test_topology.py b/openff/toolkit/_tests/test_topology.py index d652d920c..f8d8853bd 100644 --- a/openff/toolkit/_tests/test_topology.py +++ b/openff/toolkit/_tests/test_topology.py @@ -2,6 +2,7 @@ Tests for Topology """ + from __future__ import annotations import itertools diff --git a/openff/toolkit/_tests/test_utils.py b/openff/toolkit/_tests/test_utils.py index e6f0b2b1e..04d40ac00 100644 --- a/openff/toolkit/_tests/test_utils.py +++ b/openff/toolkit/_tests/test_utils.py @@ -2,6 +2,7 @@ Tests for utility methods """ + from __future__ import annotations import os diff --git a/openff/toolkit/_tests/test_utils_callback.py b/openff/toolkit/_tests/test_utils_callback.py index 90b6741b3..b3ecb045f 100644 --- a/openff/toolkit/_tests/test_utils_callback.py +++ b/openff/toolkit/_tests/test_utils_callback.py @@ -2,6 +2,7 @@ Tests for callback utility classes and functions. """ + from __future__ import annotations import pytest diff --git a/openff/toolkit/_tests/test_utils_collections.py b/openff/toolkit/_tests/test_utils_collections.py index 694018073..c5696be15 100644 --- a/openff/toolkit/_tests/test_utils_collections.py +++ b/openff/toolkit/_tests/test_utils_collections.py @@ -2,6 +2,7 @@ Tests for custom collections classes. """ + from __future__ import annotations import copy diff --git a/openff/toolkit/_tests/test_utils_serialization.py b/openff/toolkit/_tests/test_utils_serialization.py index 54cb24a21..cac0bd229 100644 --- a/openff/toolkit/_tests/test_utils_serialization.py +++ b/openff/toolkit/_tests/test_utils_serialization.py @@ -2,6 +2,7 @@ Tests for utility methods for serialization """ + from __future__ import annotations import numpy as np diff --git a/openff/toolkit/_tests/utils.py b/openff/toolkit/_tests/utils.py index 9051fded4..61b4ad0d9 100644 --- a/openff/toolkit/_tests/utils.py +++ b/openff/toolkit/_tests/utils.py @@ -2,6 +2,7 @@ Utilities for testing. """ + from __future__ import annotations import collections diff --git a/openff/toolkit/topology/_mm_molecule.py b/openff/toolkit/topology/_mm_molecule.py index 3d4d3a2a3..2161f6fb9 100644 --- a/openff/toolkit/topology/_mm_molecule.py +++ b/openff/toolkit/topology/_mm_molecule.py @@ -9,6 +9,7 @@ deserialize a Molecule or a TypedMolecule. """ + from __future__ import annotations import functools diff --git a/openff/toolkit/topology/molecule.py b/openff/toolkit/topology/molecule.py index 1c85a826b..401d2a091 100644 --- a/openff/toolkit/topology/molecule.py +++ b/openff/toolkit/topology/molecule.py @@ -24,6 +24,7 @@ * Speed up overall import time by putting non-global imports only where they are needed """ + from __future__ import annotations import hashlib diff --git a/openff/toolkit/topology/topology.py b/openff/toolkit/topology/topology.py index 3124348b2..4613f2acb 100644 --- a/openff/toolkit/topology/topology.py +++ b/openff/toolkit/topology/topology.py @@ -11,6 +11,7 @@ * Use `attrs `_ for object setter boilerplate? """ + from __future__ import annotations import re diff --git a/openff/toolkit/typing/engines/smirnoff/forcefield.py b/openff/toolkit/typing/engines/smirnoff/forcefield.py index e3c26ca64..326cfd860 100644 --- a/openff/toolkit/typing/engines/smirnoff/forcefield.py +++ b/openff/toolkit/typing/engines/smirnoff/forcefield.py @@ -10,6 +10,7 @@ * Speed up overall import time by putting non-global imports only where they are needed """ + from __future__ import annotations import logging diff --git a/openff/toolkit/typing/engines/smirnoff/io.py b/openff/toolkit/typing/engines/smirnoff/io.py index ff6e13a56..cd9e129ed 100644 --- a/openff/toolkit/typing/engines/smirnoff/io.py +++ b/openff/toolkit/typing/engines/smirnoff/io.py @@ -6,6 +6,7 @@ .. codeauthor:: Peter K. Eastman """ + from __future__ import annotations __all__ = [ diff --git a/openff/toolkit/typing/engines/smirnoff/parameters.py b/openff/toolkit/typing/engines/smirnoff/parameters.py index ead8b2470..5c3151fc9 100644 --- a/openff/toolkit/typing/engines/smirnoff/parameters.py +++ b/openff/toolkit/typing/engines/smirnoff/parameters.py @@ -6,6 +6,7 @@ New pluggable handlers can be created by creating subclasses of :class:`ParameterHandler`. """ + from __future__ import annotations __all__ = [ diff --git a/openff/toolkit/typing/engines/smirnoff/plugins.py b/openff/toolkit/typing/engines/smirnoff/plugins.py index 583d5acf4..91f338975 100644 --- a/openff/toolkit/typing/engines/smirnoff/plugins.py +++ b/openff/toolkit/typing/engines/smirnoff/plugins.py @@ -17,6 +17,7 @@ where in this example your package is named ``myapp`` and contains a class which inherits from ``ParameterHandler`` named ``CustomHandler``. """ + from __future__ import annotations import logging diff --git a/openff/toolkit/utils/ambertools_wrapper.py b/openff/toolkit/utils/ambertools_wrapper.py index 22663a2a1..c4b8e8d6e 100644 --- a/openff/toolkit/utils/ambertools_wrapper.py +++ b/openff/toolkit/utils/ambertools_wrapper.py @@ -1,6 +1,7 @@ """ Wrapper class providing a minimal consistent interface to `AmberTools `_. """ + from __future__ import annotations __all__ = ("AmberToolsToolkitWrapper",) diff --git a/openff/toolkit/utils/base_wrapper.py b/openff/toolkit/utils/base_wrapper.py index 74a836619..b423d4edb 100644 --- a/openff/toolkit/utils/base_wrapper.py +++ b/openff/toolkit/utils/base_wrapper.py @@ -1,6 +1,7 @@ """ Base class for toolkit wrappers. Defines the public API and some shared methods """ + from __future__ import annotations __all__ = ("ToolkitWrapper",) diff --git a/openff/toolkit/utils/builtin_wrapper.py b/openff/toolkit/utils/builtin_wrapper.py index efe612db4..702f2459d 100644 --- a/openff/toolkit/utils/builtin_wrapper.py +++ b/openff/toolkit/utils/builtin_wrapper.py @@ -1,6 +1,7 @@ """ Built-in ToolkitWrapper for very basic functionality. Intended for testing and not much more. """ + from __future__ import annotations __all__ = ("BuiltInToolkitWrapper",) diff --git a/openff/toolkit/utils/callback.py b/openff/toolkit/utils/callback.py index c6d29f74a..6dcd4fc09 100644 --- a/openff/toolkit/utils/callback.py +++ b/openff/toolkit/utils/callback.py @@ -2,6 +2,7 @@ Utility classes and functions to create objects supporting callback registration. """ + from __future__ import annotations __all__ = [ diff --git a/openff/toolkit/utils/collections.py b/openff/toolkit/utils/collections.py index 2badc4f59..9338c5792 100644 --- a/openff/toolkit/utils/collections.py +++ b/openff/toolkit/utils/collections.py @@ -2,6 +2,7 @@ Custom collections classes. """ + from __future__ import annotations __all__ = [ diff --git a/openff/toolkit/utils/openeye_wrapper.py b/openff/toolkit/utils/openeye_wrapper.py index ee21f8de1..33ffc2371 100644 --- a/openff/toolkit/utils/openeye_wrapper.py +++ b/openff/toolkit/utils/openeye_wrapper.py @@ -2,6 +2,7 @@ Wrapper class providing a minimal consistent interface to the `OpenEye Toolkit `_ """ + from __future__ import annotations __all__ = ("OpenEyeToolkitWrapper",) diff --git a/openff/toolkit/utils/rdkit_wrapper.py b/openff/toolkit/utils/rdkit_wrapper.py index 03fc451af..52f189fc2 100644 --- a/openff/toolkit/utils/rdkit_wrapper.py +++ b/openff/toolkit/utils/rdkit_wrapper.py @@ -2,6 +2,7 @@ """ Wrapper class providing a minimal consistent interface to the `RDKit `. """ + from __future__ import annotations __all__ = ("RDKitToolkitWrapper",) diff --git a/openff/toolkit/utils/serialization.py b/openff/toolkit/utils/serialization.py index f3e643f84..df62c213c 100644 --- a/openff/toolkit/utils/serialization.py +++ b/openff/toolkit/utils/serialization.py @@ -11,6 +11,7 @@ installed? """ + from __future__ import annotations import abc diff --git a/openff/toolkit/utils/toolkit_registry.py b/openff/toolkit/utils/toolkit_registry.py index 47b47112a..4ddbba849 100644 --- a/openff/toolkit/utils/toolkit_registry.py +++ b/openff/toolkit/utils/toolkit_registry.py @@ -1,4 +1,5 @@ "Registry for ToolkitWrapper objects" + from __future__ import annotations __all__ = ("ToolkitRegistry", "toolkit_registry_manager") diff --git a/openff/toolkit/utils/toolkits.py b/openff/toolkit/utils/toolkits.py index 3dcfc8f17..8fe3d3d22 100644 --- a/openff/toolkit/utils/toolkits.py +++ b/openff/toolkit/utils/toolkits.py @@ -19,6 +19,7 @@ * Change global variables from _INSTALLED to _AVAILABLE """ + from __future__ import annotations __all__ = ( diff --git a/openff/toolkit/utils/utils.py b/openff/toolkit/utils/utils.py index 5ca01c418..9ddf6039a 100644 --- a/openff/toolkit/utils/utils.py +++ b/openff/toolkit/utils/utils.py @@ -2,6 +2,7 @@ Utility subroutines """ + from __future__ import annotations __all__ = [ diff --git a/pyproject.toml b/pyproject.toml index a67ea2151..ebdd3458c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,8 @@ lint.isort.known-first-party = [ "openff.toolkit" ] # can't find a clean way to get Rust's globset to handle this via regex ... # https://docs.astral.sh/ruff/settings/#lint_isort_known-third-party lint.isort.known-third-party = [ "openff.interchange", "openff.utilities", "openff.units" ] -lint.isort.required-imports = ["from __future__ import annotations"] +lint.isort.required-imports = [ "from __future__ import annotations" ] + [tool.mypy] python_version = 3.12 warn_unused_configs = true diff --git a/utilities/test_plugins/setup.py b/utilities/test_plugins/setup.py index 3bdfd8926..7e04ee42b 100644 --- a/utilities/test_plugins/setup.py +++ b/utilities/test_plugins/setup.py @@ -2,6 +2,7 @@ openff-test-parameter-plugins A test package used to ensure that parameterhandler plugins are handled correctly """ + from __future__ import annotations from setuptools import setup From 1ffcb78aa65db467aecd2f2b7161156ae6736e46 Mon Sep 17 00:00:00 2001 From: Mike Henry <11765982+mikemhenry@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:02:37 -0700 Subject: [PATCH 7/7] skip openeye b/c of license issues --- .github/workflows/CI.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d52217db9..e284da347 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -25,15 +25,11 @@ jobs: os: [ubuntu-latest, macos-latest] python-version: ["3.12", "3.13", "3.14"] rdkit: [true, false] - openeye: [true, false] + openeye: [false] nagl: [true, false] exclude: - rdkit: false openeye: false - - openeye: true - python-version: "3.13" - - openeye: true - python-version: "3.14" - rdkit: false nagl: true