Skip to content

Commit 0e440f4

Browse files
committed
More consistent formatting and types
- Added autofixes to the lint script. - Added a quotes autofixer using `unify` - Added a trailing comma checker and autofixer - Applied trailing commas - Ordered requirements alphabetically - Ensure the last version of D3DShot is used (0.1.5, not 0.1.3) - Remove configuration for unused linters (black/prettier/sonarlint) - Updated types from typeshed
1 parent a139d29 commit 0e440f4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+300
-1009
lines changed

.github/workflows/lint-and-build.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,21 @@ env:
2525
GITHUB_HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }}
2626

2727
jobs:
28+
add-trailing-comma:
29+
runs-on: windows-latest
30+
steps:
31+
- name: Checkout ${{ github.repository }}/${{ github.ref }}
32+
uses: actions/checkout@v3
33+
- name: Set up Python 3.10
34+
uses: actions/setup-python@v4
35+
with:
36+
python-version: "3.10"
37+
cache: "pip"
38+
cache-dependency-path: "scripts/requirements*.txt"
39+
- run: scripts/install.ps1
40+
shell: pwsh
41+
- name: Analysing the code with add-trailing-comma
42+
run: add-trailing-comma $(git ls-files '**.py*') --py36-plus
2843
Pyright:
2944
runs-on: windows-latest
3045
strategy:

