Skip to content

Commit d4f1a77

Browse files
committed
WIP: to mypy
1 parent e1be610 commit d4f1a77

File tree

10 files changed

+64
-27
lines changed

10 files changed

+64
-27
lines changed

.pre-commit-config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,14 @@ repos:
6666
docker/.*|
6767
docs/.*|
6868
69+
tests/.*|
70+
tests_integration/.*|
71+
72+
# Exclude the following files temporarily.
73+
src/aiidalab_qe/app/submission/__init__.py|
74+
src/aiidalab_qe/app/parameters/__init__.py|
75+
src/aiidalab_qe/__main__.py|
76+
src/aiidalab_qe/common/.*|
77+
src/aiidalab_qe/plugins/.*|
78+
6979
)$

setup.cfg

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ dev =
4646
pytest-regressions~=2.2
4747
pgtest==1.3.1
4848
pytest-cov~=4.0
49+
beautifulsoup4~=4.10
50+
types-beautifulsoup4~=4.10
4951

5052
[options.package_data]
5153
aiidalab_qe.app.parameters = qeapp.yaml
@@ -71,7 +73,25 @@ show_traceback = true
7173
strict = true
7274
warn_return_any = false
7375
warn_unreachable = true
74-
explicit_package_bases = true
76+
no_namespace_packages = true
77+
78+
[mypy-ipywidgets.*]
79+
ignore_missing_imports = true
80+
81+
[mypy-aiidalab_widgets_base.*]
82+
ignore_missing_imports = true
83+
84+
[mypy-aiida_quantumespresso.*]
85+
ignore_missing_imports = true
86+
87+
[mypy-IPython.*]
88+
ignore_missing_imports = true
89+
90+
[mypy-setuptools.*]
91+
ignore_missing_imports = true
92+
93+
[mypy-aiida_pseudo.*]
94+
ignore_missing_imports = true
7595

7696
[aiidalab]
7797
title = Quantum ESPRESSO

