Skip to content

Commit ca5d2c3

Browse files
committed
fix: resolve CI failures (ruff formatting and E501 ignore)
1 parent aa783c3 commit ca5d2c3

26 files changed

Lines changed: 647 additions & 434 deletions

pymiro/app.py

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
"""
22
App entry point for pymiro.
33
"""
4-
import sys
4+
55
import asyncio
6-
from typing import Callable
6+
import sys
7+
from collections.abc import Callable
78

8-
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout
9-
import qasync # type: ignore
9+
import qasync # type: ignore
10+
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
1011

11-
from pymiro.core.vnode import VNode
12-
from pymiro.core.reconciler import reconcile
1312
from pymiro.backends.qt.renderer import QtRenderer
13+
from pymiro.core.reconciler import reconcile
1414
from pymiro.core.signals import effect
15-
from pymiro.dev import DevLogger, install_error_handler, HotReloader
15+
from pymiro.core.vnode import VNode
16+
from pymiro.dev import DevLogger, HotReloader, install_error_handler
17+
from pymiro.theme.presets import DARK_THEME, DEFAULT_THEME
1618
from pymiro.theme.provider import ThemeProvider
1719
from pymiro.theme.theme import Theme
18-
from pymiro.theme.presets import DEFAULT_THEME, DARK_THEME
20+
1921