.vscode/extensions.json

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,26 @@
55
"davidanson.vscode-markdownlint",
66
"eamodio.gitlens",
77
"ms-python.flake8",
8+
"ms-python.pylint",
89
"ms-python.python",
910
"ms-python.vscode-pylance",
1011
"ms-vscode.powershell",
1112
"pkief.material-icon-theme",
1213
"redhat.vscode-xml",
1314
"redhat.vscode-yaml",
1415
"shardulm94.trailing-spaces",
15-
"sonarsource.sonarlint-vscode",
1616
],
1717
"unwantedRecommendations": [
1818
// Must disable in this workspace //
19+
// https://github.com/microsoft/vscode/issues/40239 //
1920
//
2021
// VSCode has implemented an optimized version
2122
"coenraads.bracket-pair-colorizer",
2223
"coenraads.bracket-pair-colorizer-2",
23-
// Lots of conflicts
24-
"esbenp.prettier-vscode",
25-
// Replaced by ESLint
26-
"eg2.tslint",
27-
"ms-vscode.vscode-typescript-tslint-plugin",
2824
// Obsoleted by Pylance
2925
"ms-pyright.pyright",
26+
"ms-python.black-formatter",
3027
// Not configurable per workspace, tends to conflict with other linters
31-
// Use eslint-plugin-sonarjs for JS/TS projects
3228
"sonarsource.sonarlint-vscode",
3329
//
3430
// Don't recommend to autoinstall //

.vscode/settings.json

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,19 @@
5858
},
5959
"python.analysis.diagnosticMode": "workspace",
6060
"python.linting.enabled": true,
61-
"python.linting.pylintEnabled": true,
62-
"python.linting.pylintCategorySeverity.convention": "Warning",
63-
"python.linting.pylintCategorySeverity.refactor": "Warning",
61+
// Use the new Pylint extension instead
62+
"python.linting.pylintEnabled": false,
63+
"pylint.severity": {
64+
"convention": "Warning",
65+
"error": "Error",
66+
"fatal": "Error",
67+
"refactor": "Warning",
68+
"warning": "Warning",
69+
"info": "Information"
70+
},
6471
// Use the new Flake8 extension instead
6572
"python.linting.flake8Enabled": false,
73+
// Partial codes don't work yet: https://github.com/microsoft/vscode-flake8/issues/7
6674
"flake8.severity": {
6775
"convention": "Warning",
6876
"error": "Error",

pyproject.toml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
# https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-via-a-file
2-
[tool.black]
3-
line-length = 120
4-
# Auto generated
5-
force-exclude = "src/gen/.*\\.py$"
6-
71
# https://github.com/hhatto/autopep8#usage
82
# https://github.com/hhatto/autopep8#more-advanced-usage
93
[tool.autopep8]
@@ -87,7 +81,7 @@ ignore-paths = [
8781
# We expect stub files to be incomplete or contain useless statements
8882
"^.*.pyi$",
8983
]
90-
extension-pkg-allow-list = ["PyQt6", "PySide6", "win32ui"]
84+
extension-pkg-allow-list = ["PyQt6", "PySide6", "win32ui", "win32.win32gui"]
9185

9286
[tool.pylint.FORMAT]
9387
max-line-length = 120
@@ -146,3 +140,5 @@ generated-members = [
146140
[tool.isort]
147141
line_length = 120
148142
combine_as_imports = true
143+
include_trailing_comma = true
144+
multi_line_output = 5

scripts/lint.ps1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ $exitCodes = 0
55
Write-Host "`nRunning autofixes..."
66
isort src/ typings/
77
autopep8 $(git ls-files '**.py*') --in-place
8+
unify src/ --recursive --in-place --quote='"""'
9+
add-trailing-comma $(git ls-files '**.py*') --py36-plus
810

911
Write-Host "`nRunning Pyright..."
1012
$Env:PYRIGHT_PYTHON_FORCE_VERSION = 'latest'

scripts/requirements-dev.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
-r requirements.txt
88
#
99
# Linters and formatters
10+
add-trailing-comma
1011
bandit
1112
flake8>=5 # flake8-pyi deprecation warnings
1213
flake8-builtins
@@ -21,12 +22,15 @@ flake8-simplify
2122
pep8-naming
2223
pylint>=2.13.9,<3.0.0 # Respect ignore configuration options with --recursive=y # 3.0 still in pre-release
2324
pyright
25+
unify
2426
#
2527
# Run `./scripts/designer.ps1` to quickly open the bundled PyQt Designer.
2628
# Can also be downloaded externally as a non-python package
2729
qt6-applications
2830
# Types
2931
pywin32-stubs>=1.0.7 # Added error types
32+
types-d3dshot
3033
types-keyboard
3134
types-pyautogui
35+
types-pyinstaller
3236
typing-extensions

scripts/requirements.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@
1010
# Creating an AutoSplit executable with PyInstaller: ./scripts/build.ps1
1111
#
1212
# Dependencies:
13-
numpy>=1.23 # Updated types
14-
opencv-python-headless>=4.5.4,<4.6 # https://github.com/pyinstaller/pyinstaller/issues/6889
15-
PyQt6>=6.2.1 # Python 3.10 support
13+
certifi
1614
git+https://github.com/JohannesBuchner/imagehash.git#egg=ImageHash # Contains type information + setup as package not module
1715
keyboard
16+
numpy>=1.23 # Updated types
17+
opencv-python-headless>=4.5.4,<4.6 # https://github.com/pyinstaller/pyinstaller/issues/6889
1818
packaging
1919
Pillow>=7.2.0 # https://github.com/SerpentAI/D3DShot/issues/44
20+
psutil
2021
PyAutoGUI
22+
git+https://github.com/Avasam/python_grabber.git@complete-types#egg=pygrabber # https://github.com/andreaschiavinato/python_grabber/pull/18
23+
PyQt6>=6.2.1 # Python 3.10 support
2124
requests
22-
certifi
2325
toml
24-
psutil
25-
git+https://github.com/Avasam/python_grabber.git@complete-types#egg=pygrabber # https://github.com/andreaschiavinato/python_grabber/pull/18
2626
# Windows-only
27+
git+https://github.com/ranchen421/D3DShot.git#egg=D3DShot # D3DShot from PyPI with Pillow>=7.2.0 will install 0.1.3 instead of 0.1.5
2728
pywin32>=301
2829
winsdk>=v1.0.0b4
29-
D3DShot
3030
#
3131
# Build and compile resources
3232
PyInstaller

src/AutoSplit.py

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@
2323
from capture_method import CaptureMethodBase, CaptureMethodEnum
2424
from gen import about, design, settings, update_checker
2525
from hotkeys import HOTKEYS, after_setting_hotkey, send_command
26-
from menu_bar import (about_qt, about_qt_for_python, check_for_updates, get_default_settings_from_ui, open_about,
27-
open_settings, open_update_checker, view_help)
26+
from menu_bar import (
27+
about_qt, about_qt_for_python, check_for_updates, get_default_settings_from_ui, open_about, open_settings,
28+
open_update_checker, view_help,
29+
)
2830
from region_selection import align_region, select_region, select_window, validate_before_parsing
2931
from split_parser import BELOW_FLAG, DUMMY_FLAG, PAUSE_FLAG, parse_and_validate_images
3032
from user_profile import DEFAULT_PROFILE
31-
from utils import (AUTOSPLIT_VERSION, FIRST_WIN_11_BUILD, FROZEN, START_AUTO_SPLITTER_TEXT, WINDOWS_BUILD_NUMBER,
32-
auto_split_directory, decimal, is_valid_image)
33+
from utils import (
34+
AUTOSPLIT_VERSION, FIRST_WIN_11_BUILD, FROZEN, START_AUTO_SPLITTER_TEXT, WINDOWS_BUILD_NUMBER, auto_split_directory,
35+
decimal, is_valid_image,
36+
)
3337

3438
CHECK_FPS_ITERATIONS = 10
3539

@@ -172,9 +176,8 @@ def __init__(self, parent: QWidget | None = None): # pylint: disable=too-many-s
172176
self.align_region_button.clicked.connect(lambda: align_region(self))
173177
self.select_window_button.clicked.connect(lambda: select_window(self))
174178
self.reload_start_image_button.clicked.connect(lambda: self.__load_start_image(True, True))
175-
self.action_check_for_updates_on_open.changed.connect(lambda: user_profile.set_check_for_updates_on_open(
176-
self,
177-
self.action_check_for_updates_on_open.isChecked())
179+
self.action_check_for_updates_on_open.changed.connect(
180+
lambda: user_profile.set_check_for_updates_on_open(self, self.action_check_for_updates_on_open.isChecked()),
178181
)
179182

180183
# update x, y, width, and height when changing the value of these spinbox's are changed
@@ -186,8 +189,9 @@ def __init__(self, parent: QWidget | None = None): # pylint: disable=too-many-s
186189
# connect signals to functions
187190
self.after_setting_hotkey_signal.connect(lambda: after_setting_hotkey(self))
188191
self.start_auto_splitter_signal.connect(self.__auto_splitter)
189-
self.update_checker_widget_signal.connect(lambda latest_version, check_on_open:
190-
open_update_checker(self, latest_version, check_on_open))
192+
self.update_checker_widget_signal.connect(
193+
lambda latest_version, check_on_open: open_update_checker(self, latest_version, check_on_open),
194+
)
191195
self.load_start_image_signal.connect(self.__load_start_image)
192196
self.load_start_image_signal[bool].connect(self.__load_start_image)
193197
self.load_start_image_signal[bool, bool].connect(self.__load_start_image)
@@ -225,7 +229,8 @@ def __browse(self):
225229
new_split_image_directory = QFileDialog.getExistingDirectory(
226230
self,
227231
"Select Split Image Directory",
228-
os.path.join(self.settings_dict["split_image_directory"] or auto_split_directory, ".."))
232+
os.path.join(self.settings_dict["split_image_directory"] or auto_split_directory, ".."),
233+
)
229234

230235
# If the user doesn't select a folder, it defaults to "".
231236
if new_split_image_directory:
@@ -260,9 +265,11 @@ def __load_start_image(self, started_by_button: bool = False, wait_for_delay: bo
260265

261266
if self.start_image:
262267
if not self.is_auto_controlled \
263-
and (not self.settings_dict["split_hotkey"]
264-
or not self.settings_dict["reset_hotkey"]
265-
or not self.settings_dict["pause_hotkey"]):
268+
and (
269+
not self.settings_dict["split_hotkey"]
270+
or not self.settings_dict["reset_hotkey"]
271+
or not self.settings_dict["pause_hotkey"]
272+
):
266273
error_messages.load_start_image()
267274
QApplication.processEvents()
268275
return
@@ -334,7 +341,8 @@ def __start_image_function(self):
334341
while time() - delay_start_time < start_delay:
335342
delay_time_left = start_delay - (time() - delay_start_time)
336343
self.current_split_image.setText(
337-
f"Delayed Before Starting:\n {seconds_remaining_text(delay_time_left)}")
344+
f"Delayed Before Starting:\n {seconds_remaining_text(delay_time_left)}",
345+
)
338346
QTest.qWait(1)
339347

340348
self.start_image_status_value_label.setText("started")
@@ -366,7 +374,8 @@ def __take_screenshot(self):
366374
while True:
367375
screenshot_path = os.path.join(
368376
self.settings_dict["split_image_directory"],
369-
f"{screenshot_index:03}_SplitImage.png")
377+
f"{screenshot_index:03}_SplitImage.png",
378+
)
370379
if not os.path.exists(screenshot_path):
371380
break
372381
screenshot_index += 1
@@ -426,7 +435,7 @@ def undo_split(self, navigate_image_only: bool = False):
426435
return
427436

428437
if not navigate_image_only:
429-
for i, group in enumerate(self.split_groups,):
438+
for i, group in enumerate(self.split_groups):
430439
if i > 0 and self.split_image_number in group:
431440
self.split_image_number = self.split_groups[i - 1][-1]
432441
break
@@ -508,10 +517,13 @@ def __auto_splitter(self):
508517
# Construct a list of images + loop count tuples.
509518
self.split_images_and_loop_number = [
510519
item for flattenlist
511-
in [[(split_image, i + 1) for i in range(split_image.loops)]
520+
in [
521+
[(split_image, i + 1) for i in range(split_image.loops)]
512522
for split_image
513-
in self.split_images]
514-
for item in flattenlist]
523+
in self.split_images
524+
]
525+
for item in flattenlist
526+
]
515527

