Skip to content

Commit 80bf03c

Browse files
committed
Improved types and None checks from library updates
1 parent ef2b7e3 commit 80bf03c

7 files changed

+24
-31
lines changed

src/AutoSplit.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ def start_auto_splitter(self):
496496
or (not self.start_auto_splitter_button.isEnabled() and not self.is_auto_controlled):
497497
return
498498

499-
start_label: str = self.start_image_status_value_label.text()
499+
start_label = self.start_image_status_value_label.text()
500500
if start_label.endswith(("ready", "paused")):
501501
self.start_image_status_value_label.setText("not ready")
502502

@@ -519,7 +519,7 @@ def __auto_splitter(self): # noqa: PLR0912,PLR0915
519519
self.run_start_time = time()
520520

521521
if not (validate_before_parsing(self) and parse_and_validate_images(self)):
522-
# `safe_to_reload_start_image: bool = False` becasue __load_start_image also does this check,
522+
# `safe_to_reload_start_image: bool = False` because __load_start_image also does this check,
523523
# we don't want to double a Start/Reset Image error message
524524
self.gui_changes_on_reset(False)
525525
return

src/capture_method/BitBltCaptureMethod.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import ctypes
22
import ctypes.wintypes
3-
from typing import cast
43

54
import numpy as np
65
import pywintypes
@@ -68,7 +67,7 @@ def get_frame(self) -> tuple[MatLike | None, bool]:
6867
(selection["x"] + left_bounds, selection["y"] + top_bounds),
6968
win32con.SRCCOPY,
7069
)
71-
image = np.frombuffer(cast(bytes, bitmap.GetBitmapBits(True)), dtype=np.uint8)
70+
image = np.frombuffer(bitmap.GetBitmapBits(True), dtype=np.uint8)
7271
except (win32ui.error, pywintypes.error):
7372
# Invalid handle or the window was closed while it was being manipulated
7473
return None, False

src/capture_method/DesktopDuplicationCaptureMethod.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
import cv2
55
import d3dshot
6-
import numpy as np
76
import win32con
7+
from cv2.typing import MatLike
88
from typing_extensions import override
99
from win32 import win32gui
1010

@@ -55,7 +55,7 @@ def get_frame(self):
5555
right = selection["width"] + left
5656
bottom = selection["height"] + top
5757
screenshot = cast(
58-
np.ndarray[int, np.dtype[np.generic]] | None,
58+
MatLike | None,
5959
self.desktop_duplication.screenshot((left, top, right, bottom)),
6060
)
6161
if screenshot is None:

src/capture_method/WindowsGraphicsCaptureMethod.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,12 @@ def get_frame(self) -> tuple[MatLike | None, bool]:
9898
except OSError:
9999
return None, False
100100

101+
# We were too fast and the next frame wasn't ready yet
102+
if not frame:
103+
return self.last_captured_frame, True
104+
101105
async def coroutine():
102-
# We were too fast and the next frame wasn't ready yet
103-
if not frame:
104-
return None
105-
return await (SoftwareBitmap.create_copy_from_surface_async(frame.surface) or asyncio.sleep(0, None))
106+
return await SoftwareBitmap.create_copy_from_surface_async(frame.surface)
106107

107108
try:
108109
software_bitmap = asyncio.run(coroutine())
@@ -114,6 +115,7 @@ async def coroutine():
114115

115116
if not software_bitmap:
116117
# HACK: Can happen when starting the region selector
118+
# TODO: Validate if this is still true
117119
return self.last_captured_frame, True
118120
# raise ValueError("Unable to convert Direct3D11CaptureFrame to SoftwareBitmap.")
119121
bitmap_buffer = software_bitmap.lock_buffer(BitmapBufferAccessMode.READ_WRITE)

src/capture_method/__init__.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,13 @@ def get_input_device_resolution(index: int):
173173
return resolution
174174

175175

176-
async def get_all_video_capture_devices() -> list[CameraInfo]:
176+
async def get_all_video_capture_devices():
177177
named_video_inputs = FilterGraph().get_input_devices()
178178

