Skip to content

Commit 9a3b9bf

Browse files
authored
Merge pull request labelle-org#22 from maresb/types
Add some type hints
2 parents 65fcf51 + 6fded70 commit 9a3b9bf

21 files changed

+118
-98
lines changed

.pre-commit-config.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,16 @@ repos:
3636
hooks:
3737
- id: mypy
3838
additional_dependencies:
39+
- darkdetect
40+
- platformdirs
41+
# This is a hack to get type checking for PyQt6 but to stay under
42+
# pre-commit.ci's 250MiB limit.
43+
# <https://github.com/maresb/pyqt6-without-qt>
44+
- pyqt6-without-qt
45+
- typer
3946
- types-pillow
4047
- types-cffi
48+
- types-pygments
4149

4250
- repo: https://github.com/igorshubovych/markdownlint-cli
4351
rev: v0.39.0

src/labelle/cli/cli.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# === END LICENSE STATEMENT ===
88
import logging
99
from pathlib import Path
10-
from typing import List, Optional
10+
from typing import List, NoReturn, Optional
1111

1212
import typer
1313
from rich.console import Console
@@ -54,15 +54,15 @@
5454
LOG = logging.getLogger(__name__)
5555

5656

57-
def mm_to_payload_px(mm: float, margin: float):
57+
def mm_to_payload_px(mm: float, margin: float) -> float:
5858
"""Convert a length in mm to a number of pixels of payload.
5959
6060
The print resolution is 7 pixels/mm, and margin is subtracted from each side.
6161
"""
6262
return max(0, (mm * PIXELS_PER_MM) - margin * 2)
6363

6464

65-
def version_callback(value: bool):
65+
def version_callback(value: bool) -> None:
6666
if value:
6767
typer.echo(f"Labelle: {__version__}")
6868
raise typer.Exit()
@@ -92,7 +92,7 @@ def get_device_manager() -> DeviceManager:
9292

9393

9494
@app.command(hidden=True)
95-
def list_devices():
95+
def list_devices() -> NoReturn:
9696
device_manager = get_device_manager()
9797
console = Console()
9898
headers = ["Manufacturer", "Product", "Serial Number", "USB"]
@@ -123,7 +123,8 @@ def default(
123123
"--device",
124124
help=(
125125
"Select a particular device by filtering for a given substring "
126-
"in the device's manufacturer, product or serial number"
126+
"in the device's manufacturer, product or serial number. Call "
127+
"with 'list' to list all available devices."
127128
),
128129
rich_help_panel="Device Configuration",
129130
),
@@ -234,14 +235,17 @@ def default(
234235
Optional[int],
235236
typer.Option(help="Tape size [mm]", rich_help_panel="Device Configuration"),
236237
] = None,
237-
):
238+
) -> None:
238239
if ctx.invoked_subcommand is not None:
239240
return
240241

241242
if (not verbose) and (not is_verbose_env_vars()):
242243
# Neither --verbose flag nor the environment variable is set.
243244
set_not_verbose()
244245

246+
if device_pattern == ["list"]:
247+
list_devices()
248+
245249
# read config file
246250
try:
247251
font_path = get_font_path(font=font, style=style)
@@ -366,7 +370,7 @@ def default(
366370
output_bitmap(bitmap, output)
367371

368372

369-
def main():
373+
def main() -> None:
370374
configure_logging()
371375
app()
372376

src/labelle/gui/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
LOG = logging.getLogger(__name__)
99

1010

11-
def crash_msg_box(parent: QWidget, title: str, err: Exception):
11+
def crash_msg_box(parent: QWidget, title: str, err: Exception) -> None:
1212
print_exception(err)
1313
text = f"{err!r}\n\n{traceback.format_exc() if is_verbose() else VERBOSE_NOTICE}"
1414
QMessageBox.warning(parent, title, text)

src/labelle/gui/gui.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class LabelleWindow(QWidget):
3232
_render_context: RenderContext
3333
_render_widget: QWidget
3434

35-
def __init__(self):
35+
def __init__(self) -> None:
3636
super().__init__()
3737
self._label_bitmap_to_print = None
3838
self._detected_device = None
@@ -55,7 +55,7 @@ def __init__(self):
5555
self._label_list.populate()
5656
self._label_list.render_label()
5757

58-
def _init_elements(self):
58+
def _init_elements(self) -> None:
5959
self.setWindowTitle("Labelle GUI")
6060
self.setWindowIcon(QIcon(str(ICON_DIR / "logo_small.png")))
6161
self.setGeometry(200, 200, 1100, 400)
@@ -68,7 +68,7 @@ def _init_elements(self):
6868
minimum_horizontal_margin_mm=self._dymo_labeler.minimum_horizontal_margin_mm,
6969
)
7070