516528
# Construct groups of splits
517529
self.split_groups = []
@@ -649,7 +661,8 @@ def __similarity_threshold_loop(self, number_of_split_images: int, dummy_splits_
649661
continue
650662

651663
elif ( # pylint: disable=confusing-consecutive-elif
652-
self.split_image.check_flag(BELOW_FLAG) and self.split_below_threshold):
664+
self.split_image.check_flag(BELOW_FLAG) and self.split_below_threshold
665+
):
653666
self.split_below_threshold = False
654667
break
655668

@@ -758,10 +771,12 @@ def __get_capture_for_comparison(self):
758771
if recovered:
759772
capture, _ = self.capture_method.get_frame(self)
760773

761-
return (None
762-
if not is_valid_image(capture)
763-
else cv2.resize(capture, COMPARISON_RESIZE, interpolation=cv2.INTER_NEAREST),
764-
is_old_image)
774+
return (
775+
None
776+
if not is_valid_image(capture)
777+
else cv2.resize(capture, COMPARISON_RESIZE, interpolation=cv2.INTER_NEAREST),
778+
is_old_image,
779+
)
765780

766781
def __reset_if_should(self, capture: cv2.Mat | None):
767782
"""
@@ -856,7 +871,8 @@ def exit_program():
856871
self,
857872
"AutoSplit",
858873
f"Do you want to save changes made to settings file {settings_file_name}?",
859-
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel)
874+
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel,
875+
)
860876

861877
if warning is QMessageBox.StandardButton.Yes:
862878
if user_profile.save_settings(self):
@@ -887,10 +903,13 @@ def set_preview_image(qlabel: QLabel, image: cv2.Mat | None, transparency: bool)
887903
capture = cv2.cvtColor(image, color_code)
888904
height, width, channels = capture.shape
889905
qimage = QtGui.QImage(capture.data, width, height, width * channels, image_format)
890-
qlabel.setPixmap(QtGui.QPixmap(qimage).scaled(
891-
qlabel.size(),
892-
QtCore.Qt.AspectRatioMode.IgnoreAspectRatio,
893-
QtCore.Qt.TransformationMode.SmoothTransformation))
906+
qlabel.setPixmap(
907+
QtGui.QPixmap(qimage).scaled(
908+
qlabel.size(),
909+
QtCore.Qt.AspectRatioMode.IgnoreAspectRatio,
910+
QtCore.Qt.TransformationMode.SmoothTransformation,
911+
),
912+
)
894913

895914

896915
def seconds_remaining_text(seconds: float):

src/AutoSplitImage.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def check_flag(self, flag: int):
126126
def compare_with_capture(
127127
self,
128128
default: AutoSplit | int,
129-
capture: cv2.Mat | None
129+
capture: cv2.Mat | None,
130130
):
131131
"""
132132
Compare image with capture using image's comparison method. Falls back to combobox
@@ -145,5 +145,7 @@ def compare_with_capture(
145145

146146

147147
if True: # pylint: disable=using-constant-test
148-
from split_parser import (comparison_method_from_filename, delay_time_from_filename, flags_from_filename,
149-
loop_from_filename, pause_from_filename, threshold_from_filename)
148+
from split_parser import (
149+
comparison_method_from_filename, delay_time_from_filename, flags_from_filename, loop_from_filename,
150+
pause_from_filename, threshold_from_filename,
151+
)

src/capture_method/BitBltCaptureMethod.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ def get_frame(self, autosplit: AutoSplit) -> tuple[cv2.Mat | None, bool]:
5252
(selection["width"], selection["height"]),
5353
dc_object,
5454
(selection["x"] + left_bounds, selection["y"] + top_bounds),
55-
win32con.SRCCOPY)
55+
win32con.SRCCOPY,
56+
)
5657
image = np.frombuffer(cast(bytes, bitmap.GetBitmapBits(True)), dtype=np.uint8)
5758
image.shape = (selection["height"], selection["width"], 4)
5859
except (win32ui.error, pywintypes.error):

src/capture_method/DesktopDuplicationCaptureMethod.py

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

33
import ctypes
44
import ctypes.wintypes
5-
from typing import TYPE_CHECKING
5+
from typing import TYPE_CHECKING, cast
66

77
import cv2
88
import d3dshot
@@ -30,7 +30,8 @@ def get_frame(self, autosplit: AutoSplit):
3030
desktop_duplication.display = [
3131
display for display
3232
in desktop_duplication.displays
33-
if display.hmonitor == hmonitor][0]
33+
if display.hmonitor == hmonitor
34+
][0]
3435
offset_x, offset_y, *_ = win32gui.GetWindowRect(hwnd)
3536
offset_x -= desktop_duplication.display.position["left"]
3637
offset_y -= desktop_duplication.display.position["top"]
@@ -41,4 +42,4 @@ def get_frame(self, autosplit: AutoSplit):
4142
screenshot = desktop_duplication.screenshot((left, top, right, bottom))
4243
if screenshot is None:
4344
return None, False
44-
return cv2.cvtColor(screenshot, cv2.COLOR_RGBA2BGRA), False
45+
return cv2.cvtColor(cast(cv2.Mat, screenshot), cv2.COLOR_RGBA2BGRA), False

0 commit comments

Comments
 (0)