179179
async def get_camera_info(index: int, device_name: str):
180180
backend = ""
181-
# Probing freezes some devices (like GV-USB2 and AverMedia) if already in use
182-
# #169
183-
# FIXME: Maybe offer the option to the user to obtain more info about their devies?
181+
# Probing freezes some devices (like GV-USB2 and AverMedia) if already in use. See #169
182+
# FIXME: Maybe offer the option to the user to obtain more info about their devices?
184183
# Off by default. With a tooltip to explain the risk.
185184
# video_capture = cv2.VideoCapture(index)
186185
# video_capture.setExceptionMode(True)
@@ -203,7 +202,6 @@ async def get_camera_info(index: int, device_name: str):
203202
return [
204203
camera_info
205204
for camera_info
206-
# Note: Return type required https://github.com/python/typeshed/issues/2652
207205
in await asyncio.gather(*starmap(get_camera_info, enumerate(named_video_inputs)))
208206
if camera_info is not None
209207
]

src/user_profile.py

+7-10
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,15 @@ def __load_settings_from_file(autosplit: "AutoSplit", load_settings_file_path: s
117117
return False
118118
try:
119119
with open(load_settings_file_path, encoding="utf-8") as file:
120-
# Casting here just so we can build an actual UserProfileDict once we're done validating
121120
# Fallback to default settings if some are missing from the file. This happens when new settings are added.
122-
loaded_settings = cast(
123-
UserProfileDict,
124-
{
125-
**DEFAULT_PROFILE,
126-
**toml.load(file),
127-
},
121+
loaded_settings = UserProfileDict(
122+
123+
**DEFAULT_PROFILE,
124+
**toml.load(file),
125+
128126
)
129127
# TODO: Data Validation / fallbacks ?
130-
autosplit.settings_dict = UserProfileDict(**loaded_settings)
128+
autosplit.settings_dict = loaded_settings
131129
autosplit.last_loaded_settings = autosplit.settings_dict
132130

133131
autosplit.x_spinbox.setValue(autosplit.settings_dict["capture_region"]["x"])
@@ -204,8 +202,7 @@ def load_check_for_updates_on_open(autosplit: "AutoSplit"):
204202
Retrieve the "Check For Updates On Open" QSettings and set the checkbox state
205203
These are only global settings values. They are not *toml settings values.
206204
"""
207-
# Type not infered by PySide6
208-
# TODO: Report this issue upstream
205+
# Type not infered by PySide6: https://bugreports.qt.io/browse/PYSIDE-2542
209206
value = cast(
210207
bool,
211208
QtCore

src/utils.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
# Source does not exist, keep this under TYPE_CHECKING
2323
from _win32typing import PyCDC # pyright: ignore[reportMissingModuleSource]
2424

25-
_T = TypeVar("_T")
25+
T = TypeVar("T")
2626

2727

2828
DWMWA_EXTENDED_FRAME_BOUNDS = 9
@@ -74,9 +74,6 @@ def is_valid_hwnd(hwnd: int) -> bool:
7474
return True
7575

7676

77-
T = TypeVar("T")
78-
79-
8077
def first(iterable: Iterable[T]) -> T:
8178
"""@return: The first element of a collection. Dictionaries will return the first key."""
8279
return next(iter(iterable))
@@ -125,7 +122,7 @@ def get_direct3d_device():
125122
media_capture = MediaCapture()
126123

127124
async def init_mediacapture():
128-
await (media_capture.initialize_async() or asyncio.sleep(0))
125+
await media_capture.initialize_async()
129126

130127
asyncio.run(init_mediacapture())
131128
direct_3d_device = media_capture.media_capture_settings and media_capture.media_capture_settings.direct3_d11_device
@@ -168,7 +165,7 @@ def wrapped(*args: Any, **kwargs: Any):
168165
return wrapped
169166

170167

171-
def flatten(nested_iterable: Iterable[Iterable[_T]]) -> chain[_T]:
168+
def flatten(nested_iterable: Iterable[Iterable[T]]) -> chain[T]:
172169
return chain.from_iterable(nested_iterable)
173170

174171

0 commit comments

Comments
 (0)