Skip to content

Commit f2252f9

Browse files
authored
chore: bunch of typing fixes, run pyright on ci (#252)
* chore: bunch of typing fixes, run pyright on ci * fix test
1 parent a95379f commit f2252f9

25 files changed

+116
-70
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ jobs:
2121
- uses: actions/checkout@v4
2222
- run: pipx run check-manifest
2323

24+
pyright:
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v4
28+
- uses: astral-sh/setup-uv@v6
29+
- run: uv run pyright
30+
2431
test:
2532
name: ${{ matrix.platform }} py${{ matrix.python-version }}
2633
runs-on: ${{ matrix.platform }}

.pre-commit-config.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ repos:
2222
args: ["--fix", "--unsafe-fixes"]
2323
- id: ruff-format
2424

25-
2625
- repo: https://github.com/pre-commit/mirrors-mypy
2726
rev: v1.16.1
2827
hooks:
@@ -32,3 +31,14 @@ repos:
3231
- pydantic >2
3332
- pydantic-compat
3433
- in-n-out
34+
35+
- repo: local
36+
hooks:
37+
- id: pyright
38+
stages: [manual]
39+
name: pyright
40+
language: system
41+
exclude: "^tests/.*|^demo/.*|^docs/.*"
42+
types_or: [python, pyi]
43+
require_serial: true
44+
entry: uv run pyright

demo/keybinding_helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
w = QModelKeyBindingEdit()
99
w.editingFinished.connect(lambda: print(w.keyBinding()))
1010
w.show()
11-
sys.exit(app.exec_())
11+
sys.exit(app.exec())

demo/model_app.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from pathlib import Path
2+
from typing import TYPE_CHECKING, cast
23

34
from qtpy.QtCore import QFile, QFileInfo, QSaveFile, Qt, QTextStream
45
from qtpy.QtWidgets import QApplication, QFileDialog, QMessageBox, QTextEdit
@@ -7,6 +8,9 @@
78
from app_model.backends.qt import QModelMainWindow
89
from app_model.expressions import create_context
910

11+
if TYPE_CHECKING:
12+
from app_model.backends.qt._qmenu import QModelMenuBar
13+
1014

1115
class MainWindow(QModelMainWindow):
1216
def __init__(self, app: Application) -> None:
@@ -21,7 +25,8 @@ def __init__(self, app: Application) -> None:
2125
self.addModelToolBar(MenuId.FILE, exclude={CommandId.SAVE_AS, CommandId.EXIT})
2226
self.addModelToolBar(MenuId.EDIT)
2327
self.addModelToolBar(MenuId.HELP)
24-
self.statusBar().showMessage("Ready")
28+
if sb := self.statusBar():
29+
sb.showMessage("Ready")
2530

2631
self.set_current_file("")
2732

@@ -33,11 +38,13 @@ def _update_context(self, available: bool) -> None:
3338
self._ctx["copyAvailable"] = available
3439

3540
def _on_context_changed(self) -> None:
36-
self.menuBar().update_from_context(self._ctx)
41+
mb = cast("QModelMenuBar", self.menuBar())
42+
mb.update_from_context(self._ctx)
3743

3844
def set_current_file(self, fileName: str) -> None:
3945
self._cur_file = fileName
40-
self._text_edit.document().setModified(False)
46+
if doc := self._text_edit.document():
47+
doc.setModified(False)
4148
self.setWindowModified(False)
4249

4350
if self._cur_file:
@@ -58,11 +65,11 @@ def save_as(self) -> bool:
5865

5966
def save_file(self, fileName: str) -> bool:
6067
error = None
61-
QApplication.setOverrideCursor(Qt.WaitCursor)
68+
QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)
6269
file = QSaveFile(fileName)
6370
if file.open(QFile.OpenModeFlag.WriteOnly | QFile.OpenModeFlag.Text): # type: ignore
6471
outf = QTextStream(file)
65-
outf << self._text_edit.toPlainText()
72+
outf << self._text_edit.toPlainText() # pyright: ignore
6673
if not file.commit():
6774
reason = file.errorString()
6875
error = f"Cannot write file {fileName}:\n{reason}."
@@ -77,7 +84,7 @@ def save_file(self, fileName: str) -> bool:
7784
return True
7885

7986
def maybe_save(self) -> bool:
80-
if self._text_edit.document().isModified():
87+
if (doc := self._text_edit.document()) and doc.isModified():
8188
ret = QMessageBox.warning(
8289
self,
8390
"Application",
@@ -113,12 +120,13 @@ def load_file(self, fileName: str) -> None:
113120
return
114121

115122
inf = QTextStream(file)
116-
QApplication.setOverrideCursor(Qt.WaitCursor)
123+
QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)
117124
self._text_edit.setPlainText(inf.readAll())
118125
QApplication.restoreOverrideCursor()
119126

