diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index d4482fe685..9803ff8490 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -13,11 +13,11 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.9", "3.12"] + python-version: ["3.10", "3.12"] os: [ubuntu-latest, windows-latest] exclude: - os: windows-latest - python-version: "3.9" + python-version: "3.10" runs-on: ${{ matrix.os }} defaults: diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b6ca2e3bc..9d35ec903c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project generally adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.11.5] + +### Added + +- Added support for atomate2>=0.0.15 + +### Changed + +- The minimum supported Python version is now 3.10 in alignment with Pymatgen + +## [0.11.4] + +### Changed + +- Put a `<=` version pin on Atomate2 to resolve upstream breaking change + ## [0.11.3] ### Added diff --git a/pyproject.toml b/pyproject.toml index 249fb15581..cbd7434649 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "quacc" description="A platform to enable high-throughput, database-driven quantum chemistry and computational materials science" -version = "0.11.4" +version = "0.11.5" readme = "README.md" license = { text = "BSD-3" } authors = [{ name = "Andrew S. Rosen", email = "asrosen@princeton.edu" }] @@ -15,7 +15,6 @@ classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Science/Research", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -25,7 +24,7 @@ classifiers = [ "Operating System :: Unix", "Operating System :: MacOS", ] -requires-python = ">=3.9" +requires-python = ">=3.10" dependencies = [ "ase>=3.23.0", # for Atoms object and calculators "custodian>=2024.3.12", # for automated error corrections @@ -47,7 +46,7 @@ dask = ["dask[distributed]>=2023.12.1", "dask-jobqueue>=0.8.2"] defects = ["pymatgen-analysis-defects>=2023.8.22", "shakenbreak>=3.2.0"] jobflow = ["jobflow[fireworks]>=0.1.14", "jobflow-remote>=0.1.0"] mlp = ["matgl>=1.1.2", "chgnet>=0.3.3", "mace-torch>=0.3.3", "torch-dftd>=0.4.0"] -mp = ["atomate2<=0.0.14"] +mp = ["atomate2>=0.0.14"] newtonnet = ["newtonnet>=1.1"] parsl = ["parsl[monitoring]>=2024.5.27; platform_system!='Windows'"] phonons = ["phonopy>=2.20.0", "seekpath>=2.1.0"] diff --git a/src/quacc/calculators/vasp/params.py b/src/quacc/calculators/vasp/params.py index 052a44a8dd..283249d315 100644 --- a/src/quacc/calculators/vasp/params.py +++ b/src/quacc/calculators/vasp/params.py @@ -449,7 +449,11 @@ def convert_vasp_maker(self, VaspMaker: BaseVaspMaker) -> dict: ) self.incar_dict = input_set.incar self.pmg_kpts = input_set.kpoints - self.potcar_symbols = input_set.potcar + self.potcar_symbols = ( + input_set.potcar.split("\n") + if isinstance(input_set.potcar, str) + else input_set.potcar + ) self.potcar_functional = input_set_generator.potcar_functional self.poscar = input_set.poscar return self._convert() diff --git a/src/quacc/calculators/vasp/vasp.py b/src/quacc/calculators/vasp/vasp.py index f3a1a00c3a..ecb9587303 100644 --- a/src/quacc/calculators/vasp/vasp.py +++ b/src/quacc/calculators/vasp/vasp.py @@ -232,7 +232,7 @@ def _cleanup_params(self) -> None: # Allow the user to use setups='mysetups.yaml' to load in a custom # setups from a YAML file if ( - isinstance(self.user_calc_params.get("setups"), (str, Path)) + isinstance(self.user_calc_params.get("setups"), str | Path) and self.user_calc_params["setups"] not in ase_setups.setups_defaults ): self.user_calc_params["setups"] = load_vasp_yaml_calc( diff --git a/src/quacc/recipes/emt/defects.py b/src/quacc/recipes/emt/defects.py index f9734ae5a4..591a77063e 100644 --- a/src/quacc/recipes/emt/defects.py +++ b/src/quacc/recipes/emt/defects.py @@ -21,7 +21,8 @@ if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/recipes/emt/elastic.py b/src/quacc/recipes/emt/elastic.py index 3d1980a748..3f2e9dbbb1 100644 --- a/src/quacc/recipes/emt/elastic.py +++ b/src/quacc/recipes/emt/elastic.py @@ -10,7 +10,8 @@ from quacc.wflow_tools.customizers import customize_funcs if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/recipes/emt/phonons.py b/src/quacc/recipes/emt/phonons.py index 97f87c0e37..2a111bb1f9 100644 --- a/src/quacc/recipes/emt/phonons.py +++ b/src/quacc/recipes/emt/phonons.py @@ -10,7 +10,8 @@ from quacc.wflow_tools.customizers import customize_funcs if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/recipes/emt/slabs.py b/src/quacc/recipes/emt/slabs.py index 830e0e7c35..e0c20b3fca 100644 --- a/src/quacc/recipes/emt/slabs.py +++ b/src/quacc/recipes/emt/slabs.py @@ -10,7 +10,8 @@ from quacc.wflow_tools.customizers import customize_funcs if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/recipes/espresso/_base.py b/src/quacc/recipes/espresso/_base.py index 0937926bdf..665a504832 100644 --- a/src/quacc/recipes/espresso/_base.py +++ b/src/quacc/recipes/espresso/_base.py @@ -258,7 +258,7 @@ def prepare_copy( dict Dictionary of files to copy. """ - if isinstance(copy_files, (str, Path)): + if isinstance(copy_files, str | Path): copy_files = [copy_files] if isinstance(copy_files, list): diff --git a/src/quacc/recipes/espresso/bands.py b/src/quacc/recipes/espresso/bands.py index 2c7e7c400b..887a0cd553 100644 --- a/src/quacc/recipes/espresso/bands.py +++ b/src/quacc/recipes/espresso/bands.py @@ -18,7 +18,8 @@ from quacc.wflow_tools.customizers import customize_funcs if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/recipes/espresso/dos.py b/src/quacc/recipes/espresso/dos.py index 534bed6f72..c343a45bdf 100644 --- a/src/quacc/recipes/espresso/dos.py +++ b/src/quacc/recipes/espresso/dos.py @@ -12,7 +12,8 @@ from quacc.wflow_tools.customizers import customize_funcs if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/recipes/espresso/phonons.py b/src/quacc/recipes/espresso/phonons.py index 60b0608c77..512cdb8b60 100644 --- a/src/quacc/recipes/espresso/phonons.py +++ b/src/quacc/recipes/espresso/phonons.py @@ -23,7 +23,8 @@ if TYPE_CHECKING: from collections import UserDict - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from quacc.types import ( EspressoPhononDosSchema, diff --git a/src/quacc/recipes/mlp/phonons.py b/src/quacc/recipes/mlp/phonons.py index 4d707af4d2..87f67225b6 100644 --- a/src/quacc/recipes/mlp/phonons.py +++ b/src/quacc/recipes/mlp/phonons.py @@ -16,7 +16,8 @@ has_seekpath = bool(find_spec("seekpath")) if TYPE_CHECKING: - from typing import Any, Callable, Literal + from collections.abc import Callable + from typing import Any, Literal from ase.atoms import Atoms diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index 6268971332..d6bd43c775 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -17,7 +17,8 @@ has_seekpath = bool(find_spec("seekpath")) if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/recipes/vasp/mp.py b/src/quacc/recipes/vasp/mp.py index 9ec1988df9..5cd39f36c7 100644 --- a/src/quacc/recipes/vasp/mp.py +++ b/src/quacc/recipes/vasp/mp.py @@ -31,7 +31,8 @@ ) if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/recipes/vasp/slabs.py b/src/quacc/recipes/vasp/slabs.py index a545611708..5acf90e418 100644 --- a/src/quacc/recipes/vasp/slabs.py +++ b/src/quacc/recipes/vasp/slabs.py @@ -10,7 +10,8 @@ from quacc.wflow_tools.customizers import customize_funcs if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any from ase.atoms import Atoms diff --git a/src/quacc/runners/ase.py b/src/quacc/runners/ase.py index 8b213886fb..420e2f3b34 100644 --- a/src/quacc/runners/ase.py +++ b/src/quacc/runners/ase.py @@ -39,6 +39,7 @@ pass if TYPE_CHECKING: + from collections.abc import Callable from pathlib import Path from typing import Any @@ -206,7 +207,7 @@ def run_opt( # Handle optimizer kwargs if ( - issubclass(optimizer, (SciPyOptimizer, MolecularDynamics)) + issubclass(optimizer, SciPyOptimizer | MolecularDynamics) or optimizer.__name__ == "IRC" ): # https://gitlab.com/ase/ase/-/issues/1476 @@ -230,7 +231,7 @@ def run_opt( full_run_kwargs.pop("fmax") try: with traj, optimizer(self.atoms, **merged_optimizer_kwargs) as dyn: - if issubclass(optimizer, (SciPyOptimizer, MolecularDynamics)): + if issubclass(optimizer, SciPyOptimizer | MolecularDynamics): # https://gitlab.coms/ase/ase/-/issues/1475 # https://gitlab.com/ase/ase/-/issues/1497 dyn.run(**full_run_kwargs) diff --git a/src/quacc/runners/prep.py b/src/quacc/runners/prep.py index 2c12193878..6a74a8345c 100644 --- a/src/quacc/runners/prep.py +++ b/src/quacc/runners/prep.py @@ -74,7 +74,7 @@ def calc_setup( # Copy files to tmpdir and decompress them if needed if copy_files: - if isinstance(copy_files, (str, Path)): + if isinstance(copy_files, str | Path): copy_files = {copy_files: "*"} for source_directory, filenames in copy_files.items(): diff --git a/src/quacc/settings.py b/src/quacc/settings.py index da653b505c..327e44376c 100644 --- a/src/quacc/settings.py +++ b/src/quacc/settings.py @@ -16,7 +16,8 @@ from pydantic_settings import BaseSettings, SettingsConfigDict if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any _DEFAULT_CONFIG_FILE_PATH = Path("~", ".quacc.yaml").expanduser().resolve() diff --git a/src/quacc/types.py b/src/quacc/types.py index 5cf71a44c3..6ad2396f42 100644 --- a/src/quacc/types.py +++ b/src/quacc/types.py @@ -16,9 +16,10 @@ class DefaultSetting(BaseSettings): if TYPE_CHECKING: + from collections.abc import Callable from datetime import datetime from pathlib import Path - from typing import Any, Callable, Literal, Union + from typing import Any, Literal from ase.atoms import Atoms from ase.md.md import MolecularDynamics @@ -41,8 +42,8 @@ class DefaultSetting(BaseSettings): # ----------- File handling ----------- - Filenames = Union[str, Path, list[Union[str, Path]]] - SourceDirectory = Union[str, Path] + Filenames = str | Path | list[str | Path] + SourceDirectory = str | Path # ----------- k-point handling ----------- diff --git a/src/quacc/wflow_tools/customizers.py b/src/quacc/wflow_tools/customizers.py index 134fcd534c..d7fcb8cdbc 100644 --- a/src/quacc/wflow_tools/customizers.py +++ b/src/quacc/wflow_tools/customizers.py @@ -9,7 +9,8 @@ from quacc.utils.dicts import recursive_dict_merge if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any def strip_decorator(func: Callable) -> Callable: @@ -66,7 +67,7 @@ def strip_decorator(func: Callable) -> Callable: from prefect import Flow as PrefectFlow from prefect import Task - if isinstance(func, (Task, PrefectFlow)): + if isinstance(func, Task | PrefectFlow): func = func.fn elif hasattr(func, "__wrapped__"): func = func.__wrapped__ @@ -182,9 +183,9 @@ def customize_funcs( decorators = decorators or {} updated_funcs = [] - if not isinstance(names, (list, tuple)): + if not isinstance(names, list | tuple): names = [names] - if not isinstance(funcs, (list, tuple)): + if not isinstance(funcs, list | tuple): funcs = [funcs] if "all" in names: diff --git a/src/quacc/wflow_tools/decorators.py b/src/quacc/wflow_tools/decorators.py index f7a9a78974..1290a34977 100644 --- a/src/quacc/wflow_tools/decorators.py +++ b/src/quacc/wflow_tools/decorators.py @@ -2,8 +2,9 @@ from __future__ import annotations +from collections.abc import Callable from functools import partial, wraps -from typing import Any, Callable +from typing import Any from quacc.settings import change_settings_wrap diff --git a/src/quacc/wflow_tools/job_patterns.py b/src/quacc/wflow_tools/job_patterns.py index dfb4544b3a..8445a47f2c 100644 --- a/src/quacc/wflow_tools/job_patterns.py +++ b/src/quacc/wflow_tools/job_patterns.py @@ -7,7 +7,8 @@ from quacc.wflow_tools.decorators import job if TYPE_CHECKING: - from typing import Any, Callable + from collections.abc import Callable + from typing import Any @job diff --git a/src/quacc/wflow_tools/prefect_utils.py b/src/quacc/wflow_tools/prefect_utils.py index c4e4512e00..6fbf827222 100644 --- a/src/quacc/wflow_tools/prefect_utils.py +++ b/src/quacc/wflow_tools/prefect_utils.py @@ -56,7 +56,7 @@ def _collect_futures(futures, expr, context): result = result.get() results.append(result) - states_by_future = dict(zip(futures, results)) + states_by_future = dict(zip(futures, results, strict=False)) def replace_futures_with_states(expr, context): # Expressions inside quotes should not be modified diff --git a/tests/requirements-covalent.txt b/tests/requirements-covalent.txt index b9e5b9ceba..ebdd147ed7 100644 --- a/tests/requirements-covalent.txt +++ b/tests/requirements-covalent.txt @@ -1,4 +1,3 @@ covalent==0.235.1rc0 covalent-cloud==0.73.0 -covalent-hpc-plugin==0.0.8 covalent-slurm-plugin==0.18.0 diff --git a/tests/requirements-dask.txt b/tests/requirements-dask.txt index 682bd78af9..2b6394ba39 100644 --- a/tests/requirements-dask.txt +++ b/tests/requirements-dask.txt @@ -1,2 +1,2 @@ -dask[distributed]==2024.8.2 +dask[distributed]==2024.9.0 dask-jobqueue==0.9.0 diff --git a/tests/requirements-jobflow.txt b/tests/requirements-jobflow.txt index 356a7dbc18..87f9005461 100644 --- a/tests/requirements-jobflow.txt +++ b/tests/requirements-jobflow.txt @@ -1,3 +1,3 @@ jobflow==0.1.18 -jobflow-remote==0.1.3 +jobflow-remote==0.1.4 fireworks==2.0.3 diff --git a/tests/requirements-parsl.txt b/tests/requirements-parsl.txt index cea1e7f09b..c7fc597d0a 100644 --- a/tests/requirements-parsl.txt +++ b/tests/requirements-parsl.txt @@ -1 +1 @@ -parsl[monitoring]==2024.9.2 +parsl[monitoring]==2024.9.16 diff --git a/tests/requirements-phonons.txt b/tests/requirements-phonons.txt index 96d65aec02..0fa9b7944b 100644 --- a/tests/requirements-phonons.txt +++ b/tests/requirements-phonons.txt @@ -1,2 +1,2 @@ -phonopy==2.27.0 +phonopy==2.28.0 seekpath==2.1.0 diff --git a/tests/requirements-prefect.txt b/tests/requirements-prefect.txt index 7be0490093..96bdafb7b2 100644 --- a/tests/requirements-prefect.txt +++ b/tests/requirements-prefect.txt @@ -1,2 +1,2 @@ dask-jobqueue==0.9.0 -prefect[dask]==3.0.1 +prefect[dask]==3.0.2 diff --git a/tests/requirements.txt b/tests/requirements.txt index 523395b630..d1746ed8dc 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -6,7 +6,7 @@ monty==2024.7.30 numpy==1.26.4 psutil==5.9.8 pydantic==2.9.1 -pydantic-settings==2.4.0 -pymatgen==2024.7.18 +pydantic-settings==2.5.2 +pymatgen==2024.9.17 ruamel.yaml==0.18.6 typer==0.12.5