src/aiidalab_qe/app/configuration/advanced.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import ipywidgets as ipw
99
import traitlets as tl
10+
import typing as t
1011
from aiida import orm
1112
from aiida_quantumespresso.calculations.functions.create_kpoints_from_distance import (
1213
create_kpoints_from_distance,
@@ -222,7 +223,7 @@ def update_settings(self, **kwargs):
222223
def get_panel_value(self):
223224
# create the the initial_magnetic_moments as None (Default)
224225
# XXX: start from parameters = {} and then bundle the settings by purposes (e.g. pw, bands, etc.)
225-
parameters = {
226+
parameters: dict[str, t.Any] = {
226227
"initial_magnetic_moments": None,
227228
"pw": {
228229
"parameters": {

src/aiidalab_qe/app/configuration/pseudos.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import io
55
import re
6+
import typing as t
67

78
import ipywidgets as ipw
89
import traitlets as tl
@@ -19,6 +20,9 @@
1920
PseudoFamily,
2021
)
2122

23+
if t.TYPE_CHECKING:
24+
from aiida_pseudo.data.pseudo.upf import UpfData as TypeUpfData
25+
2226
UpfData = DataFactory("pseudo.upf")
2327
SsspFamily = GroupFactory("pseudo.family.sssp")
2428
PseudoDojoFamily = GroupFactory("pseudo.family.pseudo_dojo")
@@ -174,9 +178,8 @@ def set_text_color(self, change):
174178
self.dft_functional_help,
175179
self.dft_functional_prompt,
176180
):
177-
old_opacity = re.match(
178-
r"[\s\S]+opacity:([\S]+);[\S\s]+", html.value
179-
).groups()[0]
181+
matched = re.match(r"[\s\S]+opacity:([\S]+);[\S\s]+", html.value)
182+
old_opacity = matched.group(1) if matched else 1.0
180183
html.value = html.value.replace(
181184
f"opacity:{old_opacity};", f"opacity:{opacity};"
182185
)
@@ -344,7 +347,7 @@ def _reset(self):
344347
return
345348

346349
try:
347-
pseudos = pseudo_family.get_pseudos(structure=self.structure)
350+
pseudos = pseudo_family.get_pseudos(structure=self.structure) # type: ignore
348351
# get cutoffs dict of all elements
349352
cutoffs = self._get_cutoffs(pseudo_family)
350353
except ValueError as exception:
@@ -356,23 +359,23 @@ def _reset(self):
356359
self.pseudos = {kind: pseudo.uuid for kind, pseudo in pseudos.items()}
357360
self.set_pseudos(self.pseudos, cutoffs)
358361

359-
def _get_pseudos_family(self, pseudo_family: str) -> orm.Group:
362+
def _get_pseudos_family(self, pseudo_family: str) -> t.Optional[orm.Group]:
360363
"""Get the pseudo family from the database."""
361364
try:
362365
pseudo_set = (PseudoDojoFamily, SsspFamily, CutoffsPseudoPotentialFamily)
363-
pseudo_family = (
366+
pseudo_family_node = (
364367
orm.QueryBuilder()
365368
.append(pseudo_set, filters={"label": pseudo_family})
366369
.one()[0]
367370
)
371+
return pseudo_family_node
372+
368373
except exceptions.NotExistent as exception:
369374
raise exceptions.NotExistent(
370375
f"required pseudo family `{pseudo_family}` is not installed. Please use `aiida-pseudo install` to"
371376
"install it."
372377
) from exception
373378

374-
return pseudo_family
375-
376379
def _get_cutoffs(self, pseudo_family):
377380
"""Get the cutoffs from the pseudo family."""
378381
from aiida_pseudo.common.units import U
@@ -462,7 +465,7 @@ class PseudoUploadWidget(ipw.HBox):
462465
def __init__(
463466
self,
464467
kind: str = "",
465-
pseudo: UpfData | None = None,
468+
pseudo: TypeUpfData | None = None,
466469
cutoffs: dict | None = None,
467470
**kwargs,
468471
):

src/aiidalab_qe/app/result/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _on_click_kill_button(self, _=None):
103103
First kill the process, then update the kill button layout.
104104
"""
105105
workchain = [orm.load_node(self.process)]
106-
control.kill_processes(workchain)
106+
control.kill_processes(workchain) # type: ignore
107107

108108
# update the kill button layout
109109
self._update_kill_button_layout()

src/aiidalab_qe/app/result/workchain_viewer.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,10 @@ def __init__(self, node, export_dir=None, **kwargs):
167167
self._download_archive_button.on_click(self._download_archive)
168168
self._download_button_container = ipw.Box([self._download_archive_button])
169169

170-
if node.exit_status != 0:
170+
if node.exit_status != 0 and (final_calcjob := self._get_final_calcjob(node)):
171171
title = ipw.HTML(
172172
f"<h4>Workflow failed with exit status [{ node.exit_status }]</h4>"
173173
)
174-
final_calcjob = self._get_final_calcjob(node)
175174
env = Environment()
176175
template = resources.read_text(static, "workflow_failure.jinja")
177176
style = resources.read_text(static, "style.css")
@@ -224,7 +223,9 @@ def _download_archive(self, _):
224223
# Create archive file.
225224
with TemporaryDirectory() as tmpdir:
226225
self._prepare_calcjob_io(self.node, Path(tmpdir))
227-
shutil.make_archive(fn_archive.with_suffix(""), "zip", tmpdir)
226+
shutil.make_archive(
227+
str(fn_archive.with_suffix("")), "zip", tmpdir
228+
)
228229
Path(fn_lockfile).unlink() # Delete lock file.
229230
except Timeout:
230231
# Failed to obtain lock, presuming some other process is working on it.

src/aiidalab_qe/app/submission/__init__.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ def _update_state(self, _=None):
191191

192192
def _toggle_install_widgets(self, change):
193193
if change["new"]:
194-
self.children = [
194+
self.children = [ # type: ignore
195195
child for child in self.children if child is not change["owner"]
196196
]
197197

@@ -224,8 +224,8 @@ def _show_alert_message(self, message, alert_class="info"):
224224
def _update_resources(self, change):
225225
if change["new"] and (
226226
change["old"] is None
227-
or orm.load_code(change["new"]).computer.pk
228-
!= orm.load_code(change["old"]).computer.pk
227+
or orm.load_code(change["new"]).computer.pk # type: ignore
228+
!= orm.load_code(change["old"]).computer.pk # type: ignore
229229
):
230230
self.set_resource_defaults(orm.load_code(change["new"]).computer)
231231

@@ -277,7 +277,7 @@ def _check_resources(self):
277277

278278
num_cpus = self.resources_config.num_cpus.value
279279
on_localhost = (
280-
orm.load_node(self.pw_code.value).computer.hostname == "localhost"
280+
orm.load_node(self.pw_code.value).computer.hostname == "localhost" # type: ignore
281281
)
282282
if self.pw_code.value and on_localhost and num_cpus > 1:
283283
self._show_alert_message(
@@ -376,7 +376,7 @@ def submit(self, _=None):
376376

377377
self._update_state()
378378

379-
def _generate_label(self) -> dict:
379+
def _generate_label(self) -> str:
380380
"""Generate a label for the work chain based on the input parameters."""
381381
formula = self.input_structure.get_formula()
382382
properties = [
@@ -392,8 +392,7 @@ def _generate_label(self) -> dict:
392392
else:
393393
properties_info = f"properties on {', '.join(properties)}"
394394

395-
label = "{} {} {}".format(formula, relax_info, properties_info)
396-
return label
395+
return f"{formula} {relax_info} {properties_info}"
397396

398397
def _create_builder(self) -> ProcessBuilderNamespace:
399398
"""Create the builder for the `QeAppWorkChain` submit."""

src/aiidalab_qe/common/panel.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
66
AiiDAlab Team
77
"""
8+
from __future__ import annotations
9+
810
import ipywidgets as ipw
911

10-
DEFAULT_PARAMETERS = {}
12+
DEFAULT_PARAMETERS: dict = {}
1113

1214

1315
class Panel(ipw.VBox):
@@ -100,7 +102,7 @@ class ResultPanel(Panel):
100102

101103
title = "Result"
102104
# to specify which plugins (outputs) are needed for this result panel.
103-
workchain_labels = []
105+
workchain_labels: list = []
104106

105107
def __init__(self, node=None, **kwargs):
106108
self.node = node

src/aiidalab_qe/py.typed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Marker file for PEP 561

src/aiidalab_qe/workflows/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ def define(cls, spec):
8484
i += 1
8585
spec.outline(
8686
cls.setup,
87-
if_(cls.should_run_relax)(
88-
cls.run_relax,
89-
cls.inspect_relax
87+
if_(cls.should_run_relax)( # type: ignore
88+
cls.run_relax, # type: ignore
89+
cls.inspect_relax # type: ignore
9090
),
9191
cls.run_plugin,
9292
cls.inspect_plugin,

0 commit comments

Comments
 (0)