Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type Checking: aiida/engine (+bug fixes) #4669

Merged
merged 19 commits into from
Jan 25, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ repos:
files: >-
(?x)^(
aiida/common/progress_reporter.py|
aiida/engine/processes/calcjobs/calcjob.py|
aiida/engine/processes/.*py|
aiida/manage/database/delete/nodes.py|
aiida/tools/graph/graph_traversers.py|
aiida/tools/groups/paths.py|
Expand Down
4 changes: 2 additions & 2 deletions aiida/engine/processes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
from .workchains import *

__all__ = (
builder.__all__ + calcjobs.__all__ + exit_code.__all__ + functions.__all__ + ports.__all__ + process.__all__ +
process_spec.__all__ + workchains.__all__
builder.__all__ + calcjobs.__all__ + exit_code.__all__ + functions.__all__ + # type: ignore[name-defined]
ports.__all__ + process.__all__ + process_spec.__all__ + workchains.__all__ # type: ignore[name-defined]
)
26 changes: 12 additions & 14 deletions aiida/engine/processes/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
###########################################################################
"""Convenience classes to help building the input dictionaries for Processes."""
import collections
from typing import Any, Type, TYPE_CHECKING

from aiida.orm import Node
from aiida.engine.processes.ports import PortNamespace

if TYPE_CHECKING:
from aiida.engine.processes.process import Process

__all__ = ('ProcessBuilder', 'ProcessBuilderNamespace')


Expand All @@ -22,15 +26,15 @@ class ProcessBuilderNamespace(collections.abc.MutableMapping):
Dynamically generates the getters and setters for the input ports of a given PortNamespace
"""

def __init__(self, port_namespace):
def __init__(self, port_namespace: PortNamespace) -> None:
"""Dynamically construct the get and set properties for the ports of the given port namespace.

For each port in the given port namespace a get and set property will be constructed dynamically
and added to the ProcessBuilderNamespace. The docstring for these properties will be defined
by calling str() on the Port, which should return the description of the Port.

:param port_namespace: the inputs PortNamespace for which to construct the builder
:type port_namespace: str

"""
# pylint: disable=super-init-not-called
self._port_namespace = port_namespace
Expand All @@ -52,7 +56,7 @@ def fgetter(self, name=name):
return self._data.get(name)
elif port.has_default():

def fgetter(self, name=name, default=port.default): # pylint: disable=cell-var-from-loop
def fgetter(self, name=name, default=port.default): # type: ignore # pylint: disable=cell-var-from-loop
return self._data.get(name, default)
else:

Expand All @@ -67,16 +71,12 @@ def fsetter(self, value, name=name):
getter.setter(fsetter) # pylint: disable=too-many-function-args
setattr(self.__class__, name, getter)

def __setattr__(self, attr, value):
def __setattr__(self, attr: str, value: Any) -> None:
"""Assign the given value to the port with key `attr`.

.. note:: Any attributes without a leading underscore being set correspond to inputs and should hence be
validated with respect to the corresponding input port from the process spec

:param attr: attribute
:type attr: str

:param value: value
"""
if attr.startswith('_'):
object.__setattr__(self, attr, value)
Expand All @@ -87,7 +87,7 @@ def __setattr__(self, attr, value):
if not self._port_namespace.dynamic:
raise AttributeError(f'Unknown builder parameter: {attr}')
else:
value = port.serialize(value)
value = port.serialize(value) # type: ignore[union-attr]
validation_error = port.validate(value)
if validation_error:
raise ValueError(f'invalid attribute value {validation_error.message}')
Expand Down Expand Up @@ -126,10 +126,8 @@ def _update(self, *args, **kwds):
principle the method functions just as `collections.abc.MutableMapping.update`.

:param args: a single mapping that should be mapped on the namespace
:type args: list

:param kwds: keyword value pairs that should be mapped onto the ports
:type kwds: dict
"""
if len(args) > 1:
raise TypeError(f'update expected at most 1 arguments, got {int(len(args))}')
Expand All @@ -147,7 +145,7 @@ def _update(self, *args, **kwds):
else:
self.__setattr__(key, value)

def _inputs(self, prune=False):
def _inputs(self, prune: bool = False) -> dict:
"""Return the entire mapping of inputs specified for this builder.

:param prune: boolean, when True, will prune nested namespaces that contain no actual values whatsoever
Expand Down Expand Up @@ -182,7 +180,7 @@ def _prune(self, value):
class ProcessBuilder(ProcessBuilderNamespace): # pylint: disable=too-many-ancestors
"""A process builder that helps setting up the inputs for creating a new process."""

def __init__(self, process_class):
def __init__(self, process_class: Type['Process']):
"""Construct a `ProcessBuilder` instance for the given `Process` class.

:param process_class: the `Process` subclass
Expand All @@ -192,6 +190,6 @@ def __init__(self, process_class):
super().__init__(self._process_spec.inputs)

@property
def process_class(self):
def process_class(self) -> Type['Process']:
"""Return the process class for which this builder is constructed."""
return self._process_class
2 changes: 1 addition & 1 deletion aiida/engine/processes/calcjobs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

from .calcjob import *

__all__ = (calcjob.__all__)
__all__ = (calcjob.__all__) # type: ignore[name-defined]
Loading