From 99227c29c34aa3a215c9540c37cc4de59d3a6f9b Mon Sep 17 00:00:00 2001 From: Janosh Riebesell Date: Thu, 15 Feb 2024 15:39:32 +0100 Subject: [PATCH] Fix release CI (#314) * Add OpenBabel installation step to pytest workflow * add pmg to dev deps * Add workflow_dispatch and workflow_call trigger to test.yml * DRY: reuse test.yml workflow in release.yml and use modern python -m build over wheel * bump conda-incubator/setup-miniconda to v3 * fix doc strings missing arguments * consistently use f-str in filepath construction in QCJob * properly deprecate ScanMetalHandler using monty.dev.deprecated decorator * doc str white space normalization * fix test test_check_with_non_kspacing_wf, failing due to added class decorator --- .github/workflows/release.yml | 43 ++++------------ .github/workflows/{pytest.yml => test.yml} | 16 ++++-- custodian/ansible/actions.py | 4 +- custodian/ansible/interpreter.py | 3 +- custodian/cp2k/handlers.py | 42 +++++++-------- custodian/cp2k/interpreter.py | 5 +- custodian/cp2k/utils.py | 5 +- custodian/custodian.py | 14 ++--- custodian/feff/handlers.py | 3 +- custodian/feff/interpreter.py | 2 +- custodian/nwchem/handlers.py | 3 +- custodian/nwchem/jobs.py | 3 +- custodian/qchem/handlers.py | 5 +- custodian/qchem/jobs.py | 23 +++++---- custodian/utils.py | 10 ++-- custodian/vasp/handlers.py | 60 +++++++++++----------- custodian/vasp/interpreter.py | 5 +- custodian/vasp/jobs.py | 5 +- docs/_themes/flask_theme_support.py | 5 +- pyproject.toml | 2 +- tests/vasp/test_handlers.py | 2 +- 21 files changed, 119 insertions(+), 141 deletions(-) rename .github/workflows/{pytest.yml => test.yml} (69%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 190aa067..1949f8cb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,44 +6,21 @@ on: workflow_dispatch: jobs: - build: - strategy: - max-parallel: 1 - matrix: - os: [ubuntu-latest] - python-version: ["3.11"] - - runs-on: ${{ matrix.os }} + test: + # run test.yml first to ensure that the test suite is passing + uses: ./.github/workflows/test.yml + build: + needs: test + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: conda-incubator/setup-miniconda@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install OpenBabel - shell: bash -l {0} - run: conda install -c conda-forge openbabel - - - name: Install dependencies - shell: bash -l {0} - run: | - pip install pytest pymatgen - pip install -e . - - name: pytest - shell: bash -l {0} - env: - PMG_MAPI_KEY: ${{ secrets.PMG_MAPI_KEY }} - MPLBACKEND: "Agg" - run: | - pytest tests --color=yes - name: release - shell: bash -l {0} + run: | + pip install build twine + python -m build + twine upload --skip-existing dist/*.tar.gz env: TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }} TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} - run: | - pip install setuptools wheel twine - python setup.py sdist bdist_wheel - twine upload --skip-existing dist/*.tar.gz diff --git a/.github/workflows/pytest.yml b/.github/workflows/test.yml similarity index 69% rename from .github/workflows/pytest.yml rename to .github/workflows/test.yml index 1f722bb1..ea797b8e 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,9 @@ on: pull_request: branches: [master] paths-ignore: [docs/**] + workflow_dispatch: + # make this workflow reusable by release.yml + workflow_call: jobs: build: @@ -21,15 +24,20 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: conda-incubator/setup-miniconda@v3 + with: + python-version: ${{ matrix.python-version }} + + - name: Install OpenBabel + shell: bash -l {0} + run: conda install -c conda-forge openbabel + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies - run: | - pip install --upgrade pip - pip install --upgrade pymatgen - pip install -e '.[dev]' + run: pip install -e '.[dev]' - name: pytest env: diff --git a/custodian/ansible/actions.py b/custodian/ansible/actions.py index 04ecbdcd..11c535d1 100644 --- a/custodian/ansible/actions.py +++ b/custodian/ansible/actions.py @@ -23,8 +23,8 @@ def get_nested_dict(input_dict, key): class DictActions: - """ - Class to implement the supported mongo-like modifications on a dict. + """Class to implement the supported mongo-like modifications on a dict. + Supported keywords include the following Mongo-based keywords, with the usual meanings (refer to Mongo documentation for information): diff --git a/custodian/ansible/interpreter.py b/custodian/ansible/interpreter.py index c6f97088..b78a0f2c 100644 --- a/custodian/ansible/interpreter.py +++ b/custodian/ansible/interpreter.py @@ -31,8 +31,7 @@ class Modder: """ def __init__(self, actions=None, strict=True): - """ - Initializes a Modder from a list of supported actions. + """Initialize a Modder from a list of supported actions. Args: actions ([Action]): A sequence of supported actions. See diff --git a/custodian/cp2k/handlers.py b/custodian/cp2k/handlers.py index a2b63a5e..38cbdaa0 100644 --- a/custodian/cp2k/handlers.py +++ b/custodian/cp2k/handlers.py @@ -59,8 +59,7 @@ class StdErrHandler(ErrorHandler): error_msgs = {"seg_fault": ["SIGSEGV"], "out_of_memory": ["insufficient virtual memory"], "abort": ["SIGABRT"]} def __init__(self, std_err="std_err.txt"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: std_err (str): This is the file where the stderr for cp2k @@ -135,8 +134,7 @@ class UnconvergedScfErrorHandler(ErrorHandler): is_monitor = True def __init__(self, input_file="cp2k.inp", output_file="cp2k.out"): - """ - Initializes the error handler from a set of input and output files. + """Initialize the error handler from a set of input and output files. Args: input_file (str): Name of the CP2K input file. @@ -404,11 +402,11 @@ class DivergingScfErrorHandler(ErrorHandler): is_monitor = True def __init__(self, output_file="cp2k.out", input_file="cp2k.inp"): - """ - Initializes the error handler from an output files. + """Initializes the error handler from an output files. Args: output_file (str): Name of the CP2K output file. + input_file (str): Name of the CP2K input file. """ self.output_file = output_file self.input_file = input_file @@ -468,8 +466,7 @@ class FrozenJobErrorHandler(ErrorHandler): is_monitor = True def __init__(self, input_file="cp2k.inp", output_file="cp2k.out", timeout=3600): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: input_file (str): Name of the input file to modify if needed @@ -592,11 +589,11 @@ def correct(self): class AbortHandler(ErrorHandler): - """ - These are errors that cp2k recognizes internally, and causes a kill-signal, - as opposed to things like slow scf convergence, which is an unwanted feature of - optimization rather than an error per se. Currently this error handler recognizes - the following: + """Handles errors that cp2k recognizes internally. + + These internal errors cause a kill-signal, as opposed to things like slow scf + convergence, which is an unwanted feature of optimization rather than an error per se. + Currently this error handler recognizes the following: (1) Cholesky decomposition error in preconditioner. If this is found, the handler will try switching between Full_all/Full_single_inverse @@ -745,14 +742,14 @@ def correct(self): class NumericalPrecisionHandler(ErrorHandler): - """ - CP2K offers lots of functionality for decreasing numerical - precision in order to speed-up calculations. This can, unfortunately, - lead to convergence cycles getting 'stuck'. While it can be hard to - separate numerical issues from things like optimizer choice, slow-to-converge - systems, or divergence issues, this handler specifically detects the problem of - convergence getting stuck, where the same convergence value is returned many times - in a row. (Numerical precision can also be the cause of oscillating convergence. + """This handler detects convergence cycles getting stuck due to numerical imprecision. + + CP2K offers lots of functionality for decreasing numerical precision in order to + speed-up calculations. This can unfortunately lead to convergence cycles getting 'stuck'. + While it can be hard to separate numerical issues from things like optimizer choice, + slow-to-converge systems, or divergence issues, this handler specifically detects the + problem of convergence getting stuck, where the same convergence value is returned many + times in a row. (Numerical precision can also be the cause of oscillating convergence. This is a little harder to assess, as it can also just look like slow-convergence.) Currently, we have identified the following causes of this problem: @@ -810,6 +807,9 @@ def __init__( This will be caught and corrected, but it won't catch instances where the last n-1 convergence values are the same for each outer scf loop, but it gets reset by the preconditioner. + pgf_orb_strict (float): TODO @janosh someone who knows this code, please add a description + eps_default_strict (float): TODO @janosh likewise + eps_gvg_strict (float): TODO @janosh likewise """ self.input_file = input_file self.output_file = output_file diff --git a/custodian/cp2k/interpreter.py b/custodian/cp2k/interpreter.py index 7d76e61c..d6f0871b 100644 --- a/custodian/cp2k/interpreter.py +++ b/custodian/cp2k/interpreter.py @@ -19,8 +19,7 @@ class Cp2kModder(Modder): """ def __init__(self, filename="cp2k.inp", actions=None, strict=True, ci=None): - """ - Initializes a Modder for Cp2kInput sets. + """Initialize a Modder for Cp2kInput sets. Args: filename (str): name of cp2k input file to modify. This file will be overwritten @@ -47,7 +46,7 @@ def apply_actions(self, actions): files. Args: - actions [dict]: A list of actions of the form {'file': filename, + actions (dict): A list of actions of the form {'file': filename, 'action': moddermodification} or {'dict': cp2k_key, 'action': moddermodification}. """ diff --git a/custodian/cp2k/utils.py b/custodian/cp2k/utils.py index f3b9cef2..9d0a99a5 100644 --- a/custodian/cp2k/utils.py +++ b/custodian/cp2k/utils.py @@ -20,11 +20,12 @@ def restart(actions, output_file, input_file, no_actions_needed=False): no actions are present, then non are added by this function output_file (str): the cp2k output file name. input_file (str): the cp2k input file name. + no_actions_needed (bool): if no actions are needed, then this should be set to True. """ if actions or no_actions_needed: - o = Cp2kOutput(output_file) + out = Cp2kOutput(output_file) ci = Cp2kInput.from_file(input_file) - restart_file = o.filenames.get("restart") + restart_file = out.filenames.get("restart") restart_file = restart_file[-1] if restart_file else None wfn_restart = ci["force_eval"]["dft"].get("wfn_restart_file_name") if ci.check("force_eval/dft") else None diff --git a/custodian/custodian.py b/custodian/custodian.py index f7067582..69df44da 100644 --- a/custodian/custodian.py +++ b/custodian/custodian.py @@ -64,9 +64,9 @@ class Custodian: - """ - The Custodian class is the manager for a list of jobs given a list of - error handlers. The way it works is as follows: + """Custodian class is the manager for a list of jobs given a list of error handlers. + + The way it works is as follows: 1. Let's say you have defined a list of jobs as [job1, job2, job3, ...] and you have defined a list of possible error handlers as [err1, err2, ...] @@ -124,8 +124,7 @@ def __init__( terminate_on_nonzero_returncode=True, **kwargs, ): - """ - Initializes a Custodian from a list of jobs and error handlers. + """Initialize a Custodian from a list of jobs and error handlers. Args: handlers ([ErrorHandler]): Error handlers. In order of priority of @@ -175,6 +174,8 @@ def __init__( running job. If None, the default is to call Popen.terminate. terminate_on_nonzero_returncode (bool): If True, a non-zero return code on any Job will result in a termination. Defaults to True. + **kwargs: Any other kwargs are ignored. This is to allow for easy + subclassing and instantiation from a dict. """ self.max_errors = max_errors self.max_errors_per_job = max_errors_per_job or max_errors @@ -842,8 +843,7 @@ class CustodianError(RuntimeError): """Exception class for Custodian errors.""" def __init__(self, message, raises=False): - """ - Initializes the error with a message. + """Initialize the error with a message. Args: message (str): Message passed to Exception diff --git a/custodian/feff/handlers.py b/custodian/feff/handlers.py index 53a22ea5..af34899f 100644 --- a/custodian/feff/handlers.py +++ b/custodian/feff/handlers.py @@ -36,8 +36,7 @@ class UnconvergedErrorHandler(ErrorHandler): is_monitor = False def __init__(self, output_filename="log1.dat"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): Filename for the log1.dat file. log1.dat file diff --git a/custodian/feff/interpreter.py b/custodian/feff/interpreter.py index 3b14eaf7..02e90510 100644 --- a/custodian/feff/interpreter.py +++ b/custodian/feff/interpreter.py @@ -37,7 +37,7 @@ def apply_actions(self, actions): files. Args: - actions [dict]: A list of actions of the form {'file': filename, + actions (dict): A list of actions of the form {'file': filename, 'action': moddermodification} or {'dict': feffinput_key, 'action': moddermodification} """ diff --git a/custodian/nwchem/handlers.py b/custodian/nwchem/handlers.py index 1e402601..1ef8c9f2 100644 --- a/custodian/nwchem/handlers.py +++ b/custodian/nwchem/handlers.py @@ -17,8 +17,7 @@ class NwchemErrorHandler(ErrorHandler): """ def __init__(self, output_filename="mol.nwout"): - """ - Initializes with an output file name. + """Initialize with an output file name. Args: output_filename (str): This is the file where the stdout for nwchem diff --git a/custodian/nwchem/jobs.py b/custodian/nwchem/jobs.py index a07c5682..22596cab 100644 --- a/custodian/nwchem/jobs.py +++ b/custodian/nwchem/jobs.py @@ -28,8 +28,7 @@ def __init__( backup=True, settings_override=None, ): - """ - Initializes a basic NwChem job. + """Initialize a basic NwChem job. Args: nwchem_cmd ([str]): Command to run Nwchem as a list of args. For diff --git a/custodian/qchem/handlers.py b/custodian/qchem/handlers.py index 5af315cb..2927fea5 100644 --- a/custodian/qchem/handlers.py +++ b/custodian/qchem/handlers.py @@ -38,8 +38,7 @@ def __init__( scf_max_cycles=100, geom_max_cycles=200, ): - """ - Initializes the error handler from a set of input and output files. + """Initialize the error handler from a set of input and output files. Args: input_file (str): Name of the QChem input file. @@ -333,7 +332,7 @@ def correct(self): actions.append({"mem_static": "2000"}) elif "mem_total_too_small" in self.errors: - print("Run on a node with more memory! Current mem_total = " + str(self.outdata["mem_total"])) + print(f"Run on a node with more memory! Current mem_total = {self.outdata['mem_total']}") return {"errors": self.errors, "actions": None} elif "basis_not_supported" in self.errors: diff --git a/custodian/qchem/jobs.py b/custodian/qchem/jobs.py index 61d3b10b..47dd6c57 100644 --- a/custodian/qchem/jobs.py +++ b/custodian/qchem/jobs.py @@ -207,6 +207,7 @@ def opt_with_frequency_flattener( multimode (str): Parallelization scheme, either openmp or mpi. input_file (str): Name of the QChem input file. output_file (str): Name of the QChem output file. + qclog_file (str): Name of the file to redirect the standard output max_iterations (int): Number of perturbation -> optimization -> frequency iterations to perform. Defaults to 10. max_molecule_perturb_scale (float): The maximum scaled perturbation that @@ -308,14 +309,14 @@ def opt_with_frequency_flattener( input_file=input_file, output_file=output_file, qclog_file=qclog_file, - suffix=f".{opt_method}_" + str(ii), + suffix=f".{opt_method}_{ii}", save_scratch=True, backup=first, **QCJob_kwargs, ) ) - opt_outdata = QCOutput(output_file + f".{opt_method}_" + str(ii)).data - opt_indata = QCInput.from_file(input_file + f".{opt_method}_" + str(ii)) + opt_outdata = QCOutput(f"{output_file}.{opt_method}_{ii}").data + opt_indata = QCInput.from_file(f"{input_file}.{opt_method}_{ii}") if opt_outdata["version"] == "6": opt_geom_opt = copy.deepcopy(opt_indata.geom_opt) opt_geom_opt["initial_hessian"] = "read" @@ -355,15 +356,15 @@ def opt_with_frequency_flattener( input_file=input_file, output_file=output_file, qclog_file=qclog_file, - suffix=".freq_" + str(ii), + suffix=f".freq_{ii}", save_scratch=True, backup=first, **QCJob_kwargs, ) ) - freq_outdata = QCOutput(output_file + ".freq_" + str(ii)).data - freq_indata = QCInput.from_file(input_file + ".freq_" + str(ii)) + freq_outdata = QCOutput(f"{output_file}.freq_{ii}").data + freq_indata = QCInput.from_file(f"{input_file}.freq_{ii}") for key in freq_indata.rem: if key not in {"job_type", "geom_opt2", "scf_guess_always"}: if freq_rem.get(key, None) != freq_indata.rem[key]: @@ -455,12 +456,12 @@ def opt_with_frequency_flattener( input_file=input_file, output_file=output_file, qclog_file=qclog_file, - suffix=f".{opt_method}_" + str(ii), + suffix=f".{opt_method}_{ii}", backup=first, **QCJob_kwargs, ) ) - opt_outdata = QCOutput(output_file + f".{opt_method}_" + str(ii)).data + opt_outdata = QCOutput(f"{output_file}.{opt_method}_{ii}").data if first: orig_species = copy.deepcopy(opt_outdata.get("species")) orig_charge = copy.deepcopy(opt_outdata.get("charge")) @@ -495,13 +496,13 @@ def opt_with_frequency_flattener( input_file=input_file, output_file=output_file, qclog_file=qclog_file, - suffix=".freq_" + str(ii), + suffix=f".freq_{ii}", backup=first, **QCJob_kwargs, ) ) - outdata = QCOutput(output_file + ".freq_" + str(ii)).data - indata = QCInput.from_file(input_file + ".freq_" + str(ii)) + outdata = QCOutput(f"{output_file}.freq_{ii}").data + indata = QCInput.from_file(f"{input_file}.freq_{ii}") if "cpscf_nseg" in indata.rem: freq_rem["cpscf_nseg"] = indata.rem["cpscf_nseg"] errors = outdata.get("errors") diff --git a/custodian/utils.py b/custodian/utils.py index 9977a5d1..664279fb 100644 --- a/custodian/utils.py +++ b/custodian/utils.py @@ -64,7 +64,7 @@ class tracked_lru_cache: def __init__(self, func): """ Args: - func: function to be decorated + func: function to be decorated. """ self.func = functools.lru_cache(func) functools.update_wrapper(self, func) @@ -74,18 +74,14 @@ def __init__(self, func): self.cache_clear = self.func.cache_clear def __call__(self, *args, **kwargs): - """ - Call the decorated function - """ + """Call the decorated function.""" result = self.func(*args, **kwargs) self.cached_functions.add(self.func) return result @classmethod def tracked_cache_clear(cls): - """ - Clear the cache of all the decorated functions. - """ + """Clear the cache of all the decorated functions.""" while cls.cached_functions: f = cls.cached_functions.pop() f.cache_clear() diff --git a/custodian/vasp/handlers.py b/custodian/vasp/handlers.py index 1d4d9e77..a3f730d3 100644 --- a/custodian/vasp/handlers.py +++ b/custodian/vasp/handlers.py @@ -18,6 +18,7 @@ from math import prod import numpy as np +from monty.dev import deprecated from monty.io import zopen from monty.os.path import zpath from monty.serialization import loadfn @@ -127,8 +128,7 @@ def __init__( vtst_fixes=False, **kwargs, ): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): This is the file where the stdout for vasp @@ -152,6 +152,7 @@ def __init__( vtst_fixes (bool): Whether to consider VTST optimizers. Defaults to False for compatibility purposes, but if you have VTST, you would likely benefit from setting this to True. + **kwargs: Ignored. Added to increase signature flexibility. """ self.output_filename = output_filename self.errors = set() @@ -693,8 +694,7 @@ class LrfCommutatorHandler(ErrorHandler): error_msgs = {"lrf_comm": ["LRF_COMMUTATOR internal error"]} def __init__(self, output_filename: str = "std_err.txt"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): This is the file where the stderr for vasp @@ -750,8 +750,7 @@ class StdErrHandler(ErrorHandler): } def __init__(self, output_filename: str = "std_err.txt"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): This is the file where the stderr for vasp @@ -811,8 +810,7 @@ class AliasingErrorHandler(ErrorHandler): } def __init__(self, output_filename: str = "vasp.out"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): This is the file where the stdout for vasp @@ -895,8 +893,7 @@ class DriftErrorHandler(ErrorHandler): """Corrects for total drift exceeding the force convergence criteria.""" def __init__(self, max_drift=None, to_average=3, enaug_multiply=2): - """ - Initializes the handler with max drift + """Initialize the handler with max drift Args: max_drift (float): This defines the max drift. Leaving this at the default of None gets the max_drift from EDFIFFG. @@ -976,8 +973,7 @@ class MeshSymmetryErrorHandler(ErrorHandler): is_monitor = False def __init__(self, output_filename: str = "vasp.out", output_vasprun="vasprun.xml"): - """ - Initializes the handler with the output files to check. + """Initialize the handler with the output files to check. Args: output_filename (str): This is the file where the stdout for vasp @@ -1039,11 +1035,10 @@ class UnconvergedErrorHandler(ErrorHandler): is_monitor = False def __init__(self, output_filename: str = "vasprun.xml"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: - output_vasprun (str): Filename for the vasprun.xml file. Change + output_filename (str): Filename for the vasprun.xml file. Change this only if it is different from the default (unlikely). """ self.output_filename = output_filename @@ -1163,8 +1158,7 @@ class IncorrectSmearingHandler(ErrorHandler): is_monitor = False def __init__(self, output_filename: str = "vasprun.xml"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): Filename for the vasprun.xml file. Change @@ -1210,8 +1204,7 @@ class KspacingMetalHandler(ErrorHandler): is_monitor = False def __init__(self, output_filename: str = "vasprun.xml"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): Filename for the vasprun.xml file. Change @@ -1250,12 +1243,23 @@ def correct(self): return {"errors": ["ScanMetal"], "actions": actions} +@deprecated( + KspacingMetalHandler, + "ScanMetalHandler was deprecated on 2023-11-03 and will be removed in a future release. " + "Use KspacingMetalHandler instead.", +) class ScanMetalHandler(KspacingMetalHandler): """ScanMetalHandler was renamed because MP GGA workflow might also adopt kspacing in the future. Keeping this alias during a deprecation period for backwards compatibility. """ def __init__(self, *args, **kwargs) -> None: + """Initialize the handler with the output file to check. + + Args: + args: Positional arguments passed to parent class. + kwargs: Keyword passed to parent class. + """ warnings.warn( "ScanMetalHandler is deprecated and will be removed in a future release. " "Use KspacingMetalHandler instead.", @@ -1342,8 +1346,7 @@ class PotimErrorHandler(ErrorHandler): is_monitor = True def __init__(self, input_filename="POSCAR", output_filename="OSZICAR", dE_threshold=1): - """ - Initializes the handler with the input and output files to check. + """Initialize the handler with the input and output files to check. Args: input_filename (str): This is the POSCAR file that the run @@ -1395,8 +1398,7 @@ class FrozenJobErrorHandler(ErrorHandler): is_monitor = True def __init__(self, output_filename: str = "vasp.out", timeout=21_600) -> None: - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): This is the file where the stdout for vasp @@ -1443,8 +1445,7 @@ class NonConvergingErrorHandler(ErrorHandler): is_monitor = True def __init__(self, output_filename: str = "OSZICAR", nionic_steps=10): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): This is the OSZICAR file. Change @@ -1580,8 +1581,7 @@ class WalltimeHandler(ErrorHandler): raises_runtime_error = False def __init__(self, wall_time=None, buffer_time=300, electronic_step_stop=False): - """ - Initializes the handler with a buffer time. + """Initialize the handler with a buffer time. Args: wall_time (int): Total walltime in seconds. If this is None and @@ -1686,8 +1686,7 @@ class CheckpointHandler(ErrorHandler): is_terminating = False def __init__(self, interval=3600): - """ - Initializes the handler with an interval. + """Initialize the handler with an interval. Args: interval (int): Interval at which to checkpoint in seconds. @@ -1784,8 +1783,7 @@ class PositiveEnergyErrorHandler(ErrorHandler): is_monitor = True def __init__(self, output_filename: str = "OSZICAR"): - """ - Initializes the handler with the output file to check. + """Initialize the handler with the output file to check. Args: output_filename (str): This is the OSZICAR file. Change diff --git a/custodian/vasp/interpreter.py b/custodian/vasp/interpreter.py index cf7fb70e..89192716 100644 --- a/custodian/vasp/interpreter.py +++ b/custodian/vasp/interpreter.py @@ -10,8 +10,7 @@ class VaspModder(Modder): """A Modder for VaspInputSets.""" def __init__(self, actions=None, strict=True, vi=None): - """ - Initializes a Modder for VaspInput sets. + """Initialize a Modder for VaspInput sets. Args: actions ([Action]): A sequence of supported actions. See @@ -35,7 +34,7 @@ def apply_actions(self, actions): files. Args: - actions [dict]: A list of actions of the form {'file': filename, + actions (dict): A list of actions of the form {'file': filename, 'action': moddermodification} or {'dict': vaspinput_key, 'action': moddermodification}. """ diff --git a/custodian/vasp/jobs.py b/custodian/vasp/jobs.py index 12bb49ff..2106915f 100644 --- a/custodian/vasp/jobs.py +++ b/custodian/vasp/jobs.py @@ -444,7 +444,7 @@ def full_opt_run( half_kpts_first_relax (bool): Whether to halve the kpoint grid for the first relaxation. Speeds up difficult convergence considerably. Defaults to False. - \*\*vasp_job_kwargs: Passthrough kwargs to VaspJob. See + **vasp_job_kwargs: Passthrough kwargs to VaspJob. See :class:`custodian.vasp.jobs.VaspJob`. Returns: @@ -530,7 +530,7 @@ def constrained_opt_run( which is more robust but can be a bit slow. The code does fall back on the bisection when bfgs gives a non-sensical result, e.g., negative lattice params. - \*\*vasp_job_kwargs: Passthrough kwargs to VaspJob. See + **vasp_job_kwargs: Passthrough kwargs to VaspJob. See :class:`custodian.vasp.jobs.VaspJob`. Returns: @@ -900,6 +900,7 @@ def __init__(self, input_set, contcar_only=True, **kwargs): "pymatgen.io.vasp.sets.MPNonSCFSet". contcar_only (bool): If True (default), only CONTCAR structures are used as input to the input set. + **kwargs: Additional kwargs to pass to the input set. """ self.input_set = input_set self.contcar_only = contcar_only diff --git a/docs/_themes/flask_theme_support.py b/docs/_themes/flask_theme_support.py index b90513fb..76b16b2c 100644 --- a/docs/_themes/flask_theme_support.py +++ b/docs/_themes/flask_theme_support.py @@ -1,4 +1,5 @@ -# flasky extensions. flasky pygments style based on tango style +"""flasky extensions. flasky pygments style based on tango style.""" + from pygments.style import Style from pygments.token import ( Comment, @@ -17,6 +18,8 @@ class FlaskyStyle(Style): + """Docs code highlighting style based on tango style.""" + background_color = "#f8f8f8" default_style = "" diff --git a/pyproject.toml b/pyproject.toml index 77dde35b..6f3fab2a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ dependencies = ["monty>=2.0.6", "psutil", "ruamel.yaml>=0.15.6"] vasp = ["pymatgen"] nwchem = ["pymatgen"] qchem = ["pymatgen"] -dev = ["mypy", "pre-commit", "pytest", "pytest-cov", "ruff"] +dev = ["mypy", "pre-commit", "pymatgen", "pytest", "pytest-cov", "ruff"] error-statistics = ["sentry-sdk>=0.8.0"] [project.scripts] diff --git a/tests/vasp/test_handlers.py b/tests/vasp/test_handlers.py index 84fb4996..a7132bfd 100644 --- a/tests/vasp/test_handlers.py +++ b/tests/vasp/test_handlers.py @@ -797,7 +797,7 @@ def test_check_with_non_kspacing_wf(self): os.chdir(f"{TEST_FILES}/scan_metal") # TODO (@janosh 2023-11-03) remove when ending ScanMetalHandler deprecation period - assert issubclass(ScanMetalHandler, KspacingMetalHandler) + assert isinstance(ScanMetalHandler(), KspacingMetalHandler) class LargeSigmaHandlerTest(PymatgenTest):