2022
class App:
2123
def __init__(
@@ -24,7 +26,7 @@ def __init__(
2426
width: int = 800,
2527
height: int = 600,
2628
dev: bool = False,
27-
theme: str | Theme = "default"
29+
theme: str | Theme = "default",
2830
) -> None:
2931
self.title = title
3032
self.width = width
@@ -34,12 +36,12 @@ def __init__(
3436
self.current_tree: VNode | None = None
3537
self.logger = DevLogger(enabled=dev)
3638
self.reloader: HotReloader | None = None
37-
39+
3840
if isinstance(theme, str):
3941
self.theme = DARK_THEME if theme == "dark" else DEFAULT_THEME
4042
else:
4143
self.theme = theme
42-
44+
4345
if self.dev:
4446
install_error_handler()
4547
version = sys.version.split(" ")[0]
@@ -50,37 +52,38 @@ def run(self, component: Callable[[], VNode]) -> None:
5052
app = QApplication.instance()
5153
if app is None:
5254
app = QApplication(sys.argv)
53-
55+
5456
ThemeProvider.set(self.theme)
55-
57+
5658
# 2. create main QMainWindow
5759
main_window = QMainWindow()
5860
main_window.setWindowTitle(self.title)
5961
main_window.resize(self.width, self.height)
60-
62+
6163
central_widget = QWidget()
6264
central_layout = QVBoxLayout()
6365
central_widget.setLayout(central_layout)
6466
main_window.setCentralWidget(central_widget)
65-
67+
6668
# 3. setup qasync event loop
6769
loop = qasync.QEventLoop(app)
6870
asyncio.set_event_loop(loop)
69-
71+
7072
# 4. setup renderer
7173
self.renderer = QtRenderer(root_widget=central_widget, logger=self.logger)
72-
74+
7375
if self.dev:
7476
self.logger.mount(component.__name__)
7577
self.reloader = HotReloader(
7678
root_component=component,
7779
reconciler_fn=lambda old, new: reconcile(old, new, logger=self.logger),
7880
renderer=self.renderer,
7981
watch_dir=".",
80-
logger=self.logger
82+
logger=self.logger,
8183
)
82-
84+
8385
is_render_pending = False
86+
8487
def render_cycle() -> None:
8588
nonlocal is_render_pending
8689
is_render_pending = False
@@ -100,20 +103,21 @@ def schedule_render() -> None:
100103

101104
# initial render
102105
self._root_dispose = effect(schedule_render)
103-
106+
104107
if self.reloader:
105108
self.reloader.start()
106-
109+
107110
# Cleanup on exit
108111
if hasattr(app, "aboutToQuit"):
109112
app.aboutToQuit.connect(self._root_dispose)
110113
if self.reloader:
111114
app.aboutToQuit.connect(self.reloader.stop)
112-
115+
113116
main_window.show()
114-
117+
115118
# 6. start event loop
116119
with loop:
117120
loop.run_forever()
118121

122+
119123
__all__ = ["App"]

pymiro/backends/qt/renderer.py

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
"""
22
Qt Renderer for pymiro.
33
"""
4+
45
from typing import Any
6+
7+
from PySide6.QtCore import QMetaObject, QObject, Qt, Slot
58
from PySide6.QtWidgets import QWidget
6-
from PySide6.QtCore import QObject, QMetaObject, Qt, Slot
79

8-
from pymiro.core.reconciler import CreateNode, UpdateProps, DestroyNode, SetChildren, MoveNode, Patch
9-
from pymiro.backends.qt.widgets import create_widget, apply_prop, remove_prop
10+
from pymiro.backends.qt.widgets import apply_prop, create_widget, remove_prop
11+
from pymiro.core.reconciler import (
12+
CreateNode,
13+
DestroyNode,
14+
MoveNode,
15+
Patch,
16+
SetChildren,
17+
UpdateProps,
18+
)
19+
1020

1121
class QtRenderer(QObject):
1222
"""
1323
Implements the Renderer protocol for Qt.
1424
Mutates Qt widgets based on reconciler patches.
1525
"""
26+
1627
def __init__(self, root_widget: QWidget | None = None, logger: Any = None) -> None:
1728
super().__init__()
1829
self.logger = logger
@@ -23,11 +34,7 @@ def __init__(self, root_widget: QWidget | None = None, logger: Any = None) -> No
2334
self._pending_patches: list[Patch] = []
2435

2536
def create(
26-
self,
27-
node_id: str,
28-
type: str,
29-
props: dict[str, Any],
30-
parent_id: str | None
37+
self, node_id: str, type: str, props: dict[str, Any], parent_id: str | None
3138
) -> None:
3239
widget = create_widget(type)
3340
self.registry[node_id] = widget
@@ -51,12 +58,7 @@ def create(
5158
if layout is not None:
5259
layout.addWidget(widget)
5360

54-
def update(
55-
self,
56-
node_id: str,
57-
changed: dict[str, Any],
58-
removed: list[str]
59-
) -> None:
61+
def update(self, node_id: str, changed: dict[str, Any], removed: list[str]) -> None:
6062
widget = self.registry.get(node_id)
6163
if widget is None:
6264
return
@@ -77,8 +79,10 @@ def destroy(self, node_id: str) -> None:
7779
widget = self.registry.pop(node_id, None)
7880
if widget is None:
7981
return
80-
81-
events_to_unbind = [evt for (nid, evt) in list(self.event_connections.keys()) if nid == node_id]
82+
83+
events_to_unbind = [
84+
evt for (nid, evt) in list(self.event_connections.keys()) if nid == node_id
85+
]
8286
for evt in events_to_unbind:
8387
self.unbind_event(node_id, evt)
8488

@@ -87,88 +91,86 @@ def destroy(self, node_id: str) -> None:
8791
layout = parent_widget.layout()
8892
if layout is not None:
8993
layout.removeWidget(widget)
90-
94+
9195
widget.deleteLater()
9296

93-
def set_children(
94-
self,
95-
parent_id: str,
96-
child_ids: list[str]
97-
) -> None:
97+
def set_children(self, parent_id: str, child_ids: list[str]) -> None:
9898
parent = self.registry.get(parent_id)
9999
if parent is None:
100100
return
101101
layout = parent.layout()
102102
if layout is None:
103103
return
104-
104+
105105
for i in reversed(range(layout.count())):
106106
item = layout.itemAt(i)
107107
if item is not None:
108108
w = item.widget()
109109
if w is not None:
110110
layout.removeWidget(w)
111-
112-
is_grid = hasattr(layout, "addWidget") and parent.property("grid_cols") is not None
111+
112+
is_grid = (
113+
hasattr(layout, "addWidget") and parent.property("grid_cols") is not None
114+
)
113115
cols = parent.property("grid_cols") or 2
114-
116+
115117
for idx, cid in enumerate(child_ids):
116118
child = self.registry.get(cid)
117119
if child is not None:
118120
if is_grid:
119-
layout.addWidget(child, idx // cols, idx % cols) # type: ignore
121+
layout.addWidget(child, idx // cols, idx % cols) # type: ignore
120122
else:
121123
layout.addWidget(child)
122124

123-
def move(
124-
self,
125-
node_id: str,
126-
new_parent_id: str
127-
) -> None:
125+
def move(self, node_id: str, new_parent_id: str) -> None:
128126
widget = self.registry.get(node_id)
129127
new_parent = self.registry.get(new_parent_id)
130128
if widget is None or new_parent is None:
131129
return
132-
130+
133131
old_parent = widget.parentWidget()
134132
if old_parent is not None:
135133
old_layout = old_parent.layout()
136134
if old_layout is not None:
137135
old_layout.removeWidget(widget)
138-
136+
139137
new_layout = new_parent.layout()
140138
if new_layout is not None:
141-
is_grid = hasattr(new_layout, "addWidget") and new_parent.property("grid_cols") is not None
139+
is_grid = (
140+
hasattr(new_layout, "addWidget")
141+
and new_parent.property("grid_cols") is not None
142+
)
142143
if is_grid:
143144
# Approximate move appending to the end
144145
idx = new_layout.count()
145146
cols = new_parent.property("grid_cols") or 2
146-
new_layout.addWidget(widget, idx // cols, idx % cols) # type: ignore
147+
new_layout.addWidget(widget, idx // cols, idx % cols) # type: ignore
147148
else:
148149
new_layout.addWidget(widget)
149150

150-
def bind_event(
151-
self,
152-
node_id: str,
153-
event: str,
154-
handler: Any
155-
) -> None:
151+
def bind_event(self, node_id: str, event: str, handler: Any) -> None:
156152
widget = self.registry.get(node_id)
157153
if widget is None:
158154
return
159-
155+
160156
if (node_id, event) in self.event_connections:
161157
# Update the existing wrapper without disconnecting Qt signal
162158
self.event_connections[(node_id, event)]["state"]["handler"] = handler
163159
return
164-
160+
165161
state = {"handler": handler}
166-
162+
167163
def wrapper(*args: Any, **kwargs: Any) -> None:
168164
state["handler"](*args, **kwargs)
169-
170-
from PySide6.QtWidgets import QLineEdit, QCheckBox, QComboBox, QSlider, QTabWidget
171-
165+
166+
from PySide6.QtWidgets import (
167+
QCheckBox,
168+
QComboBox,
169+
QLineEdit,
170+
QSlider,
171+
QTabWidget,
172+
)
173+
172174
conn = None
173175
if event == "on_click" and hasattr(widget, "clicked"):
174176
conn = widget.clicked.connect(wrapper)
@@ -183,22 +185,29 @@ def wrapper(*args: Any, **kwargs: Any) -> None:
183185
conn = widget.valueChanged.connect(wrapper)
184186
elif isinstance(widget, QTabWidget):
185187
conn = widget.currentChanged.connect(wrapper)
186-
188+
187189
if conn is not None:
188-
self.event_connections[(node_id, event)] = {"conn": conn, "wrapper": wrapper, "state": state}
190+
self.event_connections[(node_id, event)] = {
191+
"conn": conn,
192+
"wrapper": wrapper,
193+
"state": state,
194+
}
189195

190-
def unbind_event(
191-
self,
192-
node_id: str,
193-
event: str
194-
) -> None:
196+
def unbind_event(self, node_id: str, event: str) -> None:
195197
data = self.event_connections.pop((node_id, event), None)
196198
if data is not None:
197199
conn = data["conn"]
198200
widget = self.registry.get(node_id)
199201
if widget is not None:
200202
try:
201-
from PySide6.QtWidgets import QLineEdit, QCheckBox, QComboBox, QSlider, QTabWidget
203+
from PySide6.QtWidgets import (
204+
QCheckBox,
205+
QComboBox,
206+
QLineEdit,
207+
QSlider,
208+
QTabWidget,
209+
)
210+
202211
if event == "on_click" and hasattr(widget, "clicked"):
203212
widget.clicked.disconnect(conn)
204213
elif event == "on_change":
@@ -236,6 +245,9 @@ def commit(self, patches: list[Patch]) -> None:
236245
for patch in patches:
237246
self.logger.commit(patch)
238247
self._pending_patches.extend(patches)
239-
QMetaObject.invokeMethod(self, "_apply_patches", Qt.ConnectionType.QueuedConnection)
248+
QMetaObject.invokeMethod(
249+
self, "_apply_patches", Qt.ConnectionType.QueuedConnection
250+
)
251+
240252

241253
__all__ = ["QtRenderer"]

0 commit comments

Comments
 (0)