120127
self.set_current_file(fileName)
121-
self.statusBar().showMessage("File loaded", 2000)
128+
if sb := self.statusBar():
129+
sb.showMessage("File loaded", 2000)
122130

123131
def about(self) -> None:
124132
QMessageBox.about(
@@ -255,4 +263,4 @@ class CommandId:
255263

256264
app.injection_store.register_provider(lambda: main_win, MainWindow)
257265
main_win.show()
258-
qapp.exec_()
266+
qapp.exec()

demo/multi_file/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
qapp = QApplication.instance() or QApplication([])
1111
app = MyApp()
1212
app.show()
13-
qapp.exec_()
13+
qapp.exec()

demo/multi_file/functions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ def open_file() -> None:
77

88

99
def close() -> None:
10-
QApplication.activeWindow().close()
10+
if win := QApplication.activeWindow():
11+
win.close()
1112
print("close")
1213

1314

demo/qapplication.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright (C) 2013 Riverbank Computing Limited.
22
# Copyright (C) 2022 The Qt Company Ltd.
33
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
4+
# pyright: reportOptionalMemberAccess=false
45

56
from fonticon_fa6 import FA6S
67
from qtpy.QtCore import QFile, QFileInfo, QSaveFile, Qt, QTextStream
@@ -204,7 +205,7 @@ def load_file(self, fileName: str) -> None:
204205
return
205206

206207
inf = QTextStream(file)
207-
QApplication.setOverrideCursor(Qt.WaitCursor)
208+
QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)
208209
self._text_edit.setPlainText(inf.readAll())
209210
QApplication.restoreOverrideCursor()
210211

@@ -213,11 +214,11 @@ def load_file(self, fileName: str) -> None:
213214

214215
def save_file(self, fileName: str) -> bool:
215216
error = None
216-
QApplication.setOverrideCursor(Qt.WaitCursor)
217+
QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)
217218
file = QSaveFile(fileName)
218219
if file.open(QFile.OpenModeFlag.WriteOnly | QFile.OpenModeFlag.Text):
219220
outf = QTextStream(file)
220-
outf << self._text_edit.toPlainText()
221+
outf << self._text_edit.toPlainText() # pyright: ignore
221222
if not file.commit():
222223
reason = file.errorString()
223224
error = f"Cannot write file {fileName}:\n{reason}."
@@ -255,4 +256,4 @@ def stripped_name(self, fullFileName: str) -> str:
255256
qapp.setAttribute(Qt.ApplicationAttribute.AA_DontShowIconsInMenus)
256257
main_win = MainWindow()
257258
main_win.show()
258-
qapp.exec_()
259+
qapp.exec()

docs/getting_started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ main.setModelMenuBar(['File'])
223223
main.addModelToolBar('File')
224224
main.show()
225225

226-
app.exec_()
226+
app.exec()
227227
```
228228

229229
You should now have a QMainWindow with a menu bar and toolbar populated with

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ dev = [
7979
"pre-commit-uv>=4",
8080
"pyqt6>=6.8.0",
8181
"rich>=13.9.4",
82+
"pyright>=1.1.402",
8283
]
8384
docs = [
8485
"griffe-fieldz>=0.1.0",
@@ -174,6 +175,11 @@ disallow_untyped_defs = false
174175
module = ["qtpy.*"]
175176
implicit_reexport = true
176177

178+
[tool.pyright]
179+
include = ["src", "demo"]
180+
reportArgumentType = "none" # hard with pydantic casting
181+
venvPath = "."
182+
177183
# https://coverage.readthedocs.io/
178184
[tool.coverage.report]
179185
show_missing = true

src/app_model/_app.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from types import MappingProxyType
88
from typing import (
99
TYPE_CHECKING,
10+
Any,
1011
ClassVar,
1112
Literal,
1213
Optional,
@@ -28,8 +29,10 @@
2829
)
2930

3031
if TYPE_CHECKING:
32+
from typing import Callable
33+
3134
from .expressions import Expr
32-
from .registries._register import CommandCallable, CommandDecorator
35+
from .registries._register import CommandDecorator
3336
from .types import (
3437
DisposeCallable,
3538
IconOrDict,
@@ -231,7 +234,7 @@ def register_action(
231234
action: str,
232235
title: str,
233236
*,
234-
callback: CommandCallable,
237+
callback: Callable[..., Any],
235238
category: str | None = ...,
236239
tooltip: str | None = ...,
237240
icon: IconOrDict | None = ...,
@@ -246,7 +249,7 @@ def register_action(
246249
action: str | Action,
247250
title: str | None = None,
248251
*,
249-
callback: CommandCallable | None = None,
252+
callback: Callable[..., Any] | None = None,
250253
category: str | None = None,
251254
tooltip: str | None = None,
252255
icon: IconOrDict | None = None,

0 commit comments

Comments
 (0)