diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index da71aeb0e..1fac6a138 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -154,7 +154,7 @@ jobs: PYTEST_ARGS+=" --runslow" fi - python -m pytest $PYTEST_ARGS $COV + python -m pytest --durations=20 $PYTEST_ARGS $COV - name: Run code snippets in docs if: ${{ matrix.rdkit == true && matrix.openeye == true }} diff --git a/.github/workflows/beta_rc.yaml b/.github/workflows/beta_rc.yaml index 45dab90de..deb0e8fa1 100644 --- a/.github/workflows/beta_rc.yaml +++ b/.github/workflows/beta_rc.yaml @@ -20,7 +20,7 @@ jobs: - ubuntu-latest - macos-latest python-version: - - 3.9 + - 3.10 env: OE_LICENSE: ${{ github.workspace }}/oe_license.txt @@ -39,12 +39,6 @@ jobs: create-args: >- python=${{ matrix.python-version }} - - name: Additional info about the build - run: | - uname -a - df -h - ulimit -a - - name: Make oe_license.txt file from GH org secret "OE_LICENSE" env: OE_LICENSE_TEXT: ${{ secrets.OE_LICENSE }} @@ -57,21 +51,16 @@ jobs: python -m pip install . - name: Install test plugins - run: | - python -m pip install utilities/test_plugins + run: python -m pip install utilities/test_plugins - name: Environment Information - run: | - conda info - conda list + run: micromamba info && micromamba list - name: Check links - run: | - pytest -r fE --tb=short openff/toolkit/_tests/test_links.py + run: pytest -r fE --tb=short openff/toolkit/_tests/test_links.py - name: Run mypy - run: | - mypy --namespace-packages -p "openff.toolkit" + run: mypy -p "openff.toolkit" - name: Run unit tests run: | diff --git a/devtools/conda-envs/beta_rc_env.yaml b/devtools/conda-envs/beta_rc_env.yaml index 4336a1fb0..bd759be64 100644 --- a/devtools/conda-envs/beta_rc_env.yaml +++ b/devtools/conda-envs/beta_rc_env.yaml @@ -25,7 +25,8 @@ dependencies: - openff-nagl-models ==0.1.0 # Toolkit-specific - ambertools >=22 - - rdkit + # https://github.com/rdkit/rdkit/issues/7221 + - rdkit >=2023.09.6 - openeye-toolkits # Test-only/optional/dev - pytest diff --git a/devtools/conda-envs/rdkit-examples.yaml b/devtools/conda-envs/rdkit-examples.yaml index 52ce52d29..962d7c7d5 100644 --- a/devtools/conda-envs/rdkit-examples.yaml +++ b/devtools/conda-envs/rdkit-examples.yaml @@ -27,7 +27,8 @@ dependencies: # AmberTools 23 brings in ParmEd 4, which doesn't yet work with examples # https://github.com/openforcefield/openff-toolkit/issues/1532 - ambertools =22.4 - - rdkit + # https://github.com/rdkit/rdkit/issues/7221 + - rdkit <2023.09.6 # Test-only/optional/dev/typing/examples - pytest - pytest-xdist diff --git a/devtools/conda-envs/rdkit.yaml b/devtools/conda-envs/rdkit.yaml index c4df2f329..2232c87c8 100644 --- a/devtools/conda-envs/rdkit.yaml +++ b/devtools/conda-envs/rdkit.yaml @@ -24,7 +24,8 @@ dependencies: - typing_extensions # Toolkit-specific - ambertools >=22 - - rdkit + # https://github.com/rdkit/rdkit/issues/7221 + - rdkit <2023.09.6 # Test-only/optional/dev/typing - pytest - pytest-cov diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index 3f83bb2a0..82871126c 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -24,7 +24,8 @@ dependencies: - openff-nagl-models ==0.1.0 # Toolkit-specific - ambertools >=22 - - rdkit + # https://github.com/rdkit/rdkit/issues/7221 + - rdkit <2023.09.6 - openeye-toolkits # Test-only/optional/dev/typing - pytest diff --git a/openff/toolkit/_tests/test_examples.py b/openff/toolkit/_tests/test_examples.py index bed901cd2..34170601c 100644 --- a/openff/toolkit/_tests/test_examples.py +++ b/openff/toolkit/_tests/test_examples.py @@ -2,7 +2,6 @@ Test that the examples in the repo run without errors. """ -import os import pathlib import re import subprocess @@ -11,10 +10,9 @@ import pytest +from openff.toolkit._tests.utils import _get_readme_path from openff.toolkit.utils import RDKIT_AVAILABLE, get_data_file_path, temporary_cd -ROOT_DIR_PATH = pathlib.Path(__file__).joinpath("../../../../").resolve() - def run_script_file(file_path): """Run through the shell a python script.""" @@ -38,19 +36,20 @@ def run_script_str(script_str): """ with tempfile.TemporaryDirectory() as tmp_dir: - temp_file_path = os.path.join(tmp_dir, "temp.py") + temp_file_path = pathlib.Path(tmp_dir, "temp.py").as_posix() + # Create temporary python script. with open(temp_file_path, "w") as f: f.write(script_str) # Run the Python script. try: run_script_file(temp_file_path) - except: # noqa + except Exception as error: script_str = textwrap.indent(script_str, " ") - raise Exception(f"The following script failed:\n{script_str}") + raise Exception(f"The following script failed:\n{script_str}") from error -def find_example_scripts(): +def find_example_scripts() -> list[str]: """Find all Python scripts, excluding Jupyter notebooks, in the examples folder. Returns @@ -58,12 +57,16 @@ def find_example_scripts(): example_file_paths : list[str] List of full paths to python scripts to execute. """ - examples_dir_path = ROOT_DIR_PATH.joinpath("examples") + # Count on the examples/ path being equivalently accessible as the README file + readme_file_path = _get_readme_path() + + if readme_file_path is None: + return list() + + examples_dir_path = pathlib.Path(_get_readme_path().parent, "examples") # Examples that require RDKit - rdkit_examples = { - examples_dir_path.joinpath("conformer_energies/conformer_energies.py"), - } + rdkit_examples = {examples_dir_path / "conformer_energies/conformer_energies.py"} example_file_paths = [] for example_file_path in examples_dir_path.glob("*/*.py"): @@ -75,7 +78,7 @@ def find_example_scripts(): return example_file_paths -def find_readme_examples(): +def find_readme_examples() -> list[str]: """Yield the Python scripts in the main README.md file. Returns @@ -83,9 +86,14 @@ def find_readme_examples(): readme_examples : list[str] The list of Python scripts included in the README.md files. """ - readme_path = ROOT_DIR_PATH.joinpath("README.md") - with open(readme_path, "r") as f: + readme_file_path = _get_readme_path() + + if readme_file_path is None: + return list() + + with open(readme_file_path, "r") as f: readme_content = f.read() + return re.findall("```python(.*?)```", readme_content, flags=re.DOTALL) diff --git a/openff/toolkit/_tests/test_forcefield.py b/openff/toolkit/_tests/test_forcefield.py index e7b836491..0eb81ad77 100644 --- a/openff/toolkit/_tests/test_forcefield.py +++ b/openff/toolkit/_tests/test_forcefield.py @@ -4075,6 +4075,7 @@ def test_toolkit_registry_bad_charge_method(self): class TestSmirnoffVersionConverter: @requires_openeye_mol2 + @pytest.mark.slow @pytest.mark.parametrize( ("freesolv_id", "forcefield_version", "allow_undefined_stereo"), generate_freesolv_parameters_assignment_cases(), diff --git a/openff/toolkit/_tests/test_links.py b/openff/toolkit/_tests/test_links.py index 262632df6..6cc2e38c2 100644 --- a/openff/toolkit/_tests/test_links.py +++ b/openff/toolkit/_tests/test_links.py @@ -1,15 +1,12 @@ -import os import re from urllib.request import Request, urlopen import pytest -ROOT_DIR_PATH = os.path.join( - os.path.dirname(os.path.realpath(__file__)), "..", "..", ".." -) +from openff.toolkit._tests.utils import _get_readme_path -def find_readme_links(): +def find_readme_links() -> list[str]: """Yield all the links in the main README.md file. Returns @@ -17,10 +14,16 @@ def find_readme_links(): readme_examples : list[str] The list of links included in the README.md file. """ - readme_file_path = os.path.join(ROOT_DIR_PATH, "README.md") - with open(readme_file_path, "r") as f: - readme_content = f.read() - return re.findall("http[s]?://(?:[0-9a-zA-Z]|[-/.%:_])+", readme_content) + readme_file_path = _get_readme_path() + + if readme_file_path is None: + return list() + + else: + with open(readme_file_path.as_posix(), "r") as f: + readme_content = f.read() + + return re.findall("http[s]?://(?:[0-9a-zA-Z]|[-/.%:_])+", readme_content) @pytest.mark.parametrize("readme_link", find_readme_links()) diff --git a/openff/toolkit/_tests/test_topology.py b/openff/toolkit/_tests/test_topology.py index 03ffe0d15..d2385a40c 100644 --- a/openff/toolkit/_tests/test_topology.py +++ b/openff/toolkit/_tests/test_topology.py @@ -1712,6 +1712,7 @@ def test_topology_hierarchy_iterators( @skip_if_missing("nglview") class TestTopologyVisaulization: + @pytest.mark.slow @requires_rdkit def test_visualize_basic(self): import nglview diff --git a/openff/toolkit/_tests/utils.py b/openff/toolkit/_tests/utils.py index 865d76db1..350ed135a 100644 --- a/openff/toolkit/_tests/utils.py +++ b/openff/toolkit/_tests/utils.py @@ -9,9 +9,11 @@ import importlib import itertools import os +import pathlib import pprint import textwrap from contextlib import contextmanager +from typing import Union import numpy as np import openmm @@ -45,6 +47,22 @@ ) +def _get_readme_path() -> Union[pathlib.Path, None]: + """ + Return a path to the README file or None if it cannot be assured to be the toolkit's README. + """ + if "site-packages" in __file__: + # This test file is being collected from the installed package, which + # does not provide the README file. + # Note that there will likely be a mis-bundled file + # $CONDA_PREFIX/lib/python3.x/site-packages/README.md, but this is not + # the toolkit's README file! + return None + + else: + return pathlib.Path(__file__).parents[3] / "README.md" + + def has_pkg(pkg_name): """ Helper function to generically check if a package is installed. Intended