71-
def _init_connections(self):
71+
def _init_connections(self) -> None:
7272
self._label_list.renderPrintPreviewSignal.connect(self._update_preview_render)
7373
self._label_list.renderPrintPayloadSignal.connect(self._update_print_render)
7474
self._actions.print_label_signal.connect(self._on_print_label)
@@ -79,7 +79,7 @@ def _init_connections(self):
7979
self._on_device_selected
8080
)
8181

82-
def _init_layout(self):
82+
def _init_layout(self) -> None:
8383
self._actions.setParent(self._render_widget)
8484
self._render.setParent(self._render_widget)
8585

@@ -97,7 +97,7 @@ def _init_layout(self):
9797
self._window_layout.addWidget(self._render_widget)
9898
self.setLayout(self._window_layout)
9999

100-
def _on_settings_changed(self, settings: Settings):
100+
def _on_settings_changed(self, settings: Settings) -> None:
101101
assert self._dymo_labeler is not None
102102
self._dymo_labeler.tape_size_mm = settings.tape_size_mm
103103

@@ -121,13 +121,13 @@ def _on_settings_changed(self, settings: Settings):
121121
self._label_list.setEnabled(is_ready)
122122
self._render_widget.setEnabled(is_ready)
123123

124-
def _update_preview_render(self, preview_bitmap):
124+
def _update_preview_render(self, preview_bitmap: Image.Image) -> None:
125125
self._render.update_preview_render(preview_bitmap)
126126

127-
def _update_print_render(self, label_bitmap_to_print):
127+
def _update_print_render(self, label_bitmap_to_print) -> None:
128128
self._label_bitmap_to_print = label_bitmap_to_print
129129

130-
def _on_print_label(self):
130+
def _on_print_label(self) -> None:
131131
try:
132132
if self._label_bitmap_to_print is None:
133133
raise RuntimeError("No label to print! Call update_label_render first.")
@@ -136,12 +136,12 @@ def _on_print_label(self):
136136
except DymoLabelerPrintError as err:
137137
crash_msg_box(self, "Printing Failed!", err)
138138

139-
def _on_device_selected(self):
139+
def _on_device_selected(self) -> None:
140140
self._dymo_labeler.device = self._device_selector.selected_device
141141
self._settings_toolbar.on_settings_changed()
142142

143143

144-
def parse(app):
144+
def parse(app) -> None:
145145
"""Parse the arguments and options of the given app object."""
146146
parser = QCommandLineParser()
147147
parser.addHelpOption()
@@ -156,7 +156,7 @@ def parse(app):
156156
set_not_verbose()
157157

158158

159-
def main():
159+
def main() -> None:
160160
configure_logging()
161161
with system_run():
162162
app = QApplication(sys.argv)

src/labelle/gui/q_actions.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@ def __init__(self, parent: Optional[QWidget] = None):
2828
self._init_connections()
2929
self._init_layout()
3030

31-
def _init_elements(self):
31+
def _init_elements(self) -> None:
3232
printer_icon = QIcon.fromTheme("printer")
3333
self._print_button.setIcon(printer_icon)
3434
self._print_button.setFixedSize(64, 64)
3535
self._print_button.setIconSize(QSize(48, 48))
3636

37-
def _init_connections(self):
37+
def _init_connections(self) -> None:
3838
self._print_button.clicked.connect(self._on_print_label)
3939

40-
def _init_layout(self):
40+
def _init_layout(self) -> None:
4141
layout = QVBoxLayout(self)
4242
layout.addWidget(
4343
self._print_button, alignment=QtCore.Qt.AlignmentFlag.AlignRight
@@ -46,16 +46,16 @@ def _init_layout(self):
4646
self._error_label, alignment=QtCore.Qt.AlignmentFlag.AlignCenter
4747
)
4848

49-
def _on_print_label(self):
49+
def _on_print_label(self) -> None:
5050
self.print_label_signal.emit()
5151

