From 6ac751c543d439ce038b0f770e8fae6d1fd13c64 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Wed, 5 Feb 2025 07:21:19 +0100 Subject: [PATCH] Extend ruff linting (#293) * Extend ruff linting * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .ci_support/release.py | 10 ++++---- .pre-commit-config.yaml | 2 +- pylammpsmpi/__init__.py | 4 +-- pylammpsmpi/mpi/lmpmpi.py | 41 +++++++++++-------------------- pylammpsmpi/wrapper/ase.py | 38 ++++++++++++---------------- pylammpsmpi/wrapper/base.py | 35 +++++++++++++------------- pylammpsmpi/wrapper/concurrent.py | 11 ++++----- pylammpsmpi/wrapper/extended.py | 7 +++--- pyproject.toml | 39 +++++++++++++++++++++++++++++ tests/test_ase_interface.py | 6 ++--- tests/test_base.py | 5 ++-- tests/test_concurrent.py | 4 ++- tests/test_executor.py | 2 ++ tests/test_pylammpsmpi_local.py | 7 +++--- 14 files changed, 118 insertions(+), 93 deletions(-) diff --git a/.ci_support/release.py b/.ci_support/release.py index cb90330..969d2d5 100644 --- a/.ci_support/release.py +++ b/.ci_support/release.py @@ -15,7 +15,7 @@ def get_setup_version_and_pattern(setup_content): version_lst.append(dep.split("==")[1]) depend_lst.append(dep.split("==")[0]) - version_high_dict = {d: v for d, v in zip(depend_lst, version_lst)} + version_high_dict = dict(zip(depend_lst, version_lst)) return version_high_dict @@ -30,13 +30,13 @@ def get_env_version(env_content): if len(lst) == 2: depend_lst.append(lst[0]) version_lst.append(lst[1]) - return {d: v for d, v in zip(depend_lst, version_lst)} + return dict(zip(depend_lst, version_lst)) def update_dependencies(setup_content, version_low_dict, version_high_dict): version_combo_dict = {} for dep, ver in version_high_dict.items(): - if dep in version_low_dict.keys() and version_low_dict[dep] != ver: + if dep in version_low_dict and version_low_dict[dep] != ver: version_combo_dict[dep] = dep + ">=" + version_low_dict[dep] + ",<=" + ver else: version_combo_dict[dep] = dep + "==" + ver @@ -52,10 +52,10 @@ def update_dependencies(setup_content, version_low_dict, version_high_dict): if __name__ == "__main__": - with open("pyproject.toml", "r") as f: + with open("pyproject.toml") as f: setup_content = f.readlines() - with open("environment.yml", "r") as f: + with open("environment.yml") as f: env_content = f.readlines() setup_content_new = update_dependencies( diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d6cd690..1d3ae15 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: hooks: - id: ruff name: ruff lint - args: ["--select", "I", "--fix"] + args: ["--fix"] files: ^pylammpsmpi/ - id: ruff-format name: ruff format diff --git a/pylammpsmpi/__init__.py b/pylammpsmpi/__init__.py index 1127b08..adcdc44 100644 --- a/pylammpsmpi/__init__.py +++ b/pylammpsmpi/__init__.py @@ -4,13 +4,13 @@ from ._version import get_versions -__all__ = [LammpsLibrary, LammpsConcurrent, LammpsBase] +__all__ = ["LammpsLibrary", "LammpsConcurrent", "LammpsBase"] __version__ = get_versions()["version"] try: from pylammpsmpi.wrapper.ase import LammpsASELibrary - __all__ += [LammpsASELibrary] + __all__ += ["LammpsASELibrary"] except ImportError: pass diff --git a/pylammpsmpi/mpi/lmpmpi.py b/pylammpsmpi/mpi/lmpmpi.py index 64f068d..1307b4d 100644 --- a/pylammpsmpi/mpi/lmpmpi.py +++ b/pylammpsmpi/mpi/lmpmpi.py @@ -1,4 +1,3 @@ -# coding: utf-8 # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. @@ -127,7 +126,7 @@ def extract_atom(job, funct_args): # extract atoms return an internal data type # this has to be reformatted name = str(funct_args[0]) - if name not in atom_properties.keys(): + if name not in atom_properties: return [] # this block prevents error when trying to access values @@ -166,14 +165,13 @@ def extract_variable(job, funct_args): ) if MPI.COMM_WORLD.rank == 0: return np.array(data) - else: - if MPI.COMM_WORLD.rank == 0: - # if type is 1 - reformat file - try: - data = job.extract_variable(*funct_args) - except ValueError: - return [] - return data + elif MPI.COMM_WORLD.rank == 0: + # if type is 1 - reformat file + try: + data = job.extract_variable(*funct_args) + except ValueError: + return [] + return data def get_natoms(job, funct_args): @@ -194,7 +192,7 @@ def gather_atoms(job, funct_args): # extract atoms return an internal data type # this has to be reformatted name = str(funct_args[0]) - if name not in atom_properties.keys(): + if name not in atom_properties: return [] # this block prevents error when trying to access values @@ -209,10 +207,7 @@ def gather_atoms(job, funct_args): # number of atoms - first dimension val = list(val) dim = atom_properties[name]["dim"] - if dim > 1: - data = [val[x : x + dim] for x in range(0, len(val), dim)] - else: - data = list(val) + data = [val[x : x + dim] for x in range(0, len(val), dim)] if dim > 1 else list(val) return np.array(data) @@ -220,7 +215,7 @@ def gather_atoms_concat(job, funct_args): # extract atoms return an internal data type # this has to be reformatted name = str(funct_args[0]) - if name not in atom_properties.keys(): + if name not in atom_properties: return [] # this block prevents error when trying to access values @@ -235,10 +230,7 @@ def gather_atoms_concat(job, funct_args): # number of atoms - first dimension val = list(val) dim = atom_properties[name]["dim"] - if dim > 1: - data = [val[x : x + dim] for x in range(0, len(val), dim)] - else: - data = list(val) + data = [val[x : x + dim] for x in range(0, len(val), dim)] if dim > 1 else list(val) return np.array(data) @@ -253,7 +245,7 @@ def gather_atoms_subset(job, funct_args): for i in range(lenids): cids[i] = ids[i] - if name not in atom_properties.keys(): + if name not in atom_properties: return [] # this block prevents error when trying to access values @@ -272,10 +264,7 @@ def gather_atoms_subset(job, funct_args): # number of atoms - first dimension val = list(val) dim = atom_properties[name]["dim"] - if dim > 1: - data = [val[x : x + dim] for x in range(0, len(val), dim)] - else: - data = list(val) + data = [val[x : x + dim] for x in range(0, len(val), dim)] if dim > 1 else list(val) return np.array(data) @@ -487,7 +476,7 @@ def _run_lammps_mpi(argument_lst): else: input_dict = None input_dict = MPI.COMM_WORLD.bcast(input_dict, root=0) - if "shutdown" in input_dict.keys() and input_dict["shutdown"]: + if "shutdown" in input_dict and input_dict["shutdown"]: job.close() if MPI.COMM_WORLD.rank == 0: interface_send(socket=socket, result_dict={"result": True}) diff --git a/pylammpsmpi/wrapper/ase.py b/pylammpsmpi/wrapper/ase.py index 27c0327..2fa4ac5 100644 --- a/pylammpsmpi/wrapper/ase.py +++ b/pylammpsmpi/wrapper/ase.py @@ -2,7 +2,7 @@ import os import warnings from ctypes import c_double, c_int -from typing import List, Optional +from typing import Optional import numpy as np from ase.atoms import Atoms @@ -45,7 +45,7 @@ def __init__( self._interactive_library = library self._cores = library.cores elif self._cores == 1: - lammps = getattr(importlib.import_module("lammps"), "lammps") + lammps = importlib.import_module("lammps").lammps if disable_log_file: self._interactive_library = lammps( cmdargs=["-screen", "none", "-log", "none"], @@ -89,7 +89,7 @@ def interactive_positions_getter(self) -> np.ndarray: positions = self._prism.vector_to_ase(positions) return positions - def interactive_positions_setter(self, positions: List[List[float]]) -> None: + def interactive_positions_setter(self, positions: list[list[float]]) -> None: """ Set the positions of atoms in the interactive library. @@ -142,7 +142,8 @@ def interactive_cells_setter(self, cell: np.ndarray) -> None: lx, ly, lz, xy, xz, yz = self._prism.get_lammps_prism() if not _check_ortho_prism(prism=self._prism): warnings.warn( - "Warning: setting upper trangular matrix might slow down the calculation" + "Warning: setting upper trangular matrix might slow down the calculation", + stacklevel=2, ) is_skewed = cell_is_skewed(cell=cell, tolerance=1.0e-8) @@ -152,19 +153,16 @@ def interactive_cells_setter(self, cell: np.ndarray) -> None: if not was_skewed: self.interactive_lib_command(command="change_box all triclinic") self.interactive_lib_command( - command="change_box all x final 0 %f y final 0 %f z final 0 %f xy final %f xz final %f yz final %f remap units box" - % (lx, ly, lz, xy, xz, yz), + command=f"change_box all x final 0 {lx:f} y final 0 {ly:f} z final 0 {lz:f} xy final {xy:f} xz final {xz:f} yz final {yz:f} remap units box", ) elif was_skewed: self.interactive_lib_command( - command="change_box all x final 0 %f y final 0 %f z final 0 %f xy final %f xz final %f yz final %f remap units box" - % (lx, ly, lz, 0.0, 0.0, 0.0), + command=f"change_box all x final 0 {lx:f} y final 0 {ly:f} z final 0 {lz:f} xy final {0.0:f} xz final {0.0:f} yz final {0.0:f} remap units box", ) self.interactive_lib_command(command="change_box all ortho") else: self.interactive_lib_command( - command="change_box all x final 0 %f y final 0 %f z final 0 %f remap units box" - % (lx, ly, lz), + command=f"change_box all x final 0 {lx:f} y final 0 {ly:f} z final 0 {lz:f} remap units box", ) def interactive_volume_getter(self) -> float: @@ -198,7 +196,7 @@ def interactive_structure_setter( dimension: int, boundary: str, atom_style: str, - el_eam_lst: List[str], + el_eam_lst: list[str], calc_md: bool = True, ) -> None: """ @@ -224,7 +222,8 @@ def interactive_structure_setter( self._prism = Prism(structure.cell) if not _check_ortho_prism(prism=self._prism): warnings.warn( - "Warning: setting upper trangular matrix might slow down the calculation" + "Warning: setting upper trangular matrix might slow down the calculation", + stacklevel=2, ) xhi, yhi, zhi, xy, xz, yz = self._prism.get_lammps_prism() if self._prism.is_skewed(): @@ -274,13 +273,11 @@ def interactive_structure_setter( for id_eam, el_eam in enumerate(el_eam_lst): if el_eam in el_struct_lst: self.interactive_lib_command( - command="mass {0:3d} {1:f}".format( - id_eam + 1, atomic_masses[atomic_numbers[el_eam]] - ), + command=f"mass {id_eam + 1:3d} {atomic_masses[atomic_numbers[el_eam]]:f}", ) else: self.interactive_lib_command( - command="mass {0:3d} {1:f}".format(id_eam + 1, 1.00), + command=f"mass {id_eam + 1:3d} {1.00:f}", ) if not _check_ortho_prism(prism=self._prism): positions = self._prism.vector_to_lammps(structure.positions).flatten() @@ -476,10 +473,7 @@ def cell_is_skewed(cell, tolerance=1.0e-8): """ volume = np.abs(np.linalg.det(cell)) prod = np.linalg.norm(cell, axis=-1).prod() - if volume > 0: - if abs(volume - prod) / volume < tolerance: - return False - return True + return not (volume > 0 and abs(volume - prod) / volume < tolerance) def _check_ortho_prism(prism, rtol=0.0, atol=1e-08): @@ -553,11 +547,11 @@ def get_fixed_atom_boolean_vector(structure): fixed_atom_vector[c_dict["kwargs"]["indices"]] = [True, True, True] elif c_dict["name"] == "FixedPlane": if all(np.isin(c_dict["kwargs"]["direction"], [0, 1])): - if "indices" in c_dict["kwargs"].keys(): + if "indices" in c_dict["kwargs"]: fixed_atom_vector[c_dict["kwargs"]["indices"]] = np.array( c_dict["kwargs"]["direction"] ).astype(bool) - elif "a" in c_dict["kwargs"].keys(): + elif "a" in c_dict["kwargs"]: fixed_atom_vector[c_dict["kwargs"]["a"]] = np.array( c_dict["kwargs"]["direction"] ).astype(bool) diff --git a/pylammpsmpi/wrapper/base.py b/pylammpsmpi/wrapper/base.py index 8bd9d1f..72d533a 100644 --- a/pylammpsmpi/wrapper/base.py +++ b/pylammpsmpi/wrapper/base.py @@ -1,8 +1,7 @@ -# coding: utf-8 # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. -from typing import List, Union +from typing import Union from pylammpsmpi.wrapper.concurrent import LammpsConcurrent @@ -72,7 +71,7 @@ def extract_global(self, name: str) -> Union[int, float, str]: """ return super().extract_global(name=name).result() - def extract_box(self) -> List[Union[float, List[float], List[int]]]: + def extract_box(self) -> list[Union[float, list[float], list[int]]]: """ Get the simulation box @@ -87,7 +86,7 @@ def extract_box(self) -> List[Union[float, List[float], List[int]]]: """ return super().extract_box().result() - def extract_atom(self, name: str) -> Union[List[int], List[float]]: + def extract_atom(self, name: str) -> Union[list[int], list[float]]: """ Extract a property of the atoms @@ -102,7 +101,7 @@ def extract_atom(self, name: str) -> Union[List[int], List[float]]: """ return super().extract_atom(name=name).result() - def extract_fix(self, *args) -> Union[int, float, List[Union[int, float]]]: + def extract_fix(self, *args) -> Union[int, float, list[Union[int, float]]]: """ Extract a fix value @@ -116,7 +115,7 @@ def extract_fix(self, *args) -> Union[int, float, List[Union[int, float]]]: """ return super().extract_fix(*args).result() - def extract_variable(self, *args) -> Union[int, float, List[Union[int, float]]]: + def extract_variable(self, *args) -> Union[int, float, list[Union[int, float]]]: """ Extract the value of a variable @@ -180,11 +179,11 @@ def reset_box(self, *args) -> None: def generate_atoms( self, - ids: List[int] = None, - type: List[int] = None, - x: List[float] = None, - v: List[float] = None, - image: List[int] = None, + ids: list[int] = None, + type: list[int] = None, + x: list[float] = None, + v: list[float] = None, + image: list[int] = None, shrinkexceed: bool = False, ) -> None: """ @@ -224,11 +223,11 @@ def generate_atoms( def create_atoms( self, n: int, - id: List[int], - type: List[int], - x: List[float], - v: List[float] = None, - image: List[int] = None, + id: list[int], + type: list[int], + x: list[float], + v: list[float] = None, + image: list[int] = None, shrinkexceed: bool = False, ) -> None: """ @@ -290,7 +289,7 @@ def has_ffmpeg_support(self) -> bool: return super().has_ffmpeg_support.result() @property - def installed_packages(self) -> List[str]: + def installed_packages(self) -> list[str]: return super().installed_packages.result() def set_fix_external_callback(self, *args) -> None: @@ -305,7 +304,7 @@ def get_neighlist(self, *args): """ return super().get_neighlist(*args).result() - def find_pair_neighlist(self, style: str) -> int: + def find_pair_neighlist(self, *args) -> int: """Find neighbor list index of pair style neighbor list Try finding pair instance that matches style. If exact is set, the pair must match style exactly. If exact is 0, style must only be contained. If pair is diff --git a/pylammpsmpi/wrapper/concurrent.py b/pylammpsmpi/wrapper/concurrent.py index 27b4de8..4faa4e6 100644 --- a/pylammpsmpi/wrapper/concurrent.py +++ b/pylammpsmpi/wrapper/concurrent.py @@ -1,4 +1,3 @@ -# coding: utf-8 # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. @@ -6,7 +5,7 @@ import sys from concurrent.futures import Future from queue import Queue -from typing import Any, List, Optional +from typing import Any, Optional from executorlib.standalone.interactive.communication import interface_bootup from executorlib.standalone.interactive.spawner import MpiExecSpawner @@ -27,7 +26,7 @@ def execute_async( future_queue: Any, - cmdargs: Optional[List[str]] = None, + cmdargs: Optional[list[str]] = None, cores: int = 1, oversubscribe: bool = False, cwd: Optional[str] = None, @@ -61,10 +60,10 @@ def execute_async( ) while True: task_dict = future_queue.get() - if "shutdown" in task_dict.keys() and task_dict["shutdown"]: + if "shutdown" in task_dict and task_dict["shutdown"]: interface.shutdown(wait=task_dict["wait"]) break - elif "command" in task_dict.keys() and "future" in task_dict.keys(): + elif "command" in task_dict and "future" in task_dict: f = task_dict.pop("future") if f.set_running_or_notify_cancel(): f.set_result(interface.send_and_receive_dict(input_dict=task_dict)) @@ -196,7 +195,7 @@ def extract_atom(self, name: str) -> Future: val : Future A future object representing the extracted property of the atoms. """ - return self._send_and_receive_dict(command="extract_atom", data=list([name])) + return self._send_and_receive_dict(command="extract_atom", data=[name]) def extract_fix(self, *args) -> Future: """ diff --git a/pylammpsmpi/wrapper/extended.py b/pylammpsmpi/wrapper/extended.py index 799e625..4e87f19 100644 --- a/pylammpsmpi/wrapper/extended.py +++ b/pylammpsmpi/wrapper/extended.py @@ -1,8 +1,7 @@ -# coding: utf-8 # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. -from typing import Any, List, Optional +from typing import Any, Optional from pylammpsmpi.wrapper.base import LammpsConcurrent @@ -257,7 +256,7 @@ def __init__( working_directory: str = ".", client: Any = None, mode: str = "local", - cmdargs: Optional[List[str]] = None, + cmdargs: Optional[list[str]] = None, ) -> None: self.cores = cores self.working_directory = working_directory @@ -317,7 +316,7 @@ def close(self) -> None: """ self.lmp.close() - def __dir__(self) -> List[str]: + def __dir__(self) -> list[str]: """ Get the list of attributes and methods of the LammpsLibrary object diff --git a/pyproject.toml b/pyproject.toml index 706554b..8a2a3ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,45 @@ include = ["pylammpsmpi*"] [tool.setuptools.dynamic] version = {attr = "pylammpsmpi.__version__"} +[tool.ruff] +exclude = [".ci_support", "docs", "notebooks", "setup.py", "_version.py"] + +[tool.ruff.lint] +select = [ + # pycodestyle + "E", + # Pyflakes + "F", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # flake8-simplify + "SIM", + # isort + "I", + # flake8-comprehensions + "C4", + # eradicate + "ERA", + # pylint + "PL", +] +ignore = [ + # ignore exception naming + "B904", + # ignore line-length violations + "E501", + # Too many arguments in function definition + "PLR0913", + # Magic value used in comparison + "PLR2004", + # Too many branches + "PLR0912", + # Too many statements + "PLR0915", +] + [tool.versioneer] VCS = "git" style = "pep440-pre" diff --git a/tests/test_ase_interface.py b/tests/test_ase_interface.py index a7c458b..82296a0 100644 --- a/tests/test_ase_interface.py +++ b/tests/test_ase_interface.py @@ -1,18 +1,18 @@ import logging import unittest +import numpy as np from ase.atoms import Atoms from ase.build import bulk from ase.calculators.lammps.coordinatetransform import Prism -from ase.constraints import FixAtoms, FixedPlane, FixCom -import numpy as np +from ase.constraints import FixAtoms, FixCom, FixedPlane from pylammpsmpi import LammpsASELibrary, LammpsLibrary from pylammpsmpi.wrapper.ase import ( cell_is_skewed, + get_lammps_indicies_from_ase_structure, get_species_symbols, get_structure_indices, - get_lammps_indicies_from_ase_structure, set_selective_dynamics, ) diff --git a/tests/test_base.py b/tests/test_base.py index 2763e29..cba9c24 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,10 +1,11 @@ -# coding: utf-8 # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. +import os import unittest + import numpy as np -import os + from pylammpsmpi import LammpsBase diff --git a/tests/test_concurrent.py b/tests/test_concurrent.py index 95fb64a..a93584c 100644 --- a/tests/test_concurrent.py +++ b/tests/test_concurrent.py @@ -1,6 +1,8 @@ +import os import unittest + import numpy as np -import os + from pylammpsmpi import LammpsConcurrent diff --git a/tests/test_executor.py b/tests/test_executor.py index 9aaccd8..57ccb4c 100644 --- a/tests/test_executor.py +++ b/tests/test_executor.py @@ -1,7 +1,9 @@ import unittest + from ase.build import bulk from executorlib import SingleNodeExecutor from executorlib.standalone.serialize import cloudpickle_register + from pylammpsmpi import LammpsASELibrary diff --git a/tests/test_pylammpsmpi_local.py b/tests/test_pylammpsmpi_local.py index c68c1ab..259be60 100644 --- a/tests/test_pylammpsmpi_local.py +++ b/tests/test_pylammpsmpi_local.py @@ -1,11 +1,12 @@ -# coding: utf-8 # Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department # Distributed under the terms of "New BSD License", see the LICENSE file. -import unittest -import numpy as np import os import sys +import unittest + +import numpy as np + from pylammpsmpi import LammpsLibrary