Skip to content
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
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,24 @@ jobs:

- name: Run pytest
run: pytest -v tests/

pre-commit:

runs-on: ubuntu-latest
timeout-minutes: 30

steps:

- uses: actions/checkout@v7

- name: Set up uv
uses: astral-sh/setup-uv@v7
with:
python-version: '3.12'
activate-environment: true

- name: Install dependencies
run: uv pip install -e .[dev]

- name: Run pre-commit
run: pre-commit run --all-files || (git status --short; git diff; exit 1)
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ apps_meta.sqlite
*.egg-info
aiidalab_home.egg-info/*
build/*
uv.lock

# Transient per-session notebook copies created by Appmode.
*-[0-9].ipynb
Expand Down
8 changes: 7 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
ci:
autoupdate_schedule: quarterly
skip: [ty]
Comment thread
edan-bainglass marked this conversation as resolved.
Comment thread
edan-bainglass marked this conversation as resolved.

repos:

Expand All @@ -17,9 +18,14 @@ repos:
rev: v0.15.20
hooks:
- id: ruff-format
- id: ruff
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix, --show-fixes]

- repo: https://github.com/astral-sh/ty-pre-commit
rev: v0.0.65
hooks:
- id: ty

- repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt
rev: 0.2.3
hooks:
Expand Down
11 changes: 11 additions & 0 deletions __builtins__.pyi
Comment thread
edan-bainglass marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
def display(
*objs,
include=None,
exclude=None,
metadata=None,
transient=None,
display_id=None,
**kwargs,
): ...

jupyter_notebook_url: str
2 changes: 1 addition & 1 deletion home/node_preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
def render_node_preview(node):
"""Render a node preview using AWB when it is available."""
try:
from aiidalab_widgets_base import viewer # noqa: PLC0415
from aiidalab_widgets_base import viewer # ty: ignore[unresolved-import]
except ImportError:
return ipw.HTML(
value=str(node) + "<br><em>" + AWB_UNAVAILABLE_MESSAGE + "</em>"
Expand Down
12 changes: 8 additions & 4 deletions home/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ def __init__(self, process=None, **kwargs):

def generate_flat_mapping(
self, process: orm.ProcessNode | None = None
) -> None | dict[str, str]:
) -> dict[str, str] | None:
"""Generate a dict of input to node uuid mapping.

If the input port is a namespace, it will further parse the namespace and attach the entity the
Expand Down Expand Up @@ -384,7 +384,7 @@ def flatten(d, parent_key="", sep="."):

return options_map

def show_selected_input(self, change=None):
def show_selected_input(self, change):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why drop the default?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess otherwise ty complained about line 392 and on. But this also means that show_selected_input can only be used as a handler, or with an empty dict. I'm guessing we weren't using it directly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I've checked that we're not calling this function directly anywhere (and ty would anyway complain otherwise)

"""Function that displays process inputs selected in the `inputs` Dropdown widget."""
with self.output:
self.info.value = ""
Expand Down Expand Up @@ -506,8 +506,10 @@ def __init__(self, process=None, **kwargs):
children=[ipw.HBox([outputs, self.info]), self.output], **kwargs
)

def show_selected_output(self, change=None):
def show_selected_output(self, change):
"""Function that displays process output selected in the `outputs` Dropdown widget."""
if self.process is None:
return
with self.output:
self.info.value = ""
clear_output()
Expand Down Expand Up @@ -598,6 +600,8 @@ def update(self):

@property
def current_state(self):
if self.process is None or self.process.process_state is None:
return None
return self.process.process_state.value


Expand Down Expand Up @@ -646,7 +650,7 @@ def update(self, _=None):
process_state=self.process_states,
process_label=self.process_label,
exit_status=None,
failed=None,
failed=False,
)
relationships = {}
if self.incoming_node:
Expand Down
2 changes: 1 addition & 1 deletion open_app.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
" redirect = query.get(\"redirect\", None)\n",
" if redirect:\n",
" redirect_url = urlparse.urlunsplit(\n",
" url._replace(path=redirect[0], query=None, fragment=None)\n",
" url._replace(path=redirect[0], query=None, fragment=None) # ty: ignore[invalid-argument-type]\n",
" )\n",
" header.value = (\n",
" f'Redirecting now to <a href=\"{redirect_url}\">{redirect_url}</a>...'\n",
Expand Down
13 changes: 11 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ build-backend = "setuptools.build_meta"
[tool.ruff]
line-length = 88
show-fixes = true
target-version = "py38"
target-version = "py39"

[tool.ruff.lint]
ignore = ["E501", "E402", "B904", "TRY003"]
ignore = ["E501", "E402", "B904", "TRY003", "PLC0415"]
select = [
"A", # flake8-builtins
"ARG", # flake8-unused-arguments
Expand All @@ -30,3 +30,12 @@ select = [
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["ARG001"]
"tests_notebooks/*" = ["ARG001"]

# TODO: Fix type errors in these files
[[tool.ty.overrides]]
include = [
"home/code_setup.py",
"home/computational_resources.py",
]
[tool.ty.overrides.rules]
all = "ignore"
Comment thread
edan-bainglass marked this conversation as resolved.
Outdated
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ dev =
pytest-docker~=3.1.0
pytest-selenium~=4.1.0
selenium~=4.23.0
types-pexpect~=4.9
types-requests~=2.32
types-Markdown>=3.4

[flake8]
ignore =
Expand Down
4 changes: 2 additions & 2 deletions start.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@
"\n",
"home = AiidaLabHome()\n",
"if \"move_up\" in parsed_url:\n",
" home.move_updown(parsed_url[\"move_up\"][0], -1)\n",
" home.move_updown(parsed_url[\"move_up\"][0], -1) # ty: ignore[invalid-argument-type]\n",
"elif \"move_down\" in parsed_url:\n",
" home.move_updown(parsed_url[\"move_down\"][0], +1)\n",
" home.move_updown(parsed_url[\"move_down\"][0], +1) # ty: ignore[invalid-argument-type]\n",
"home.render()"
]
},
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@ def multiply_add_completed_workchain(aiida_local_code_bash):
"z": orm.Int(3),
"code": aiida_local_code_bash,
}
_, process = engine.run_get_node(MultiplyAddWorkChain, **inputs)
_, process = engine.run_get_node(MultiplyAddWorkChain, **inputs) # ty: ignore[invalid-argument-type]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inputs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, ty doesn't understand that the inputs dict arguments are mapped into MultiplyAddWorkChain I think

return process
2 changes: 1 addition & 1 deletion tests/test_computational_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ def test_optional_new_code_setup_widget():
assert not hasattr(widget, "btn_setup_new_code")
assert not hasattr(widget, "_setup_new_code_output")
assert not hasattr(widget, "resource_setup")
selection_row = widget.children[0] # type: ignore
selection_row = widget.children[0]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this showing the power of ty? I recall mypy would complain about indexing children. Or did ipywidgets fix their types for children in v8?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, I think ty is just hiding this error somehow, since it thinks that widget.children has type Never

    --> tests/test_computational_resources.py:1039:17
     |
1039 |     reveal_type(widget.children)
     |                 ^^^^^^^^^^^^^^^ `Never`


assert len(selection_row.children) == 1 # no new code setup button


Expand Down
8 changes: 4 additions & 4 deletions tests/test_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ def test_refresh_calls_do_refresh(run_threads_synchronously):
widget = _DummySection()
widget.refresh()
assert widget.refresh_calls == 1
assert widget.refresh_button.disabled is False
assert widget.refresh_button.disabled is False # ty: ignore[unresolved-attribute]
assert widget.info.value == ""
assert "Last updated" in widget._last_updated.value
assert "Last updated" in widget._last_updated.value # ty: ignore[unresolved-attribute]


def test_refresh_guards_reentry(run_threads_synchronously, monkeypatch):
Expand All @@ -52,6 +52,6 @@ def test_refresh_shows_error_on_exception(run_threads_synchronously):
widget = _DummySection(fail=True)
widget.refresh()
assert "Failed to refresh" in widget.info.value
assert widget.refresh_button.disabled is False
assert widget.refresh_button.disabled is False # ty: ignore[unresolved-attribute]
Comment thread
danielhollas marked this conversation as resolved.
Outdated
assert widget._refreshing is False
assert widget._last_updated.value == ""
assert widget._last_updated.value == "" # ty: ignore[unresolved-attribute]
2 changes: 1 addition & 1 deletion tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def capture_display(monkeypatch):
def test_render_node_preview_uses_awb_when_available(monkeypatch):
node = orm.Int(1)
module = types.ModuleType("aiidalab_widgets_base")
module.viewer = lambda _: "mock-viewer"
module.viewer = lambda _: "mock-viewer" # ty: ignore[unresolved-attribute]

monkeypatch.setitem(sys.modules, "aiidalab_widgets_base", module)

Expand Down
Loading