52-
def clear_error(self):
52+
def clear_error(self) -> None:
5353
self._error_label.setText("")
5454
self._last_error = None
5555
self._print_button.setEnabled(True)
5656
self._print_button.setCursor(Qt.CursorShape.ArrowCursor)
5757

58-
def set_error(self, error: str):
58+
def set_error(self, error: str) -> None:
5959
if self._last_error == error:
6060
return
6161
self._last_error = error

src/labelle/gui/q_device_selector.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@ def __init__(self, parent=None):
3737
self._last_scan_error_changed()
3838
self.selectedDeviceChangedSignal.emit()
3939

40-
def _init_elements(self):
40+
def _init_elements(self) -> None:
4141
self.device_manager = OnlineDeviceManager()
4242

43-
def _init_connections(self):
43+
def _init_connections(self) -> None:
4444
self.device_manager.devices_changed_signal.connect(self.repopulate)
4545
self.device_manager.last_scan_error_changed_signal.connect(
4646
self._last_scan_error_changed
4747
)
4848
self._devices.currentIndexChanged.connect(self._index_changed)
4949

50-
def repopulate(self):
50+
def repopulate(self) -> None:
5151
old_hashes = {device.hash for device in self.device_manager.devices}
5252
self._devices.clear()
5353
for idx, device in enumerate(self.device_manager.devices):
@@ -71,19 +71,19 @@ def repopulate(self):
7171
if new_hashes != old_hashes:
7272
self.selectedDeviceChangedSignal.emit()
7373

74-
def _index_changed(self, index):
74+
def _index_changed(self, index) -> None:
7575
if index >= 0:
7676
self._selected_device = self.device_manager.devices[index]
7777
else:
7878
self._selected_device = None
7979
self.selectedDeviceChangedSignal.emit()
8080

81-
def _last_scan_error_changed(self):
81+
def _last_scan_error_changed(self) -> None:
8282
last_scan_error = self.device_manager.last_scan_error or ""
8383
self._error_label.setText(str(last_scan_error))
8484
self.repopulate()
8585

86-
def _init_layout(self):
86+
def _init_layout(self) -> None:
8787
self._devices.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents)
8888
self._action_devices = self.addWidget(self._devices)
8989
self._action_error_label = self.addWidget(self._error_label)

src/labelle/gui/q_label_widgets.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737

3838
class FontStyle(QComboBox):
39-
def __init__(self):
39+
def __init__(self) -> None:
4040
super().__init__()
4141
# Populate font_style
4242
for font_path in get_available_fonts():
@@ -67,17 +67,17 @@ class BaseLabelWidget(QWidget):
6767

6868
itemRenderSignal = QtCore.pyqtSignal(name="itemRenderSignal")
6969

70-
def content_changed(self):
70+
def content_changed(self) -> None:
7171
"""Emit the itemRenderSignal when the content of the label is changed."""
7272
self.itemRenderSignal.emit()
7373

7474
@property
75-
def render_engine_impl(self):
75+
def render_engine_impl(self) -> None:
7676
"""Abstract method for getting the render engine of the label."""
7777
pass
7878

7979
@property
80-
def render_engine(self):
80+
def render_engine(self) -> Optional[RenderEngine]:
8181
try:
8282
return self.render_engine_impl
8383
except RenderEngineException as err:
@@ -151,7 +151,7 @@ def __init__(self, render_context: RenderContext, parent: Optional[QWidget] = No
151151
self.align.currentTextChanged.connect(self.content_changed)
152152
self.setLayout(layout)
153153

154-
def content_changed(self):
154+
def content_changed(self) -> None:
155155
"""Manage changes to the label contents.
156156
157157
In particular, update the height of the label and emit the itemRenderSignal
@@ -357,7 +357,7 @@ def set_text_fields_visibility(self, visible):
357357
QIcon(str(ICON_DIR / "barcode_icon.png")).pixmap(32, 32)
358358
)
359359

360-
def toggle_text_fields_and_rerender(self):
360+
def toggle_text_fields_and_rerender(self) -> None:
361361
is_checked = self.show_text_checkbox.isChecked()
362362
self.set_text_fields_visibility(is_checked)
363363
self.content_changed() # Trigger rerender

0 commit comments

Comments
 (0)