Skip to content

Commit

Permalink
Run pydocstyle and pycodestyle over src/ (#203)
Browse files Browse the repository at this point in the history
Implementation of #202:
- Use `testpaths = src test` in `setup.cfg`.
- Handle the resulting linting-related errors, all which have been hidden up until now.
- Added a codecov yaml file.
  • Loading branch information
BvB93 committed Jun 18, 2020
1 parent a390dba commit 0269cc9
Show file tree
Hide file tree
Showing 24 changed files with 164 additions and 100 deletions.
1 change: 1 addition & 0 deletions .github/workflows/pythonapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ jobs:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
version: [3.7, 3.8]

Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ install:

script:
# Run the unitary tests excluding the expensive computations
- pytest -m "not (slow or long)" --cov=qmflows test
- pytest -m "not (slow or long)"
- coverage xml && coverage report -m

branches:
Expand Down
8 changes: 8 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
target: 80
patch:
default:
target: 0
9 changes: 8 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ branch = True
source = src

[pycodestyle]
ignore = E302,E301,W504 # E302 & E301 due pycodestyle's awful support for @overload
select = W503 # W503 looks better than W504
max-line-length = 100

[tool:pytest]
testpaths = test
testpaths = src test
addopts = --pycodestyle --pydocstyle --tb=short --cov --cov-report xml --cov-report term --cov-report html
markers = slow: A marker for slow tests requiring external quantum-chemical packages.

Expand All @@ -23,3 +25,8 @@ source-dir = docs
build-dir = docs/_build
all_files = 1
builder = html

[pydocstyle]
convention = numpy
add-ignore = D401 # First line should be in imperative mood
ignore-decorators = overload
10 changes: 6 additions & 4 deletions src/qmflows/components/reactivity.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""A module containing the :class:`Coordinate` baseclass and its subclasses."""

from typing import Callable, Any, ClassVar, Tuple, overload

import scm.plams.interfaces.molecule.rdkit as molkit
Expand Down Expand Up @@ -50,11 +52,11 @@ def get_current_value(self, mol: MolType) -> float:
return self.fun(conf, *xs)

@overload
def get_settings(self, value: Any, mol: None) -> Settings: ...

def get_settings(self, value: Any, mol: None) -> Settings:
...
@overload
def get_settings(self, value: None, mol: MolType) -> Settings: ...

def get_settings(self, value: None, mol: MolType) -> Settings:
...
def get_settings(self, value=None, mol=None):
"""Map a :class:`str` representation of :attr:`Coordinate.atoms` to *value*."""
s = Settings()
Expand Down
16 changes: 10 additions & 6 deletions src/qmflows/cp2k_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,13 @@ def set_prm(settings: Settings, key: Union[str, Tuple[str, ...]],
@overload
def set_prm_values(prm_key: str, prm_map: MappingScalar,
atom_map: MutableMapping[Optional[str], int],
settings_base: List[Settings], atom_key: str) -> None: ...
@overload
settings_base: List[Settings], atom_key: str) -> None:
...
@overload # noqa: E302
def set_prm_values(prm_key: Sequence[str], prm_map: MappingSequence,
atom_map: MutableMapping[Optional[str], int],
settings_base: List[Settings], atom_key: str) -> None: ...
settings_base: List[Settings], atom_key: str) -> None:
...
def set_prm_values(prm_key, prm_map, atom_map,
settings_base, atom_key) -> None: # noqa: E302
"""Assign the actual values specified in :func:`set_prm`.
Expand Down Expand Up @@ -366,9 +368,11 @@ def _(unit: Optional[str]) -> List[str]:


@overload
def _construct_df(columns: Sequence[str], prm_map: MappingSequence) -> pd.DataFrame: ...
@overload
def _construct_df(columns: str, prm_map: MappingScalar) -> pd.DataFrame: ...
def _construct_df(columns: Sequence[str], prm_map: MappingSequence) -> pd.DataFrame:
...
@overload # noqa: E302
def _construct_df(columns: str, prm_map: MappingScalar) -> pd.DataFrame:
...
def _construct_df(columns, prm_map) -> pd.DataFrame: # noqa: E302
"""Convert *prm_map* into a :class:`pandas.DataFrame` of strings with *columns* as columns.
Expand Down
1 change: 1 addition & 0 deletions src/qmflows/data/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Various non-`.py` files used throughout QMFlows."""
1 change: 1 addition & 0 deletions src/qmflows/data/dictionaries/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Various :class:`~qmflows.packages.packages.Package`-related .yaml files."""
2 changes: 2 additions & 0 deletions src/qmflows/examples/Conditional_workflows/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Various examples involving conditional workflows."""

from .calc_freqs import example_freqs

__all__ = ['example_freqs']
14 changes: 7 additions & 7 deletions src/qmflows/examples/Conditional_workflows/calc_freqs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""A module with examples related to frequency calculations."""

__all__ = ['example_freqs']

from noodles import gather
Expand All @@ -6,16 +8,14 @@


def is_successful(result):
"""
Define the condition for a successful calculation
"""
return result.status not in ["failed", "crashed"]
"""Define the condition for a successful calculation."""
return result.status not in {"failed", "crashed"}


def example_freqs():
"""
This examples illustrates the possibility to use different packages interchangeably.
Analytical frequencies are not available for B3LYP in ADF
"""An examples which illustrates the possibility using different packages interchangeably.
Analytical frequencies are not available for B3LYP in ADF.
This workflow captures the resulting error and submits the same job to ORCA.
"""
# Generate water molecule
Expand Down
12 changes: 6 additions & 6 deletions src/qmflows/examples/Constrained_and_TS_optimizations/H2O2_TS.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
"""A module holding the :func:`example_H2O2_TS` example function."""

__all__ = ['example_H2O2_TS']

import scm.plams.interfaces.molecule.rdkit as molkit
from qmflows import (orca, dftb, templates, Dihedral, run, Settings, logger)


def example_H2O2_TS():
"""
This example generates an approximate TS for rotation in hydrogen peroxide
using DFTB, and performs a full TS optimization in Orca.
It illustrates using a hessian from one package, DFTB in this case,
to initialize a TS optimization in another, i.e. Orca in this case
"""
"""Am example which generates an approximate TS for rotation in hydrogen peroxide using DFTB, and performs a full TS optimization in Orca.
It illustrates using a hessian from one package, DFTB in this case,
to initialize a TS optimization in another, *i.e.* Orca in this case
""" # noqa: E501
# Generate hydrogen peroxide molecule
h2o2 = molkit.from_smarts('[H]OO[H]')

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Various examples related to constrained geometry optimizations."""

from .generic_constraints import example_generic_constraints
from .H2O2_TS import example_H2O2_TS
from .partial_geometry_opt import example_partial_geometry_opt
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""An example workflow for generic constrained geometry optimizations."""

__all__ = ['example_generic_constraints']

import scm.plams.interfaces.molecule.rdkit as molkit
Expand All @@ -7,10 +9,10 @@

def example_generic_constraints():
"""Run different job with geometric constrains.
This examples illustrates that, by using generic keywords, it is possible
to call different packages interchangeably with the same Settings
to call different packages interchangeably with the same Settings.
"""

# build hydrogen fluoride molecule
hydrogen_fluoride = molkit.from_smiles('F[H]')

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""A module containing the example :func:`example_partial_geometry_opt` function."""

__all__ = ['example_partial_geometry_opt']

import scm.plams.interfaces.molecule.rdkit as molkit
Expand All @@ -6,9 +8,7 @@


def example_partial_geometry_opt():
"""
Performa partial optimization freezing the Hydrogen atoms
"""
"""Performa partial optimization freezing the Hydrogen atoms."""
methanol = molkit.from_smiles('CO')

# optimize only H atoms
Expand Down
2 changes: 2 additions & 0 deletions src/qmflows/examples/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Various example workflows for QMFlows."""

from .Conditional_workflows import example_freqs
from .Constrained_and_TS_optimizations import (
example_H2O2_TS, example_generic_constraints, example_partial_geometry_opt)
Expand Down
2 changes: 2 additions & 0 deletions src/qmflows/packages/SCM.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def molecule(self) -> Optional[plams.Molecule]:

@property
def geometry(self) -> Optional[plams.Molecule]:
"""An alias for :attr:`ADF_Result.molecule`."""
return self.molecule


Expand Down Expand Up @@ -180,6 +181,7 @@ def molecule(self) -> plams.Molecule:

@property
def geometry(self) -> Optional[plams.Molecule]:
"""An alias for :attr:`DFTB_Result.molecule`."""
return self.molecule


Expand Down
2 changes: 2 additions & 0 deletions src/qmflows/packages/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""A set of modules for managing various quantum-chemical packages."""

from .packages import (
Package, Result, SerMolecule, SerSettings, load_properties,
run, registry)
Expand Down
6 changes: 3 additions & 3 deletions src/qmflows/packages/cp2k_mm.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,20 @@


class CP2KMM_Result(Result):
"""Class providing access to CP2KMM result."""
"""A class providing access to CP2KMM result."""

prop_mapping: ClassVar[_Settings] = load_properties('CP2KMM', prefix='properties')


class CP2KMM(CP2K):
"""This class setup the requirement to run a `CP2K Job <https://www.cp2k.org/>`_ for classical forcefield calculations.
"""A Package subclass for running `CP2K Jobs <https://www.cp2k.org/>`_ for classical forcefield calculations.
It uses plams together with the templates to generate the stucture input
and also uses Plams to invoke the binary CP2K code.
This class is not intended to be called directly by the user, instead the
:data:`cp2k_mm` function should be called.
""" # noqa
""" # noqa: E501

generic_mapping: ClassVar[_Settings] = load_properties('CP2KMM', prefix='generic2')
result_type: ClassVar[Type[Result]] = CP2KMM_Result
Expand Down
2 changes: 1 addition & 1 deletion src/qmflows/packages/cp2k_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def molecule(self) -> plams.Molecule:


class CP2K(Package):
"""This class setup the requirement to run a `CP2K Job <https://www.cp2k.org/>`_.
"""A Package subclass for running `CP2K Jobs <https://www.cp2k.org/>`_.
It uses plams together with the templates to generate the stucture input
and also uses Plams to invoke the binary CP2K code.
Expand Down
2 changes: 1 addition & 1 deletion src/qmflows/packages/orca.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def molecule(self) -> Optional[plams.Molecule]:


class ORCA(Package):
"""This class prepare the input to run a Orca job using both PLAMS and templates.
"""A class for preparing the input for running a Orca job using both PLAMS and templates.
It also does the manangement of the input/output files resulting
from running Orca and returns a Results object that containing the methods
Expand Down
23 changes: 16 additions & 7 deletions src/qmflows/packages/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,57 +24,66 @@

T = TypeVar('T')

ReturnDict = Dict[str, T] # This should technically be a :class:`typing.TypedDict`
MakeRec = Callable[[T], ReturnDict]


class SerMolecule(Serialiser):
"""Based on the Plams molecule this class encode and decode the information related to the molecule using the JSON format.""" # noqa: E501

def __init__(self) -> None:
"""Initialize a :class:`SerMolecule` instance."""
super().__init__(Molecule)

def encode(self, obj: Molecule, make_rec: MakeRec) -> ReturnDict:
def encode(self, obj: Molecule, make_rec: Callable[[T], Dict[str, T]]) -> Dict[str, T]:
"""Encode the passed PLAMS Molecule."""
return make_rec(obj.as_dict())

def decode(self, cls: Type[Molecule], data: Mapping) -> Molecule:
"""Decode the passed data into a PLAMS Molecule."""
return cls.from_dict(data)


class SerMol(Serialiser):
"""Based on the RDKit molecule this class encodes and decodes the information related to the molecule using a string.""" # noqa: E501

def __init__(self) -> None:
"""Initialize a :class:`SerMol` instance."""
super().__init__(Mol)

def encode(self, obj: Mol, make_rec: MakeRec) -> ReturnDict:
def encode(self, obj: Mol, make_rec: Callable[[T], Dict[str, T]]) -> Dict[str, T]:
"""Encode the passed RDKit Mol."""
return make_rec(base64.b64encode(obj.ToBinary()).decode('ascii'))

def decode(self, cls: Type[Mol], data: str) -> Mol:
"""Decode the passed data into a RDKit Mol."""
return cls(base64.b64decode(data.encode('ascii')))


class SerSettings(Serialiser):
"""Class to encode and decode the :class:`~qmflows.Settings` class using its internal dictionary structure.""" # noqa: E501

def __init__(self) -> None:
"""Initialize a :class:`SerSettings` instance."""
super().__init__(Settings)

def encode(self, obj: Settings, make_rec: MakeRec) -> ReturnDict:
def encode(self, obj: Settings, make_rec: Callable[[T], Dict[str, T]]) -> Dict[str, T]:
"""Encode the passed PLAMS Settings."""
return make_rec(obj.as_dict())

def decode(self, cls: Type[Settings], data: Mapping) -> Settings:
"""Decode the passed data into a PLAMS Settings."""
return cls(data)


class SerNDFrame(Serialiser):
"""Class to encode and decode the :class:`pandas.Series` and :class:`pandas.DataFrame` instances.""" # noqa: E501

def __init__(self, name: Any = NDFrame) -> None:
"""Initialize a :class:`SerNDFrame` instance."""
super().__init__(name)

def encode(self, obj: NDFrame, make_rec: MakeRec) -> ReturnDict:
def encode(self, obj: NDFrame, make_rec: Callable[[T], Dict[str, T]]) -> Dict[str, T]:
"""Encode the passed pandas Series or DataFrame."""
return make_rec(obj.to_dict())

def decode(self, cls: Type[NDFrame], data: Mapping) -> NDFrame:
"""Decode the passed data into a pandas Series or DataFrame."""
return cls(data)

0 comments on commit 0269cc9

Please sign in to comment.