Skip to content

Commit 88d7d6a

Browse files
AvasamToufool
andauthored
Linted pyi files (#137)
* hooked new settings window to actual values * Linted pyi files * Initial UI update for 2.0.0. Add settings window. * hooked new settings window to actual values * Better "seconds remaining" text * Undo split goes to the end of the group * Turn off pyright(reportFunctionMemberAccess) in favor of pylint(no-member) * Massively sped up Flake tests Removed 400+kb of type stubs * Centralized qWait typing fix * Autosort imports * Resynced settings Co-authored-by: Austin <[email protected]>
1 parent 60a1277 commit 88d7d6a

Some content is hidden

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

41 files changed

+389
-121508
lines changed

.flake8

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
[flake8]
22
color=always
33
max-line-length=120
4-
; Auto generated
5-
exclude=src/gen/
6-
; Linebreak before binary operator
7-
; Allow default value other than "..."
8-
; Allow imports at the bottom of file
9-
ignore=W503,Y015,E402
4+
exclude=
5+
src/gen/, ; Auto generated
6+
typings/cv2-stubs/__init__.pyi, ; External existing stub
7+
ignore=
8+
W503, ; Linebreak before binary operator
9+
E402, ; Allow imports at the bottom of file
10+
Y026, ; Not using typing_extensions
1011
per-file-ignores=
12+
; Docstrings in type stubs
13+
; Function bodys contain other than just ... (eg: raise)
14+
; Single quote docstrings
15+
typings/cv2-stubs/__init__.pyi: Q000,N8,E704, Y021,Y010,Q002
16+
1117
; Quotes
12-
__init__.pyi:Q000
18+
; Allow ... on same line as def
19+
; Line too long
20+
; Naming conventions can't be controlled for external libraries
21+
typings/**: Q000,E704,E501,N8
22+
1323
; PyQt methods
1424
ignore-names=closeEvent,paintEvent,keyPressEvent,mousePressEvent,mouseMoveEvent,mouseReleaseEvent
1525
; McCabe max-complexity is also taken care of by Pylint and doesn't fail the build there

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ jobs:
6464
pip install -r "scripts/requirements.txt"
6565
- run: scripts/compile_resources.bat
6666
- name: Analysing the code with ${{ job.name }}
67-
run: pylint --reports=y --output-format=colorized $(git ls-files '**/*.py*')
67+
run: pylint --reports=y --output-format=colorized $(git ls-files '**/*.py')
6868
Flake8:
6969
runs-on: windows-latest
7070
strategy:

.vscode/settings.json

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,14 @@
5959
"python.linting.pylintCategorySeverity.convention": "Warning",
6060
"python.linting.pylintCategorySeverity.refactor": "Warning",
6161
"python.linting.flake8Enabled": true,
62+
// pycodestyles
6263
"python.linting.flake8CategorySeverity.E": "Warning",
64+
// Pyflakes
65+
"python.linting.flake8CategorySeverity.F": "Warning",
66+
// PEP8 Naming convention
67+
"python.linting.flake8CategorySeverity.N": "Warning",
68+
// PYI
69+
"python.linting.flake8CategorySeverity.Y": "Warning",
6370
// PyRight obsoletes mypy
6471
"python.linting.mypyEnabled": false,
6572
// Is already wrapped by Flake8, prospector and pylama
@@ -69,16 +76,4 @@
6976
// Just another wrapper, use Flake8 OR this
7077
"python.linting.pylamaEnabled": false,
7178
"python.linting.banditEnabled": true,
72-
// Copy those over to your user settings
73-
"sonarlint.rules": {
74-
"python:S1192": {
75-
"level": "off"
76-
},
77-
"python:S3776": {
78-
"level": "off"
79-
},
80-
"python:S107": {
81-
"level": "off"
82-
},
83-
},
8479
}

