From 1a4bec9d0a980780fd808d1e9604dc7d7001c938 Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Mon, 26 Feb 2024 13:10:43 +0100 Subject: [PATCH] Dependencies: Switch to using `ruff` for linting and formatting (#326) `ruff` replaces `yapf`, `isort` and `pylint` as it is much faster than all these three tools combined. --- .github/workflows/validate_release_tag.py | 9 +- .pre-commit-config.yaml | 27 +--- aiida_common_workflows/cli/__init__.py | 6 +- aiida_common_workflows/cli/launch.py | 96 +++++++++---- aiida_common_workflows/cli/options.py | 54 +++---- aiida_common_workflows/cli/plot.py | 10 +- aiida_common_workflows/cli/root.py | 2 +- aiida_common_workflows/common/__init__.py | 5 +- .../common/visualization/dissociation.py | 5 +- .../common/visualization/eos.py | 21 ++- .../generators/generator.py | 2 +- aiida_common_workflows/plugins/__init__.py | 5 +- aiida_common_workflows/plugins/entry_point.py | 3 +- aiida_common_workflows/protocol/__init__.py | 6 +- aiida_common_workflows/protocol/registry.py | 2 +- .../utils/sphinx_extension/input_generator.py | 6 +- .../workflows/bands/__init__.py | 2 +- .../workflows/bands/generator.py | 4 +- .../workflows/bands/siesta/__init__.py | 2 +- .../workflows/bands/siesta/generator.py | 2 +- .../workflows/bands/workchain.py | 2 +- .../workflows/dissociation.py | 16 +-- aiida_common_workflows/workflows/eos.py | 15 +- .../workflows/relax/__init__.py | 2 +- .../workflows/relax/abinit/__init__.py | 2 +- .../workflows/relax/abinit/generator.py | 53 +++---- .../workflows/relax/abinit/workchain.py | 2 +- .../workflows/relax/bigdft/__init__.py | 2 +- .../workflows/relax/bigdft/generator.py | 93 ++++++------ .../workflows/relax/castep/__init__.py | 2 +- .../workflows/relax/castep/extractors.py | 2 +- .../workflows/relax/castep/generator.py | 44 +++--- .../workflows/relax/cp2k/__init__.py | 2 +- .../workflows/relax/cp2k/generator.py | 23 +-- .../workflows/relax/cp2k/workchain.py | 13 +- .../workflows/relax/fleur/__init__.py | 2 +- .../workflows/relax/fleur/extractors.py | 10 +- .../workflows/relax/fleur/generator.py | 54 +++---- .../workflows/relax/fleur/workchain.py | 2 +- .../workflows/relax/gaussian/__init__.py | 2 +- .../workflows/relax/gaussian/generator.py | 21 +-- .../workflows/relax/gaussian/workchain.py | 2 +- .../workflows/relax/generator.py | 2 +- .../workflows/relax/gpaw/__init__.py | 2 +- .../workflows/relax/gpaw/generator.py | 36 ++--- .../workflows/relax/nwchem/__init__.py | 2 +- .../workflows/relax/nwchem/generator.py | 10 +- .../workflows/relax/nwchem/workchain.py | 2 +- .../workflows/relax/orca/__init__.py | 2 +- .../workflows/relax/orca/generator.py | 13 +- .../workflows/relax/orca/workchain.py | 4 +- .../relax/quantum_espresso/__init__.py | 2 +- .../relax/quantum_espresso/extractors.py | 2 +- .../relax/quantum_espresso/generator.py | 35 ++--- .../relax/quantum_espresso/workchain.py | 6 +- .../workflows/relax/siesta/__init__.py | 2 +- .../workflows/relax/siesta/extractors.py | 2 +- .../workflows/relax/siesta/generator.py | 35 +++-- .../workflows/relax/vasp/__init__.py | 2 +- .../workflows/relax/vasp/generator.py | 133 ++++++++---------- .../workflows/relax/wien2k/__init__.py | 2 +- .../workflows/relax/wien2k/generator.py | 13 +- .../workflows/relax/workchain.py | 2 +- docs/source/conf.py | 2 +- pyproject.toml | 54 +++---- tests/cli/test_launch.py | 54 ++++--- tests/cli/test_options.py | 9 +- tests/cli/test_plot.py | 4 +- tests/conftest.py | 40 +++--- tests/generators/test_generator.py | 5 +- tests/protocol/test_registry.py | 22 ++- tests/workflows/bands/test_implementations.py | 12 +- tests/workflows/bands/test_workchain.py | 4 +- .../test_workchain_diss_curve.py | 66 ++++----- tests/workflows/eos/test_workchain_eos.py | 57 ++++---- tests/workflows/relax/test_abinit.py | 11 +- tests/workflows/relax/test_bigdft.py | 11 +- tests/workflows/relax/test_castep.py | 56 ++------ tests/workflows/relax/test_cp2k.py | 11 +- tests/workflows/relax/test_fleur.py | 20 +-- tests/workflows/relax/test_gaussian.py | 11 +- tests/workflows/relax/test_implementations.py | 42 ++---- tests/workflows/relax/test_nwchem.py | 11 +- tests/workflows/relax/test_orca.py | 11 +- .../workflows/relax/test_quantum_espresso.py | 13 +- tests/workflows/relax/test_siesta.py | 12 +- tests/workflows/relax/test_vasp.py | 11 +- tests/workflows/relax/test_workchain.py | 4 +- 88 files changed, 691 insertions(+), 806 deletions(-) diff --git a/.github/workflows/validate_release_tag.py b/.github/workflows/validate_release_tag.py index 0bd5e57e..001a39d6 100644 --- a/.github/workflows/validate_release_tag.py +++ b/.github/workflows/validate_release_tag.py @@ -17,8 +17,11 @@ def get_version_from_module(content: str) -> str: try: return next( - ast.literal_eval(statement.value) for statement in module.body if isinstance(statement, ast.Assign) - for target in statement.targets if isinstance(target, ast.Name) and target.id == '__version__' + ast.literal_eval(statement.value) + for statement in module.body + if isinstance(statement, ast.Assign) + for target in statement.targets + if isinstance(target, ast.Name) and target.id == '__version__' ) except StopIteration as exception: raise IOError('Unable to find the `__version__` attribute in the module.') from exception @@ -30,7 +33,7 @@ def get_version_from_module(content: str) -> str: args = parser.parse_args() TAG_PREFIX = 'refs/tags/v' assert args.GITHUB_REF.startswith(TAG_PREFIX), f'GITHUB_REF should start with "{TAG_PREFIX}": {args.GITHUB_REF}' - tag_version = args.GITHUB_REF[len(TAG_PREFIX):] + tag_version = args.GITHUB_REF[len(TAG_PREFIX) :] package_version = get_version_from_module(Path('aiida_common_workflows/__init__.py').read_text(encoding='utf-8')) error_message = f'The tag version `{tag_version}` is different from the package version `{package_version}`' assert tag_version == package_version, error_message diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a5577ac4..b0e10291 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,24 +13,9 @@ repos: hooks: - id: flynt -- repo: https://github.com/pycqa/isort - rev: 5.12.0 - hooks: - - id: isort - -- repo: https://github.com/pre-commit/mirrors-yapf - rev: v0.31.0 - hooks: - - id: yapf - name: yapf - types: [python] - args: ['-i'] - additional_dependencies: ['toml'] - -- repo: local - hooks: - - id: pylint - name: pylint - entry: pylint - types: [python] - language: system +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.9 + hooks: + - id: ruff-format + - id: ruff + args: [--fix, --exit-non-zero-on-fix, --show-fixes] diff --git a/aiida_common_workflows/cli/__init__.py b/aiida_common_workflows/cli/__init__.py index 6e5f6fb3..a678a2f6 100644 --- a/aiida_common_workflows/cli/__init__.py +++ b/aiida_common_workflows/cli/__init__.py @@ -1,11 +1,7 @@ # -*- coding: utf-8 -*- -# pylint: disable=wrong-import-position,wildcard-import + """Module for the command line interface.""" import click_completion # Activate the completion of parameter types provided by the click_completion package click_completion.init() - -from .launch import cmd_launch -from .plot import cmd_plot -from .root import cmd_root diff --git a/aiida_common_workflows/cli/launch.py b/aiida_common_workflows/cli/launch.py index 8cef39d6..857452ac 100644 --- a/aiida_common_workflows/cli/launch.py +++ b/aiida_common_workflows/cli/launch.py @@ -2,8 +2,8 @@ """Commands to launch common workflows.""" import functools -from aiida.cmdline.params import types import click +from aiida.cmdline.params import types from aiida_common_workflows.plugins import get_workflow_entry_point_names, load_workflow_entry_point @@ -41,7 +41,7 @@ def cmd_launch(): @options.CODES() @options.PROTOCOL( type=click.Choice(['fast', 'moderate', 'precise', 'verification-PBE-v1', 'verification-PBE-v1-sirius']), - default='fast' + default='fast', ) @options.RELAX_TYPE() @options.ELECTRONIC_TYPE() @@ -57,10 +57,25 @@ def cmd_launch(): @options.REFERENCE_WORKCHAIN() @options.ENGINE_OPTIONS() @click.option('--show-engines', is_flag=True, help='Show information on the required calculation engines.') -def cmd_relax( # pylint: disable=too-many-branches - plugin, structure, codes, protocol, relax_type, electronic_type, spin_type, threshold_forces, threshold_stress, - number_machines, number_mpi_procs_per_machine, number_cores_per_mpiproc, wallclock_seconds, daemon, - magnetization_per_site, reference_workchain, engine_options, show_engines +def cmd_relax( # noqa: PLR0912,PLR0913,PLR0915 + plugin, + structure, + codes, + protocol, + relax_type, + electronic_type, + spin_type, + threshold_forces, + threshold_stress, + number_machines, + number_mpi_procs_per_machine, + number_cores_per_mpiproc, + wallclock_seconds, + daemon, + magnetization_per_site, + reference_workchain, + engine_options, + show_engines, ): """Relax a crystal structure using the common relax workflow for one of the existing plugin implementations. @@ -69,7 +84,7 @@ def cmd_relax( # pylint: disable=too-many-branches If no code is installed for at least one of the calculation engines, the command will fail. Use the `--show-engine` flag to display the required calculation engines for the selected plugin workflow. """ - # pylint: disable=too-many-locals,too-many-statements + process_class = load_workflow_entry_point('relax', plugin) generator = process_class.get_input_generator() @@ -81,19 +96,19 @@ def cmd_relax( # pylint: disable=too-many-branches if len(number_machines) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-machines' + param_hint='--number-machines', ) if number_mpi_procs_per_machine is not None and len(number_mpi_procs_per_machine) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-mpi-procs-per-machine' + param_hint='--number-mpi-procs-per-machine', ) if number_cores_per_mpiproc is not None and len(number_cores_per_mpiproc) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-cores-per-mpiproc' + param_hint='--number-cores-per-mpiproc', ) if wallclock_seconds is None: @@ -102,7 +117,7 @@ def cmd_relax( # pylint: disable=too-many-branches if len(wallclock_seconds) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--wallclock-seconds' + param_hint='--wallclock-seconds', ) if not generator.is_valid_protocol(protocol): @@ -195,10 +210,24 @@ def cmd_relax( # pylint: disable=too-many-branches @options.MAGNETIZATION_PER_SITE() @options.ENGINE_OPTIONS() @click.option('--show-engines', is_flag=True, help='Show information on the required calculation engines.') -def cmd_eos( # pylint: disable=too-many-branches,too-many-statements - plugin, structure, codes, protocol, relax_type, electronic_type, spin_type, threshold_forces, threshold_stress, - number_machines, number_mpi_procs_per_machine, number_cores_per_mpiproc, wallclock_seconds, daemon, - magnetization_per_site, engine_options, show_engines +def cmd_eos( # noqa: PLR0912,PLR0913,PLR0915 + plugin, + structure, + codes, + protocol, + relax_type, + electronic_type, + spin_type, + threshold_forces, + threshold_stress, + number_machines, + number_mpi_procs_per_machine, + number_cores_per_mpiproc, + wallclock_seconds, + daemon, + magnetization_per_site, + engine_options, + show_engines, ): """Compute the equation of state of a crystal structure using the common relax workflow. @@ -207,7 +236,7 @@ def cmd_eos( # pylint: disable=too-many-branches,too-many-statements If no code is installed for at least one of the calculation engines, the command will fail. Use the `--show-engine` flag to display the required calculation engines for the selected plugin workflow. """ - # pylint: disable=too-many-locals + from aiida_common_workflows.plugins import get_entry_point_name_from_class from aiida_common_workflows.workflows.eos import EquationOfStateWorkChain @@ -222,19 +251,19 @@ def cmd_eos( # pylint: disable=too-many-branches,too-many-statements if len(number_machines) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-machines' + param_hint='--number-machines', ) if number_mpi_procs_per_machine is not None and len(number_mpi_procs_per_machine) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-mpi-procs-per-machine' + param_hint='--number-mpi-procs-per-machine', ) if number_cores_per_mpiproc is not None and len(number_cores_per_mpiproc) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-cores-per-mpiproc' + param_hint='--number-cores-per-mpiproc', ) if wallclock_seconds is None: @@ -243,7 +272,7 @@ def cmd_eos( # pylint: disable=too-many-branches,too-many-statements if len(wallclock_seconds) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--wallclock-seconds' + param_hint='--wallclock-seconds', ) if not generator.is_valid_protocol(protocol): @@ -332,10 +361,21 @@ def cmd_eos( # pylint: disable=too-many-branches,too-many-statements @options.MAGNETIZATION_PER_SITE() @options.ENGINE_OPTIONS() @click.option('--show-engines', is_flag=True, help='Show information on the required calculation engines.') -def cmd_dissociation_curve( # pylint: disable=too-many-branches - plugin, structure, codes, protocol, electronic_type, spin_type, number_machines, number_mpi_procs_per_machine, +def cmd_dissociation_curve( # noqa: PLR0912, PLR0913 + plugin, + structure, + codes, + protocol, + electronic_type, + spin_type, + number_machines, + number_mpi_procs_per_machine, number_cores_per_mpiproc, - wallclock_seconds, daemon, magnetization_per_site, engine_options, show_engines + wallclock_seconds, + daemon, + magnetization_per_site, + engine_options, + show_engines, ): """Compute the dissociation curve of a diatomic molecule using the common relax workflow. @@ -347,7 +387,7 @@ def cmd_dissociation_curve( # pylint: disable=too-many-branches If no code is installed for at least one of the calculation engines, the command will fail. Use the `--show-engine` flag to display the required calculation engines for the selected plugin workflow. """ - # pylint: disable=too-many-locals + from aiida_common_workflows.plugins import get_entry_point_name_from_class from aiida_common_workflows.workflows.dissociation import DissociationCurveWorkChain from aiida_common_workflows.workflows.relax.generator import RelaxType @@ -363,19 +403,19 @@ def cmd_dissociation_curve( # pylint: disable=too-many-branches if len(number_machines) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-machines' + param_hint='--number-machines', ) if number_mpi_procs_per_machine is not None and len(number_mpi_procs_per_machine) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-mpi-procs-per-machine' + param_hint='--number-mpi-procs-per-machine', ) if number_cores_per_mpiproc is not None and len(number_cores_per_mpiproc) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--number-cores-per-mpiproc' + param_hint='--number-cores-per-mpiproc', ) if wallclock_seconds is None: @@ -384,7 +424,7 @@ def cmd_dissociation_curve( # pylint: disable=too-many-branches if len(wallclock_seconds) != number_engines: raise click.BadParameter( f'{process_class.__name__} has {number_engines} engine steps, so requires {number_engines} values', - param_hint='--wallclock-seconds' + param_hint='--wallclock-seconds', ) if not generator.is_valid_protocol(protocol): diff --git a/aiida_common_workflows/cli/options.py b/aiida_common_workflows/cli/options.py index 43619f6e..82567e0e 100644 --- a/aiida_common_workflows/cli/options.py +++ b/aiida_common_workflows/cli/options.py @@ -3,9 +3,9 @@ import json import pathlib +import click from aiida.cmdline.params import options, types from aiida.cmdline.utils.decorators import with_dbenv -import click from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType @@ -23,10 +23,11 @@ def get_workchain_plugins(): """Return the registered entry point names for the ``CommonRelaxWorkChain``.""" from aiida.plugins import entry_point + group = 'aiida.workflows' entry_point_prefix = 'common_workflows.relax.' names = entry_point.get_entry_point_names(group) - return {name[len(entry_point_prefix):] for name in names if name.startswith(entry_point_prefix)} + return {name[len(entry_point_prefix) :] for name in names if name.startswith(entry_point_prefix)} def get_relax_types_eos(): @@ -100,20 +101,19 @@ def convert(self, value, param, ctx): try: structure = StructureData(ase=ase.io.read(filepath)) - except Exception as exception: # pylint: disable=broad-except + except Exception as exception: raise click.BadParameter( f'file `{value}` could not be parsed into a `StructureData`: {exception}' ) from exception - duplicate = QueryBuilder().append( - StructureData, - filters={ - 'extras._aiida_hash': structure.base.caching._get_hash() # pylint: disable=protected-access - } - ).first() + duplicate = ( + QueryBuilder() + .append(StructureData, filters={'extras._aiida_hash': structure.base.caching._get_hash()}) + .first() + ) if duplicate: - return duplicate[0] # pylint: disable=unsubscriptable-object + return duplicate[0] return structure @@ -127,7 +127,7 @@ def convert(self, value, param, ctx): help='One or multiple codes identified by their ID, UUID or label. What codes are required is dependent on the ' 'selected plugin and can be shown using the `--show-engines` option. If no explicit codes are specified, one will ' 'be loaded from the database based on the required input plugins. If multiple codes are matched, a random one will ' - 'be selected.' + 'be selected.', ) STRUCTURE = options.OverridableOption( @@ -136,7 +136,7 @@ def convert(self, value, param, ctx): type=StructureDataParamType(), default='Si', help='Select a structure: either choose one of the default structures listed above, or an existing `StructureData` ' - 'identifier, or a file on disk with a structure definition that can be parsed by `ase`.' + 'identifier, or a file on disk with a structure definition that can be parsed by `ase`.', ) PROTOCOL = options.OverridableOption( @@ -145,7 +145,7 @@ def convert(self, value, param, ctx): type=click.Choice(['fast', 'moderate', 'precise', 'verification-PBE-v1', 'verification-PBE-v1-sirius']), default='fast', show_default=True, - help='Select the protocol with which the inputs for the workflow should be generated.' + help='Select the protocol with which the inputs for the workflow should be generated.', ) RELAX_TYPE = options.OverridableOption( @@ -155,7 +155,7 @@ def convert(self, value, param, ctx): default='positions', show_default=True, callback=lambda ctx, param, value: RelaxType(value), - help='Select the relax type with which the workflow should be run.' + help='Select the relax type with which the workflow should be run.', ) ELECTRONIC_TYPE = options.OverridableOption( @@ -165,7 +165,7 @@ def convert(self, value, param, ctx): default='metal', show_default=True, callback=lambda ctx, param, value: ElectronicType(value), - help='Select the electronic type with which the workflow should be run.' + help='Select the electronic type with which the workflow should be run.', ) SPIN_TYPE = options.OverridableOption( @@ -175,21 +175,21 @@ def convert(self, value, param, ctx): default='none', show_default=True, callback=lambda ctx, param, value: SpinType(value), - help='Select the spin type with which the workflow should be run.' + help='Select the spin type with which the workflow should be run.', ) THRESHOLD_FORCES = options.OverridableOption( '--threshold-forces', type=click.FLOAT, required=False, - help='Optional convergence threshold for the forces. Note that not all plugins may support this option.' + help='Optional convergence threshold for the forces. Note that not all plugins may support this option.', ) THRESHOLD_STRESS = options.OverridableOption( '--threshold-stress', type=click.FLOAT, required=False, - help='Optional convergence threshold for the stress. Note that not all plugins may support this option.' + help='Optional convergence threshold for the stress. Note that not all plugins may support this option.', ) DAEMON = options.OverridableOption( @@ -197,7 +197,7 @@ def convert(self, value, param, ctx): '--daemon', is_flag=True, default=False, - help='Submit the process to the daemon instead of running it locally.' + help='Submit the process to the daemon instead of running it locally.', ) WALLCLOCK_SECONDS = options.OverridableOption( @@ -207,7 +207,7 @@ def convert(self, value, param, ctx): type=click.INT, metavar='VALUES', required=False, - help='Define the wallclock seconds to request for each engine step.' + help='Define the wallclock seconds to request for each engine step.', ) NUMBER_MACHINES = options.OverridableOption( @@ -217,7 +217,7 @@ def convert(self, value, param, ctx): type=click.INT, metavar='VALUES', required=False, - help='Define the number of machines to request for each engine step.' + help='Define the number of machines to request for each engine step.', ) NUMBER_MPI_PROCS_PER_MACHINE = options.OverridableOption( @@ -227,7 +227,7 @@ def convert(self, value, param, ctx): type=click.INT, metavar='VALUES', required=False, - help='Define the number of MPI processes per machine to request for each engine step.' + help='Define the number of MPI processes per machine to request for each engine step.', ) NUMBER_CORES_PER_MPIPROC = options.OverridableOption( @@ -237,7 +237,7 @@ def convert(self, value, param, ctx): type=click.INT, metavar='VALUES', required=False, - help='Define the number of cores (threads) per MPI processes to use for each engine step.' + help='Define the number of cores (threads) per MPI processes to use for each engine step.', ) MAGNETIZATION_PER_SITE = options.OverridableOption( @@ -245,7 +245,7 @@ def convert(self, value, param, ctx): type=click.FLOAT, cls=options.MultipleValueOption, required=False, - help='Optional list containing the initial spin polarization per site in units of electrons.' + help='Optional list containing the initial spin polarization per site in units of electrons.', ) PRECISIONS = options.OverridableOption( @@ -254,7 +254,7 @@ def convert(self, value, param, ctx): cls=options.MultipleValueOption, type=click.INT, required=False, - help='Specify the precision of floats used when printing them to stdout with the `--print-table` option.' + help='Specify the precision of floats used when printing them to stdout with the `--print-table` option.', ) PRINT_TABLE = options.OverridableOption( @@ -266,7 +266,7 @@ def convert(self, value, param, ctx): '--reference-workchain', type=types.WorkflowParamType(), required=False, - help='An instance of a completed workchain of the same type as would be run for the given plugin.' + help='An instance of a completed workchain of the same type as would be run for the given plugin.', ) OUTPUT_FILE = options.OverridableOption( @@ -283,5 +283,5 @@ def convert(self, value, param, ctx): 'with bash escaping, using single quotes, and using instead double quotes for valid JSON strings! The backticks ' 'are here used instead only to delimit code). This will add the `account` option to the "relax" engine. If your ' 'common workflow needs multiple engines, you should pass the options for each engine that you need to modify. ' - ' Suggestion: use the `--show-engines` option to know which engines are required by this common workflow.' + ' Suggestion: use the `--show-engines` option to know which engines are required by this common workflow.', ) diff --git a/aiida_common_workflows/cli/plot.py b/aiida_common_workflows/cli/plot.py index 9133f8e8..3c8760f5 100644 --- a/aiida_common_workflows/cli/plot.py +++ b/aiida_common_workflows/cli/plot.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- """Commands to plot results from a workflow.""" +import click from aiida.cmdline.params import arguments from aiida.cmdline.utils import echo from aiida.plugins import WorkflowFactory -import click from . import options from .root import cmd_root @@ -24,7 +24,7 @@ def cmd_plot(): @options.OUTPUT_FILE() def cmd_plot_eos(workflow, precisions, print_table, output_file): """Plot the results from an `EquationOfStateWorkChain`.""" - # pylint: disable=too-many-locals + from aiida.common import LinkType from tabulate import tabulate @@ -65,7 +65,7 @@ def cmd_plot_eos(workflow, precisions, print_table, output_file): if print_table: tabulate_inputs = { 'tabular_data': list(zip(volumes, energies, magnetizations)), - 'headers': ['Volume (Å^3)', 'Energy (eV)', 'Total magnetization (μB)'] + 'headers': ['Volume (Å^3)', 'Energy (eV)', 'Total magnetization (μB)'], } if precisions is not None: @@ -97,7 +97,7 @@ def cmd_plot_eos(workflow, precisions, print_table, output_file): @options.OUTPUT_FILE() def cmd_plot_dissociation_curve(workflow, precisions, print_table, output_file): """Plot the results from a `DissociationCurveWorkChain`.""" - # pylint: disable=too-many-locals + from aiida.common import LinkType from tabulate import tabulate @@ -138,7 +138,7 @@ def cmd_plot_dissociation_curve(workflow, precisions, print_table, output_file): if print_table: tabulate_inputs = { 'tabular_data': list(zip(distances, energies, magnetizations)), - 'headers': ['Distance (Å)', 'Energy (eV)', 'Total magnetization (μB)'] + 'headers': ['Distance (Å)', 'Energy (eV)', 'Total magnetization (μB)'], } if precisions is not None: diff --git a/aiida_common_workflows/cli/root.py b/aiida_common_workflows/cli/root.py index 81953871..d2e37b53 100644 --- a/aiida_common_workflows/cli/root.py +++ b/aiida_common_workflows/cli/root.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Command line interface ``acwf``.""" +import click from aiida.cmdline.groups import VerdiCommandGroup from aiida.cmdline.params import options, types -import click @click.group('acwf', cls=VerdiCommandGroup, context_settings={'help_option_names': ['-h', '--help']}) diff --git a/aiida_common_workflows/common/__init__.py b/aiida_common_workflows/common/__init__.py index 591b6b22..29ea1b2a 100644 --- a/aiida_common_workflows/common/__init__.py +++ b/aiida_common_workflows/common/__init__.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=redefined-builtin,undefined-variable """Module for resources common to the entire `aiida-common-workflows` package.""" -from .types import * +from .types import ElectronicType, RelaxType, SpinType -all = (types.__all__,) +__all__ = ('ElectronicType', 'SpinType', 'RelaxType') diff --git a/aiida_common_workflows/common/visualization/dissociation.py b/aiida_common_workflows/common/visualization/dissociation.py index 406c8fbd..c308e6a8 100644 --- a/aiida_common_workflows/common/visualization/dissociation.py +++ b/aiida_common_workflows/common/visualization/dissociation.py @@ -6,10 +6,7 @@ def get_dissociation_plot( - distances: typing.List[float], - energies: typing.List[float], - unit_distance: str = 'Å', - unit_energy: str = 'eV' + distances: typing.List[float], energies: typing.List[float], unit_distance: str = 'Å', unit_energy: str = 'eV' ) -> plt: """Plot the dissociation curve for a given set of distances and energies. diff --git a/aiida_common_workflows/common/visualization/eos.py b/aiida_common_workflows/common/visualization/eos.py index 92bae4ba..3b5d1ada 100644 --- a/aiida_common_workflows/common/visualization/eos.py +++ b/aiida_common_workflows/common/visualization/eos.py @@ -6,19 +6,19 @@ import numpy -def birch_murnaghan(V, E0, V0, B0, B01): +def birch_murnaghan(V, E0, V0, B0, B01): # noqa: N803 """Compute energy by Birch Murnaghan formula.""" - # pylint: disable=invalid-name - r = (V0 / V)**(2. / 3.) - return E0 + 9. / 16. * B0 * V0 * (r - 1.)**2 * (2. + (B01 - 4.) * (r - 1.)) + + r = (V0 / V) ** (2.0 / 3.0) + return E0 + 9.0 / 16.0 * B0 * V0 * (r - 1.0) ** 2 * (2.0 + (B01 - 4.0) * (r - 1.0)) def fit_birch_murnaghan_params(volumes, energies): """Fit Birch Murnaghan parameters.""" - # pylint: disable=invalid-name + from scipy.optimize import curve_fit - params, covariance = curve_fit( # pylint: disable=unbalanced-tuple-unpacking + params, covariance = curve_fit( birch_murnaghan, xdata=volumes, ydata=energies, @@ -26,18 +26,15 @@ def fit_birch_murnaghan_params(volumes, energies): energies.min(), # E0 volumes.mean(), # V0 0.1, # B0 - 3., # B01 + 3.0, # B01 ), - sigma=None + sigma=None, ) return params, covariance def get_eos_plot( - volumes: typing.List[float], - energies: typing.List[float], - unit_volume: str = 'Å^3', - unit_energy: str = 'eV' + volumes: typing.List[float], energies: typing.List[float], unit_volume: str = 'Å^3', unit_energy: str = 'eV' ) -> plt: """Plot the Equation of State for a given set of volumes and energies diff --git a/aiida_common_workflows/generators/generator.py b/aiida_common_workflows/generators/generator.py index 80e1fc75..8ddaf7a2 100644 --- a/aiida_common_workflows/generators/generator.py +++ b/aiida_common_workflows/generators/generator.py @@ -49,7 +49,7 @@ def define(cls, spec): The ports defined on the specification are the inputs that will be accepted by the ``get_builder`` method. """ - def __init__(self, *args, **kwargs): # pylint: disable=unused-argument + def __init__(self, *args, **kwargs): """Construct an instance of the input generator, validating the class attributes.""" def raise_invalid(message): diff --git a/aiida_common_workflows/plugins/__init__.py b/aiida_common_workflows/plugins/__init__.py index cc4f037a..543a8395 100644 --- a/aiida_common_workflows/plugins/__init__.py +++ b/aiida_common_workflows/plugins/__init__.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable,invalid-all-object """Module with utilities for working with the plugins provided by this plugin package.""" -from .entry_point import * +from .entry_point import get_entry_point_name_from_class, get_workflow_entry_point_names, load_workflow_entry_point -__all__ = (entry_point.__all__,) +__all__ = ('get_workflow_entry_point_names', 'get_entry_point_name_from_class', 'load_workflow_entry_point') diff --git a/aiida_common_workflows/plugins/entry_point.py b/aiida_common_workflows/plugins/entry_point.py index 3c37ee47..4b96d31a 100644 --- a/aiida_common_workflows/plugins/entry_point.py +++ b/aiida_common_workflows/plugins/entry_point.py @@ -22,12 +22,13 @@ def get_workflow_entry_point_names(workflow: str, leaf: bool = False) -> typing. if not leaf: return [name for name in entry_points_names if name.startswith(prefix)] - return [name[len(prefix):] for name in entry_points_names if name.startswith(prefix)] + return [name[len(prefix) :] for name in entry_points_names if name.startswith(prefix)] def get_entry_point_name_from_class(cls) -> str: """Return the full entry point string for the given class.""" from aiida.plugins.entry_point import get_entry_point_from_class + return get_entry_point_from_class(cls.__module__, cls.__name__)[1] diff --git a/aiida_common_workflows/protocol/__init__.py b/aiida_common_workflows/protocol/__init__.py index 456ef299..da316b32 100644 --- a/aiida_common_workflows/protocol/__init__.py +++ b/aiida_common_workflows/protocol/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with utilities to define and implement workchain protocols.""" -from .registry import * +from .registry import ProtocolRegistry -__all__ = (registry.__all__,) +__all__ = ('ProtocolRegistry',) diff --git a/aiida_common_workflows/protocol/registry.py b/aiida_common_workflows/protocol/registry.py index c2302c3f..72109465 100644 --- a/aiida_common_workflows/protocol/registry.py +++ b/aiida_common_workflows/protocol/registry.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=unsupported-membership-test,unsubscriptable-object + """Module with base protocol registry.""" import copy import typing diff --git a/aiida_common_workflows/utils/sphinx_extension/input_generator.py b/aiida_common_workflows/utils/sphinx_extension/input_generator.py index 5c4314c5..d4552385 100644 --- a/aiida_common_workflows/utils/sphinx_extension/input_generator.py +++ b/aiida_common_workflows/utils/sphinx_extension/input_generator.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- """Define a Restructured Text directive to auto-document :class:`aiida_common_workflows.generators.InputGenerator`.""" import inspect +import typing as t from aiida.common.utils import get_object_from_string from aiida.engine import Process @@ -22,6 +23,7 @@ def setup_extension(app): class CommonInputGeneratorDocumenter(ClassDocumenter): """Sphinx documenter class for AiiDA Processes.""" + directivetype = 'common-input-generator' objtype = 'common-input-generator' priority = 10 @@ -39,7 +41,7 @@ class CommonInputGeneratorDirective(SphinxDirective): final_argument_whitespace = True EXPAND_NAMESPACES_FLAG = 'expand-namespaces' - option_spec = {'module': directives.unchanged_required, EXPAND_NAMESPACES_FLAG: directives.flag} + option_spec: t.ClassVar = {'module': directives.unchanged_required, EXPAND_NAMESPACES_FLAG: directives.flag} signature = 'InputGenerator' annotation = 'common-input-generator' @@ -55,7 +57,7 @@ def initialize(self): Includes importing the process class. """ - # pylint: disable=attribute-defined-outside-init + load_profile() self.class_name = self.arguments[0].split('(')[0] diff --git a/aiida_common_workflows/workflows/bands/__init__.py b/aiida_common_workflows/workflows/bands/__init__.py index 25914de1..15bc1dfe 100644 --- a/aiida_common_workflows/workflows/bands/__init__.py +++ b/aiida_common_workflows/workflows/bands/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the base classes for the common bands workchains.""" from .generator import * diff --git a/aiida_common_workflows/workflows/bands/generator.py b/aiida_common_workflows/workflows/bands/generator.py index 2995fcb9..2d2c7073 100644 --- a/aiida_common_workflows/workflows/bands/generator.py +++ b/aiida_common_workflows/workflows/bands/generator.py @@ -27,14 +27,14 @@ def define(cls, spec): 'bands_kpoints', valid_type=plugins.DataFactory('core.array.kpoints'), required=True, - help='The full list of kpoints where to calculate bands, in (direct) coordinates of the reciprocal space.' + help='The full list of kpoints where to calculate bands, in (direct) coordinates of the reciprocal space.', ) spec.input( 'parent_folder', valid_type=orm.RemoteData, required=True, help='Parent folder that contains file to restart from (density matrix, wave-functions..). What is used ' - 'is plugin dependent.' + 'is plugin dependent.', ) spec.input_namespace( 'engines', diff --git a/aiida_common_workflows/workflows/bands/siesta/__init__.py b/aiida_common_workflows/workflows/bands/siesta/__init__.py index b31fb266..ffa90613 100644 --- a/aiida_common_workflows/workflows/bands/siesta/__init__.py +++ b/aiida_common_workflows/workflows/bands/siesta/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common bands workchain for Siesta.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/bands/siesta/generator.py b/aiida_common_workflows/workflows/bands/siesta/generator.py index 5930547d..0ad334a6 100644 --- a/aiida_common_workflows/workflows/bands/siesta/generator.py +++ b/aiida_common_workflows/workflows/bands/siesta/generator.py @@ -26,7 +26,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + engines = kwargs.get('engines', None) parent_folder = kwargs['parent_folder'] bands_kpoints = kwargs['bands_kpoints'] diff --git a/aiida_common_workflows/workflows/bands/workchain.py b/aiida_common_workflows/workflows/bands/workchain.py index c72bd931..ef7fb26b 100644 --- a/aiida_common_workflows/workflows/bands/workchain.py +++ b/aiida_common_workflows/workflows/bands/workchain.py @@ -27,7 +27,7 @@ def get_input_generator(cls) -> CommonBandsInputGenerator: :return: input generator """ - return cls._generator_class(process_class=cls) # pylint: disable=not-callable + return cls._generator_class(process_class=cls) @classmethod def define(cls, spec): diff --git a/aiida_common_workflows/workflows/dissociation.py b/aiida_common_workflows/workflows/dissociation.py index 18e30322..e92dabe0 100644 --- a/aiida_common_workflows/workflows/dissociation.py +++ b/aiida_common_workflows/workflows/dissociation.py @@ -28,7 +28,7 @@ def validate_inputs(value, _): try: generator.get_builder(structure=value['molecule'], **value['generator_inputs']) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: return f'`{generator.__class__.__name__}.get_builder()` fails for the provided `generator_inputs`: {exc}' @@ -93,6 +93,7 @@ def set_distance(molecule: orm.StructureData, distance: orm.Float) -> orm.Struct sites and which are separated by the target distance. """ import numpy as np + vector_diff = np.array(molecule.sites[1].position) - np.array(molecule.sites[0].position) versor_diff = vector_diff / np.linalg.norm(vector_diff) new_molecule = molecule.clone() @@ -160,7 +161,7 @@ def get_distances(self): count = self.inputs.distances_count.value maximum = self.inputs.distance_max.value minimum = self.inputs.distance_min.value - return [orm.Float(minimum + i * (maximum-minimum) / (count-1)) for i in range(count)] + return [orm.Float(minimum + i * (maximum - minimum) / (count - 1)) for i in range(count)] def get_sub_workchain_builder(self, distance, reference_workchain=None): """Return the builder for the relax workchain.""" @@ -168,11 +169,9 @@ def get_sub_workchain_builder(self, distance, reference_workchain=None): process_class = WorkflowFactory(self.inputs.sub_process_class) builder = process_class.get_input_generator().get_builder( - structure=molecule, - reference_workchain=reference_workchain, - **self.inputs.generator_inputs + structure=molecule, reference_workchain=reference_workchain, **self.inputs.generator_inputs ) - builder._update(**self.inputs.get('sub_process', {})) # pylint: disable=protected-access + builder._update(**self.inputs.get('sub_process', {})) distance_node = molecule.creator.inputs.distance @@ -191,7 +190,7 @@ def inspect_init(self): """Check that the first workchain finished successfully or abort the workchain.""" if not self.ctx.children[0].is_finished_ok: self.report('Initial sub process did not finish successful so aborting the workchain.') - return self.exit_codes.ERROR_SUB_PROCESS_FAILED.format(cls=self.inputs.sub_process_class) # pylint: disable=no-member + return self.exit_codes.ERROR_SUB_PROCESS_FAILED.format(cls=self.inputs.sub_process_class) def run_dissociation(self): """Run the sub process at each distance to compute the total energy.""" @@ -208,10 +207,9 @@ def inspect_results(self): Collect the total energies and return an array with the results. """ if any(not child.is_finished_ok for child in self.ctx.children): - return self.exit_codes.ERROR_SUB_PROCESS_FAILED.format(cls=self.inputs.sub_process_class) # pylint: disable=no-member + return self.exit_codes.ERROR_SUB_PROCESS_FAILED.format(cls=self.inputs.sub_process_class) for index, child in enumerate(self.ctx.children): - energy = child.outputs.total_energy distance = self.ctx.distance_nodes[index] diff --git a/aiida_common_workflows/workflows/eos.py b/aiida_common_workflows/workflows/eos.py index 0b3ce565..dcad7ef3 100644 --- a/aiida_common_workflows/workflows/eos.py +++ b/aiida_common_workflows/workflows/eos.py @@ -23,7 +23,7 @@ def validate_inputs(value, _): try: generator.get_builder(structure=value['structure'], **value['generator_inputs']) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: return f'`{generator.__class__.__name__}.get_builder()` fails for the provided `generator_inputs`: {exc}' @@ -69,7 +69,7 @@ def validate_relax_type(value, _): def scale_structure(structure: orm.StructureData, scale_factor: orm.Float) -> orm.StructureData: """Scale the structure with the given scaling factor.""" ase = structure.get_ase().copy() - ase.set_cell(ase.get_cell() * float(scale_factor)**(1 / 3), scale_atoms=True) + ase.set_cell(ase.get_cell() * float(scale_factor) ** (1 / 3), scale_atoms=True) return orm.StructureData(ase=ase) @@ -144,11 +144,8 @@ def get_sub_workchain_builder(self, scale_factor, reference_workchain=None): if reference_workchain is not None: base_inputs['reference_workchain'] = reference_workchain - builder = process_class.get_input_generator().get_builder( - **base_inputs, - **self.inputs.generator_inputs - ) - builder._update(**self.inputs.get('sub_process', {})) # pylint: disable=protected-access + builder = process_class.get_input_generator().get_builder(**base_inputs, **self.inputs.generator_inputs) + builder._update(**self.inputs.get('sub_process', {})) return builder, structure @@ -172,7 +169,7 @@ def inspect_init(self): """Check that the first workchain finished successfully or abort the workchain.""" if not self.ctx.children[0].is_finished_ok: self.report('Initial sub process did not finish successful so aborting the workchain.') - return self.exit_codes.ERROR_SUB_PROCESS_FAILED.format(cls=self.inputs.sub_process_class) # pylint: disable=no-member + return self.exit_codes.ERROR_SUB_PROCESS_FAILED.format(cls=self.inputs.sub_process_class) def run_eos(self): """Run the sub process at each scale factor to compute the structure volume and total energy.""" @@ -188,7 +185,7 @@ def run_eos(self): def inspect_eos(self): """Inspect all children workflows to make sure they finished successfully.""" if any(not child.is_finished_ok for child in self.ctx.children): - return self.exit_codes.ERROR_SUB_PROCESS_FAILED.format(cls=self.inputs.sub_process_class) # pylint: disable=no-member + return self.exit_codes.ERROR_SUB_PROCESS_FAILED.format(cls=self.inputs.sub_process_class) for index, child in enumerate(self.ctx.children): try: diff --git a/aiida_common_workflows/workflows/relax/__init__.py b/aiida_common_workflows/workflows/relax/__init__.py index 93e92222..0d6a7905 100644 --- a/aiida_common_workflows/workflows/relax/__init__.py +++ b/aiida_common_workflows/workflows/relax/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the base classes for the common structure relaxation workchains.""" from .generator import * diff --git a/aiida_common_workflows/workflows/relax/abinit/__init__.py b/aiida_common_workflows/workflows/relax/abinit/__init__.py index 22e7b0ef..b30341e0 100644 --- a/aiida_common_workflows/workflows/relax/abinit/__init__.py +++ b/aiida_common_workflows/workflows/relax/abinit/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for Abinit.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/abinit/generator.py b/aiida_common_workflows/workflows/relax/abinit/generator.py index 0f145697..7d7c09ae 100644 --- a/aiida_common_workflows/workflows/relax/abinit/generator.py +++ b/aiida_common_workflows/workflows/relax/abinit/generator.py @@ -6,11 +6,11 @@ import typing as t import warnings +import numpy as np +import yaml from aiida import engine, orm, plugins from aiida.common import exceptions -import numpy as np from pymatgen.core import units -import yaml from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -45,21 +45,21 @@ def define(cls, spec): """ super().define(spec) spec.inputs['spin_type'].valid_type = ChoiceType(tuple(SpinType)) - spec.inputs['relax_type'].valid_type = ChoiceType([ - t for t in RelaxType if t not in (RelaxType.VOLUME, RelaxType.SHAPE, RelaxType.CELL) - ]) + spec.inputs['relax_type'].valid_type = ChoiceType( + [t for t in RelaxType if t not in (RelaxType.VOLUME, RelaxType.SHAPE, RelaxType.CELL)] + ) spec.inputs['electronic_type'].valid_type = ChoiceType( (ElectronicType.METAL, ElectronicType.INSULATOR, ElectronicType.UNKNOWN) ) spec.inputs['engines']['relax']['code'].valid_type = CodeType('abinit') spec.inputs['protocol'].valid_type = ChoiceType(('fast', 'moderate', 'precise', 'verification-PBE-v1')) - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] @@ -100,11 +100,9 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: override = { 'abinit': { - 'metadata': { - 'options': engines['relax']['options'] - }, + 'metadata': {'options': engines['relax']['options']}, 'pseudos': pseudo_family.get_pseudos(structure=structure), - 'parameters': cutoff_parameters + 'parameters': cutoff_parameters, } } @@ -148,16 +146,16 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # Add a model macroscopic dielectric constant protocol['base']['abinit']['parameters']['diemac'] = 2.0 - inputs = generate_inputs(self.process_class._process_class, protocol, code, pbc_structure, override) # pylint: disable=protected-access + inputs = generate_inputs(self.process_class._process_class, protocol, code, pbc_structure, override) elif False in structure.pbc: raise ValueError( f'The input structure has periodic boundary conditions {structure.pbc}, but partial ' 'periodic boundary conditions are not supported.' ) else: - inputs = generate_inputs(self.process_class._process_class, protocol, code, structure, override) # pylint: disable=protected-access + inputs = generate_inputs(self.process_class._process_class, protocol, code, structure, override) - builder._update(inputs) # pylint: disable=protected-access + builder._update(inputs) # RelaxType if relax_type == RelaxType.NONE: @@ -201,8 +199,9 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: 'all of the initial magnetizations per site are close to zero; doing a non-spin-polarized ' 'calculation' ) - elif ((sum_is_zero and not all_are_zero) or - (not all_non_zero_pos and not all_non_zero_neg)): # antiferromagnetic + elif (sum_is_zero and not all_are_zero) or ( + not all_non_zero_pos and not all_non_zero_neg + ): # antiferromagnetic print('Detected antiferromagnetic!') builder.abinit['parameters']['nsppol'] = 1 # antiferromagnetic system builder.abinit['parameters']['nspden'] = 2 # scalar spin-magnetization in the z-axis @@ -267,7 +266,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: orm.CalcFunctionNode, tag='calcfunc', edge_filters={'label': 'create_kpoints_from_distance'}, - with_incoming='base' + with_incoming='base', ) query_builder.append(orm.KpointsData, tag='kpoints', with_incoming='calcfunc') query_builder.order_by({orm.KpointsData: {'ctime': 'desc'}}) @@ -301,7 +300,7 @@ def generate_inputs( protocol: t.Dict, code: orm.Code, structure: StructureData, - override: t.Dict[str, t.Any] = None + override: t.Optional[t.Dict[str, t.Any]] = None, ) -> t.Dict[str, t.Any]: """Generate the input parameters for the given workchain type for a given code and structure. @@ -320,11 +319,11 @@ def generate_inputs( :param override: a dictionary to override specific inputs :return: input dictionary """ - # pylint: disable=too-many-arguments,unused-argument + from aiida.common.lang import type_check - AbinitCalculation = plugins.CalculationFactory('abinit') # pylint: disable=invalid-name - AbinitBaseWorkChain = plugins.WorkflowFactory('abinit.base') # pylint: disable=invalid-name + AbinitCalculation = plugins.CalculationFactory('abinit') # noqa: N806 + AbinitBaseWorkChain = plugins.WorkflowFactory('abinit.base') # noqa: N806 type_check(structure, orm.StructureData) @@ -359,10 +358,7 @@ def recursive_merge(left: t.Dict[str, t.Any], right: t.Dict[str, t.Any]) -> t.Di def generate_inputs_base( - protocol: t.Dict, - code: orm.Code, - structure: StructureData, - override: t.Dict[str, t.Any] = None + protocol: t.Dict, code: orm.Code, structure: StructureData, override: t.Optional[t.Dict[str, t.Any]] = None ) -> t.Dict[str, t.Any]: """Generate the inputs for the `AbinitBaseWorkChain` for a given code, structure and pseudo potential family. @@ -391,10 +387,7 @@ def generate_inputs_base( def generate_inputs_calculation( - protocol: t.Dict, - code: orm.Code, - structure: StructureData, - override: t.Dict[str, t.Any] = None + protocol: t.Dict, code: orm.Code, structure: StructureData, override: t.Optional[t.Dict[str, t.Any]] = None ) -> t.Dict[str, t.Any]: """Generate the inputs for the `AbinitCalculation` for a given code, structure and pseudo potential family. @@ -411,7 +404,7 @@ def generate_inputs_calculation( 'structure': structure, 'pseudos': merged['pseudos'], 'parameters': orm.Dict(dict=merged['parameters']), - 'metadata': merged.get('metadata', {}) + 'metadata': merged.get('metadata', {}), } return dictionary diff --git a/aiida_common_workflows/workflows/relax/abinit/workchain.py b/aiida_common_workflows/workflows/relax/abinit/workchain.py index 48a3984c..44c941ac 100644 --- a/aiida_common_workflows/workflows/relax/abinit/workchain.py +++ b/aiida_common_workflows/workflows/relax/abinit/workchain.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.workchain.CommonRelaxWorkChain` for Abinit.""" +import numpy as np from aiida import orm from aiida.common import exceptions from aiida.engine import calcfunction from aiida_abinit.workflows.base import AbinitBaseWorkChain -import numpy as np from ..workchain import CommonRelaxWorkChain from .generator import AbinitCommonRelaxInputGenerator diff --git a/aiida_common_workflows/workflows/relax/bigdft/__init__.py b/aiida_common_workflows/workflows/relax/bigdft/__init__.py index 5b6bef36..b0ce8298 100644 --- a/aiida_common_workflows/workflows/relax/bigdft/__init__.py +++ b/aiida_common_workflows/workflows/relax/bigdft/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for BigDFT.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/bigdft/generator.py b/aiida_common_workflows/workflows/relax/bigdft/generator.py index 7422907c..bc9ec93b 100644 --- a/aiida_common_workflows/workflows/relax/bigdft/generator.py +++ b/aiida_common_workflows/workflows/relax/bigdft/generator.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for BigDFT.""" +import typing as t + from aiida import engine, plugins from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType @@ -17,7 +19,7 @@ class BigDftCommonRelaxInputGenerator(CommonRelaxInputGenerator): """Input generator for the `BigDftCommonRelaxWorkChain`.""" _default_protocol = 'moderate' - _protocols = { + _protocols: t.ClassVar = { 'fast': { 'description': 'This profile should be chosen if accurate forces are required, but there is no need for ' 'extremely accurate energies.', @@ -31,23 +33,21 @@ class BigDftCommonRelaxInputGenerator(CommonRelaxInputGenerator): 'idsx': 0, 'gnrm_cv': 1e-8, 'hgrids': 0.4, - 'disablesym': 'no' + 'disablesym': 'no', }, 'mix': { 'iscf': 17, 'itrpmax': 200, - 'rpnrm_cv': 1.E-12, + 'rpnrm_cv': 1.0e-12, 'norbsempty': 120, 'tel': 0.00225, 'occopt': 2, 'alphamix': 0.8, - 'alphadiis': 1.0 - } - }, - 'inputdict_linear': { - 'import': 'linear' + 'alphadiis': 1.0, + }, }, - 'kpoints_distance': 142 # Equivalent length of K-space resolution (Bohr) + 'inputdict_linear': {'import': 'linear'}, + 'kpoints_distance': 142, # Equivalent length of K-space resolution (Bohr) }, 'moderate': { 'description': 'This profile should be chosen if accurate forces are required, but there is no need for ' @@ -62,23 +62,21 @@ class BigDftCommonRelaxInputGenerator(CommonRelaxInputGenerator): 'idsx': 0, 'gnrm_cv': 1e-8, 'hgrids': 0.4, - 'disablesym': 'no' + 'disablesym': 'no', }, 'mix': { 'iscf': 17, 'itrpmax': 200, - 'rpnrm_cv': 1.E-12, + 'rpnrm_cv': 1.0e-12, 'norbsempty': 120, 'tel': 0.00225, 'occopt': 2, 'alphamix': 0.8, - 'alphadiis': 1.0 - } - }, - 'inputdict_linear': { - 'import': 'linear' + 'alphadiis': 1.0, + }, }, - 'kpoints_distance': 274 + 'inputdict_linear': {'import': 'linear'}, + 'kpoints_distance': 274, }, 'precise': { 'description': 'This profile should be chosen if accurate forces are required, but there is no need for ' @@ -93,23 +91,21 @@ class BigDftCommonRelaxInputGenerator(CommonRelaxInputGenerator): 'idsx': 0, 'gnrm_cv': 1e-8, 'hgrids': 0.3, - 'disablesym': 'no' + 'disablesym': 'no', }, 'mix': { 'iscf': 17, 'itrpmax': 200, - 'rpnrm_cv': 1.E-12, + 'rpnrm_cv': 1.0e-12, 'norbsempty': 120, 'tel': 0.00225, 'occopt': 2, 'alphamix': 0.8, - 'alphadiis': 1.0 - } - }, - 'inputdict_linear': { - 'import': 'linear' + 'alphadiis': 1.0, + }, }, - 'kpoints_distance': 274 + 'inputdict_linear': {'import': 'linear'}, + 'kpoints_distance': 274, }, 'verification-PBE-v1': { 'description': 'Protocol used for bulk run of EoS verification project', @@ -123,23 +119,21 @@ class BigDftCommonRelaxInputGenerator(CommonRelaxInputGenerator): 'idsx': 0, 'gnrm_cv': 1e-8, 'hgrids': 0.4, - 'disablesym': 'no' + 'disablesym': 'no', }, 'mix': { 'iscf': 17, 'itrpmax': 200, - 'rpnrm_cv': 1.E-12, + 'rpnrm_cv': 1.0e-12, 'norbsempty': 120, 'tel': 0.00225, 'occopt': 2, 'alphamix': 0.8, - 'alphadiis': 1.0 - } - }, - 'inputdict_linear': { - 'import': 'linear' + 'alphadiis': 1.0, + }, }, - 'kpoints_distance': 274 + 'inputdict_linear': {'import': 'linear'}, + 'kpoints_distance': 274, }, } @@ -156,12 +150,12 @@ def define(cls, spec): spec.inputs['electronic_type'].valid_type = ChoiceType((ElectronicType.METAL, ElectronicType.INSULATOR)) spec.inputs['engines']['relax']['code'].valid_type = CodeType('bigdft') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + import copy structure = kwargs['structure'] @@ -192,28 +186,33 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: else: hgrids = logfile.get('dft').get('hgrids') first_hgrid = hgrids[0] if isinstance(hgrids, list) else hgrids - inputdict['dft']['hgrids'] = first_hgrid * builder.BigDFT.structure.cell_lengths[0] / \ - reference_workchain.inputs.structure.cell_lengths[0] + inputdict['dft']['hgrids'] = ( + first_hgrid + * builder.BigDFT.structure.cell_lengths[0] + / reference_workchain.inputs.structure.cell_lengths[0] + ) if electronic_type is ElectronicType.METAL: if 'mix' not in inputdict: inputdict['mix'] = {} - inputdict['mix'].update({ - 'iscf': 17, - 'itrpmax': 200, - 'rpnrm_cv': 1.E-12, - 'norbsempty': 120, - 'tel': 0.01, - 'alphamix': 0.8, - 'alphadiis': 1.0 - }) + inputdict['mix'].update( + { + 'iscf': 17, + 'itrpmax': 200, + 'rpnrm_cv': 1.0e-12, + 'norbsempty': 120, + 'tel': 0.01, + 'alphamix': 0.8, + 'alphadiis': 1.0, + } + ) if spin_type is SpinType.NONE: inputdict['dft'].update({'nspin': 1}) elif spin_type is SpinType.COLLINEAR: inputdict['dft'].update({'nspin': 2}) if magnetization_per_site: - for (i, atom) in enumerate(inputdict['posinp']['positions']): + for i, atom in enumerate(inputdict['posinp']['positions']): atom['IGSpin'] = int(magnetization_per_site[i]) # correctly set kpoints from protocol fast and moderate. If precise, use the ones from set_inputfile/set_kpt if self.get_protocol(protocol).get('kpoints_distance'): diff --git a/aiida_common_workflows/workflows/relax/castep/__init__.py b/aiida_common_workflows/workflows/relax/castep/__init__.py index 93b2baa4..3aa6a6fa 100644 --- a/aiida_common_workflows/workflows/relax/castep/__init__.py +++ b/aiida_common_workflows/workflows/relax/castep/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for CASTEP""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/castep/extractors.py b/aiida_common_workflows/workflows/relax/castep/extractors.py index 23e3258d..c419dc35 100644 --- a/aiida_common_workflows/workflows/relax/castep/extractors.py +++ b/aiida_common_workflows/workflows/relax/castep/extractors.py @@ -32,6 +32,6 @@ def get_ts_energy(common_relax_workchain): e_ks = castep_base_wc.outputs.output_parameters['total energy'] free_e = castep_base_wc.outputs.output_parameters['free energy'] - ts = e_ks - free_e #pylint: disable=invalid-name + ts = e_ks - free_e return ts diff --git a/aiida_common_workflows/workflows/relax/castep/generator.py b/aiida_common_workflows/workflows/relax/castep/generator.py index 07fa63ee..dffd20e5 100644 --- a/aiida_common_workflows/workflows/relax/castep/generator.py +++ b/aiida_common_workflows/workflows/relax/castep/generator.py @@ -2,27 +2,26 @@ """Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for CASTEP""" import collections import copy -from math import pi import pathlib import typing as t +from math import pi +import yaml from aiida import engine, orm, plugins from aiida.common import exceptions from aiida_castep.data import get_pseudos_from_structure from aiida_castep.data.otfg import OTFGGroup -import yaml from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType from ..generator import CommonRelaxInputGenerator -# pylint: disable=import-outside-toplevel, too-many-branches, too-many-statements KNOWN_BUILTIN_FAMILIES = ('C19', 'NCP19', 'QC5', 'C17', 'C9') __all__ = ('CastepCommonRelaxInputGenerator',) -StructureData = plugins.DataFactory('core.structure') # pylint: disable=invalid-name +StructureData = plugins.DataFactory('core.structure') class CastepCommonRelaxInputGenerator(CommonRelaxInputGenerator): @@ -59,12 +58,12 @@ def define(cls, spec): spec.inputs['electronic_type'].valid_type = ChoiceType((ElectronicType.METAL, ElectronicType.INSULATOR)) spec.inputs['engines']['relax']['code'].valid_type = CodeType('castep.castep') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] @@ -127,7 +126,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # Symmetry should be off, unless QUANTISATION_AXIS is supplied # that would be too advanced, here I just turn it off param.pop('symmetry_generate', None) - #elif spin_type == SpinType.SPIN_ORBIT: + # elif spin_type == SpinType.SPIN_ORBIT: # param['spin_treatment'] = 'noncollinear' # param['spin_orbit_coupling'] = True # param.pop('symmetry_generate', None) @@ -157,13 +156,13 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # Process electronic type # for plane-wave DFT density mixing is most efficient for both metal and insulators # these days. Here we stick to the default of CASTEP and do nothing here. - #if electronic_type == ElectronicType.METAL: + # if electronic_type == ElectronicType.METAL: # # Use fine kpoints grid for all metallic calculations # No need to do this since the default is spacing is sufficiently fine # override['base']['kpoints_spacing'] = 0.03 - #elif electronic_type in (ElectronicType.INSULATOR, ElectronicType.AUTOMATIC): + # elif electronic_type in (ElectronicType.INSULATOR, ElectronicType.AUTOMATIC): # pass - #else: + # else: # raise ValueError('Unsupported `electronic_type` {}.'.format(electronic_type)) # Raise the cut off energy for very soft pseudopotentials @@ -186,7 +185,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: ensure_otfg_family(pseudos_family) builder = self.process_class.get_builder() - inputs = generate_inputs(self.process_class._process_class, protocol, code, structure, override) # pylint: disable=protected-access + inputs = generate_inputs(self.process_class._process_class, protocol, code, structure, override) # Finally, apply the logic for previous workchain if reference_workchain: @@ -204,7 +203,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: inputs['calc']['kpoints'] = previous_kpoints inputs['base'].pop('kpoints_spacing', None) - builder._update(inputs) # pylint: disable=protected-access + builder._update(inputs) return builder @@ -233,7 +232,7 @@ def generate_inputs( protocol: t.Dict, code: orm.Code, structure: orm.StructureData, - override: t.Dict[str, t.Any] = None + override: t.Optional[t.Dict[str, t.Any]] = None, ) -> t.Dict[str, t.Any]: """Generate the input parameters for the given workchain type for a given code, structure and pseudo family. @@ -249,7 +248,7 @@ def generate_inputs( :param override: a dictionary to override specific inputs :return: input dictionary """ - # pylint: disable=too-many-arguments,unused-argument + from aiida.common.lang import type_check family_name = protocol['relax']['base']['pseudos_family'] @@ -262,9 +261,9 @@ def generate_inputs( family = protocol['relax']['base']['pseudos_family'] raise ValueError(f'protocol `{name}` requires the `{family}` `pseudos family` but could not be found.') from exc - CastepCalculation = plugins.CalculationFactory('castep.castep') # pylint: disable=invalid-name - CastepBaseWorkChain = plugins.WorkflowFactory('castep.base') # pylint: disable=invalid-name - CastepRelaxWorkChain = plugins.WorkflowFactory('castep.relax') # pylint: disable=invalid-name + CastepCalculation = plugins.CalculationFactory('castep.castep') # noqa: N806 + CastepBaseWorkChain = plugins.WorkflowFactory('castep.base') # noqa: N806 + CastepRelaxWorkChain = plugins.WorkflowFactory('castep.relax') # noqa: N806 type_check(structure, orm.StructureData) @@ -288,7 +287,7 @@ def generate_inputs_relax( code: orm.Code, structure: orm.StructureData, otfg_family: OTFGGroup, - override: t.Dict[str, t.Any] = None + override: t.Optional[t.Dict[str, t.Any]] = None, ) -> t.Dict[str, t.Any]: """Generate the inputs for the `CastepCommonRelaxWorkChain` for a given code, structure and pseudo potential family. @@ -313,7 +312,7 @@ def generate_inputs_relax( 'base': merged['base'], 'calc': calc, 'structure': structure, - 'relax_options': orm.Dict(dict=merged['relax_options']) + 'relax_options': orm.Dict(dict=merged['relax_options']), } return dictionary @@ -324,7 +323,7 @@ def generate_inputs_base( code: orm.Code, structure: orm.StructureData, otfg_family: OTFGGroup, - override: t.Dict[str, t.Any] = None + override: t.Optional[t.Dict[str, t.Any]] = None, ) -> t.Dict[str, t.Any]: """Generate the inputs for the `CastepBaseWorkChain` for a given code, structure and pseudo potential family. @@ -362,7 +361,7 @@ def generate_inputs_calculation( code: orm.Code, structure: orm.StructureData, otfg_family: OTFGGroup, - override: t.Dict[str, t.Any] = None + override: t.Optional[t.Dict[str, t.Any]] = None, ) -> t.Dict[str, t.Any]: """Generate the inputs for the `CastepCalculation` for a given code, structure and pseudo potential family. @@ -374,6 +373,7 @@ def generate_inputs_calculation( :return: the fully defined input dictionary. """ from aiida_castep.calculations.helper import CastepHelper + override = {} if not override else override.get('calc', {}) # This merge perserves the merged `parameters` in the override merged_calc = recursive_merge(protocol['calc'], override) @@ -401,7 +401,7 @@ def generate_inputs_calculation( 'code': code, 'parameters': orm.Dict(dict=param), 'pseudos': get_pseudos_from_structure(structure, otfg_family.label), - 'metadata': merged_calc.get('metadata', {}) + 'metadata': merged_calc.get('metadata', {}), } # Add the settings input if present if 'settings' in merged_calc: diff --git a/aiida_common_workflows/workflows/relax/cp2k/__init__.py b/aiida_common_workflows/workflows/relax/cp2k/__init__.py index d9e8ffd2..c176cf43 100644 --- a/aiida_common_workflows/workflows/relax/cp2k/__init__.py +++ b/aiida_common_workflows/workflows/relax/cp2k/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for CP2K.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/cp2k/generator.py b/aiida_common_workflows/workflows/relax/cp2k/generator.py index 51b39f8c..946eeb3a 100644 --- a/aiida_common_workflows/workflows/relax/cp2k/generator.py +++ b/aiida_common_workflows/workflows/relax/cp2k/generator.py @@ -4,9 +4,9 @@ import pathlib import typing as t -from aiida import engine, orm, plugins import numpy as np import yaml +from aiida import engine, orm, plugins from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -15,14 +15,14 @@ __all__ = ('Cp2kCommonRelaxInputGenerator',) -StructureData = plugins.DataFactory('core.structure') # pylint: disable=invalid-name -KpointsData = plugins.DataFactory('core.array.kpoints') # pylint: disable=invalid-name +StructureData = plugins.DataFactory('core.structure') +KpointsData = plugins.DataFactory('core.array.kpoints') EV_A3_TO_GPA = 160.21766208 def dict_merge(dct, merge_dct): - """ Taken from https://gist.github.com/angstwad/bf22d1822c38a92ec0a9 + """Taken from https://gist.github.com/angstwad/bf22d1822c38a92ec0a9 Recursive dict merge. Inspired by :meth:``dict.update()``, instead of updating only top-level keys, dict_merge recurses down into dicts nested to an arbitrary depth, updating keys. The ``merge_dct`` is merged into @@ -32,7 +32,7 @@ def dict_merge(dct, merge_dct): :return: None """ for k in merge_dct.keys(): - if (k in dct and isinstance(dct[k], dict) and isinstance(merge_dct[k], collections.abc.Mapping)): + if k in dct and isinstance(dct[k], dict) and isinstance(merge_dct[k], collections.abc.Mapping): dict_merge(dct[k], merge_dct[k]) else: dct[k] = merge_dct[k] @@ -85,7 +85,7 @@ def tags_and_magnetization(structure, magnetization_per_site): return structure, None -def guess_multiplicity(structure: StructureData, magnetization_per_site: t.List[float] = None): +def guess_multiplicity(structure: StructureData, magnetization_per_site: t.Optional[t.List[float]] = None): """Get total spin multiplicity from atomic magnetizations.""" spin_multiplicity = 1 if magnetization_per_site: @@ -172,12 +172,12 @@ def define(cls, spec): spec.inputs['electronic_type'].valid_type = ChoiceType((ElectronicType.METAL, ElectronicType.INSULATOR)) spec.inputs['engines']['relax']['code'].valid_type = CodeType('cp2k') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] @@ -239,6 +239,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: parameters['FORCE_EVAL']['DFT']['UKS'] = False if magnetization_per_site is not None: import warnings + warnings.warn('`magnetization_per_site` will be ignored as `spin_type` is set to SpinType.NONE') elif spin_type == SpinType.COLLINEAR: @@ -251,14 +252,14 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: if 'sirius' in protocol: dict_merge( parameters, - get_kinds_section(structure, basis_pseudo=None, magnetization_tags=magnetization_tags, use_sirius=True) + get_kinds_section(structure, basis_pseudo=None, magnetization_tags=magnetization_tags, use_sirius=True), ) else: dict_merge( parameters, get_kinds_section( structure, basis_pseudo=basis_pseudo, magnetization_tags=magnetization_tags, use_sirius=False - ) + ), ) # Relaxation type. @@ -356,7 +357,7 @@ def _get_cell_ref(structure, reference_workchain, scale_factor): # workchain and any subsequent workchains pass - cell = [[v * scale_factor**(1 / 3) for v in row] for row in structure.cell] + cell = [[v * scale_factor ** (1 / 3) for v in row] for row in structure.cell] # start with an A, B, C: cell_ref = {idx: f'[angstrom] {row[0]:<15} {row[1]:<15} {row[2]:<15}' for idx, row in zip('ABC', cell)} diff --git a/aiida_common_workflows/workflows/relax/cp2k/workchain.py b/aiida_common_workflows/workflows/relax/cp2k/workchain.py index 86b87bc1..0d5cae2a 100644 --- a/aiida_common_workflows/workflows/relax/cp2k/workchain.py +++ b/aiida_common_workflows/workflows/relax/cp2k/workchain.py @@ -2,17 +2,17 @@ """Implementation of `aiida_common_workflows.common.relax.workchain.CommonRelaxWorkChain` for CP2K.""" import re +import numpy as np from aiida import orm from aiida.engine import calcfunction from aiida.plugins import WorkflowFactory -import numpy as np from ..workchain import CommonRelaxWorkChain from .generator import Cp2kCommonRelaxInputGenerator __all__ = ('Cp2kCommonRelaxWorkChain',) -Cp2kBaseWorkChain = WorkflowFactory('cp2k.base') # pylint: disable=invalid-name +Cp2kBaseWorkChain = WorkflowFactory('cp2k.base') EV_A3_TO_BAR = 1602176.6208 HA_BOHR_TO_EV_A = 51.42208619083232 @@ -37,8 +37,11 @@ def get_forces_output_folder(folder, structure): except FileNotFoundError: try: content = folder.get_object_content('aiida-requested-forces-1_0.xyz') - lines = re.search('Atom Kind Element(.*?)SUM OF ATOMIC FORCES', content, - flags=re.S).group(1).splitlines()[1:-1] + lines = ( + re.search('Atom Kind Element(.*?)SUM OF ATOMIC FORCES', content, flags=re.S) + .group(1) + .splitlines()[1:-1] + ) forces_position = 3 except FileNotFoundError: return None @@ -46,7 +49,7 @@ def get_forces_output_folder(folder, structure): # Extract forces. forces_array = np.empty((natoms, 3)) for i, line in enumerate(lines): - forces_array[i] = [float(s) for s in line.split()[forces_position:forces_position + 3]] + forces_array[i] = [float(s) for s in line.split()[forces_position : forces_position + 3]] forces = orm.ArrayData() forces.set_array(name='forces', array=forces_array * HA_BOHR_TO_EV_A) return forces diff --git a/aiida_common_workflows/workflows/relax/fleur/__init__.py b/aiida_common_workflows/workflows/relax/fleur/__init__.py index 125dc38e..806961fa 100644 --- a/aiida_common_workflows/workflows/relax/fleur/__init__.py +++ b/aiida_common_workflows/workflows/relax/fleur/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for FLEUR.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/fleur/extractors.py b/aiida_common_workflows/workflows/relax/fleur/extractors.py index 5f80d1ae..5a302d59 100644 --- a/aiida_common_workflows/workflows/relax/fleur/extractors.py +++ b/aiida_common_workflows/workflows/relax/fleur/extractors.py @@ -29,12 +29,12 @@ def get_ts_energy(common_relax_workchain): fleur_calc_out = fleur_relax_wc.outputs.last_scf.last_calc output_parameters = fleur_calc_out.output_parameters - ts = None #pylint: disable=invalid-name + ts = None if 'ts_energy' in output_parameters.keys(): - ts = output_parameters['ts_energy'] #pylint: disable=invalid-name + ts = output_parameters['ts_energy'] elif fleur_relax_wc.is_finished_ok: - #This check makes sure that the parsing worked before so we don't get - #nasty surprises in load_outxml + # This check makes sure that the parsing worked before so we don't get + # nasty surprises in load_outxml with fleur_calc_out.retrieved.open('out.xml', 'rb') as file: xmltree, schema_dict = load_outxml(file) @@ -46,6 +46,6 @@ def get_ts_energy(common_relax_workchain): pass else: if ts_all: - ts = ts_all[-1] * HTR_TO_EV #pylint: disable=invalid-name + ts = ts_all[-1] * HTR_TO_EV return ts diff --git a/aiida_common_workflows/workflows/relax/fleur/generator.py b/aiida_common_workflows/workflows/relax/fleur/generator.py index 6ef4089a..7077a6a9 100644 --- a/aiida_common_workflows/workflows/relax/fleur/generator.py +++ b/aiida_common_workflows/workflows/relax/fleur/generator.py @@ -4,9 +4,9 @@ import pathlib import typing as t -from aiida import engine, orm, plugins -from aiida.common.constants import elements as PeriodicTableElements import yaml +from aiida import engine, orm, plugins +from aiida.common.constants import elements from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -22,22 +22,16 @@ class FleurCommonRelaxInputGenerator(CommonRelaxInputGenerator): """Generator of inputs for the `FleurCommonRelaxWorkChain`.""" _default_protocol = 'moderate' - _protocols = { - 'fast': { - 'description': 'return in a quick way a result that may not be reliable' - }, - 'moderate': { - 'description': 'reliable result (could be published), but no emphasis on convergence' - }, - 'precise': { - 'description': 'high level of accuracy' - }, + _protocols: t.ClassVar = { + 'fast': {'description': 'return in a quick way a result that may not be reliable'}, + 'moderate': {'description': 'reliable result (could be published), but no emphasis on convergence'}, + 'precise': {'description': 'high level of accuracy'}, 'oxides_validation': { 'description': 'high level of accuracy. Used for validating oxide results for common-workflows' }, 'verification-PBE-v1': { 'description': 'high level of accuracy. Used for validating oxide results for common-workflows' - } + }, } def __init__(self, *args, **kwargs): @@ -68,12 +62,12 @@ def define(cls, spec): spec.inputs['engines']['relax']['code'].valid_type = CodeType('fleur.fleur') spec.inputs['engines']['inpgen']['code'].valid_type = CodeType('fleur.inpgen') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] @@ -91,6 +85,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # Checks if protocol exists if protocol not in self.get_protocol_names(): import warnings + warnings.warn(f'no protocol implemented with name {protocol}, using default moderate') protocol = self.get_default_protocol_name() else: @@ -130,7 +125,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: 'change_mixing_criterion': 0.025, 'atoms_off': [], 'run_final_scf': True, # we always run a final scf after the relaxation - 'relaxation_type': 'atoms' + 'relaxation_type': 'atoms', } wf_para_dict = recursive_merge(default_wf_para, protocol.get('relax', {})) @@ -153,7 +148,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: dict={ 'significant_figures_cell': 9, 'significant_figures_position': 9, - 'profile': protocol['inpgen-protocol'] + 'profile': protocol['inpgen-protocol'], } ) @@ -163,11 +158,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: 'fleur_runmax': 2, 'itmax_per_run': 120, 'force_converged': force_criterion, - 'force_dict': { - 'qfix': 2, - 'forcealpha': 0.75, - 'forcemix': 'straight' - }, + 'force_dict': {'qfix': 2, 'forcealpha': 0.75, 'forcemix': 'straight'}, 'use_relax_xml': True, 'mode': relaxation_mode, } @@ -206,12 +197,12 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: 'options': options_scf, # options do not matter on QM, in general they do... 'inpgen': inpgen_code, - 'fleur': fleur_code + 'fleur': fleur_code, }, - 'wf_parameters': wf_para + 'wf_parameters': wf_para, } - builder._update(inputs) # pylint: disable=protected-access + builder._update(inputs) return builder @@ -227,8 +218,8 @@ def prepare_calc_parameters(parameters, spin_type, magnetization_per_site, struc :param kmax: int, basis cutoff for the simulations :return: orm.Dict """ - # pylint: disable=too-many-locals - #parameters_b = None + + # parameters_b = None # Spin type options if spin_type == SpinType.NONE: @@ -249,10 +240,11 @@ def prepare_calc_parameters(parameters, spin_type, magnetization_per_site, struc if magnetization_per_site is not None: # Do for now sake we have this. If the structure is not rightly prepared it will run, but # the set magnetization will be wrong - atomic_numbers = {data['symbol']: num for num, data in PeriodicTableElements.items()} + atomic_numbers = {data['symbol']: num for num, data in elements.items()} if spin_type == SpinType.NONE: import warnings + warnings.warn('`magnetization_per_site` will be ignored as `spin_type` is set to SpinType.NONE') if spin_type == SpinType.COLLINEAR: # add atom lists for each kind and set bmu in muBohr @@ -272,7 +264,7 @@ def prepare_calc_parameters(parameters, spin_type, magnetization_per_site, struc if kind_name != site_symbol: head = kind_name.rstrip('0123456789') try: - kind_namet = int(kind_name[len(head):]) + kind_namet = int(kind_name[len(head) :]) except ValueError: kind_namet = 0 kind_id = f'{atomic_number}.{kind_namet}' @@ -282,7 +274,7 @@ def prepare_calc_parameters(parameters, spin_type, magnetization_per_site, struc # Better would be a valid parameter data merge from aiida-fleur, to merge atom lists # right add_parameter_dict = recursive_merge(add_parameter_dict, mag_dict) - #structure, parameters_b = break_symmetry(structure, parameterdata=orm.Dict(dict=add_parameter_dict)) + # structure, parameters_b = break_symmetry(structure, parameterdata=orm.Dict(dict=add_parameter_dict)) new_parameters = orm.Dict(dict=add_parameter_dict) @@ -311,7 +303,7 @@ def get_parameters(reference_workchain): last_scf = orm.load_node(last_scf) except NotExistent: # something went wrong in the previous workchain run - #.. we just continue without previous parameters but defaults. + # .. we just continue without previous parameters but defaults. return None if last_scf.process_class is fleur_scf_wc: fleurinp = last_scf.outputs.fleurinp diff --git a/aiida_common_workflows/workflows/relax/fleur/workchain.py b/aiida_common_workflows/workflows/relax/fleur/workchain.py index df945b4c..6c4c1291 100644 --- a/aiida_common_workflows/workflows/relax/fleur/workchain.py +++ b/aiida_common_workflows/workflows/relax/fleur/workchain.py @@ -11,7 +11,7 @@ @calcfunction -def get_forces_from_trajectory(trajectory): # pylint: disable=unused-argument +def get_forces_from_trajectory(trajectory): """Calcfunction to get forces from trajectory""" forces = orm.ArrayData() # currently the fleur relax workchain does not output trajectory data, diff --git a/aiida_common_workflows/workflows/relax/gaussian/__init__.py b/aiida_common_workflows/workflows/relax/gaussian/__init__.py index b6465874..84fddd69 100644 --- a/aiida_common_workflows/workflows/relax/gaussian/__init__.py +++ b/aiida_common_workflows/workflows/relax/gaussian/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for Gaussian.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/gaussian/generator.py b/aiida_common_workflows/workflows/relax/gaussian/generator.py index 1783f0a4..fc5fe840 100644 --- a/aiida_common_workflows/workflows/relax/gaussian/generator.py +++ b/aiida_common_workflows/workflows/relax/gaussian/generator.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for Gaussian.""" import copy +import typing as t -from aiida import engine, orm, plugins import numpy as np +from aiida import engine, orm, plugins from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -22,7 +23,7 @@ class GaussianCommonRelaxInputGenerator(CommonRelaxInputGenerator): """Input generator for the `GaussianCommonRelaxWorkChain`.""" _default_protocol = 'moderate' - _protocols = { + _protocols: t.ClassVar = { 'fast': { 'description': 'Optimal performance, minimal accuracy.', 'functional': 'PBEPBE', @@ -30,7 +31,7 @@ class GaussianCommonRelaxInputGenerator(CommonRelaxInputGenerator): 'route_parameters': { 'nosymm': None, 'opt': 'loose', - } + }, }, 'moderate': { 'description': 'Moderate performance, moderate accuracy.', @@ -40,7 +41,7 @@ class GaussianCommonRelaxInputGenerator(CommonRelaxInputGenerator): 'int': 'ultrafine', 'nosymm': None, 'opt': None, - } + }, }, 'precise': { 'description': 'Low performance, high accuracy', @@ -50,8 +51,8 @@ class GaussianCommonRelaxInputGenerator(CommonRelaxInputGenerator): 'int': 'superfine', 'nosymm': None, 'opt': 'tight', - } - } + }, + }, } @classmethod @@ -66,12 +67,12 @@ def define(cls, spec): spec.inputs['electronic_type'].valid_type = ChoiceType((ElectronicType.METAL, ElectronicType.INSULATOR)) spec.inputs['engines']['relax']['code'].valid_type = CodeType('gaussian') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] @@ -96,7 +97,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: link0_parameters['%mem'] = '2048MB' else: # If memory is set, specify 80% of it to gaussian - link0_parameters['%mem'] = '%dMB' % ((0.8 * options['max_memory_kb']) // 1024) # pylint: disable=consider-using-f-string) + link0_parameters['%mem'] = '%dMB' % ((0.8 * options['max_memory_kb']) // 1024) # Determine the number of processors that should be specified to Gaussian n_proc = None @@ -180,7 +181,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: 'basis_set': sel_protocol['basis_set'], 'charge': 0, 'multiplicity': spin_multiplicity, - 'route_parameters': route_params + 'route_parameters': route_params, } builder = self.process_class.get_builder() diff --git a/aiida_common_workflows/workflows/relax/gaussian/workchain.py b/aiida_common_workflows/workflows/relax/gaussian/workchain.py index b27876c6..b5c815ea 100644 --- a/aiida_common_workflows/workflows/relax/gaussian/workchain.py +++ b/aiida_common_workflows/workflows/relax/gaussian/workchain.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.workchain.CommonRelaxWorkChain` for Gaussian.""" +import numpy as np from aiida import orm from aiida.engine import calcfunction from aiida.plugins import WorkflowFactory -import numpy as np from ..workchain import CommonRelaxWorkChain from .generator import GaussianCommonRelaxInputGenerator diff --git a/aiida_common_workflows/workflows/relax/generator.py b/aiida_common_workflows/workflows/relax/generator.py index 808c8cfc..b23a41b8 100644 --- a/aiida_common_workflows/workflows/relax/generator.py +++ b/aiida_common_workflows/workflows/relax/generator.py @@ -28,7 +28,7 @@ def define(cls, spec): spec.input( 'structure', valid_type=plugins.DataFactory('core.structure'), - help='The structure whose geometry should be optimized.' + help='The structure whose geometry should be optimized.', ) spec.input( 'protocol', diff --git a/aiida_common_workflows/workflows/relax/gpaw/__init__.py b/aiida_common_workflows/workflows/relax/gpaw/__init__.py index 6b347a35..ff5e0065 100644 --- a/aiida_common_workflows/workflows/relax/gpaw/__init__.py +++ b/aiida_common_workflows/workflows/relax/gpaw/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for GPAW.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/gpaw/generator.py b/aiida_common_workflows/workflows/relax/gpaw/generator.py index 60378c6b..a21e306c 100644 --- a/aiida_common_workflows/workflows/relax/gpaw/generator.py +++ b/aiida_common_workflows/workflows/relax/gpaw/generator.py @@ -3,10 +3,10 @@ from __future__ import annotations import pathlib -from typing import Any, Dict, List, Tuple +import typing as t -from aiida import engine, orm, plugins import yaml +from aiida import engine, orm, plugins from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType @@ -21,15 +21,17 @@ class GpawCommonRelaxInputGenerator(CommonRelaxInputGenerator): """Input generator for the `GpawCommonRelaxWorkChain`.""" _default_protocol = 'moderate' - _engine_types = {'relax': {'code_plugin': 'ase.ase', 'description': 'The code to perform the relaxation.'}} - _relax_types = { + _engine_types: t.ClassVar = { + 'relax': {'code_plugin': 'ase.ase', 'description': 'The code to perform the relaxation.'} + } + _relax_types: t.ClassVar = { RelaxType.NONE: 'Do not perform relaxation.', RelaxType.POSITIONS: 'Relax only the atomic positions while keeping the cell fixed.', } - _spin_types = { + _spin_types: t.ClassVar = { SpinType.NONE: 'Treat the system without spin polarization.', } - _electronic_types = { + _electronic_types: t.ClassVar = { ElectronicType.METAL: 'Treat the system as a metal with smeared occupations.', } @@ -43,20 +45,20 @@ def _initialize_protocols(self): with open(str(pathlib.Path(__file__).parent / 'protocol.yml'), encoding='utf-8') as handle: self._protocols = yaml.safe_load(handle) - def _construct_builder( # pylint: disable=arguments-differ,too-many-locals + def _construct_builder( # noqa: PLR0913 self, structure: StructureData, - engines: Dict[str, Any], + engines: t.Dict[str, t.Any], *, - protocol: str = None, + protocol: t.Optional[str] = None, relax_type: RelaxType | str = RelaxType.POSITIONS, electronic_type: ElectronicType | str = ElectronicType.METAL, spin_type: SpinType | str = SpinType.NONE, - magnetization_per_site: List[float] | Tuple[float] | None = None, - threshold_forces: float = None, - threshold_stress: float = None, + magnetization_per_site: t.List[float] | t.Tuple[float] | None = None, + threshold_forces: t.Optional[float] = None, + threshold_stress: t.Optional[float] = None, reference_workchain=None, - **kwargs + **kwargs, ) -> engine.ProcessBuilder: """Return a process builder for the corresponding workchain class with inputs set according to the protocol. @@ -77,7 +79,7 @@ def _construct_builder( # pylint: disable=arguments-differ,too-many-locals """ protocol = protocol or self.get_default_protocol_name() - super().get_builder( # pylint: disable=too-many-function-args + super().get_builder( structure, engines, protocol=protocol, @@ -88,7 +90,7 @@ def _construct_builder( # pylint: disable=arguments-differ,too-many-locals threshold_forces=threshold_forces, threshold_stress=threshold_stress, reference_workchain=reference_workchain, - **kwargs + **kwargs, ) if isinstance(electronic_type, str): @@ -105,9 +107,7 @@ def _construct_builder( # pylint: disable=arguments-differ,too-many-locals parameters = protocol['parameters'] parameters['atoms_getters'] = [ 'temperature', - ['forces', { - 'apply_constraint': True - }], + ['forces', {'apply_constraint': True}], ['masses', {}], ] if relax_type == RelaxType.NONE: diff --git a/aiida_common_workflows/workflows/relax/nwchem/__init__.py b/aiida_common_workflows/workflows/relax/nwchem/__init__.py index 14c9f0c9..912c84e1 100644 --- a/aiida_common_workflows/workflows/relax/nwchem/__init__.py +++ b/aiida_common_workflows/workflows/relax/nwchem/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for NWChem.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/nwchem/generator.py b/aiida_common_workflows/workflows/relax/nwchem/generator.py index 454bcbf0..25dd1014 100644 --- a/aiida_common_workflows/workflows/relax/nwchem/generator.py +++ b/aiida_common_workflows/workflows/relax/nwchem/generator.py @@ -3,9 +3,9 @@ import pathlib import warnings -from aiida import engine, orm, plugins import numpy as np import yaml +from aiida import engine, orm, plugins from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -48,12 +48,12 @@ def define(cls, spec): spec.inputs['electronic_type'].valid_type = ChoiceType((ElectronicType.METAL, ElectronicType.INSULATOR)) spec.inputs['engines']['relax']['code'].valid_type = CodeType('nwchem.nwchem') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] @@ -78,7 +78,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: else: reciprocal_axes_lengths = np.linalg.norm(np.linalg.inv(structure.cell), axis=1) kpoints = np.ceil(reciprocal_axes_lengths / target_spacing).astype(int).tolist() - parameters['nwpw']['monkhorst-pack'] = '{} {} {}'.format(*kpoints) # pylint: disable=consider-using-f-string + parameters['nwpw']['monkhorst-pack'] = '{} {} {}'.format(*kpoints) # Relaxation type if relax_type == RelaxType.POSITIONS: @@ -95,7 +95,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: else: raise ValueError(f'relax_type `{relax_type.value}` is not supported') - # Electronic type + # Electronic type if electronic_type == ElectronicType.INSULATOR: pass elif electronic_type == ElectronicType.METAL: diff --git a/aiida_common_workflows/workflows/relax/nwchem/workchain.py b/aiida_common_workflows/workflows/relax/nwchem/workchain.py index 60637412..ed420dc4 100644 --- a/aiida_common_workflows/workflows/relax/nwchem/workchain.py +++ b/aiida_common_workflows/workflows/relax/nwchem/workchain.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.workchain.CommonRelaxWorkChain` for NWChem.""" +import numpy as np from aiida import orm from aiida.engine import calcfunction from aiida.plugins import WorkflowFactory -import numpy as np from ..workchain import CommonRelaxWorkChain from .generator import NwchemCommonRelaxInputGenerator diff --git a/aiida_common_workflows/workflows/relax/orca/__init__.py b/aiida_common_workflows/workflows/relax/orca/__init__.py index fc7f1d1c..b84739e4 100644 --- a/aiida_common_workflows/workflows/relax/orca/__init__.py +++ b/aiida_common_workflows/workflows/relax/orca/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for Orca.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/orca/generator.py b/aiida_common_workflows/workflows/relax/orca/generator.py index 28526deb..b6efa3e6 100644 --- a/aiida_common_workflows/workflows/relax/orca/generator.py +++ b/aiida_common_workflows/workflows/relax/orca/generator.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for Orca.""" -from copy import deepcopy import os import warnings +from copy import deepcopy -from aiida import engine, orm -from aiida.plugins import DataFactory import numpy as np import yaml +from aiida import engine, orm +from aiida.plugins import DataFactory from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -34,8 +34,7 @@ def __init__(self, *args, **kwargs): def raise_invalid(message): raise RuntimeError(f'invalid protocol registry `{self.__class__.__name__}`: ' + message) - for k, v in self._protocols.items(): # pylint: disable=invalid-name - + for k, v in self._protocols.items(): if 'input_keywords' not in v: raise_invalid(f'protocol `{k}` does not define the mandatory key `input_keywords`') @@ -58,12 +57,12 @@ def define(cls, spec): spec.inputs['electronic_type'].valid_type = ChoiceType((ElectronicType.METAL, ElectronicType.INSULATOR)) spec.inputs['engines']['relax']['code'].valid_type = CodeType('orca_main') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] diff --git a/aiida_common_workflows/workflows/relax/orca/workchain.py b/aiida_common_workflows/workflows/relax/orca/workchain.py index a0b298f1..1a89a21b 100644 --- a/aiida_common_workflows/workflows/relax/orca/workchain.py +++ b/aiida_common_workflows/workflows/relax/orca/workchain.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.workchain.CommonRelaxWorkChain` for Orca.""" +import numpy as np from aiida.engine import calcfunction from aiida.orm import ArrayData, Float from aiida.plugins import WorkflowFactory -import numpy as np from ..workchain import CommonRelaxWorkChain from .generator import OrcaCommonRelaxInputGenerator @@ -59,4 +59,4 @@ def convert_outputs(self): self.out('total_magnetization', get_total_magnetization(self.ctx.workchain.outputs.output_parameters)) -#EOF +# EOF diff --git a/aiida_common_workflows/workflows/relax/quantum_espresso/__init__.py b/aiida_common_workflows/workflows/relax/quantum_espresso/__init__.py index 7b873bc8..2b10631c 100644 --- a/aiida_common_workflows/workflows/relax/quantum_espresso/__init__.py +++ b/aiida_common_workflows/workflows/relax/quantum_espresso/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable,cyclic-import + """Module with the implementations of the common structure relaxation workchain for Quantum ESPRESSO.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/quantum_espresso/extractors.py b/aiida_common_workflows/workflows/relax/quantum_espresso/extractors.py index 4e247bee..5982bb5d 100644 --- a/aiida_common_workflows/workflows/relax/quantum_espresso/extractors.py +++ b/aiida_common_workflows/workflows/relax/quantum_espresso/extractors.py @@ -10,7 +10,7 @@ def get_ts_energy(common_relax_workchain: QuantumEspressoCommonRelaxWorkChain) -> float: - """ Return the T * S value of a concluded ``QuantumEspressoCommonRelaxWorkChain``. + """Return the T * S value of a concluded ``QuantumEspressoCommonRelaxWorkChain``. Here, T is the fictitious temperature due to the use of smearing and S is the entropy. This "smearing contribution" to the free energy in Quantum ESPRESSO is expressed as -T * S: diff --git a/aiida_common_workflows/workflows/relax/quantum_espresso/generator.py b/aiida_common_workflows/workflows/relax/quantum_espresso/generator.py index 2f615c39..b258f42d 100644 --- a/aiida_common_workflows/workflows/relax/quantum_espresso/generator.py +++ b/aiida_common_workflows/workflows/relax/quantum_espresso/generator.py @@ -2,9 +2,9 @@ """Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for Quantum ESPRESSO.""" from importlib import resources +import yaml from aiida import engine, orm, plugins from aiida_quantumespresso.workflows.protocols.utils import recursive_merge -import yaml from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -23,8 +23,9 @@ def create_magnetic_allotrope(structure, magnetization_per_site): :param magnetization_per_site: List of magnetizations (defined as magnetic moments) for each site in the provided `structure`. """ - # pylint: disable=too-many-locals,too-many-branches,too-many-statements + import string + if structure.is_alloy: raise ValueError('Alloys are currently not supported.') @@ -32,12 +33,13 @@ def create_magnetic_allotrope(structure, magnetization_per_site): allotrope_magnetic_moments = {} for element in structure.get_symbols_set(): - # Filter the sites and magnetic moments on the site element element_sites, element_magnetic_moments = zip( - *[(site, magnetic_moment) - for site, magnetic_moment in zip(structure.sites, magnetization_per_site) - if site.kind_name.rstrip(string.digits) == element] + *[ + (site, magnetic_moment) + for site, magnetic_moment in zip(structure.sites, magnetization_per_site) + if site.kind_name.rstrip(string.digits) == element + ] ) magnetic_moment_set = set(element_magnetic_moments) if len(magnetic_moment_set) > 10: @@ -82,6 +84,7 @@ def __init__(self, *args, **kwargs): def _load_local_protocols(): """Load the protocols defined in the ``aiida-common-workflows`` package.""" from .. import quantum_espresso + with resources.open_text(quantum_espresso, 'protocol.yml') as handle: protocol_dict = yaml.safe_load(handle) return protocol_dict @@ -101,12 +104,12 @@ def define(cls, spec): spec.inputs['electronic_type'].valid_type = ChoiceType((ElectronicType.METAL, ElectronicType.INSULATOR)) spec.inputs['engines']['relax']['code'].valid_type = CodeType('quantumespresso.pw') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals,protected-access + from aiida_quantumespresso.common import types from qe_tools import CONSTANTS @@ -156,20 +159,8 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: overrides = {} options_overrides = { - 'base': { - 'pw': { - 'metadata': { - 'options': engines['relax']['options'] - } - } - }, - 'base_final_scf': { - 'pw': { - 'metadata': { - 'options': engines['relax']['options'] - } - } - }, + 'base': {'pw': {'metadata': {'options': engines['relax']['options']}}}, + 'base_final_scf': {'pw': {'metadata': {'options': engines['relax']['options']}}}, } overrides = recursive_merge(overrides, options_overrides) diff --git a/aiida_common_workflows/workflows/relax/quantum_espresso/workchain.py b/aiida_common_workflows/workflows/relax/quantum_espresso/workchain.py index 302b14ba..22d571da 100644 --- a/aiida_common_workflows/workflows/relax/quantum_espresso/workchain.py +++ b/aiida_common_workflows/workflows/relax/quantum_espresso/workchain.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.workchain.CommonRelaxWorkChain` for Quantum ESPRESSO.""" +import pint from aiida import orm from aiida.engine import calcfunction from aiida.plugins import WorkflowFactory -import pint from ..workchain import CommonRelaxWorkChain from .generator import QuantumEspressoCommonRelaxInputGenerator @@ -55,9 +55,9 @@ def convert_outputs(self): forces, stress = extract_from_trajectory(outputs.output_trajectory).values() try: - total_energy, total_magnetization = result # pylint: disable=unbalanced-dict-unpacking + total_energy, total_magnetization = result except ValueError: - total_energy, total_magnetization = list(result)[0], None + total_energy, total_magnetization = next(iter(result)), None if 'output_structure' in outputs: self.out('relaxed_structure', outputs.output_structure) diff --git a/aiida_common_workflows/workflows/relax/siesta/__init__.py b/aiida_common_workflows/workflows/relax/siesta/__init__.py index 8475c406..82fce403 100644 --- a/aiida_common_workflows/workflows/relax/siesta/__init__.py +++ b/aiida_common_workflows/workflows/relax/siesta/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for Siesta.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/siesta/extractors.py b/aiida_common_workflows/workflows/relax/siesta/extractors.py index 37d2bfea..9373f219 100644 --- a/aiida_common_workflows/workflows/relax/siesta/extractors.py +++ b/aiida_common_workflows/workflows/relax/siesta/extractors.py @@ -26,6 +26,6 @@ def get_ts_energy(common_relax_workchain): e_ks = siesta_base_wc.outputs.output_parameters['E_KS'] free_e = siesta_base_wc.outputs.output_parameters['FreeE'] - ts = e_ks - free_e #pylint: disable=invalid-name + ts = e_ks - free_e return ts diff --git a/aiida_common_workflows/workflows/relax/siesta/generator.py b/aiida_common_workflows/workflows/relax/siesta/generator.py index c6fcf922..e3af78a8 100644 --- a/aiida_common_workflows/workflows/relax/siesta/generator.py +++ b/aiida_common_workflows/workflows/relax/siesta/generator.py @@ -2,9 +2,9 @@ """Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for SIESTA.""" import os +import yaml from aiida import engine, orm, plugins from aiida.common import exceptions -import yaml from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -31,8 +31,7 @@ def __init__(self, *args, **kwargs): def raise_invalid(message): raise RuntimeError(f'invalid protocol registry `{self.__class__.__name__}`: ' + message) - for k, v in self._protocols.items(): # pylint: disable=invalid-name - + for k, v in self._protocols.items(): if 'parameters' not in v: raise_invalid(f'protocol `{k}` does not define the mandatory key `parameters`') if 'mesh-cutoff' in v['parameters']: @@ -72,12 +71,12 @@ def define(cls, spec): spec.inputs['electronic_type'].valid_type = ChoiceType((ElectronicType.METAL, ElectronicType.INSULATOR)) spec.inputs['engines']['relax']['code'].valid_type = CodeType('siesta.siesta') - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] @@ -91,6 +90,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # Checks if protocol not in self.get_protocol_names(): import warnings + warnings.warn(f'no protocol implemented with name {protocol}, using default moderate') protocol = self.get_default_protocol_name() if 'relax' not in engines: @@ -110,7 +110,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # Parameters, including scf ... parameters = self._get_param(protocol, structure, reference_workchain) - #... relax options ... + # ... relax options ... if relax_type != RelaxType.NONE: parameters['md-type-of-run'] = 'cg' parameters['md-num-cg-steps'] = 100 @@ -123,12 +123,13 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: parameters['md-max-force-tol'] = str(threshold_forces) + ' eV/Ang' if threshold_stress: parameters['md-max-stress-tol'] = str(threshold_stress) + ' eV/Ang**3' - #... spin options (including initial magentization) ... + # ... spin options (including initial magentization) ... if spin_type == SpinType.COLLINEAR: parameters['spin'] = 'polarized' if magnetization_per_site is not None: if spin_type == SpinType.NONE: import warnings + warnings.warn('`magnetization_per_site` will be ignored as `spin_type` is set to SpinType.NONE') if spin_type == SpinType.COLLINEAR: in_spin_card = '\n' @@ -155,7 +156,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: return builder - def _get_param(self, key, structure, reference_workchain): # pylint: disable=too-many-branches,too-many-locals + def _get_param(self, key, structure, reference_workchain): # noqa: PLR0912 """ Method to construct the `parameters` input. Heuristics are applied, a dictionary with the parameters is returned. @@ -166,7 +167,7 @@ def _get_param(self, key, structure, reference_workchain): # pylint: disable=to parameters['%' + par] = value parameters.pop(par, None) - if 'atomic_heuristics' in self._protocols[key]: # pylint: disable=too-many-nested-blocks + if 'atomic_heuristics' in self._protocols[key]: atomic_heuristics = self._protocols[key]['atomic_heuristics'] if 'mesh-cutoff' in parameters: @@ -203,16 +204,18 @@ def _get_param(self, key, structure, reference_workchain): # pylint: disable=to f'Wrong `mesh-cutoff` units for heuristc {kind.symbol} of protocol {key}' ) from exc if 'grid-sampling' in cust_param: - parameters['%block GridCellSampling' - ] = cust_param['grid-sampling'] + '\n%endblock GridCellSampling' + parameters['%block GridCellSampling'] = ( + cust_param['grid-sampling'] + '\n%endblock GridCellSampling' + ) if meshcut_glob is not None: parameters['mesh-cutoff'] = f'{meshcut_glob} {meshcut_units}' - #We fix the `mesh-sizes` to the one of reference_workchain, we need to access - #the underline SiestaBaseWorkChain. + # We fix the `mesh-sizes` to the one of reference_workchain, we need to access + # the underline SiestaBaseWorkChain. if reference_workchain is not None: from aiida.orm import WorkChainNode + siesta_base_outs = reference_workchain.base.links.get_outgoing(node_class=WorkChainNode).one().node.outputs mesh = siesta_base_outs.output_parameters.base.attributes.get('mesh') parameters['mesh-sizes'] = f'[{mesh[0]} {mesh[1]} {mesh[2]}]' @@ -220,14 +223,14 @@ def _get_param(self, key, structure, reference_workchain): # pylint: disable=to return parameters - def _get_basis(self, key, structure): #pylint: disable=too-many-branches + def _get_basis(self, key, structure): # noqa: PLR0912 """ Method to construct the `basis` input. Heuristics are applied, a dictionary with the basis is returned. """ basis = self._protocols[key]['basis'].copy() - if 'atomic_heuristics' in self._protocols[key]: # pylint: disable=too-many-nested-blocks + if 'atomic_heuristics' in self._protocols[key]: atomic_heuristics = self._protocols[key]['atomic_heuristics'] pol_dict = {} @@ -277,6 +280,7 @@ def _get_basis(self, key, structure): #pylint: disable=too-many-branches def _get_kpoints(self, key, structure, reference_workchain): from aiida.orm import KpointsData + if reference_workchain: kpoints_mesh = KpointsData() kpoints_mesh.set_cell_from_structure(structure) @@ -300,4 +304,5 @@ def _get_kpoints(self, key, structure, reference_workchain): def _get_pseudo_fam(self, key): from aiida.orm import Str + return Str(self._protocols[key]['pseudo_family']) diff --git a/aiida_common_workflows/workflows/relax/vasp/__init__.py b/aiida_common_workflows/workflows/relax/vasp/__init__.py index f503e9aa..f4361271 100644 --- a/aiida_common_workflows/workflows/relax/vasp/__init__.py +++ b/aiida_common_workflows/workflows/relax/vasp/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable,cyclic-import + """Module with the implementations of the common structure relaxation workchain for VASP.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/vasp/generator.py b/aiida_common_workflows/workflows/relax/vasp/generator.py index e52d3e03..6242cdb7 100644 --- a/aiida_common_workflows/workflows/relax/vasp/generator.py +++ b/aiida_common_workflows/workflows/relax/vasp/generator.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- """Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for VASP.""" import pathlib +import typing as t +import yaml from aiida import engine, plugins from aiida.common.extendeddicts import AttributeDict -import yaml from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -20,19 +21,11 @@ class VaspCommonRelaxInputGenerator(CommonRelaxInputGenerator): """Input generator for the `VaspCommonRelaxWorkChain`.""" _default_protocol = 'moderate' - _protocols = { - 'fast': { - 'description': 'Fast and not so accurate.' - }, - 'moderate': { - 'description': 'Possibly a good compromise for quick checks.' - }, - 'precise': { - 'description': 'Decent level of accuracy with some exceptions.' - }, - 'verification-PBE-v1': { - 'description': 'Used for the ACWF study on unaries and oxides.' - } + _protocols: t.ClassVar = { + 'fast': {'description': 'Fast and not so accurate.'}, + 'moderate': {'description': 'Possibly a good compromise for quick checks.'}, + 'precise': {'description': 'Decent level of accuracy with some exceptions.'}, + 'verification-PBE-v1': {'description': 'Used for the ACWF study on unaries and oxides.'}, } def __init__(self, *args, **kwargs): @@ -64,12 +57,12 @@ def define(cls, spec): spec.inputs['engines']['relax']['code'].valid_type = CodeType('vasp.vasp') spec.inputs['protocol'].valid_type = ChoiceType(('fast', 'moderate', 'precise', 'verification-PBE-v1')) - def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: + def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR0912,PLR0915 """Construct a process builder based on the provided keyword arguments. The keyword arguments will have been validated against the input generator specification. """ - # pylint: disable=too-many-branches,too-many-statements,too-many-locals + structure = kwargs['structure'] engines = kwargs['engines'] protocol = kwargs['protocol'] @@ -120,68 +113,62 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # Set settings # Make sure the VASP parser is configured for the problem settings = AttributeDict() - settings.update({ - 'parser_settings': { - 'critical_notifications': { - 'add_brmix': True, - 'add_cnormn': False, - 'add_denmp': True, - 'add_dentet': True, - 'add_edddav_zhegv': True, - 'add_eddrmm_zhegv': True, - 'add_edwav': True, - 'add_fexcp': True, - 'add_fock_acc': True, - 'add_non_collinear': True, - 'add_not_hermitian': True, - 'add_pzstein': True, - 'add_real_optlay': True, - 'add_rhosyg': True, - 'add_rspher': True, - 'add_set_indpw_full': True, - 'add_sgrcon': True, - 'add_no_potimm': True, - 'add_magmom': True, - 'add_bandocc': True - }, - 'add_energies': True, - 'add_forces': True, - 'add_stress': True, - 'add_misc': { - 'type': - 'dict', - 'quantities': [ - 'total_energies', 'maximum_stress', 'maximum_force', 'magnetization', 'notifications', - 'run_status', 'run_stats', 'version' - ], - 'link_name': - 'misc' - }, - 'energy_type': ['energy_free', 'energy_no_entropy'] + settings.update( + { + 'parser_settings': { + 'critical_notifications': { + 'add_brmix': True, + 'add_cnormn': False, + 'add_denmp': True, + 'add_dentet': True, + 'add_edddav_zhegv': True, + 'add_eddrmm_zhegv': True, + 'add_edwav': True, + 'add_fexcp': True, + 'add_fock_acc': True, + 'add_non_collinear': True, + 'add_not_hermitian': True, + 'add_pzstein': True, + 'add_real_optlay': True, + 'add_rhosyg': True, + 'add_rspher': True, + 'add_set_indpw_full': True, + 'add_sgrcon': True, + 'add_no_potimm': True, + 'add_magmom': True, + 'add_bandocc': True, + }, + 'add_energies': True, + 'add_forces': True, + 'add_stress': True, + 'add_misc': { + 'type': 'dict', + 'quantities': [ + 'total_energies', + 'maximum_stress', + 'maximum_force', + 'magnetization', + 'notifications', + 'run_status', + 'run_stats', + 'version', + ], + 'link_name': 'misc', + }, + 'energy_type': ['energy_free', 'energy_no_entropy'], + } } - }) + ) builder.settings = plugins.DataFactory('core.dict')(dict=settings) # Configure the handlers handler_overrides = { - 'handler_unfinished_calc_ionic_alt': { - 'enabled': True - }, - 'handler_unfinished_calc_generic_alt': { - 'enabled': True - }, - 'handler_electronic_conv_alt': { - 'enabled': True - }, - 'handler_unfinished_calc_ionic': { - 'enabled': False - }, - 'handler_unfinished_calc_generic': { - 'enabled': False - }, - 'handler_electronic_conv': { - 'enabled': False - } + 'handler_unfinished_calc_ionic_alt': {'enabled': True}, + 'handler_unfinished_calc_generic_alt': {'enabled': True}, + 'handler_electronic_conv_alt': {'enabled': True}, + 'handler_unfinished_calc_ionic': {'enabled': False}, + 'handler_unfinished_calc_generic': {'enabled': False}, + 'handler_electronic_conv': {'enabled': False}, } builder.handler_overrides = plugins.DataFactory('core.dict')(dict=handler_overrides) diff --git a/aiida_common_workflows/workflows/relax/wien2k/__init__.py b/aiida_common_workflows/workflows/relax/wien2k/__init__.py index 848e8bd6..d407abe7 100644 --- a/aiida_common_workflows/workflows/relax/wien2k/__init__.py +++ b/aiida_common_workflows/workflows/relax/wien2k/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=undefined-variable + """Module with the implementations of the common structure relaxation workchain for Wien2k.""" from .generator import * from .workchain import * diff --git a/aiida_common_workflows/workflows/relax/wien2k/generator.py b/aiida_common_workflows/workflows/relax/wien2k/generator.py index cd4109e2..5823686e 100644 --- a/aiida_common_workflows/workflows/relax/wien2k/generator.py +++ b/aiida_common_workflows/workflows/relax/wien2k/generator.py @@ -2,8 +2,8 @@ """Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for Wien2k.""" import os -from aiida import engine, orm, plugins import yaml +from aiida import engine, orm, plugins from aiida_common_workflows.common import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators import ChoiceType, CodeType @@ -60,6 +60,7 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # Checks if protocol not in self.get_protocol_names(): import warnings + warnings.warn(f'no protocol implemented with name {protocol}, using default moderate') protocol = self.get_default_protocol_name() if not all(x in engines.keys() for x in ['relax']): @@ -94,11 +95,13 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # derive k mesh from the ref. workchain and pass as input if 'kmesh3' in ref_wrkchn_res_dict and ref_wrkchn_res_dict['kmesh3']: # check if kmesh3 is in results dict inpdict['-numk'] = '0' + ' ' + ref_wrkchn_res_dict['kmesh3'] - if 'kmesh3k' in ref_wrkchn_res_dict and ref_wrkchn_res_dict['kmesh3k' - ]: # check if kmesh3k is in results dict + if ( + 'kmesh3k' in ref_wrkchn_res_dict and ref_wrkchn_res_dict['kmesh3k'] + ): # check if kmesh3k is in results dict inpdict['-numk2'] = '0' + ' ' + ref_wrkchn_res_dict['kmesh3k'] - if 'fftmesh3k' in ref_wrkchn_res_dict and ref_wrkchn_res_dict['fftmesh3k' - ]: # check if fftmesh3k is in results dict + if ( + 'fftmesh3k' in ref_wrkchn_res_dict and ref_wrkchn_res_dict['fftmesh3k'] + ): # check if fftmesh3k is in results dict inpdict['-fft'] = ref_wrkchn_res_dict['fftmesh3k'] # res = NodeNumberJobResource(num_machines=8, num_mpiprocs_per_machine=1, num_cores_per_mpiproc=1) diff --git a/aiida_common_workflows/workflows/relax/workchain.py b/aiida_common_workflows/workflows/relax/workchain.py index 04017a3e..204c78e8 100644 --- a/aiida_common_workflows/workflows/relax/workchain.py +++ b/aiida_common_workflows/workflows/relax/workchain.py @@ -27,7 +27,7 @@ def get_input_generator(cls) -> CommonRelaxInputGenerator: :return: input generator """ - return cls._generator_class(process_class=cls) # pylint: disable=not-callable + return cls._generator_class(process_class=cls) @classmethod def define(cls, spec): diff --git a/docs/source/conf.py b/docs/source/conf.py index fdf15606..6c95d861 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=missing-module-docstring,redefined-builtin,invalid-name + # Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full diff --git a/pyproject.toml b/pyproject.toml index 0c80d41f..b9ac0de6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,6 @@ docs = [ ] pre-commit = [ 'pre-commit~=2.2', - 'pylint~=2.16.0', ] tests = [ 'pytest~=7.2', @@ -105,34 +104,30 @@ exclude = [ line-length = 120 fail-on-change = true -[tool.isort] -force_sort_within_sections = true -include_trailing_comma = true -line_length = 120 -multi_line_output = 3 - -[tool.pydocstyle] +[tool.ruff] ignore = [ - 'D104', - 'D202', - 'D203', - 'D213' + 'PLR2004', # Magic value used in comparison + 'PLE0604', # Invalid object in `__all__`, must contain only strings + 'F403', # Star imports unable to detect undefined names + 'F405', # Import may be undefined or defined from star imports ] - -[tool.pylint.format] -max-line-length = 120 - -[tool.pylint.messages_control] -disable = [ - 'import-outside-toplevel', - 'inconsistent-return-statements', - 'too-many-arguments', - 'duplicate-code', - 'no-member', - 'too-few-public-methods', - 'wrong-import-order' +line-length = 120 +select = [ + 'E', # pydocstyle + 'W', # pydocstyle + 'F', # pyflakes + 'I', # isort + 'N', # pep8-naming + 'PLC', + 'PLE', + 'PLR', + 'PLW', + 'RUF' # ruff ] +[tool.ruff.format] +quote-style = 'single' + [tool.pytest.ini_options] testpaths = [ 'tests', @@ -151,12 +146,3 @@ filterwarnings = [ 'ignore:Creating AiiDA configuration folder.*:UserWarning', 'ignore:Object of type .* not in session, .* operation along .* will not proceed:sqlalchemy.exc.SAWarning', ] - -[tool.yapf] -align_closing_bracket_with_visual_indent = true -based_on_style = 'google' -coalesce_brackets = true -column_limit = 120 -dedent_closing_brackets = true -indent_dictionary_value = false -split_arguments_when_comma_terminated = true diff --git a/tests/cli/test_launch.py b/tests/cli/test_launch.py index fea7e9db..e211bf58 100644 --- a/tests/cli/test_launch.py +++ b/tests/cli/test_launch.py @@ -27,8 +27,10 @@ def test_relax_wallclock_seconds(run_cli_command, generate_structure, generate_c # Passing two values for `-w` should raise as only one value is required options = ['-S', str(structure.pk), '-w', '100', '100', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_relax, options, raises=click.BadParameter) - assert 'Error: Invalid value for --wallclock-seconds: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' \ - 'requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --wallclock-seconds: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' + 'requires 1 values' in result.output_lines + ) def test_relax_number_machines(run_cli_command, generate_structure, generate_code): @@ -39,8 +41,10 @@ def test_relax_number_machines(run_cli_command, generate_structure, generate_cod # Passing two values for `-m` should raise as only one value is required options = ['-S', str(structure.pk), '-m', '100', '100', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_relax, options, raises=click.BadParameter) - assert 'Error: Invalid value for --number-machines: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' \ - 'requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --number-machines: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' + 'requires 1 values' in result.output_lines + ) def test_relax_number_mpi_procs_per_machine(run_cli_command, generate_structure, generate_code): @@ -53,8 +57,10 @@ def test_relax_number_mpi_procs_per_machine(run_cli_command, generate_structure, # Passing two values for `-n` should raise as only one value is required options = ['-S', str(structure.pk), '-n', '10', '10', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_relax, options, raises=click.BadParameter) - assert 'Error: Invalid value for --number-mpi-procs-per-machine: QuantumEspressoCommonRelaxWorkChain has 1 engine '\ - 'steps, so requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --number-mpi-procs-per-machine: QuantumEspressoCommonRelaxWorkChain has 1 engine ' + 'steps, so requires 1 values' in result.output_lines + ) @pytest.mark.usefixtures('with_clean_database') @@ -103,8 +109,10 @@ def test_eos_wallclock_seconds(run_cli_command, generate_structure, generate_cod # Passing two values for `-w` should raise as only one value is required options = ['-S', str(structure.pk), '-w', '100', '100', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_eos, options, raises=click.BadParameter) - assert 'Error: Invalid value for --wallclock-seconds: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' \ - 'requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --wallclock-seconds: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' + 'requires 1 values' in result.output_lines + ) def test_eos_number_machines(run_cli_command, generate_structure, generate_code): @@ -115,8 +123,10 @@ def test_eos_number_machines(run_cli_command, generate_structure, generate_code) # Passing two values for `-m` should raise as only one value is required options = ['-S', str(structure.pk), '-m', '100', '100', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_eos, options, raises=click.BadParameter) - assert 'Error: Invalid value for --number-machines: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' \ - 'requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --number-machines: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' + 'requires 1 values' in result.output_lines + ) def test_eos_number_mpi_procs_per_machine(run_cli_command, generate_structure, generate_code): @@ -129,8 +139,10 @@ def test_eos_number_mpi_procs_per_machine(run_cli_command, generate_structure, g # Passing two values for `-n` should raise as only one value is required options = ['-S', str(structure.pk), '-n', '10', '10', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_eos, options, raises=click.BadParameter) - assert 'Error: Invalid value for --number-mpi-procs-per-machine: QuantumEspressoCommonRelaxWorkChain has 1 engine '\ - 'steps, so requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --number-mpi-procs-per-machine: QuantumEspressoCommonRelaxWorkChain has 1 engine ' + 'steps, so requires 1 values' in result.output_lines + ) def test_eos_relax_types(run_cli_command, generate_structure, generate_code): @@ -152,8 +164,10 @@ def test_dissociation_curve_wallclock_seconds(run_cli_command, generate_structur # Passing two values for `-w` should raise as only one value is required options = ['-S', str(structure.pk), '-w', '100', '100', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_dissociation_curve, options, raises=click.BadParameter) - assert 'Error: Invalid value for --wallclock-seconds: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' \ - 'requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --wallclock-seconds: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' + 'requires 1 values' in result.output_lines + ) @pytest.mark.usefixtures('aiida_profile') @@ -175,8 +189,10 @@ def test_dissociation_curve_number_machines(run_cli_command, generate_structure, # Passing two values for `-m` should raise as only one value is required options = ['-S', str(structure.pk), '-m', '100', '100', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_dissociation_curve, options, raises=click.BadParameter) - assert 'Error: Invalid value for --number-machines: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' \ - 'requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --number-machines: QuantumEspressoCommonRelaxWorkChain has 1 engine steps, so ' + 'requires 1 values' in result.output_lines + ) def test_dissociation_curve_number_mpi_procs_per_machine(run_cli_command, generate_structure, generate_code): @@ -189,8 +205,10 @@ def test_dissociation_curve_number_mpi_procs_per_machine(run_cli_command, genera # Passing two values for `-n` should raise as only one value is required options = ['-S', str(structure.pk), '-n', '10', '10', '--', 'quantum_espresso'] result = run_cli_command(launch.cmd_dissociation_curve, options, raises=click.BadParameter) - assert 'Error: Invalid value for --number-mpi-procs-per-machine: QuantumEspressoCommonRelaxWorkChain has 1 engine '\ - 'steps, so requires 1 values' in result.output_lines + assert ( + 'Error: Invalid value for --number-mpi-procs-per-machine: QuantumEspressoCommonRelaxWorkChain has 1 engine ' + 'steps, so requires 1 values' in result.output_lines + ) def test_relax_magn_per_type(run_cli_command, generate_structure, generate_code): diff --git a/tests/cli/test_options.py b/tests/cli/test_options.py index 63ba696f..5ff70f8b 100644 --- a/tests/cli/test_options.py +++ b/tests/cli/test_options.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -# pylint: disable=redefined-outer-name + """Tests for the :mod:`aiida_common_workflows.cli.launch` module.""" import json import pathlib -from aiida import orm import click import pytest +from aiida import orm from aiida_common_workflows.cli import options @@ -69,14 +69,15 @@ def test_parse_from_file_duplicate(self, structure_param_type, filepath_cif): assert result.uuid == structure.uuid @pytest.mark.parametrize( - 'label, formula', ( + 'label, formula', + ( ('Al', 'Al4'), ('Fe', 'Fe2'), ('GeTe', 'GeTe'), ('Si', 'Si2'), ('NH3-pyramidal', 'H3N'), ('NH3-planar', 'H3N'), - ) + ), ) def test_parse_predefined_defaults(self, structure_param_type, label, formula): """Test the shortcut labels. diff --git a/tests/cli/test_plot.py b/tests/cli/test_plot.py index 91f3a76a..e2860a32 100644 --- a/tests/cli/test_plot.py +++ b/tests/cli/test_plot.py @@ -96,7 +96,7 @@ def test_plot_eos_missing_outputs(run_cli_command, generate_eos_node): options = [str(node.pk)] result = run_cli_command(plot.cmd_plot_eos, options, raises=SystemExit) - assert 'is missing required outputs: (\'total_energies\',)' in result.output + assert "is missing required outputs: ('total_energies',)" in result.output def test_plot_dissociation_curve(run_cli_command, generate_dissociation_curve_node, monkeypatch): @@ -178,4 +178,4 @@ def test_plot_dissociation_curve_missing_outputs(run_cli_command, generate_disso options = [str(node.pk)] result = run_cli_command(plot.cmd_plot_dissociation_curve, options, raises=SystemExit) - assert 'is missing required outputs: (\'total_energies\',)' in result.output + assert "is missing required outputs: ('total_energies',)" in result.output diff --git a/tests/conftest.py b/tests/conftest.py index 2de56684..f7667183 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,18 +1,19 @@ # -*- coding: utf-8 -*- -# pylint: disable=redefined-outer-name + """Configuration and fixtures for unit test suite.""" import io import os import pathlib import tempfile +import typing as t +import click +import pytest from aiida import engine from aiida.common import exceptions from aiida.common.constants import elements -import click -import pytest -pytest_plugins = ['aiida.manage.tests.pytest_fixtures'] # pylint: disable=invalid-name +pytest_plugins = ['aiida.manage.tests.pytest_fixtures'] @pytest.fixture(scope='session', autouse=True) @@ -36,7 +37,7 @@ def run_cli_command(): """ from click.testing import Result - def _run_cli_command(command: click.Command, options: list = None, raises: bool = False) -> Result: + def _run_cli_command(command: click.Command, options: t.Optional[list] = None, raises: bool = False) -> Result: """Run the command and check the result. .. note:: the `output_lines` attribute is added to return value containing list of stripped output lines. @@ -79,7 +80,7 @@ def _generate_input_generator_cls(inputs_dict=None): class TestInputGenerator(InputGenerator): """Test subclass of ``InputGenerator``.""" - _protocols = {'moderate': {'description': 'bla'}} + _protocols: t.ClassVar = {'moderate': {'description': 'bla'}} _default_protocol = 'moderate' @classmethod @@ -116,7 +117,7 @@ def _generate_structure(symbols=None): if symbol not in valid_symbols: raise ValueError(f'symbol `{symbol}` is not a valid element.') - structure.append_atom(position=(0. + index * 1, 0. + index * 1, 0. + index * 1), symbols=[symbol]) + structure.append_atom(position=(0.0 + index * 1, 0.0 + index * 1, 0.0 + index * 1), symbols=[symbol]) return structure @@ -238,6 +239,7 @@ def generate_upf_data(): def _generate_upf_data(element): """Return `UpfData` node.""" from aiida_pseudo.data.pseudo import UpfData + content = f'\n' stream = io.BytesIO(content.encode('utf-8')) return UpfData(stream, filename=f'{element}.upf') @@ -311,7 +313,7 @@ def sssp(generate_upf_data): """Create an SSSP pseudo potential family from scratch.""" from aiida.plugins import GroupFactory - SsspFamily = GroupFactory('pseudo.family.sssp') # pylint: disable=invalid-name + SsspFamily = GroupFactory('pseudo.family.sssp') # noqa: N806 label = 'SSSP/1.3/PBEsol/efficiency' try: @@ -325,7 +327,6 @@ def sssp(generate_upf_data): with tempfile.TemporaryDirectory() as dirpath: for values in elements.values(): - element = values['symbol'] upf = generate_upf_data(element) filename = os.path.join(dirpath, f'{element}.upf') @@ -335,7 +336,7 @@ def sssp(generate_upf_data): handle.write(source.read()) handle.flush() - cutoffs_dict['normal'][element] = {'cutoff_wfc': 30., 'cutoff_rho': 240.} + cutoffs_dict['normal'][element] = {'cutoff_wfc': 30.0, 'cutoff_rho': 240.0} family = SsspFamily.create_from_folder(pathlib.Path(dirpath), label) @@ -350,7 +351,7 @@ def pseudo_dojo_jthxml_family(generate_jthxml_data): """Create a PseudoDojo JTH-XML pseudo potential family from scratch.""" from aiida import plugins - PseudoDojoFamily = plugins.GroupFactory('pseudo.family.pseudo_dojo') # pylint: disable=invalid-name + PseudoDojoFamily = plugins.GroupFactory('pseudo.family.pseudo_dojo') # noqa: N806 label = 'PseudoDojo/1.0/PBE/SR/standard/jthxml' try: @@ -364,7 +365,6 @@ def pseudo_dojo_jthxml_family(generate_jthxml_data): with tempfile.TemporaryDirectory() as dirpath: for values in elements.values(): - element = values['symbol'] upf = generate_jthxml_data(element) filename = os.path.join(dirpath, f'{element}.jthxml') @@ -374,7 +374,7 @@ def pseudo_dojo_jthxml_family(generate_jthxml_data): handle.write(source.read()) handle.flush() - cutoffs_dict['normal'][element] = {'cutoff_wfc': 30., 'cutoff_rho': 240.} + cutoffs_dict['normal'][element] = {'cutoff_wfc': 30.0, 'cutoff_rho': 240.0} family = PseudoDojoFamily.create_from_folder( pathlib.Path(dirpath), label, pseudo_type=plugins.DataFactory('pseudo.jthxml') @@ -387,11 +387,11 @@ def pseudo_dojo_jthxml_family(generate_jthxml_data): @pytest.fixture(scope='session') -def pseudo_dojo_psp8_family(generate_psp8_data): # pylint: disable=too-many-locals +def pseudo_dojo_psp8_family(generate_psp8_data): """Create a PseudoDojo PSP8 pseudo potential family from scratch.""" from aiida import plugins - PseudoDojoFamily = plugins.GroupFactory('pseudo.family.pseudo_dojo') # pylint: disable=invalid-name + PseudoDojoFamily = plugins.GroupFactory('pseudo.family.pseudo_dojo') # noqa: N806 label = 'PseudoDojo/0.41/PBE/SR/standard/psp8' try: @@ -404,8 +404,7 @@ def pseudo_dojo_psp8_family(generate_psp8_data): # pylint: disable=too-many-loc cutoffs_dict = {'normal': {}} with tempfile.TemporaryDirectory() as dirpath: - for (element_number, element_info) in elements.items(): - + for element_number, element_info in elements.items(): element = element_info['symbol'] upf = generate_psp8_data(element, float(element_number)) filename = os.path.join(dirpath, f'{element}.psp8') @@ -415,7 +414,7 @@ def pseudo_dojo_psp8_family(generate_psp8_data): # pylint: disable=too-many-loc handle.write(source.read()) handle.flush() - cutoffs_dict['normal'][element] = {'cutoff_wfc': 30., 'cutoff_rho': 240.} + cutoffs_dict['normal'][element] = {'cutoff_wfc': 30.0, 'cutoff_rho': 240.0} family = PseudoDojoFamily.create_from_folder( pathlib.Path(dirpath), label, pseudo_type=plugins.DataFactory('pseudo.psp8') @@ -432,8 +431,8 @@ def psml_family(generate_psml_data): """Create a pseudopotential family with PsmlData potentials from scratch.""" from aiida import plugins - PsmlData = plugins.DataFactory('pseudo.psml') # pylint: disable=invalid-name - PseudoPotentialFamily = plugins.GroupFactory('pseudo.family') # pylint: disable=invalid-name + PsmlData = plugins.DataFactory('pseudo.psml') # noqa: N806 + PseudoPotentialFamily = plugins.GroupFactory('pseudo.family') # noqa: N806 label = 'PseudoDojo/0.4/PBE/FR/standard/psml' try: @@ -445,7 +444,6 @@ def psml_family(generate_psml_data): with tempfile.TemporaryDirectory() as dirpath: for values in elements.values(): - element = values['symbol'] upf = generate_psml_data(element) filename = os.path.join(dirpath, f'{element}.psml') diff --git a/tests/generators/test_generator.py b/tests/generators/test_generator.py index 7f211417..2e21db48 100644 --- a/tests/generators/test_generator.py +++ b/tests/generators/test_generator.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.generators.generator` module.""" +import pytest from aiida import orm from aiida.plugins import WorkflowFactory -import pytest from aiida_common_workflows.generators import InputGenerator @@ -92,8 +92,7 @@ def construct_builder(self, **kwargs): def test_get_builder_immutable_kwargs_nested(generate_input_generator_cls, generate_structure): - """Test that calling ``get_builder`` does not mutate the ``kwargs`` when they are nodes, even if nested. - """ + """Test that calling ``get_builder`` does not mutate the ``kwargs`` when they are nodes, even if nested.""" cls = generate_input_generator_cls(inputs_dict={'space.structure': orm.StructureData}) generator = cls(process_class=WorkflowFactory('common_workflows.relax.siesta')) diff --git a/tests/protocol/test_registry.py b/tests/protocol/test_registry.py index 1649cd2e..bf793598 100644 --- a/tests/protocol/test_registry.py +++ b/tests/protocol/test_registry.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- -# pylint: disable=function-redefined,redefined-outer-name """Tests for the :mod:`aiida_common_workflows.protocol.registry` module.""" +import typing as t + import pytest from aiida_common_workflows.protocol import ProtocolRegistry @@ -13,7 +14,10 @@ def protocol_registry() -> ProtocolRegistry: class SubProtocolRegistry(ProtocolRegistry): """Valid protocol registry implementation.""" - _protocols = {'efficiency': {'description': 'description'}, 'precision': {'description': 'description'}} + _protocols: t.ClassVar = { + 'efficiency': {'description': 'description'}, + 'precision': {'description': 'description'}, + } _default_protocol = 'efficiency' return SubProtocolRegistry() @@ -34,7 +38,7 @@ class SubProtocolRegistry(ProtocolRegistry): class SubProtocolRegistry(ProtocolRegistry): """Invalid protocol registry implementation.""" - _protocols = {'efficiency': {}, 'precision': 'wrong_type'} + _protocols: t.ClassVar = {'efficiency': {}, 'precision': 'wrong_type'} _default_protocol = None with pytest.raises(RuntimeError): @@ -43,7 +47,7 @@ class SubProtocolRegistry(ProtocolRegistry): class SubProtocolRegistry(ProtocolRegistry): """Invalid protocol registry implementation.""" - _protocols = {'efficiency': {'description': 'description'}, 'precision': {}} + _protocols: t.ClassVar = {'efficiency': {'description': 'description'}, 'precision': {}} _default_protocol = None with pytest.raises(RuntimeError): @@ -52,7 +56,10 @@ class SubProtocolRegistry(ProtocolRegistry): class SubProtocolRegistry(ProtocolRegistry): """Invalid protocol registry implementation.""" - _protocols = {'efficiency': {'description': 'description'}, 'precision': {'description': 'description'}} + _protocols: t.ClassVar = { + 'efficiency': {'description': 'description'}, + 'precision': {'description': 'description'}, + } _default_protocol = None with pytest.raises(RuntimeError): @@ -61,7 +68,10 @@ class SubProtocolRegistry(ProtocolRegistry): class SubProtocolRegistry(ProtocolRegistry): """Invalid protocol registry implementation.""" - _protocols = {'efficiency': {'description': 'description'}, 'precision': {'description': 'description'}} + _protocols: t.ClassVar = { + 'efficiency': {'description': 'description'}, + 'precision': {'description': 'description'}, + } _default_protocol = 'non-existant' with pytest.raises(RuntimeError): diff --git a/tests/workflows/bands/test_implementations.py b/tests/workflows/bands/test_implementations.py index bd8f42cc..c45e07fc 100644 --- a/tests/workflows/bands/test_implementations.py +++ b/tests/workflows/bands/test_implementations.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.quantum_espresso` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, orm, plugins + import pytest +from aiida import engine, orm, plugins from aiida_common_workflows.generators.ports import InputGeneratorPort from aiida_common_workflows.plugins import get_workflow_entry_point_names @@ -21,12 +21,8 @@ def test_spec(workchain): generator_spec = generator.spec() required_ports = { - 'bands_kpoints': { - 'valid_type': plugins.DataFactory('core.array.kpoints') - }, - 'parent_folder': { - 'valid_type': orm.RemoteData - }, + 'bands_kpoints': {'valid_type': plugins.DataFactory('core.array.kpoints')}, + 'parent_folder': {'valid_type': orm.RemoteData}, 'engines': {}, } diff --git a/tests/workflows/bands/test_workchain.py b/tests/workflows/bands/test_workchain.py index 1f37f35d..b4703b7d 100644 --- a/tests/workflows/bands/test_workchain.py +++ b/tests/workflows/bands/test_workchain.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# pylint: disable=abstract-method,arguments-differ,redefined-outer-name + """Tests for the :mod:`aiida_common_workflows.workflows.bands.workchain` module.""" -from aiida.plugins import WorkflowFactory import pytest +from aiida.plugins import WorkflowFactory from aiida_common_workflows.plugins import get_workflow_entry_point_names from aiida_common_workflows.workflows.bands import CommonBandsInputGenerator diff --git a/tests/workflows/dissociation_curve/test_workchain_diss_curve.py b/tests/workflows/dissociation_curve/test_workchain_diss_curve.py index b626ba5a..d11818da 100644 --- a/tests/workflows/dissociation_curve/test_workchain_diss_curve.py +++ b/tests/workflows/dissociation_curve/test_workchain_diss_curve.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -# pylint: disable=redefined-outer-name + """Tests for the :mod:`aiida_common_workflows.workflows.dissociation` module.""" import copy +import pytest from aiida import orm from aiida.engine import WorkChain from aiida.plugins import WorkflowFactory -import pytest from aiida_common_workflows.plugins import get_workflow_entry_point_names from aiida_common_workflows.workflows import dissociation @@ -35,9 +35,11 @@ def test_validate_sub_process_class(ctx): def test_validate_sub_process_class_plugins(ctx, common_relax_workchain): """Test the `validate_sub_process_class` validator.""" from aiida_common_workflows.plugins import get_entry_point_name_from_class - assert dissociation.validate_sub_process_class( - get_entry_point_name_from_class(common_relax_workchain).name, ctx - ) is None + + assert ( + dissociation.validate_sub_process_class(get_entry_point_name_from_class(common_relax_workchain).name, ctx) + is None + ) @pytest.mark.usefixtures('sssp') @@ -48,41 +50,38 @@ def test_validate_inputs_distance(ctx, generate_code, generate_structure): 'sub_process_class': 'common_workflows.relax.quantum_espresso', 'generator_inputs': { 'engines': { - 'relax': { - 'code': generate_code('quantumespresso.pw'), - 'options': { - 'resources': { - 'num_machines': 1 - } - } - } + 'relax': {'code': generate_code('quantumespresso.pw'), 'options': {'resources': {'num_machines': 1}}} }, - 'spin_type': 'collinear' - } + 'spin_type': 'collinear', + }, } value = copy.deepcopy(base_values) - assert dissociation.validate_inputs( - value, ctx - ) == 'neither `distances` nor the `distances_count`, `distance_min`, and `distance_max` set were defined.' + assert ( + dissociation.validate_inputs(value, ctx) + == 'neither `distances` nor the `distances_count`, `distance_min`, and `distance_max` set were defined.' + ) value = copy.deepcopy(base_values) value.update({'distances_count': 3, 'distance_min': 0.5}) - assert dissociation.validate_inputs( - value, ctx - ) == 'neither `distances` nor the `distances_count`, `distance_min`, and `distance_max` set were defined.' + assert ( + dissociation.validate_inputs(value, ctx) + == 'neither `distances` nor the `distances_count`, `distance_min`, and `distance_max` set were defined.' + ) value = copy.deepcopy(base_values) value.update({'distances_count': 3, 'distance_max': 1.5}) - assert dissociation.validate_inputs( - value, ctx - ) == 'neither `distances` nor the `distances_count`, `distance_min`, and `distance_max` set were defined.' + assert ( + dissociation.validate_inputs(value, ctx) + == 'neither `distances` nor the `distances_count`, `distance_min`, and `distance_max` set were defined.' + ) value = copy.deepcopy(base_values) value.update({'distance_max': 2, 'distance_min': 0.5}) - assert dissociation.validate_inputs( - value, ctx - ) == 'neither `distances` nor the `distances_count`, `distance_min`, and `distance_max` set were defined.' + assert ( + dissociation.validate_inputs(value, ctx) + == 'neither `distances` nor the `distances_count`, `distance_min`, and `distance_max` set were defined.' + ) value = copy.deepcopy(base_values) value.update({'distance_max': 2, 'distance_min': 0.5, 'distances_count': 3}) @@ -110,17 +109,10 @@ def test_validate_inputs_generator_inputs(ctx, generate_code, generate_structure 'sub_process_class': 'common_workflows.relax.quantum_espresso', 'generator_inputs': { 'engines': { - 'relax': { - 'code': generate_code('quantumespresso.pw'), - 'options': { - 'resources': { - 'num_machines': 1 - } - } - } + 'relax': {'code': generate_code('quantumespresso.pw'), 'options': {'resources': {'num_machines': 1}}} }, - 'spin_type': 'collinear' - } + 'spin_type': 'collinear', + }, } assert dissociation.validate_inputs(value, ctx) is None diff --git a/tests/workflows/eos/test_workchain_eos.py b/tests/workflows/eos/test_workchain_eos.py index d406fdc9..e654c0de 100644 --- a/tests/workflows/eos/test_workchain_eos.py +++ b/tests/workflows/eos/test_workchain_eos.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -# pylint: disable=redefined-outer-name + """Tests for the :mod:`aiida_common_workflows.workflows.eos` module.""" import copy +import pytest from aiida import orm from aiida.engine import WorkChain from aiida.plugins import WorkflowFactory -import pytest from aiida_common_workflows.plugins import get_workflow_entry_point_names from aiida_common_workflows.workflows import eos @@ -40,16 +40,12 @@ def _generate_eos_inputs(): 'engines': { 'relax': { 'code': generate_code('quantumespresso.pw').store(), - 'options': { - 'resources': { - 'num_machines': 1 - } - } + 'options': {'resources': {'num_machines': 1}}, } }, 'electronic_type': 'metal', - 'relax_type': 'positions' - } + 'relax_type': 'positions', + }, } return _generate_eos_inputs @@ -65,6 +61,7 @@ def test_validate_sub_process_class(ctx): def test_validate_sub_process_class_plugins(ctx, common_relax_workchain): """Test the `validate_sub_process_class` validator.""" from aiida_common_workflows.plugins import get_entry_point_name_from_class + assert eos.validate_sub_process_class(get_entry_point_name_from_class(common_relax_workchain).name, ctx) is None @@ -74,21 +71,24 @@ def test_validate_inputs_scale(ctx, generate_eos_inputs): base_values = generate_eos_inputs() value = copy.deepcopy(base_values) - assert eos.validate_inputs( - value, ctx - ) == 'neither `scale_factors` nor the pair of `scale_count` and `scale_increment` were defined.' + assert ( + eos.validate_inputs(value, ctx) + == 'neither `scale_factors` nor the pair of `scale_count` and `scale_increment` were defined.' + ) value = copy.deepcopy(base_values) value.update({'scale_count': 2}) - assert eos.validate_inputs( - value, ctx - ) == 'neither `scale_factors` nor the pair of `scale_count` and `scale_increment` were defined.' + assert ( + eos.validate_inputs(value, ctx) + == 'neither `scale_factors` nor the pair of `scale_count` and `scale_increment` were defined.' + ) value = copy.deepcopy(base_values) value.update({'scale_increment': 2}) - assert eos.validate_inputs( - value, ctx - ) == 'neither `scale_factors` nor the pair of `scale_count` and `scale_increment` were defined.' + assert ( + eos.validate_inputs(value, ctx) + == 'neither `scale_factors` nor the pair of `scale_count` and `scale_increment` were defined.' + ) value = copy.deepcopy(base_values) value.update({'scale_count': 2, 'scale_increment': 0.2}) @@ -137,21 +137,18 @@ def test_validate_scale_increment(ctx): def test_validate_relax_type(ctx): """Test the `validate_relax_type` validator.""" assert eos.validate_relax_type(RelaxType.NONE, ctx) is None - assert eos.validate_relax_type( - RelaxType.CELL, ctx - ) == '`generator_inputs.relax_type`. Equation of state and relaxation with variable volume not compatible.' + assert ( + eos.validate_relax_type(RelaxType.CELL, ctx) + == '`generator_inputs.relax_type`. Equation of state and relaxation with variable volume not compatible.' + ) @pytest.mark.parametrize( - 'scaling_inputs, expected', ( - ({ - 'scale_factors': [0.98, 1.0, 1.02] - }, (0.98, 1.0, 1.02)), - ({ - 'scale_count': 3, - 'scale_increment': 0.02 - }, (0.98, 1.0, 1.02)), - ) + 'scaling_inputs, expected', + ( + ({'scale_factors': [0.98, 1.0, 1.02]}, (0.98, 1.0, 1.02)), + ({'scale_count': 3, 'scale_increment': 0.02}, (0.98, 1.0, 1.02)), + ), ) @pytest.mark.usefixtures('sssp') def test_get_scale_factors(generate_workchain, generate_eos_inputs, scaling_inputs, expected): diff --git a/tests/workflows/relax/test_abinit.py b/tests/workflows/relax/test_abinit.py index 51e9cd98..0458d7ad 100644 --- a/tests/workflows/relax/test_abinit.py +++ b/tests/workflows/relax/test_abinit.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.abinit` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.abinit') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,12 +16,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('abinit').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } diff --git a/tests/workflows/relax/test_bigdft.py b/tests/workflows/relax/test_bigdft.py index 9f3720fa..504ca04f 100644 --- a/tests/workflows/relax/test_bigdft.py +++ b/tests/workflows/relax/test_bigdft.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.bigdft` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.bigdft') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,12 +16,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('bigdft').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } diff --git a/tests/workflows/relax/test_castep.py b/tests/workflows/relax/test_castep.py index f6ec4db1..6ff8a500 100644 --- a/tests/workflows/relax/test_castep.py +++ b/tests/workflows/relax/test_castep.py @@ -1,14 +1,14 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.castep` module.""" -# pylint: disable=abstract-method,arguments-differ,redefined-outer-name,unused-argument + import copy +import pytest from aiida import engine, plugins from aiida.orm import StructureData from aiida.plugins import WorkflowFactory from aiida_castep.data.otfg import OTFGGroup from ase.build.bulk import bulk -import pytest from aiida_common_workflows.workflows.relax.castep.generator import ( CastepCommonRelaxInputGenerator, @@ -28,14 +28,14 @@ @pytest.fixture -def nacl(with_database): # pylint: disable=invalid-name +def nacl(with_database): """Get an NaCl structure""" structure = StructureData(ase=bulk('NaCl', 'rocksalt', 4.2)) return structure @pytest.fixture -def si(with_database): # pylint: disable=invalid-name +def si(with_database): """Get an NaCl structure""" structure = StructureData(ase=bulk('Si', 'diamond', 5.43)) return structure @@ -61,15 +61,7 @@ def default_builder_inputs(generate_code, generate_structure, castep_code): return { 'structure': generate_structure(symbols=('Si',)), 'engines': { - 'relax': { - 'code': castep_code, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } - } + 'relax': {'code': castep_code, 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}} }, } @@ -124,12 +116,7 @@ def test_calc_generator(nacl, castep_code, with_otfg): """Test the functionality of the calculation generator""" protcol = { 'kpoints_spacing': 0.05, - 'calc': { - 'parameters': { - 'task': 'geometryoptimisation', - 'basis_precision': 'medium' - } - } + 'calc': {'parameters': {'task': 'geometryoptimisation', 'basis_precision': 'medium'}}, } override = {'calc': {'parameters': {'cut_off_energy': 220}}} otfg = OTFGGroup.collection.get(label='C19') @@ -146,12 +133,7 @@ def test_base_generator(castep_code, nacl, with_otfg): protcol = { 'kpoints_spacing': 0.05, 'max_iterations': 5, - 'calc': { - 'parameters': { - 'task': 'geometryoptimisation', - 'basis_precision': 'medium' - } - } + 'calc': {'parameters': {'task': 'geometryoptimisation', 'basis_precision': 'medium'}}, } override = {'calc': {'parameters': {'cut_off_energy': 220}, 'metadata': {'label': 'test'}}} otfg = OTFGGroup.collection.get(label='C19') @@ -167,22 +149,14 @@ def test_base_generator(castep_code, nacl, with_otfg): def test_relax_generator(castep_code, nacl, with_otfg): """Test for generating the relax namespace""" - CastepCommonRelaxWorkChain = WorkflowFactory('castep.relax') # pylint: disable=invalid-name - protocol = CastepCommonRelaxInputGenerator(process_class=CastepCommonRelaxWorkChain - ).get_protocol('moderate')['relax'] + CastepCommonRelaxWorkChain = WorkflowFactory('castep.relax') # noqa: N806 + protocol = CastepCommonRelaxInputGenerator(process_class=CastepCommonRelaxWorkChain).get_protocol('moderate')[ + 'relax' + ] override = { 'base': { - 'metadata': { - 'label': 'test' - }, - 'calc': { - 'parameters': { - 'cut_off_energy': 220 - }, - 'metadata': { - 'label': 'test' - } - } + 'metadata': {'label': 'test'}, + 'calc': {'parameters': {'cut_off_energy': 220}, 'metadata': {'label': 'test'}}, } } otfg = OTFGGroup.collection.get(label='C19') @@ -198,7 +172,7 @@ def test_relax_generator(castep_code, nacl, with_otfg): assert generated['base']['metadata']['label'] == 'test' -def test_generate_inputs(castep_code, nacl, si): # pylint: disable=invalid-name +def test_generate_inputs(castep_code, nacl, si): """ Test for the generator """ @@ -214,7 +188,7 @@ def test_generate_inputs(castep_code, nacl, si): # pylint: disable=invalid-name assert 'structure' in output['calc'] -def test_input_generator(castep_code, nacl, si): # pylint: disable=invalid-name +def test_input_generator(castep_code, nacl, si): """Test for the input generator""" gen = CastepCommonRelaxInputGenerator(process_class=CastepCommonRelaxWorkChain) engines = {'relax': {'code': castep_code, 'options': {}}} diff --git a/tests/workflows/relax/test_cp2k.py b/tests/workflows/relax/test_cp2k.py index 0bff3ba7..cd818f4c 100644 --- a/tests/workflows/relax/test_cp2k.py +++ b/tests/workflows/relax/test_cp2k.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.cp2k` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.cp2k') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,12 +16,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('cp2k').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } diff --git a/tests/workflows/relax/test_fleur.py b/tests/workflows/relax/test_fleur.py index 434c5de4..1345bcec 100644 --- a/tests/workflows/relax/test_fleur.py +++ b/tests/workflows/relax/test_fleur.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.fleur` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.fleur') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,22 +16,12 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('fleur.fleur').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, }, 'inpgen': { 'code': generate_code('fleur.inpgen').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, + }, }, } diff --git a/tests/workflows/relax/test_gaussian.py b/tests/workflows/relax/test_gaussian.py index 2c15264c..7cd61881 100644 --- a/tests/workflows/relax/test_gaussian.py +++ b/tests/workflows/relax/test_gaussian.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.gaussian` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.gaussian') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,12 +16,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('gaussian').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } diff --git a/tests/workflows/relax/test_implementations.py b/tests/workflows/relax/test_implementations.py index ac15de6c..57cf530b 100644 --- a/tests/workflows/relax/test_implementations.py +++ b/tests/workflows/relax/test_implementations.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.quantum_espresso` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, orm, plugins + import pytest +from aiida import engine, orm, plugins from aiida_common_workflows.common.types import ElectronicType, RelaxType, SpinType from aiida_common_workflows.generators.ports import InputGeneratorPort @@ -22,34 +22,16 @@ def test_spec(workchain): generator_spec = generator.spec() required_ports = { - 'structure': { - 'valid_type': plugins.DataFactory('core.structure') - }, - 'protocol': { - 'valid_type': str - }, - 'spin_type': { - 'valid_type': SpinType - }, - 'relax_type': { - 'valid_type': RelaxType - }, - 'electronic_type': { - 'valid_type': ElectronicType - }, - 'magnetization_per_site': { - 'valid_type': list - }, - 'threshold_forces': { - 'valid_type': float - }, - 'threshold_stress': { - 'valid_type': float - }, - 'reference_workchain': { - 'valid_type': orm.WorkChainNode - }, - 'engines': {} + 'structure': {'valid_type': plugins.DataFactory('core.structure')}, + 'protocol': {'valid_type': str}, + 'spin_type': {'valid_type': SpinType}, + 'relax_type': {'valid_type': RelaxType}, + 'electronic_type': {'valid_type': ElectronicType}, + 'magnetization_per_site': {'valid_type': list}, + 'threshold_forces': {'valid_type': float}, + 'threshold_stress': {'valid_type': float}, + 'reference_workchain': {'valid_type': orm.WorkChainNode}, + 'engines': {}, } for port_name, values in required_ports.items(): diff --git a/tests/workflows/relax/test_nwchem.py b/tests/workflows/relax/test_nwchem.py index 56c4b57c..55683dcd 100644 --- a/tests/workflows/relax/test_nwchem.py +++ b/tests/workflows/relax/test_nwchem.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.nwchem` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.nwchem') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,12 +16,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('nwchem.nwchem').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } diff --git a/tests/workflows/relax/test_orca.py b/tests/workflows/relax/test_orca.py index 545e7019..126f4c9d 100644 --- a/tests/workflows/relax/test_orca.py +++ b/tests/workflows/relax/test_orca.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.orca` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.orca') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,12 +16,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('orca_main').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } diff --git a/tests/workflows/relax/test_quantum_espresso.py b/tests/workflows/relax/test_quantum_espresso.py index 7eb20a0c..bf8a168a 100644 --- a/tests/workflows/relax/test_quantum_espresso.py +++ b/tests/workflows/relax/test_quantum_espresso.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.quantum_espresso` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins from qe_tools import CONSTANTS from aiida_common_workflows.workflows.relax.generator import ElectronicType, RelaxType, SpinType @@ -19,12 +19,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('quantumespresso.pw').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } @@ -211,6 +206,6 @@ def test_magnetization_per_site(generate_code, generate_structure): structure=structure, engines=engines, magnetization_per_site=magnetization_per_site, - spin_type=SpinType.COLLINEAR + spin_type=SpinType.COLLINEAR, ) assert builder['base']['pw']['parameters']['SYSTEM']['starting_magnetization'] == {'Si': 0.0, 'Ge': 0.025} diff --git a/tests/workflows/relax/test_siesta.py b/tests/workflows/relax/test_siesta.py index ec5a5650..4693ce03 100644 --- a/tests/workflows/relax/test_siesta.py +++ b/tests/workflows/relax/test_siesta.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.siesta` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.siesta') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,13 +16,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('siesta.siesta').store().uuid, - 'options': { - 'max_wallclock_seconds': 3600, - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'max_wallclock_seconds': 3600, 'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } diff --git a/tests/workflows/relax/test_vasp.py b/tests/workflows/relax/test_vasp.py index 4b3d8753..86734b23 100644 --- a/tests/workflows/relax/test_vasp.py +++ b/tests/workflows/relax/test_vasp.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """Tests for the :mod:`aiida_common_workflows.workflows.relax.vasp` module.""" -# pylint: disable=redefined-outer-name -from aiida import engine, plugins + import pytest +from aiida import engine, plugins WORKCHAIN = plugins.WorkflowFactory('common_workflows.relax.vasp') GENERATOR = WORKCHAIN.get_input_generator() @@ -16,12 +16,7 @@ def default_builder_inputs(generate_code, generate_structure): 'engines': { 'relax': { 'code': generate_code('vasp.vasp').store().uuid, - 'options': { - 'resources': { - 'num_machines': 1, - 'tot_num_mpiprocs': 1 - } - } + 'options': {'resources': {'num_machines': 1, 'tot_num_mpiprocs': 1}}, } }, } diff --git a/tests/workflows/relax/test_workchain.py b/tests/workflows/relax/test_workchain.py index 1d872aab..22573202 100644 --- a/tests/workflows/relax/test_workchain.py +++ b/tests/workflows/relax/test_workchain.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# pylint: disable=abstract-method,arguments-differ,redefined-outer-name + """Tests for the :mod:`aiida_common_workflows.workflows.relax.workchain` module.""" -from aiida.plugins import WorkflowFactory import pytest +from aiida.plugins import WorkflowFactory from aiida_common_workflows.plugins import get_workflow_entry_point_names from aiida_common_workflows.workflows.relax import CommonRelaxInputGenerator