Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update minimal Python version to 3.11: #296

Merged
merged 3 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/lint-and-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
# Ruff is version and platform sensible
matrix:
os: [windows-latest, ubuntu-22.04]
python-version: ["3.10", "3.11", "3.12"]
python-version: ["3.11", "3.12"]
steps:
- name: Checkout ${{ github.repository }}/${{ github.ref }}
uses: actions/checkout@v4
Expand All @@ -66,7 +66,7 @@ jobs:
# Pyright is version and platform sensible
matrix:
os: [windows-latest, ubuntu-22.04]
python-version: ["3.10", "3.11", "3.12"]
python-version: ["3.11", "3.12"]
steps:
- name: Checkout ${{ github.repository }}/${{ github.ref }}
uses: actions/checkout@v4
Expand Down
1 change: 0 additions & 1 deletion .sonarcloud.properties

This file was deleted.

4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ To understand how to use AutoSplit and how it works in-depth, please read the [t
- Should work on Ubuntu 20.04+ (Only tested on Ubuntu 22.04)
- Wayland is not currently supported
- WSL2/WSLg requires an additional Desktop Environment, external X11 server, and/or systemd
- Python 3.10+ (Not required for normal use. Refer to the [build instructions](/docs/build%20instructions.md) if you'd like run the application directly in Python).
- Python 3.11+ (Not required for normal use. Refer to the [build instructions](/docs/build%20instructions.md) if you'd like run the application directly in Python).

## Timer Integration

Expand Down Expand Up @@ -102,6 +102,8 @@ Not a developer? You can still help through the following methods:
- <https://github.com/opencv/opencv/issues/23906>
- <https://github.com/pywinrt/python-winsdk/issues/11>
- <https://github.com/pyinstaller/pyinstaller-hooks-contrib/issues/807>
- <https://github.com/hukkin/tomli-w/pull/46>
- <https://github.com/uiri/toml/issues/270>
- <https://github.com/microsoft/vscode/issues/40239>
- <https://github.com/microsoft/vscode/issues/168411>
- <https://github.com/python/mypy/issues/6700>
Expand Down
2 changes: 1 addition & 1 deletion docs/build instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

### All platforms

- [Python](https://www.python.org/downloads/) 3.10+.
- [Python](https://www.python.org/downloads/) 3.11+.
- [Node](https://nodejs.org) is optional, but required for complete linting.
- Alternatively you can install the [pyright python wrapper](https://pypi.org/project/pyright/) which has a bit of an overhead delay.
- [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) is used to run all the scripts
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# https://github.com/microsoft/pyright/blob/main/docs/configuration.md#sample-pyprojecttoml-file
[tool.pyright]
typeCheckingMode = "strict"
pythonVersion = "3.10"
pythonVersion = "3.11"
# Prefer `pyright: ignore`
enableTypeIgnoreComments = false

Expand Down
2 changes: 1 addition & 1 deletion ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# These configs are incompatible with ruff<0.5.7

# https://docs.astral.sh/ruff/configuration/
target-version = "py310" # Change this to the oldest supported version by your application
target-version = "py311" # Change this to the oldest supported version by your application
line-length = 100
preview = true

Expand Down
12 changes: 6 additions & 6 deletions scripts/python_build_from_source_linux.bash
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ sudo apt update
sudo apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libsqlite3-dev libreadline-dev libffi-dev curl libbz2-dev tk-dev

# Download Python binary package:
wget https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tgz
wget https://www.python.org/ftp/python/3.11.10/Python-3.11.10.tgz

# Unzip the package:
tar -xzf Python-3.10.13.tgz
tar -xzf Python-3.11.10.tgz

# Execute configure script
cd Python-3.10.13
cd Python-3.11.10
./configure --enable-optimizations --enable-shared

# Build Python 3.10
# Build Python 3.11
make -j 2

# Install Python 3.10
# Install Python 3.11
sudo make install

# Verify the installation
python3.10 -V
python3.11 -V

echo "If Python version did not print, you may need to stop active processes"
2 changes: 1 addition & 1 deletion scripts/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ PyWinCtl>=0.0.42 # py.typed
# When needed, dev builds can be found at https://download.qt.io/snapshots/ci/pyside/dev?C=M;O=D
PySide6-Essentials>=6.6.0 # Python 3.12 support
scipy>=1.11.2 # Python 3.12 support
toml
tomli-w
typing-extensions>=4.4.0 # @override decorator support
#
# Build and compile resources
Expand Down
6 changes: 3 additions & 3 deletions src/AutoSplitImage.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import os
import tomllib
from enum import IntEnum, auto
from math import sqrt
from typing import TYPE_CHECKING

import cv2
import numpy as np
import toml
from cv2.typing import MatLike

import error_messages
Expand Down Expand Up @@ -133,8 +133,8 @@ def __parse_text_file(self, path: str):
error_messages.tesseract_missing(path)
return

with open(path, encoding="utf-8") as f:
data = toml.load(f)
with open(path, mode="rb") as f:
data = tomllib.load(f)

self.texts = [text.lower().strip() for text in data["texts"]]
self.__rect = (data["left"], data["right"], data["top"], data["bottom"])
Expand Down
37 changes: 9 additions & 28 deletions src/capture_method/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
import sys
from collections import OrderedDict
from dataclasses import dataclass
from enum import Enum, EnumMeta, auto, unique
from enum import EnumMeta, StrEnum, auto, unique
from itertools import starmap
from typing import TYPE_CHECKING, TypedDict, cast
from typing import TYPE_CHECKING, Never, TypedDict, cast

from typing_extensions import Never, override
from typing_extensions import override

from capture_method.CaptureMethodBase import CaptureMethodBase
from capture_method.VideoCaptureDeviceCaptureMethod import VideoCaptureDeviceCaptureMethod
Expand Down Expand Up @@ -49,7 +49,7 @@ class Region(TypedDict):
height: int


class CaptureMethodEnumMeta(EnumMeta):
class ContainerEnumMeta(EnumMeta):
# Allow checking if simple string is enum
@override
def __contains__(cls, other: object):
Expand All @@ -61,35 +61,16 @@ def __contains__(cls, other: object):


@unique
# TODO: Try StrEnum in Python 3.11
class CaptureMethodEnum(Enum, metaclass=CaptureMethodEnumMeta):
# Allow TOML to save as a simple string
@override
def __repr__(self):
return self.value

# Allow direct comparison with strings
@override
def __eq__(self, other: object):
if isinstance(other, str):
return self.value == other
if isinstance(other, Enum):
return self.value == other.value
return other == self

# Restore hashing functionality for use in Maps
@override
def __hash__(self):
return self.value.__hash__()

class CaptureMethodEnum(StrEnum, metaclass=ContainerEnumMeta):
# Capitalize the string value from auto()
@override
@staticmethod
def _generate_next_value_(
name: "str | CaptureMethodEnum",
name: str,
start: int,
count: int,
last_values: list["str | CaptureMethodEnum"],
):
last_values: list[str],
) -> str:
return name

NONE = ""
Expand Down
6 changes: 3 additions & 3 deletions src/menu_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def __setup_bindings(self):

def add_or_del(checked: Literal[0, 2], command: CommandStr = command):
if checked:
_screenshot_on_setting.add(command)
_screenshot_on_setting.append(command)
else:
_screenshot_on_setting.remove(command)

Expand Down Expand Up @@ -502,10 +502,10 @@ def get_default_settings_from_ui(autosplit: "AutoSplit"):
"split_image_directory": autosplit.split_image_folder_input.text(),
"screenshot_directory": default_settings_dialog.screenshot_directory_input.text(),
"open_screenshot": default_settings_dialog.open_screenshot_checkbox.isChecked(),
"screenshot_on": {
"screenshot_on": [
getattr(default_settings_dialog, f"screenshot_on_{command}_checkbox").isChecked()
for command in _DEBUG_SCREENSHOT_COMMANDS
},
],
"captured_window_title": "",
"capture_region": {
"x": autosplit.x_spinbox.value(),
Expand Down
20 changes: 11 additions & 9 deletions src/user_profile.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import os
import tomllib
from copy import deepcopy
from typing import TYPE_CHECKING, TypedDict, cast

import toml
import tomli_w
from PySide6 import QtCore, QtWidgets
from typing_extensions import deprecated, override

Expand Down Expand Up @@ -40,7 +41,7 @@ class UserProfileDict(TypedDict):
split_image_directory: str
screenshot_directory: str
open_screenshot: bool
screenshot_on: set[CommandStr]
screenshot_on: list[CommandStr]
captured_window_title: str
capture_region: Region

Expand Down Expand Up @@ -73,7 +74,7 @@ def copy():
split_image_directory="",
screenshot_directory="",
open_screenshot=True,
screenshot_on=set(),
screenshot_on=[],
captured_window_title="",
capture_region=Region(x=0, y=0, width=1, height=1),
)
Expand Down Expand Up @@ -112,8 +113,9 @@ def save_settings_as(autosplit: "AutoSplit"):

def __save_settings_to_file(autosplit: "AutoSplit", save_settings_file_path: str):
# Save settings to a .toml file
with open(save_settings_file_path, "w", encoding="utf-8") as file:
toml.dump(autosplit.settings_dict, file)
with open(save_settings_file_path, "wb") as file:
# https://github.com/hukkin/tomli-w/pull/46
tomli_w.dump(autosplit.settings_dict, file) # pyright: ignore[reportArgumentType]
Comment on lines +116 to +118
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

autosplit.last_saved_settings = deepcopy(autosplit.settings_dict)
autosplit.last_successfully_loaded_settings_file_path = save_settings_file_path
return save_settings_file_path
Expand All @@ -132,14 +134,14 @@ def __load_settings_from_file(autosplit: "AutoSplit", load_settings_file_path: s
settings_widget.close()

try:
with open(load_settings_file_path, encoding="utf-8") as file:
with open(load_settings_file_path, mode="rb") as file:
# Casting here just so we can build an actual UserProfileDict once we're done validating
# Fallback to default settings if some are missing from the file.
# This happens when new settings are added.
loaded_settings = DEFAULT_PROFILE | cast(UserProfileDict, toml.load(file))
loaded_settings = DEFAULT_PROFILE | cast(UserProfileDict, tomllib.load(file))

# TODO: Data Validation / fallbacks ?
loaded_settings["screenshot_on"] = set(loaded_settings["screenshot_on"])
loaded_settings["screenshot_on"] = list(set(loaded_settings["screenshot_on"]))
autosplit.settings_dict = UserProfileDict(**loaded_settings)
autosplit.last_saved_settings = deepcopy(autosplit.settings_dict)

Expand All @@ -148,7 +150,7 @@ def __load_settings_from_file(autosplit: "AutoSplit", load_settings_file_path: s
autosplit.width_spinbox.setValue(autosplit.settings_dict["capture_region"]["width"])
autosplit.height_spinbox.setValue(autosplit.settings_dict["capture_region"]["height"])
autosplit.split_image_folder_input.setText(autosplit.settings_dict["split_image_directory"])
except (FileNotFoundError, MemoryError, TypeError, toml.TomlDecodeError):
except (FileNotFoundError, MemoryError, TypeError, tomllib.TOMLDecodeError):
autosplit.show_error_signal.emit(error_messages.invalid_settings)
return False

Expand Down
Loading