PyInstaller/hooks/hook-cv2.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
# ------------------------------------------------------------------
2-
# Copyright (c) 2020 PyInstaller Development Team.
3-
#
4-
# This file is distributed under the terms of the GNU General Public
5-
# License (version 2.0 or later).
6-
#
7-
# The full license is available in LICENSE.GPL.txt, distributed with
8-
# this software.
9-
#
10-
# SPDX-License-Identifier: GPL-2.0-or-later
11-
# ------------------------------------------------------------------
12-
# https://github.com/pyinstaller/pyinstaller-hooks-contrib/blob/master/src/_pyinstaller_hooks_contrib/hooks/stdhooks/hook-cv2.py
13-
14-
from PyInstaller.utils.hooks import collect_dynamic_libs, collect_data_files
1+
"""
2+
Copyright (c) 2020 PyInstaller Development Team.
3+
4+
This file is distributed under the terms of the GNU General Public
5+
License (version 2.0 or later).
6+
7+
The full license is available in LICENSE.GPL.txt, distributed with
8+
this software.
9+
10+
SPDX-License-Identifier: GPL-2.0-or-later
11+
12+
https://github.com/pyinstaller/pyinstaller-hooks-contrib/blob/master/src/_pyinstaller_hooks_contrib/hooks/stdhooks/hook-cv2.py
13+
"""
14+
15+
from PyInstaller.utils.hooks import collect_data_files, collect_dynamic_libs
1516

1617
hiddenimports = ["numpy"]
1718

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ This program can be used to automatically start, split, and reset your preferred
6767

6868
### Comparison Method
6969

