Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/Toufool/AutoSplit into refac…
Browse files Browse the repository at this point in the history
…tor-async-image-capture
  • Loading branch information
Avasam committed Mar 9, 2024
2 parents ef4b69d + b1625b9 commit 9d28705
Show file tree
Hide file tree
Showing 24 changed files with 112 additions and 10,542 deletions.
20 changes: 11 additions & 9 deletions .github/ISSUE_TEMPLATE/bug-or-crash-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,40 @@ assignees: ''

---

**Describe the bug**
### Describe the bug
<!-- A clear and concise description of what the bug is. -->

**To Reproduce**
### To Reproduce

Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
### Expected behavior
<!-- A clear and concise description of what you expected to happen. -->

**Screenshots and recordings**
### Screenshots and recordings
<!-- If applicable, add screenshots and/or recordings to help explain your problem. -->

**Traceback or Crash Report**
### Traceback or Crash Report

If AutoSplit showed an exception traceback, please paste it here:

```
```py

```
<!-- If AutoSplit crashed and closed without saying anything, please check Windows' Event Viewer, under Windows Logs > Application, for any recent error relating to AutoSplit -->

**Version (please complete the following information):**
### Version (please complete the following information)

- OS: [e.g. Windows 10.0.19045]
- AutoSplit: [e.g. v2.0.0]

**AutoSplit Profile and Split Images**
### AutoSplit Profile and Split Images
<!-- Please include your AutoSplit profile `.toml` file. You can also add your Split Images if relevant. -->

**Additional context**
### Additional context
<!-- Add any other context about the problem here. -->
8 changes: 4 additions & 4 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ assignees: ''

---

**Is your feature request related to a problem? Please describe.**
### Is your feature request related to a problem? Please describe
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->

**Describe the solution you'd like**
### Describe the solution you'd like
<!-- A clear and concise description of what you want to happen. -->

**Describe alternatives you've considered**
### Describe alternatives you've considered
<!-- A clear and concise description of any alternative solutions or features you've considered. -->

**Additional context**
### Additional context
<!-- Add any other context or screenshots about the feature request here. -->
<!-- Please include an AutoSplit profile `.toml` file and/or Split Images if relevant. -->
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repos:
- id: pretty-format-ini
args: [--autofix]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.1.11" # Must match requirements-dev.txt
rev: "v0.3.2" # Must match requirements-dev.txt
hooks:
- id: ruff
args: [--fix]
Expand Down
19 changes: 17 additions & 2 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Refer to the [build instructions](/docs/build%20instructions.md) if you're inter

## Linting and formatting

The project is setup to automatically configure VSCode witht he proper extensions and settings. Linters and formatters will be run on save.
The project is setup to automatically configure VSCode with the proper extensions and settings. Fixers and formatters will be run on save.
If you use a different IDE or for some reason cannot / don't want to use the recommended extensions, you can run `scripts/lint.ps1`.
Project configurations for other IDEs are welcome.

If you like to use pre-commit hooks, `.pre-commit-config.yaml` is setup for such uses.

Expand All @@ -28,6 +29,16 @@ Your Pull Request has to pass all checks ot be accepted. If it is still a work-i
Most coding standards will be enforced by automated tooling.
As time goes on, project-specific standards and "gotchas" in the frameworks we use will be listed here.

### Keep shipped dependencies and bundle size low

The bigger the bundle, the longer it takes to boot single-file executables. That is because we need to ship everything and the bootloader basically has to extract it all.
Our main use case is a single-file that is as easy to use as possible for the end user.
Keeping install time, build time and bandwith as low as possible is also a nice-to-have.

You should also consider whether the work the dependency is doing is simple enough that you could implement it yourself.

For these reasons, it's important to consider the impacts of adding any new dependency bundled with AutoSplit.

### Magic numbers

Please avoid using magic numbers and prefer constants and enums that have a meaningful name when possible.
Expand All @@ -38,6 +49,10 @@ For image shape and channels, please use `utils.ImageShape` and `utils.ColorChan

