diff --git a/src/AutoSplit.py b/src/AutoSplit.py index 41e20ca5..00ffe3f1 100644 --- a/src/AutoSplit.py +++ b/src/AutoSplit.py @@ -128,8 +128,7 @@ def _show_error_signal_slot(error_message_box: Callable[..., object]): self.setupUi(self) self.setWindowTitle( - f"AutoSplit v{AUTOSPLIT_VERSION}" + - (" (externally controlled)" if self.is_auto_controlled else ""), + f"AutoSplit v{AUTOSPLIT_VERSION}" + (" (externally controlled)" if self.is_auto_controlled else ""), ) # Hotkeys need to be initialized to be passed as thread arguments in hotkeys.py @@ -331,11 +330,9 @@ def __start_image_function(self): if below_flag and not self.split_below_threshold and similarity_diff >= 0: self.split_below_threshold = True return - if ( - (below_flag and self.split_below_threshold and similarity_diff < 0 and is_valid_image(capture)) - or (not below_flag and similarity_diff >= 0) + if (below_flag and self.split_below_threshold and similarity_diff < 0 and is_valid_image(capture)) or ( + not below_flag and similarity_diff >= 0 ): - self.timer_start_image.stop() self.split_below_threshold = False @@ -430,10 +427,7 @@ def __check_fps(self): self.fps_value_label.setText(str(fps)) def __is_current_split_out_of_range(self): - return ( - self.split_image_number < 0 - or self.split_image_number > len(self.split_images_and_loop_number) - 1 - ) + return self.split_image_number < 0 or self.split_image_number > len(self.split_images_and_loop_number) - 1 def undo_split(self, navigate_image_only: bool = False): """Undo Split" and "Prev. Img." buttons connect to here.""" @@ -497,10 +491,7 @@ def reset(self): # Functions for the hotkeys to return to the main thread from signals and start their corresponding functions def start_auto_splitter(self): # If the auto splitter is already running or the button is disabled, don't emit the signal to start it. - if ( - self.is_running - or (not self.start_auto_splitter_button.isEnabled() and not self.is_auto_controlled) - ): + if self.is_running or (not self.start_auto_splitter_button.isEnabled() and not self.is_auto_controlled): return start_label: str = self.start_image_status_value_label.text() @@ -533,11 +524,7 @@ def __auto_splitter(self): # noqa: PLR0912,PLR0915 # Construct a list of images + loop count tuples. self.split_images_and_loop_number = list( - flatten( - [(split_image, i + 1) for i in range(split_image.loops)] - for split_image - in self.split_images - ), + flatten([(split_image, i + 1) for i in range(split_image.loops)] for split_image in self.split_images), ) # Construct groups of splits @@ -668,7 +655,7 @@ def __similarity_threshold_loop(self, number_of_split_images: int, dummy_splits_ self.previous_image_button.setEnabled(self.split_image_number != 0) if not self.is_auto_controlled: # If its the last non-dummy split image and last loop number, disable the skip split button - self.skip_split_button.setEnabled(dummy_splits_array[self.split_image_number:].count(False) > 1) + self.skip_split_button.setEnabled(dummy_splits_array[self.split_image_number :].count(False) > 1) self.undo_split_button.setEnabled(self.split_image_number != 0) QApplication.processEvents() diff --git a/src/AutoSplitImage.py b/src/AutoSplitImage.py index 9a0dcd6f..eee4493d 100644 --- a/src/AutoSplitImage.py +++ b/src/AutoSplitImage.py @@ -51,30 +51,22 @@ class AutoSplitImage: def get_delay_time(self, default: AutoSplit | int): """Get image's delay time or fallback to the default value from spinbox.""" - default_value = default \ - if isinstance(default, int) \ - else default.settings_dict["default_delay_time"] + default_value = default if isinstance(default, int) else default.settings_dict["default_delay_time"] return default_value if self.__delay_time is None else self.__delay_time def __get_comparison_method(self, default: AutoSplit | int): """Get image's comparison or fallback to the default value from combobox.""" - default_value = default \ - if isinstance(default, int) \ - else default.settings_dict["default_comparison_method"] + default_value = default if isinstance(default, int) else default.settings_dict["default_comparison_method"] return default_value if self.__comparison_method is None else self.__comparison_method def get_pause_time(self, default: AutoSplit | float): """Get image's pause time or fallback to the default value from spinbox.""" - default_value = default \ - if isinstance(default, float) \ - else default.settings_dict["default_pause_time"] + default_value = default if isinstance(default, float) else default.settings_dict["default_pause_time"] return default_value if self.__pause_time is None else self.__pause_time def get_similarity_threshold(self, default: AutoSplit | float): """Get image's similarity threshold or fallback to the default value from spinbox.""" - default_value = default \ - if isinstance(default, float) \ - else default.settings_dict["default_similarity_threshold"] + default_value = default if isinstance(default, float) else default.settings_dict["default_similarity_threshold"] return default_value if self.__similarity_threshold is None else self.__similarity_threshold def __init__(self, path: str): diff --git a/src/capture_method/DesktopDuplicationCaptureMethod.py b/src/capture_method/DesktopDuplicationCaptureMethod.py index ee07ac11..16b6b437 100644 --- a/src/capture_method/DesktopDuplicationCaptureMethod.py +++ b/src/capture_method/DesktopDuplicationCaptureMethod.py @@ -45,9 +45,7 @@ def get_frame(self, autosplit: AutoSplit): left_bounds, top_bounds, *_ = get_window_bounds(hwnd) self.desktop_duplication.display = next( - display for display - in self.desktop_duplication.displays - if display.hmonitor == hmonitor + display for display in self.desktop_duplication.displays if display.hmonitor == hmonitor ) offset_x, offset_y, *_ = win32gui.GetWindowRect(hwnd) offset_x -= self.desktop_duplication.display.position["left"] diff --git a/src/capture_method/VideoCaptureDeviceCaptureMethod.py b/src/capture_method/VideoCaptureDeviceCaptureMethod.py index 2dce2d53..e0b55507 100644 --- a/src/capture_method/VideoCaptureDeviceCaptureMethod.py +++ b/src/capture_method/VideoCaptureDeviceCaptureMethod.py @@ -37,8 +37,7 @@ class VideoCaptureDeviceCaptureMethod(CaptureMethodBase): name = "Video Capture Device" short_description = "see below" description = ( - "\nUses a Video Capture Device, like a webcam, virtual cam, or capture card. " - + "\nYou can select one below. " + "\nUses a Video Capture Device, like a webcam, virtual cam, or capture card. " + "\nYou can select one below. " ) capture_device: cv2.VideoCapture diff --git a/src/capture_method/WindowsGraphicsCaptureMethod.py b/src/capture_method/WindowsGraphicsCaptureMethod.py index fda748b6..4accde5c 100644 --- a/src/capture_method/WindowsGraphicsCaptureMethod.py +++ b/src/capture_method/WindowsGraphicsCaptureMethod.py @@ -104,7 +104,8 @@ async def coroutine(): # We were too fast and the next frame wasn't ready yet if not frame: return None - return await (SoftwareBitmap.create_copy_from_surface_async(frame.surface) or asyncio.sleep(0, None)) + return await SoftwareBitmap.create_copy_from_surface_async(frame.surface) or asyncio.sleep(0, None) + try: software_bitmap = asyncio.run(coroutine()) except SystemError as exception: @@ -148,7 +149,5 @@ def recover_window(self, captured_window_title: str, autosplit: AutoSplit): @override def check_selected_region_exists(self, autosplit: AutoSplit): return bool( - is_valid_hwnd(autosplit.hwnd) - and self.frame_pool - and self.session, + is_valid_hwnd(autosplit.hwnd) and self.frame_pool and self.session, ) diff --git a/src/capture_method/__init__.py b/src/capture_method/__init__.py index 7a023d68..c367f665 100644 --- a/src/capture_method/__init__.py +++ b/src/capture_method/__init__.py @@ -199,20 +199,11 @@ async def get_camera_info(index: int, device_name: str): # video_capture.release() resolution = get_input_device_resolution(index) - return CameraInfo(index, device_name, False, backend, resolution) \ - if resolution is not None \ - else None + return CameraInfo(index, device_name, False, backend, resolution) if resolution is not None else None # Note: Return type required https://github.com/python/typeshed/issues/2652 future = asyncio.gather( - *[ - get_camera_info(index, name) for index, name - in enumerate(named_video_inputs) - ], + *[get_camera_info(index, name) for index, name in enumerate(named_video_inputs)], ) - return [ - camera_info for camera_info - in await future - if camera_info is not None - ] + return [camera_info for camera_info in await future if camera_info is not None] diff --git a/src/compare.py b/src/compare.py index cdb48aff..75b60b7b 100644 --- a/src/compare.py +++ b/src/compare.py @@ -47,9 +47,7 @@ def compare_l2_norm(source: MatLike, capture: MatLike, mask: MatLike | None = No # The L2 Error is summed across all pixels, so this normalizes max_error = ( - sqrt(source.size) * MAXBYTE - if not is_valid_image(mask) - else sqrt(cv2.countNonZero(mask) * MASK_SIZE_MULTIPLIER) + sqrt(source.size) * MAXBYTE if not is_valid_image(mask) else sqrt(cv2.countNonZero(mask) * MASK_SIZE_MULTIPLIER) ) if not max_error: @@ -73,11 +71,7 @@ def compare_template(source: MatLike, capture: MatLike, mask: MatLike | None = N # matchTemplate returns the sum of square differences, this is the max # that the value can be. Used for normalizing from 0 to 1. - max_error = ( - source.size * MAXBYTE * MAXBYTE - if not is_valid_image(mask) - else cv2.countNonZero(mask) - ) + max_error = source.size * MAXBYTE * MAXBYTE if not is_valid_image(mask) else cv2.countNonZero(mask) return 1 - (min_val / max_error) diff --git a/src/hotkeys.py b/src/hotkeys.py index 0c25dac2..73cd7309 100644 --- a/src/hotkeys.py +++ b/src/hotkeys.py @@ -91,10 +91,7 @@ def _send_hotkey(hotkey_or_scan_code: int | str | None): # Deal with regular inputs # If an int or does not contain the following strings - if ( - isinstance(hotkey_or_scan_code, int) - or not any(key in hotkey_or_scan_code for key in ("num ", "decimal", "+")) - ): + if isinstance(hotkey_or_scan_code, int) or not any(key in hotkey_or_scan_code for key in ("num ", "decimal", "+")): keyboard.send(hotkey_or_scan_code) return @@ -103,11 +100,7 @@ def _send_hotkey(hotkey_or_scan_code: int | str | None): # keyboard also has issues with capitalization modifier (shift+A) # keyboard.send(keyboard.key_to_scan_codes(key_or_scan_code)[1]) pyautogui.hotkey( - *[ - "+" if key == "plus" else key - for key - in hotkey_or_scan_code.replace(" ", "").split("+") - ], + *["+" if key == "plus" else key for key in hotkey_or_scan_code.replace(" ", "").split("+")], ) @@ -130,9 +123,7 @@ def __validate_keypad(expected_key: str, keyboard_event: keyboard.KeyboardEvent) if keyboard_event.name and is_digit(keyboard_event.name[-1]): # Prevent "regular numbers" and "keypad numbers" from activating each other return bool( - keyboard_event.is_keypad - if expected_key.startswith("num ") - else not keyboard_event.is_keypad, + keyboard_event.is_keypad if expected_key.startswith("num ") else not keyboard_event.is_keypad, ) # Prevent "keypad action keys" from triggering "regular numbers" and "keypad numbers" @@ -156,9 +147,7 @@ def __get_key_name(keyboard_event: keyboard.KeyboardEvent): # Normally this is done by keyboard.get_hotkey_name. But our code won't always get there. if event_name == "+": return "plus" - return f"num {keyboard_event.name}" \ - if keyboard_event.is_keypad and is_digit(keyboard_event.name) \ - else event_name + return f"num {keyboard_event.name}" if keyboard_event.is_keypad and is_digit(keyboard_event.name) else event_name def __get_hotkey_name(names: list[str]): @@ -237,11 +226,8 @@ def toggle_auto_reset_image(): def is_valid_hotkey_name(hotkey_name: str): - return any( - key and not keyboard.is_modifier(keyboard.key_to_scan_codes(key)[0]) - for key - in hotkey_name.split("+") - ) + return any(key and not keyboard.is_modifier(keyboard.key_to_scan_codes(key)[0]) for key in hotkey_name.split("+")) + # TODO: using getattr/setattr is NOT a good way to go about this. It was only temporarily done to # reduce duplicated code. We should use a dictionary of hotkey class or something. diff --git a/src/menu_bar.py b/src/menu_bar.py index 34a979cd..5ac516de 100644 --- a/src/menu_bar.py +++ b/src/menu_bar.py @@ -147,8 +147,7 @@ def __init__(self, autosplit: AutoSplit): # Don't autofocus any particular field self.setFocus() - -# region Build the Capture method combobox + # region Build the Capture method combobox capture_method_values = CAPTURE_METHODS.values() self.__set_all_capture_devices() @@ -159,17 +158,13 @@ def __init__(self, autosplit: AutoSplit): # list_view.setFixedWidth(self.capture_method_combobox.width()) # self.capture_method_combobox.setView(list_view) - self.capture_method_combobox.addItems([ - f"- {method.name} ({method.short_description})" - for method in capture_method_values - ]) + self.capture_method_combobox.addItems( + [f"- {method.name} ({method.short_description})" for method in capture_method_values] + ) self.capture_method_combobox.setToolTip( - "\n\n".join([ - f"{method.name} :\n{method.description}" - for method in capture_method_values - ]), + "\n\n".join([f"{method.name} :\n{method.description}" for method in capture_method_values]), ) -# endregion + # endregion self.__setup_bindings() @@ -243,21 +238,21 @@ def __set_all_capture_devices(self): if len(self.__video_capture_devices) > 0: for i in range(self.capture_device_combobox.count()): self.capture_device_combobox.removeItem(i) - self.capture_device_combobox.addItems([ - f"* {device.name}" - + (f" [{device.backend}]" if device.backend else "") - + (" (occupied)" if device.occupied else "") - for device in self.__video_capture_devices - ]) + self.capture_device_combobox.addItems( + [ + f"* {device.name}" + + (f" [{device.backend}]" if device.backend else "") + + (" (occupied)" if device.occupied else "") + for device in self.__video_capture_devices + ] + ) self.__enable_capture_device_if_its_selected_method() else: self.capture_device_combobox.setPlaceholderText("No device found.") def __set_readme_link(self): self.custom_image_settings_info_label.setText( - self.custom_image_settings_info_label - .text() - .format(GITHUB_REPOSITORY=GITHUB_REPOSITORY), + self.custom_image_settings_info_label.text().format(GITHUB_REPOSITORY=GITHUB_REPOSITORY), ) # HACK: This is a workaround because custom_image_settings_info_label # simply will not open links with a left click no matter what we tried. @@ -296,7 +291,7 @@ def hotkey_connect(hotkey: Hotkey): set_hotkey_hotkey_button.setEnabled(False) hotkey_input.setEnabled(False) -# region Set initial values + # region Set initial values # Capture Settings self.fps_limit_spinbox.setValue(self.autosplit.settings_dict["fps_limit"]) self.live_capture_region_checkbox.setChecked(self.autosplit.settings_dict["live_capture_region"]) @@ -318,8 +313,8 @@ def hotkey_connect(hotkey: Hotkey): self.loop_splits_checkbox.setChecked(self.autosplit.settings_dict["loop_splits"]) self.start_also_resets_checkbox.setChecked(self.autosplit.settings_dict["start_also_resets"]) self.enable_auto_reset_image_checkbox.setChecked(self.autosplit.settings_dict["enable_auto_reset"]) -# endregion -# region Binding + # endregion + # region Binding # Capture Settings self.fps_limit_spinbox.valueChanged.connect(self.__fps_limit_changed) self.live_capture_region_checkbox.stateChanged.connect( @@ -359,6 +354,8 @@ def hotkey_connect(hotkey: Hotkey): self.enable_auto_reset_image_checkbox.stateChanged.connect( lambda: self.__set_value("enable_auto_reset", self.enable_auto_reset_image_checkbox.isChecked()), ) + + # endregion diff --git a/src/split_parser.py b/src/split_parser.py index 7afabf23..4f96d780 100644 --- a/src/split_parser.py +++ b/src/split_parser.py @@ -178,8 +178,7 @@ def parse_and_validate_images(autosplit: AutoSplit): # Get split images all_images = [ AutoSplitImage(os.path.join(autosplit.settings_dict["split_image_directory"], image_name)) - for image_name - in os.listdir(autosplit.settings_dict["split_image_directory"]) + for image_name in os.listdir(autosplit.settings_dict["split_image_directory"]) ] # Find non-split images and then remove them from the list @@ -190,19 +189,11 @@ def parse_and_validate_images(autosplit: AutoSplit): error_message: Callable[[], object] | None = None # If there is no start hotkey set but a Start Image is present, and is not auto controlled, throw an error. - if ( - start_image - and not autosplit.settings_dict["split_hotkey"] - and not autosplit.is_auto_controlled - ): + if start_image and not autosplit.settings_dict["split_hotkey"] and not autosplit.is_auto_controlled: error_message = error_messages.load_start_image # If there is no reset hotkey set but a Reset Image is present, and is not auto controlled, throw an error. - elif ( - reset_image - and not autosplit.settings_dict["reset_hotkey"] - and not autosplit.is_auto_controlled - ): + elif reset_image and not autosplit.settings_dict["reset_hotkey"] and not autosplit.is_auto_controlled: error_message = error_messages.reset_hotkey # Make sure that each of the images follows the guidelines for correct format diff --git a/src/user_profile.py b/src/user_profile.py index 1f6a8c32..a8c6490f 100644 --- a/src/user_profile.py +++ b/src/user_profile.py @@ -177,11 +177,7 @@ def load_settings(autosplit: AutoSplit, from_path: str = ""): def load_settings_on_open(autosplit: AutoSplit): - settings_files = [ - file for file - in os.listdir(auto_split_directory) - if file.endswith(".toml") - ] + settings_files = [file for file in os.listdir(auto_split_directory) if file.endswith(".toml")] # Find all .tomls in AutoSplit folder, error if there is not exactly 1 error = None @@ -206,9 +202,7 @@ def load_check_for_updates_on_open(autosplit: AutoSplit): # TODO: Report this issue upstream value = cast( bool, - QtCore - .QSettings("AutoSplit", "Check For Updates On Open") - .value("check_for_updates_on_open", True, type=bool), + QtCore.QSettings("AutoSplit", "Check For Updates On Open").value("check_for_updates_on_open", True, type=bool), ) autosplit.action_check_for_updates_on_open.setChecked(value) @@ -216,6 +210,4 @@ def load_check_for_updates_on_open(autosplit: AutoSplit): def set_check_for_updates_on_open(design_window: design.Ui_MainWindow, value: bool): """Sets the "Check For Updates On Open" QSettings value and the checkbox state.""" design_window.action_check_for_updates_on_open.setChecked(value) - QtCore \ - .QSettings("AutoSplit", "Check For Updates On Open") \ - .setValue("check_for_updates_on_open", value) + QtCore.QSettings("AutoSplit", "Check For Updates On Open").setValue("check_for_updates_on_open", value) diff --git a/src/utils.py b/src/utils.py index 60e3b107..418bf056 100644 --- a/src/utils.py +++ b/src/utils.py @@ -127,7 +127,7 @@ def get_direct3d_device(): media_capture = MediaCapture() async def init_mediacapture(): - await (media_capture.initialize_async() or asyncio.sleep(0)) + await media_capture.initialize_async() or asyncio.sleep(0) asyncio.run(init_mediacapture()) direct_3d_device = media_capture.media_capture_settings and media_capture.media_capture_settings.direct3_d11_device @@ -171,11 +171,7 @@ def wrapped(*args: Any, **kwargs: Any): def flatten(nested_iterable: Iterable[Iterable[_T]]) -> Generator[_T, None, None]: - return ( - item for flatten - in nested_iterable - for item in flatten - ) + return (item for flatten in nested_iterable for item in flatten) # Environment specifics