70-
- There are three comparison methods to choose from: L2 Norm, Histograms, and pHash.
70+
- There are three comparison methods to choose from: L2 Norm, Histograms, and Perceptual Hash (or pHash).
7171
- L2 Norm: This method should be fine to use for most cases. it finds the difference between each pixel, squares it, and sums it over the entire image and takes the square root. This is very fast but is a problem if your image is high frequency. Any translational movement or rotation can cause similarity to be very different.
7272
- Histograms: An explanation on Histograms comparison can be found [here](https://mpatacchiola.github.io/blog/2016/11/12/the-simplest-classifier-histogram-intersection.html). This is a great method to use if you are using several masked images.
73-
- pHash: An explanation on pHash comparison can be found [here](http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html). It is highly recommended to NOT use pHash if you use masked images. It is very inaccurate.
73+
- Perceptual Hash: An explanation on pHash comparison can be found [here](http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html). It is highly recommended to NOT use pHash if you use masked images. It is very inaccurate.
7474

7575
### Full Content Rendering
7676

pyproject.toml

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,24 @@ aggressive = 3
1616
pythonPlatform = "Windows"
1717
typeCheckingMode = "strict"
1818
# Extra strict
19-
reportPropertyTypeMismatch=true
20-
reportUninitializedInstanceVariable=true
21-
reportCallInDefaultInitializer=true
22-
reportImplicitStringConcatenation=true
19+
reportImplicitStringConcatenation="error"
20+
reportCallInDefaultInitializer="error"
21+
reportMissingSuperCall="none" # False positives on base classes
22+
reportPropertyTypeMismatch="error"
23+
reportUninitializedInstanceVariable="error"
24+
reportUnnecessaryTypeIgnoreComment="error"
25+
reportUnusedCallResult="none"
2326
ignore = [
2427
# Auto generated
2528
"src/gen/",
26-
# We expect stub files to be incomplete or contain useless statements as they're external
29+
# We expect stub files to be incomplete or contain useless statements
2730
"typings/",
2831
]
29-
reportMissingTypeStubs = "information"
32+
reportMissingTypeStubs = "warning"
3033
# False positives with TYPE_CHECKING
3134
reportImportCycles = "information"
32-
# PyQt .connect
33-
reportFunctionMemberAccess = "information"
35+
# False positives with PyQt .connect . pylint(no-member) works instead
36+
reportFunctionMemberAccess = "none"
3437
# Extra runtime safety
3538
reportUnnecessaryComparison = "warning"
3639
# Flake8 does a better job
@@ -42,7 +45,7 @@ reportUnknownMemberType = "none"
4245
# https://pylint.pycqa.org/en/latest/technical_reference/features.html
4346
[tool.pylint.REPORTS]
4447
# Just like default but any error will make drop to 9 or less
45-
evaluation = "10.0 - error - ((float(warning * 10 + refactor + convention) / statement) * 10)"
48+
evaluation = "10.0 - error - ((float((warning + convention) * 10 + refactor ) / statement) * 10)"
4649
[tool.pylint.MASTER]
4750
fail-under = 9.0
4851
# https://pylint.pycqa.org/en/latest/technical_reference/extensions.html
@@ -70,14 +73,18 @@ load-plugins = [
7073
# "pylint.extensions.comparison_placement",
7174
# "pylint.extensions.for_any_all",
7275
]
73-
ignore-paths = [
76+
# Auto generated (doesn't work)
77+
ignore-paths = ["src/gen/.*"]
78+
# We expect stub files to be incomplete or contain useless statements
79+
ignore-patterns = [
80+
".*\\.pyi",
7481
# Auto generated
75-
"^src/gen/.*$",
76-
# We expect stub files to be incomplete or contain useless statements as they're external
77-
"^typings/.*$",
82+
"about.py",
83+
"design.py",
84+
"resources_rc.py",
85+
"settings.py",
86+
"update_checker.py",
7887
]
79-
# No need to mention the fixmes
80-
disable = ["fixme"]
8188
extension-pkg-allow-list = ["PyQt6", "win32ui"]
8289

8390
[tool.pylint.FORMAT]
@@ -87,8 +94,8 @@ max-line-length = 120
8794
# Same as SonarLint
8895
max-args = 7
8996
# Arbitrary to 2 bytes
90-
max-attributes = 16
91-
max-locals = 16
97+
max-attributes = 15
98+
max-locals = 15
9299

93100
[tool.pylint.'MESSAGES CONTROL']
94101
# Same as SonarLint
@@ -103,16 +110,24 @@ good-names = [
103110
# PyQt methods
104111
"closeEvent", "paintEvent", "keyPressEvent", "mousePressEvent", "mouseMoveEvent", "mouseReleaseEvent",
105112
# https://github.com/PyCQA/pylint/issues/2018
106-
"x", "y", "a0", "i", "t0", "t1"]
113+
"id", "x", "y", "a0", "i", "t0", "t1"]
107114
disable = [
115+
# No need to mention the fixmes
116+
"fixme",
108117
"missing-docstring",
109118
# We group imports
110119
"wrong-import-position",
111120
# Already taken care of and grayed out. Also conflicts with Pylance reportIncompatibleMethodOverride
112121
"unused-argument",
113122
# Already taken care of by Flake8
114123
"unused-import",
124+
# Similar lines in 2 files, doesn't really work
125+
"R0801",
115126
]
116127

117128
[tool.pylint.TYPECHECK]
118129
generated-members = "cv2"
130+
131+
[tool.isort]
132+
line_length = 120
133+
combine_as_imports = true

res/settings.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@
192192
</item>
193193
<item>
194194
<property name="text">
195-
<string>pHash</string>
195+
<string>Perceptual Hash</string>
196196
</property>
197197
</item>
198198
</widget>

scripts/install.bat

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
py -3.9 -m pip install wheel
2-
py -3.9 -m pip install -r "%~p0requirements.txt"
3-
npm install -g pyright
1+
py -3.9 -m pip install wheel --upgrade
2+
py -3.9 -m pip install -r "%~p0requirements.txt" --upgrade
3+
npm install -g pyright@latest
44
CALL "%~p0compile_resources.bat"

scripts/lint.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ if ($LastExitCode -gt 0) {
1313
}
1414

1515
Write-Host "`nRunning Pylint..."
16-
pylint --score=n --output-format=colorized $(git ls-files '**/*.py*')
16+
pylint --score=n --output-format=colorized $(git ls-files '**/*.py')
1717
$exitCodes += $LastExitCode
1818
if ($LastExitCode -gt 0) {
1919
Write-Host "`Pylint failed ($LastExitCode)" -ForegroundColor Red

scripts/requirements.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ PySide6
2222
pyautogui
2323
pywin32
2424
requests
25-
# Linting and Types
25+
# Linting, formatters and Types
2626
bandit
27+
isort
2728
flake8
29+
flake8-pyi
2830
flake8-quotes
29-
pylint
30-
pywin32-stubs
31+
flake8-isort
32+
pylint>=2.13
33+
git+https://github.com/Avasam/pywin32-stubs.git#egg=pywin32-stubs # https://github.com/kaluluosi/pywin32-stubs/pull/4
3134
simplejson
3235
types-simplejson>=3.17.2
3336
types-requests

src/AutoControlledWorker.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
from __future__ import annotations
2+
23
from typing import TYPE_CHECKING
3-
if TYPE_CHECKING:
4-
from AutoSplit import AutoSplit
4+
55
from PyQt6 import QtCore
66

77
import error_messages
88
import settings_file as settings
99

10+
if TYPE_CHECKING:
11+
from AutoSplit import AutoSplit
12+
1013

1114
class AutoControlledWorker(QtCore.QObject):
1215
def __init__(self, autosplit: AutoSplit):

src/AutoSplit.py

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,34 @@
77
# - Externals
88
# - Internals
99
from __future__ import annotations
10-
from collections.abc import Callable
11-
from types import FunctionType, TracebackType
12-
from typing import Optional, Union
1310

14-
import sys
15-
import os
1611
import ctypes
12+
import os
1713
import signal
14+
import sys
1815
import traceback
16+
from collections.abc import Callable
1917
from time import time
18+
from types import FunctionType, TracebackType
19+
from typing import Optional, Union
2020

2121
import certifi
2222
import cv2
23-
from PyQt6 import QtCore, QtGui, QtTest
23+
from PyQt6 import QtCore, QtGui
24+
from PyQt6.QtTest import QTest
2425
from PyQt6.QtWidgets import QApplication, QFileDialog, QMainWindow, QMessageBox, QWidget
2526
from win32 import win32gui
26-
from AutoSplitImage import COMPARISON_RESIZE, AutoSplitImage, ImageType
2727

2828
import error_messages
2929
import settings_file as settings
3030
from AutoControlledWorker import AutoControlledWorker
31+
from AutoSplitImage import COMPARISON_RESIZE, AutoSplitImage, ImageType
3132
from capture_windows import capture_region, set_ui_image
3233
from gen import about, design, settings as settings_ui, update_checker
33-
from hotkeys import send_command, after_setting_hotkey
34-
from menu_bar import get_default_settings_from_ui, open_about, VERSION, open_settings, view_help, check_for_updates, \
35-
open_update_checker
36-
from screen_region import select_region, select_window, align_region, validate_before_parsing
34+
from hotkeys import after_setting_hotkey, send_command
35+
from menu_bar import (VERSION, check_for_updates, get_default_settings_from_ui, open_about, open_settings,
36+
open_update_checker, view_help)
37+
from screen_region import align_region, select_region, select_window, validate_before_parsing
3738
from settings_file import FROZEN
3839
from split_parser import BELOW_FLAG, DUMMY_FLAG, PAUSE_FLAG, parse_and_validate_images
3940

@@ -343,13 +344,11 @@ def __start_image_function(self):
343344
delay_time_left = start_delay - (time() - delay_start_time)
344345
self.current_split_image.setText(
345346
f"Delayed Before Starting:\n {seconds_remaining_text(delay_time_left)}")
346-
# Email sent to [email protected]
347-
QtTest.QTest.qWait(1) # type: ignore
347+
QTest.qWait(1)
348348

349349
self.start_image_status_value_label.setText("started")
350350
send_command(self, "start")
351-
# Email sent to [email protected]
352-
QtTest.QTest.qWait(int(1 / self.settings_dict["fps_limit"])) # type: ignore
351+
QTest.qWait(int(1 / self.settings_dict["fps_limit"]))
353352
self.start_auto_splitter()
354353

355354
# update x, y, width, height when spinbox values are changed
@@ -605,8 +604,7 @@ def __auto_splitter(self):
605604

606605
# limit the number of time the comparison runs to reduce cpu usage
607606
frame_interval: float = 1 / self.settings_dict["fps_limit"]
608-
# Email sent to [email protected]
609-
QtTest.QTest.qWait(int(frame_interval - (time() - start) % frame_interval)) # type: ignore
607+
QTest.qWait(int(frame_interval - (time() - start) % frame_interval))
610608
QApplication.processEvents()
611609

612610
# comes here when threshold gets met
@@ -636,8 +634,7 @@ def __auto_splitter(self):
636634
capture = self.__get_capture_for_comparison()
637635
if self.__reset_if_should(capture):
638636
continue
639-
# Email sent to [email protected]
640-
QtTest.QTest.qWait(1) # type: ignore
637+
QTest.qWait(1)
641638

642639
self.waiting_for_split_delay = False
643640

@@ -691,8 +688,7 @@ def __auto_splitter(self):
691688
send_command(self, "reset")
692689
self.reset()
693690
continue
694-
# Email sent to [email protected]
695-
QtTest.QTest.qWait(1) # type: ignore
691+
QTest.qWait(1)
696692

697693
# loop breaks to here when the last image splits
698694
self.gui_changes_on_reset()
@@ -760,8 +756,7 @@ def __get_capture_for_comparison(self):
760756
if capture is None:
761757
# Try to recover by using the window name
762758
self.live_image.setText("Trying to recover window...")
763-
# https://github.com/kaluluosi/pywin32-stubs/issues/7
764-
hwnd = win32gui.FindWindow(None, self.settings_dict["captured_window_title"]) # type: ignore
759+
hwnd = win32gui.FindWindow(None, self.settings_dict["captured_window_title"])
765760
# Don't fallback to desktop
766761
if hwnd:
767762
self.hwnd = hwnd

0 commit comments

Comments
 (0)