Skip to content

Commit 3846b65

Browse files
authored
fix(ci): address remaining pyright errors (#1368)
* fix(ci): address remaining pyright errors * fix: implement review feedback
1 parent a7b6636 commit 3846b65

6 files changed

Lines changed: 51 additions & 32 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ include = ["src/tagstudio", "tests"]
102102
reportAny = false
103103
reportIgnoreCommentWithoutRule = false
104104
reportImplicitStringConcatenation = false
105+
reportImportCycles = false
105106
reportMissingTypeArgument = false
106107
reportMissingTypeStubs = false
107108
# reportOptionalMemberAccess = false
@@ -110,6 +111,7 @@ reportUnknownArgumentType = false
110111
reportUnknownLambdaType = false
111112
reportUnknownMemberType = false
112113
reportUnusedCallResult = false
114+
reportUninitializedInstanceVariable = false
113115

114116
[tool.ruff]
115117
exclude = ["home_ui.py", "resources.py", "resources_rc.py"]

src/tagstudio/qt/controllers/preview_thumb_controller.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44

55
import io
66
from pathlib import Path
7-
from typing import TYPE_CHECKING
7+
from typing import TYPE_CHECKING, override
88

99
import cv2
1010
import rawpy
1111
import structlog
1212
from PIL import Image, UnidentifiedImageError
1313
from PIL.Image import DecompressionBombError
1414
from PySide6.QtCore import QSize
15+
from rawpy import (
16+
LibRawFileUnsupportedError, # pyright: ignore[reportPrivateImportUsage]
17+
LibRawIOError, # pyright: ignore[reportPrivateImportUsage]
18+
)
1519

1620
from tagstudio.core.library.alchemy.library import Library
1721
from tagstudio.core.media_types import MediaCategories
@@ -50,8 +54,8 @@ def __get_image_stats(self, filepath: Path) -> FileAttributeData:
5054
stats.width = image.width
5155
stats.height = image.height
5256
except (
53-
rawpy.LibRawIOError,
54-
rawpy.LibRawFileUnsupportedError,
57+
LibRawIOError,
58+
LibRawFileUnsupportedError,
5559
FileNotFoundError,
5660
):
5761
pass
@@ -144,18 +148,22 @@ def display_file(self, filepath: Path) -> FileAttributeData:
144148
self._display_image(filepath)
145149
return self.__get_image_stats(filepath)
146150

151+
@override
147152
def _open_file_action_callback(self):
148153
open_file(
149154
self.__current_file, windows_start_command=self.__driver.settings.windows_start_command
150155
)
151156

157+
@override
152158
def _open_explorer_action_callback(self):
153159
open_file(self.__current_file, file_manager=True)
154160

161+
@override
155162
def _delete_action_callback(self):
156163
if bool(self.__current_file):
157164
self.__driver.delete_files_callback(self.__current_file)
158165

166+
@override
159167
def _button_wrapper_callback(self):
160168
open_file(
161169
self.__current_file, windows_start_command=self.__driver.settings.windows_start_command

src/tagstudio/qt/helpers/text_wrapper.py

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

88
def wrap_line(
99
text: str,
10-
font: ImageFont.ImageFont,
10+
font: ImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont,
1111
width: int = 256,
1212
draw: ImageDraw.ImageDraw | None = None,
1313
) -> int:
@@ -31,7 +31,7 @@ def wrap_line(
3131

3232
def wrap_full_text(
3333
text: str,
34-
font: ImageFont.ImageFont,
34+
font: ImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont,
3535
width: int = 256,
3636
draw: ImageDraw.ImageDraw | None = None,
3737
) -> str:

src/tagstudio/qt/previews/renderer.py

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
UnidentifiedImageError,
4444
)
4545
from PIL.Image import DecompressionBombError
46-
from pillow_heif import register_heif_opener
46+
from pillow_heif import register_heif_opener # pyright: ignore[reportUnknownVariableType]
4747
from PySide6.QtCore import (
4848
QBuffer,
4949
QFile,
@@ -58,6 +58,10 @@
5858
from PySide6.QtGui import QGuiApplication, QImage, QPainter, QPixmap
5959
from PySide6.QtPdf import QPdfDocument, QPdfDocumentRenderOptions
6060
from PySide6.QtSvg import QSvgRenderer
61+
from rawpy import (
62+
LibRawFileUnsupportedError, # pyright: ignore[reportPrivateImportUsage]
63+
LibRawIOError, # pyright: ignore[reportPrivateImportUsage]
64+
)
6165

6266
from tagstudio.core.constants import (
6367
FONT_SAMPLE_SIZES,
@@ -75,9 +79,11 @@
7579
from tagstudio.qt.helpers.image_effects import replace_transparent_pixels
7680
from tagstudio.qt.helpers.text_wrapper import wrap_full_text
7781
from tagstudio.qt.models.palette import UI_COLORS, ColorType, UiColor, get_ui_color
78-
from tagstudio.qt.previews.vendored.blender_renderer import blend_thumb
82+
from tagstudio.qt.previews.vendored.blender_renderer import (
83+
blend_thumb, # pyright: ignore[reportUnknownVariableType]
84+
)
7985
from tagstudio.qt.previews.vendored.pydub.audio_segment import (
80-
_AudioSegment as AudioSegment,
86+
_AudioSegment as AudioSegment, # pyright: ignore[reportPrivateUsage]
8187
)
8288
from tagstudio.qt.resource_manager import ResourceManager
8389

@@ -118,7 +124,7 @@ class _TarFile:
118124
def __init__(self, filepath: Path, mode: Literal["r"]) -> None:
119125
self.tar: tarfile.TarFile
120126
self.filepath = filepath
121-
self.mode = mode
127+
self.mode: Literal["r"] = mode
122128

123129
def namelist(self) -> list[str]:
124130
return self.tar.getnames()
@@ -127,10 +133,10 @@ def read(self, name: str) -> bytes:
127133
return unwrap(self.tar.extractfile(name)).read()
128134

129135
def __enter__(self) -> "_TarFile":
130-
self.tar = tarfile.open(self.filepath, self.mode).__enter__()
136+
self.tar = tarfile.open(name=self.filepath, mode=self.mode).__enter__()
131137
return self
132138

133-
def __exit__(self, *args) -> None:
139+
def __exit__(self, *args) -> None: # pyright: ignore[reportUnknownParameterType, reportMissingParameterType]
134140
self.tar.__exit__(*args)
135141

136142

@@ -293,7 +299,7 @@ def _render_mask(
293299

294300
im: Image.Image = Image.new(
295301
mode="L",
296-
size=tuple([d * smooth_factor for d in size]), # type: ignore
302+
size=tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
297303
color="black",
298304
)
299305
draw = ImageDraw.Draw(im)
@@ -324,7 +330,7 @@ def _render_edge(
324330
# Highlight
325331
im_hl: Image.Image = Image.new(
326332
mode="RGBA",
327-
size=tuple([d * smooth_factor for d in size]), # type: ignore
333+
size=tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
328334
color="#00000000",
329335
)
330336
draw = ImageDraw.Draw(im_hl)
@@ -343,7 +349,7 @@ def _render_edge(
343349
# Shadow
344350
im_sh: Image.Image = Image.new(
345351
mode="RGBA",
346-
size=tuple([d * smooth_factor for d in size]), # type: ignore
352+
size=tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
347353
color="#00000000",
348354
)
349355
draw = ImageDraw.Draw(im_sh)
@@ -388,21 +394,21 @@ def _render_center_icon(
388394
# Create larger blank image based on smooth_factor
389395
im: Image.Image = Image.new(
390396
"RGBA",
391-
size=tuple([d * smooth_factor for d in size]), # type: ignore
397+
size=tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
392398
color="#FF000000",
393399
)
394400

395401
# Create solid background color
396402
bg: Image.Image
397403
bg = Image.new(
398404
"RGB",
399-
size=tuple([d * smooth_factor for d in size]), # type: ignore
405+
size=tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
400406
color="#000000FF",
401407
)
402408

403409
# Use a background image if provided
404410
if bg_image:
405-
bg_im = Image.Image.resize(bg_image, size=tuple([d * smooth_factor for d in size])) # type: ignore
411+
bg_im = Image.Image.resize(bg_image, size=tuple([d * smooth_factor for d in size])) # type: ignore # pyright: ignore[reportArgumentType]
406412
bg_im = ImageEnhance.Brightness(bg_im).enhance(0.3) # Reduce the brightness
407413
bg.paste(bg_im)
408414

@@ -411,7 +417,7 @@ def _render_center_icon(
411417
bg,
412418
(0, 0),
413419
mask=self._get_mask(
414-
tuple([d * smooth_factor for d in size]), # type: ignore
420+
tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
415421
(pixel_ratio * smooth_factor),
416422
),
417423
)
@@ -495,19 +501,19 @@ def _render_corner_icon(
495501
# Create larger blank image based on smooth_factor
496502
im: Image.Image = Image.new(
497503
"RGBA",
498-
size=tuple([d * smooth_factor for d in size]), # type: ignore
504+
size=tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
499505
color="#00000000",
500506
)
501507

502508
bg: Image.Image
503509
# Use a background image if provided
504510
if bg_image:
505-
bg = Image.Image.resize(bg_image, size=tuple([d * smooth_factor for d in size])) # type: ignore
511+
bg = Image.Image.resize(bg_image, size=tuple([d * smooth_factor for d in size])) # type: ignore # pyright: ignore[reportArgumentType]
506512
# Create solid background color
507513
else:
508514
bg = Image.new(
509515
"RGB",
510-
size=tuple([d * smooth_factor for d in size]), # type: ignore
516+
size=tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
511517
color="#000000",
512518
)
513519
# Apply color overlay
@@ -521,7 +527,7 @@ def _render_corner_icon(
521527
bg,
522528
(0, 0),
523529
mask=self._get_mask(
524-
tuple([d * smooth_factor for d in size]), # type: ignore
530+
tuple([d * smooth_factor for d in size]), # type: ignore # pyright: ignore[reportArgumentType]
525531
(pixel_ratio * smooth_factor),
526532
),
527533
)
@@ -662,17 +668,17 @@ def _audio_album_thumb(filepath: Path, ext: str) -> Image.Image | None:
662668
artwork = None
663669
if ext in [".mp3"]:
664670
id3_tags: id3.ID3 = id3.ID3(filepath)
665-
id3_covers: list = id3_tags.getall("APIC")
671+
id3_covers: list = id3_tags.getall("APIC") # pyright: ignore[reportUnknownVariableType]
666672
if id3_covers:
667673
artwork = Image.open(BytesIO(id3_covers[0].data))
668674
elif ext in [".flac"]:
669675
flac_tags: flac.FLAC = flac.FLAC(filepath)
670-
flac_covers: list = flac_tags.pictures
676+
flac_covers: list = flac_tags.pictures # pyright: ignore[reportUnknownVariableType]
671677
if flac_covers:
672678
artwork = Image.open(BytesIO(flac_covers[0].data))
673679
elif ext in [".mp4", ".m4a", ".aac"]:
674680
mp4_tags: mp4.MP4 = mp4.MP4(filepath)
675-
mp4_covers: list | None = mp4_tags.get("covr") # pyright: ignore[reportAssignmentType]
681+
mp4_covers: list | None = mp4_tags.get("covr") # pyright: ignore[reportUnknownVariableType]
676682
if mp4_covers:
677683
artwork = Image.open(BytesIO(mp4_covers[0]))
678684
if artwork:
@@ -1088,7 +1094,7 @@ def _font_long_thumb(filepath: Path, size: int) -> Image.Image | None:
10881094
font = ImageFont.truetype(filepath, size=font_size)
10891095
text_wrapped: str = wrap_full_text(
10901096
FONT_SAMPLE_TEXT,
1091-
font=font, # pyright: ignore[reportArgumentType]
1097+
font=font,
10921098
width=size,
10931099
draw=draw,
10941100
)
@@ -1120,8 +1126,8 @@ def _image_raw_thumb(filepath: Path) -> Image.Image | None:
11201126
)
11211127
except (
11221128
DecompressionBombError,
1123-
rawpy.LibRawIOError,
1124-
rawpy.LibRawFileUnsupportedError,
1129+
LibRawIOError,
1130+
LibRawFileUnsupportedError,
11251131
) as e:
11261132
logger.error("Couldn't render thumbnail", filepath=filepath, error=type(e).__name__)
11271133
return im
@@ -1137,6 +1143,7 @@ def _image_exr_thumb(filepath: Path) -> Image.Image | None:
11371143
try:
11381144
# Load the EXR data to an array and rotate the color space from BGRA -> RGBA
11391145
raw_array = cv2.imread(str(filepath), cv2.IMREAD_UNCHANGED)
1146+
assert raw_array is not None
11401147
raw_array[..., :3] = raw_array[..., 2::-1]
11411148

11421149
# Correct the gamma of the raw array
@@ -1209,7 +1216,7 @@ def _image_vector_thumb(filepath: Path, size: int) -> Image.Image:
12091216
# Write the image to a buffer as png
12101217
buffer: QBuffer = QBuffer()
12111218
buffer.open(QBuffer.OpenModeFlag.ReadWrite)
1212-
q_image.save(buffer, "PNG") # type: ignore[call-overload]
1219+
q_image.save(device=buffer, format="PNG") # type: ignore # pyright: ignore[reportArgumentType]
12131220

12141221
# Load the image from the buffer
12151222
im = Image.new("RGB", (size, size), color="#1e1e1e")
@@ -1258,7 +1265,7 @@ def get_image(path: str) -> Image.Image | None:
12581265
return im
12591266

12601267
@staticmethod
1261-
def _model_stl_thumb(filepath: Path, size: int) -> Image.Image | None:
1268+
def _model_stl_thumb(filepath: Path, size: int) -> Image.Image | None: # pyright: ignore[reportUnusedParameter]
12621269
"""Render a thumbnail for an STL file.
12631270
12641271
Args:
@@ -1614,6 +1621,7 @@ def render_ignored(
16141621

16151622
def fetch_cached_image(file_name: Path):
16161623
image: Image.Image | None = None
1624+
assert self.driver.cache_manager is not None
16171625
cached_path = self.driver.cache_manager.get_file_path(file_name)
16181626

16191627
if cached_path and cached_path.is_file():
@@ -1876,6 +1884,7 @@ def _render(
18761884
image = self._resize_image(image, (adj_size, adj_size))
18771885

18781886
if save_to_file and savable_media_type and image:
1887+
assert self.driver.cache_manager is not None
18791888
self.driver.cache_manager.save_image(image, save_to_file, mode="RGBA")
18801889

18811890
except (

src/tagstudio/qt/utils/custom_runnable.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from PySide6.QtCore import QObject, QRunnable, Signal
66

77

8-
class CustomRunnable(QRunnable, QObject):
8+
class CustomRunnable(QRunnable, QObject): # pyright: ignore[reportUnsafeMultipleInheritance]
99
done = Signal()
1010

1111
def __init__(self, function) -> None:

tests/qt/test_tag_search_panel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_tag_widget_actions_replaced_correctly(qtbot: QtBot, qt_driver: QtDriver
2929
# Set the widget
3030
tags = library.tags
3131
panel.set_tag_widget(tags[0], 0)
32-
tag_widget: TagWidget = panel.scroll_layout.itemAt(0).widget()
32+
tag_widget: TagWidget = panel.scroll_layout.itemAt(0).widget() # pyright: ignore[reportAssignmentType]
3333

3434
should_replace_actions = {
3535
tag_widget: ["on_edit()", "on_remove()"],

0 commit comments

Comments
 (0)