To avoid image shape mismatch issues, and to keep code simpler, we standardize the image color format to BGRA. This should always be done early in the pipeline, so whatever functionality takes care of obtaining an image should also ensure its color format. You can do so with `cv2.cvtColor` (ie: `cv2.cvtColor(image, cv2.COLOR_RGBA2BGRA)` or `cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)`).

### Split-specific setting overrides

Whenever a split image overrides a default global setting, we add a getter that handles the logic of checking for a split-specific override, then falling back to globals. This avoids repeating the fallback logic in multiple places. See `AutoSpitImage.get_*` methods for examples.

## Testing

None 😦 Please help us create test suites, we lack the time, but we really want (need!) them. <https://github.com/Toufool/AutoSplit/issues/216>
None 😦 Please help us create test suites, we lack the time, but we really want (*need!*) them. <https://github.com/Toufool/AutoSplit/issues/216>
19 changes: 12 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
[tool.ruff]
target-version = "py310"
line-length = 120
select = ["ALL"]
preview = true

[tool.ruff.lint]
select = ["ALL"]
# https://docs.astral.sh/ruff/rules/
ignore = [
###
Expand Down Expand Up @@ -58,21 +60,23 @@ ignore = [
# Python 3.11, introduced "zero cost" exception handling
"PERF203", # try-except-in-loop

### FIXME/TODO (no warnings in Ruff yet: https://github.com/astral-sh/ruff/issues/1256 & https://github.com/astral-sh/ruff/issues/1774):
### FIXME/TODO: I'd normally set them as temporarily warnings, but no warnings in Ruff yet:
### https://github.com/astral-sh/ruff/issues/1256 & https://github.com/astral-sh/ruff/issues/1774):
"CPY001", # flake8-copyright
"PTH", # flake8-use-pathlib
# Ignore until linux support
"EXE", # flake8-executable
]

[tool.ruff.per-file-ignores]
[tool.ruff.lint.per-file-ignores]
"typings/**/*.pyi" = [
"F811", # Re-exports false positives
"F821", # https://github.com/astral-sh/ruff/issues/3011
# The following can't be controlled for external libraries:
"A", # Shadowing builtin names
"ICN001", # unconventional-import-alias
"N8", # Naming conventions
"PLC2701", # Private name import
"PLR0904", # Too many public methods
"PLR0913", # Argument count
"PLR0917", # Too many positional arguments
Expand All @@ -81,11 +85,11 @@ ignore = [
]

# https://docs.astral.sh/ruff/settings/#flake8-implicit-str-concat
[tool.ruff.flake8-implicit-str-concat]
[tool.ruff.lint.flake8-implicit-str-concat]
allow-multiline = false

# https://docs.astral.sh/ruff/settings/#isort
[tool.ruff.isort]
[tool.ruff.lint.isort]
combine-as-imports = true
split-on-trailing-comma = false
# Unlike isort, Ruff only counts relative imports as local-folder by default for know.
Expand All @@ -107,13 +111,13 @@ known-local-folder = [
]

# https://docs.astral.sh/ruff/settings/#mccabe
[tool.ruff.mccabe]
[tool.ruff.lint.mccabe]
# Hard limit, arbitrary to 4 bytes
max-complexity = 31
# Arbitrary to 2 bytes, same as SonarLint
# max-complexity = 15

[tool.ruff.pylint]
[tool.ruff.lint.pylint]
# Arbitrary to 1 byte, same as SonarLint
max-args = 7
# At least same as max-complexity
Expand All @@ -132,6 +136,7 @@ ignore = [
# Autofixed by Ruff
# Check for the "Fix" flag https://docs.astral.sh/ruff/rules/#pycodestyle-e-w
"E2", # Whitespace
"E3", # Blank lines
"E703", # useless-semicolon
"E71", # Statement (comparisons)
"E731", # lambda-assignment
Expand Down
5 changes: 4 additions & 1 deletion scripts/compile_resources.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ Else {
$GITHUB_REPOSITORY = $Env:GITHUB_HEAD_REPOSITORY
If (-not $GITHUB_REPOSITORY) {
$repo_url = git config --get remote.origin.url
$GITHUB_REPOSITORY = $repo_url.substring(19, $repo_url.length - 19) -replace '\.git', ''
# Validate in case the repo was downloaded rather than cloned
If ($repo_url) {
$GITHUB_REPOSITORY = $repo_url.substring(19, $repo_url.length - 19) -replace '\.git', ''
}
}
If (-not $GITHUB_REPOSITORY) {
$GITHUB_REPOSITORY = 'Toufool/AutoSplit'
Expand Down
7 changes: 5 additions & 2 deletions scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ If ($IsLinux) {
}
# Ensures installation tools are up to date. This also aliases pip to pip3 on MacOS.
&"$python" -m pip install wheel pip setuptools --upgrade
# Upgrading QT to 6.6.2 w/o first uninstalling shiboken6 can lead to issues
# https://bugreports.qt.io/browse/PYSIDE-2616?focusedId=777285&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-777285
&"$python" -m pip uninstall shiboken6
&"$python" -m pip install -r "$PSScriptRoot/requirements$dev.txt" --upgrade
# These libraries install extra requirements we don't want
# Open suggestion for support in requirements files: https://github.com/pypa/pip/issues/9948 & https://github.com/pypa/pip/pull/10837
Expand Down Expand Up @@ -72,11 +75,11 @@ If ($IsLinux) {
Set-Content "$libPath/QtWidgets.pyi"
}
# Uninstall optional dependencies if PyAutoGUI or D3DShot was installed outside this script
# pyscreeze -> pyscreenshot -> mss deps call SetProcessDpiAwareness, used to be installed on Windows
# PyScreeze -> pyscreenshot -> mss deps call SetProcessDpiAwareness, used to be installed on Windows
# Pillow, pygetwindow, pymsgbox, pytweening, MouseInfo are picked up by PySide6
# (also --exclude from build script, but more consistent with unfrozen run)
&"$python" -m pip uninstall pyscreenshot mss pygetwindow pymsgbox pytweening MouseInfo -y
If ($IsWindows) { &"$python" -m pip uninstall pyscreeze Pillow -y }
If ($IsWindows) { &"$python" -m pip uninstall PyScreeze Pillow -y }

# Don't compile resources on the Build CI job as it'll do so in build script
If ($dev) {
Expand Down
4 changes: 2 additions & 2 deletions scripts/requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# Linters & Formatters
add-trailing-comma>=3.1.0 # Must match .pre-commit-config.yaml
autopep8>=2.0.4 # Must match .pre-commit-config.yaml
ruff>=0.1.11 # New checks # Must match .pre-commit-config.yaml
ruff>=0.3.2 # New checks # Must match .pre-commit-config.yaml
#
# Types
types-D3DShot ; sys_platform == 'win32'
Expand All @@ -23,5 +23,5 @@ types-psutil
types-PyAutoGUI
types-pyinstaller
types-python-xlib ; sys_platform == 'linux'
types-pywin32>=306.0.0.8 ; sys_platform == 'win32'
types-pywin32>=306.0.0.20240130 ; sys_platform == 'win32'
types-toml
4 changes: 2 additions & 2 deletions scripts/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Dependencies:
git+https://github.com/boppreh/keyboard.git#egg=keyboard # Fix install on macos and linux-ci https://github.com/boppreh/keyboard/pull/568
numpy>=1.26 # Python 3.12 support
opencv-python-headless>=4.8.1.78 # Typing fixes
opencv-python-headless>=4.9.0.80 # Typing fixes
packaging
psutil>=5.9.6 # Python 3.12 fixes
# PyAutoGUI # See install.ps1
Expand All @@ -29,5 +29,5 @@ winsdk>=1.0.0b10 ; sys_platform == 'win32' # Python 3.12 support
# D3DShot # See install.ps1
#
# Linux-only dependencies
pyscreeze ; sys_platform == 'linux'
PyScreeze ; sys_platform == 'linux'
python-xlib ; sys_platform == 'linux'
2 changes: 1 addition & 1 deletion src/AutoSplit.py
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ def set_preview_image(qlabel: QLabel, image: MatLike | None):
capture = image

qimage = QtGui.QImage(

Check failure on line 897 in src/AutoSplit.py

View workflow job for this annotation

GitHub Actions / Pyright (ubuntu-22.04, 3.10)

No overloads for "__init__" match the provided arguments (reportCallIssue)

Check failure on line 897 in src/AutoSplit.py

View workflow job for this annotation

GitHub Actions / Pyright (ubuntu-22.04, 3.11)

No overloads for "__init__" match the provided arguments (reportCallIssue)
capture.data, # pyright: ignore[reportGeneralTypeIssues] # https://bugreports.qt.io/browse/PYSIDE-2476
capture.data,

Check failure on line 898 in src/AutoSplit.py

View workflow job for this annotation

GitHub Actions / Pyright (ubuntu-22.04, 3.10)

Argument of type "memoryview" cannot be assigned to parameter "data" of type "bytes" in function "__init__"   "memoryview" is incompatible with "bytes"   Set disableBytesTypePromotions to false to enable type promotion behavior for "bytearray" and "memoryview" (reportArgumentType)

Check failure on line 898 in src/AutoSplit.py

View workflow job for this annotation

GitHub Actions / Pyright (ubuntu-22.04, 3.11)

Argument of type "memoryview" cannot be assigned to parameter "data" of type "bytes" in function "__init__"   "memoryview" is incompatible with "bytes"   Set disableBytesTypePromotions to false to enable type promotion behavior for "bytearray" and "memoryview" (reportArgumentType)
width,
height,
width * channels,
Expand Down
2 changes: 1 addition & 1 deletion src/capture_method/CaptureMethodBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def __init__(self, autosplit: "AutoSplit"):

def reinitialize(self):
self.close()
self.__init__(self._autosplit_ref) # type: ignore[misc]
self.__init__(self._autosplit_ref) # type: ignore[misc] # noqa: PLC2801

def close(self):
# Some capture methods don't need any cleanup
Expand Down
2 changes: 1 addition & 1 deletion src/capture_method/VideoCaptureDeviceCaptureMethod.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
if TYPE_CHECKING:
from AutoSplit import AutoSplit

OBS_VIRTUALCAM_PLUGIN_BLANK_PIXEL = [127, 129, 128]
OBS_VIRTUALCAM_PLUGIN_BLANK_PIXEL = (127, 129, 128)


def is_blank(image: MatLike):
Expand Down
6 changes: 2 additions & 4 deletions src/capture_method/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# pyright: reportUnknownMemberType=false
# Complete type for PIL.features.check_feature upstream
import asyncio
import os
import sys
Expand All @@ -16,7 +14,7 @@
from utils import WGC_MIN_BUILD, WINDOWS_BUILD_NUMBER, first, try_get_direct3d_device

if sys.platform == "win32":
from _ctypes import COMError
from _ctypes import COMError # noqa: PLC2701
from pygrabber.dshow_graph import FilterGraph

from capture_method.BitBltCaptureMethod import BitBltCaptureMethod
Expand Down Expand Up @@ -120,7 +118,7 @@ def __getitem__( # type:ignore[override] # pyright: ignore[reportIncompatibleMe
return super().__getitem__(__key)

@override
def get(self, key: CaptureMethodEnum, __default: object = None):
def get(self, key: CaptureMethodEnum, default: object = None, /):
"""
Returns the `CaptureMethodBase` subclass for `CaptureMethodEnum` if `CaptureMethodEnum` is available,
else defaults to the first available `CaptureMethodEnum`.
Expand Down
6 changes: 3 additions & 3 deletions src/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from utils import BGRA_CHANNEL_COUNT, MAXBYTE, ColorChannel, ImageShape, is_valid_image

MAXRANGE = MAXBYTE + 1
CHANNELS = [ColorChannel.Red.value, ColorChannel.Green.value, ColorChannel.Blue.value]
HISTOGRAM_SIZE = [8, 8, 8]
RANGES = [0, MAXRANGE, 0, MAXRANGE, 0, MAXRANGE]
CHANNELS = (ColorChannel.Red.value, ColorChannel.Green.value, ColorChannel.Blue.value)
HISTOGRAM_SIZE = (8, 8, 8)
RANGES = (0, MAXRANGE, 0, MAXRANGE, 0, MAXRANGE)
MASK_SIZE_MULTIPLIER = ColorChannel.Alpha * MAXBYTE * MAXBYTE


Expand Down
2 changes: 1 addition & 1 deletion src/hotkeys.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

Commands = Literal["split", "start", "pause", "reset", "skip", "undo"]
Hotkey = Literal["split", "reset", "skip_split", "undo_split", "pause", "screenshot", "toggle_auto_reset_image"]
HOTKEYS: list[Hotkey] = ["split", "reset", "skip_split", "undo_split", "pause", "screenshot", "toggle_auto_reset_image"]
HOTKEYS = ("split", "reset", "skip_split", "undo_split", "pause", "screenshot", "toggle_auto_reset_image")


def remove_all_hotkeys():
Expand Down
10 changes: 4 additions & 6 deletions src/menu_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import sys
import webbrowser
from functools import partial
from typing import TYPE_CHECKING, Any, cast
from urllib.error import URLError
from urllib.request import urlopen
Expand All @@ -23,7 +24,7 @@
get_all_video_capture_devices,
)
from gen import about, design, settings as settings_ui, update_checker
from hotkeys import HOTKEYS, Hotkey, set_hotkey
from hotkeys import HOTKEYS, set_hotkey
from utils import AUTOSPLIT_VERSION, GITHUB_REPOSITORY, decimal, fire_and_forget

if TYPE_CHECKING:
Expand Down Expand Up @@ -286,16 +287,13 @@ def __select_screenshot_directory(self):
self.screenshot_directory_input.setText(self._autosplit_ref.settings_dict["screenshot_directory"])

def __setup_bindings(self):
# Hotkey initial values and bindings
def hotkey_connect(hotkey: Hotkey):
return lambda: set_hotkey(self._autosplit_ref, hotkey)

"""Hotkey initial values and bindings."""
for hotkey in HOTKEYS:
hotkey_input: QtWidgets.QLineEdit = getattr(self, f"{hotkey}_input")
set_hotkey_hotkey_button: QtWidgets.QPushButton = getattr(self, f"set_{hotkey}_hotkey_button")
hotkey_input.setText(self._autosplit_ref.settings_dict.get(f"{hotkey}_hotkey", ""))

set_hotkey_hotkey_button.clicked.connect(hotkey_connect(hotkey))
set_hotkey_hotkey_button.clicked.connect(partial(set_hotkey, hotkey=hotkey))
# Make it very clear that hotkeys are not used when auto-controlled
if self._autosplit_ref.is_auto_controlled and hotkey != "toggle_auto_reset_image":
set_hotkey_hotkey_button.setEnabled(False)
Expand Down
6 changes: 3 additions & 3 deletions src/region_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import win32api
import win32gui
from win32con import SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN
from winsdk._winrt import initialize_with_window
from winsdk._winrt import initialize_with_window # noqa: PLC2701
from winsdk.windows.foundation import AsyncStatus, IAsyncOperation
from winsdk.windows.graphics.capture import GraphicsCaptureItem, GraphicsCapturePicker

Expand All @@ -45,7 +45,7 @@
GNOME_DESKTOP_ICONS_EXTENSION = "@!0,0;BDHF"
ALIGN_REGION_THRESHOLD = 0.9
BORDER_WIDTH = 2
SUPPORTED_IMREAD_FORMATS = [
SUPPORTED_IMREAD_FORMATS = (
("Windows bitmaps", "*.bmp *.dib"),
("JPEG files", "*.jpeg *.jpg *.jpe"),
("JPEG 2000 files", "*.jp2"),
Expand All @@ -58,7 +58,7 @@
("TIFF files", "*.tiff *.tif"),
("OpenEXR Image files", "*.exr"),
("Radiance HDR", "*.hdr *.pic"),
]
)
"""https://docs.opencv.org/4.8.0/d4/da8/group__imgcodecs.html#imread"""
IMREAD_EXT_FILTER = (
"All Files ("
Expand Down
Loading

0 comments on commit 9d28705

Please sign in to comment.