From 4f605479afdbef0ef5b72d9dc1f3b3635bf3f58e Mon Sep 17 00:00:00 2001 From: Danila Date: Tue, 1 Apr 2025 23:12:27 +0300 Subject: [PATCH 1/6] docs: testing section added --- README.md | 82 +++++++++++++++++++++++++++++++------------ tests/__init__.py | 0 tests/polygon_test.py | 59 ------------------------------- tests/test_polygon.py | 62 ++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 81 deletions(-) create mode 100644 tests/__init__.py delete mode 100644 tests/polygon_test.py create mode 100644 tests/test_polygon.py diff --git a/README.md b/README.md index d0a4e71..100fd82 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,89 @@ # XCoder - easy to use modding tool + Multiplatform modding tool for ANY Supercell\`s game. ## About -Work with Supercell\`s files on **any** os! SC and CSV are supported for all Supercell\`s games. + +Work with Supercell\`s files on **any** os! SC and CSV are supported for all +Supercell\`s games. ### Features: + - SC compile / decompile; - Compression and decompression. ### How to install and use + - On Windows: - - Download Python 3.7 or newer version from [official page](https://www.python.org/downloads/); - - Install Python. While Installing, enable such parameters as "Add Python to PATH", "Install pip", "Install py launcher", "Associate files with Python" and "Add Python to environment variables"; - - Download XCoder from the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; - - Locate the extracted directory and install required modules: - ```pip install -r requirements.txt```; - - Execute "main.py" file. + - Download Python 3.7 or newer version + from [official page](https://www.python.org/downloads/); + - Install Python. While Installing, enable such parameters as "Add Python to + PATH", "Install pip", "Install py launcher", "Associate files with Python" and " + Add Python to environment variables"; + - Download XCoder from + the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; + - Locate the extracted directory and install required modules: + ```pip install -r requirements.txt```; + - Execute "main.py" file. - On Linux: - - Open Terminal and install Python by executing following command: - ```sudo apt-get update && sudo apt-get install python3 python3-pip```; - - Download XCoder from the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; - - Locate the extracted directory and install required modules by executing following command: - ```sudo pip3 install -r requirements.txt```; - - Execute "main.py" file. + - Open Terminal and install Python by executing following command: + ```sudo apt-get update && sudo apt-get install python3 python3-pip```; + - Download XCoder from + the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; + - Locate the extracted directory and install required modules by executing following + command: + ```sudo pip3 install -r requirements.txt```; + - Execute "main.py" file. - On Android: - - Download and install PyDroid app from [Google Play](https://play.google.com/store/apps/details?id=ru.iiec.pydroid3); - - Open PyDroid and wait until Python installs; - - Download XCoder from the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; - - Install loguru using pip; - - In PyDroid open and execute "main.py" file. + - Download and install PyDroid app + from [Google Play](https://play.google.com/store/apps/details?id=ru.iiec.pydroid3); + - Open PyDroid and wait until Python installs; + - Download XCoder from + the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; + - Install loguru using pip; + - In PyDroid open and execute "main.py" file. + +### Testing + +The project supports unit-testing using the unittest module. To run tests by yourself, you can use the command: + +```cmd +python -m unittest +``` + +or + +```sh +python3 -m unittest +``` + +or using the poetry + +```sh +poetry run python -m unittest +``` ### How to enable KTX section -![KTX section demo](docs/KTX section.png) +![KTX section demo](docs/KTX%20section.png) -**Supercell also uses KTX textures in new versions of the games, so it is advisable to perform this step.** +**Supercell also uses KTX textures in new versions of the games, so it is advisable to +perform this step.** -To enable the KTX module, you need to get the "PVRTexToolCLI" binary from the official site: https://developer.imaginationtech.com/pvrtextool/. +To enable the KTX module, you need to get the "PVRTexToolCLI" binary from the official +site: https://developer.imaginationtech.com/pvrtextool/. Then it is necessary to put CLI in "system/bin/" folder in the main script folder. ### In the plans: + - CSV updating. ## Credits -This tool is based on Original [XCoder](https://github.com/MasterDevX/xcoder), Developer: [MasterDevX](https://github.com/MasterDevX)
+ +This tool is based on Original [XCoder](https://github.com/MasterDevX/xcoder), +Developer: [MasterDevX](https://github.com/MasterDevX)
Many thanks to [spiky_Spike](https://github.com/spiky-s) for the provided developments diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/polygon_test.py b/tests/polygon_test.py deleted file mode 100644 index c15120a..0000000 --- a/tests/polygon_test.py +++ /dev/null @@ -1,59 +0,0 @@ -from system.lib.math.point import Point -from system.lib.math.polygon import PointOrder, Polygon, get_polygon_point_order - - -def create_polygon_from_tuple(*polygon: tuple[float, float]) -> Polygon: - return [Point(x, y) for x, y in polygon] - - -def assert_equals(expected, existing) -> None: - assert expected == existing, f"Got {existing}, while {expected=}" - - -def test1(): - polygon = create_polygon_from_tuple( - (4.0, 4.0), (5.0, -2.0), (-1.0, -4.0), (-6.0, 0.0), (-2.0, 5.0), (0.0, 1.0) - ) - - assert_equals(PointOrder.CLOCKWISE, get_polygon_point_order(polygon)) - polygon = create_polygon_from_tuple((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)) - - assert_equals(PointOrder.CLOCKWISE, get_polygon_point_order(polygon)) - - polygon = create_polygon_from_tuple( - (160.0, -73.0), - (89.0, -73.0), - (89.0, -10.0), - (143.0, 10.0), - (156.0, 10.0), - (160.0, -46.0), - ) - - assert_equals(PointOrder.CLOCKWISE, get_polygon_point_order(polygon)) - - polygon = create_polygon_from_tuple( - (5.0, 0.0), (6.0, 4.0), (4.0, 5.0), (1.0, 5.0), (1.0, 0.0) - ) - - assert_equals(PointOrder.COUNTER_CLOCKWISE, get_polygon_point_order(polygon)) - - polygon = create_polygon_from_tuple( - (0.0, 0.0), (11.0, 0.0), (0.0, 10.0), (10.0, 10.0) - ) - - assert_equals(PointOrder.COUNTER_CLOCKWISE, get_polygon_point_order(polygon)) - - polygon = create_polygon_from_tuple( - (20.0, -73.0), - (91.0, -73.0), - (91.0, -10.0), - (37.0, 10.0), - (24.0, 10.0), - (20.0, -46.0), - ) - - assert_equals(PointOrder.COUNTER_CLOCKWISE, get_polygon_point_order(polygon)) - - -if __name__ == "__main__": - test1() diff --git a/tests/test_polygon.py b/tests/test_polygon.py new file mode 100644 index 0000000..e9b2d3b --- /dev/null +++ b/tests/test_polygon.py @@ -0,0 +1,62 @@ +from unittest import TestCase + +from system.lib.math.point import Point +from system.lib.math.polygon import PointOrder, Polygon, get_polygon_point_order + + +def create_polygon_from_tuple(*polygon: tuple[float, float]) -> Polygon: + return [Point(x, y) for x, y in polygon] + + +class PolygonTestCase(TestCase): + def test_clockwise_square(self): + polygon = create_polygon_from_tuple( + (0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0) + ) + + self.assertEqual(PointOrder.CLOCKWISE, get_polygon_point_order(polygon)) + + def test_clockwise_real1(self): + polygon = create_polygon_from_tuple( + (4.0, 4.0), (5.0, -2.0), (-1.0, -4.0), (-6.0, 0.0), (-2.0, 5.0), (0.0, 1.0) + ) + + self.assertEqual(PointOrder.CLOCKWISE, get_polygon_point_order(polygon)) + + def test_clockwise_real2(self): + polygon = create_polygon_from_tuple( + (160.0, -73.0), + (89.0, -73.0), + (89.0, -10.0), + (143.0, 10.0), + (156.0, 10.0), + (160.0, -46.0), + ) + + self.assertEqual(PointOrder.CLOCKWISE, get_polygon_point_order(polygon)) + + def test_counter_clockwise_real1(self): + polygon = create_polygon_from_tuple( + (5.0, 0.0), (6.0, 4.0), (4.0, 5.0), (1.0, 5.0), (1.0, 0.0) + ) + + self.assertEqual(PointOrder.COUNTER_CLOCKWISE, get_polygon_point_order(polygon)) + + def test_counter_clockwise_real2(self): + polygon = create_polygon_from_tuple( + (0.0, 0.0), (11.0, 0.0), (0.0, 10.0), (10.0, 10.0) + ) + + self.assertEqual(PointOrder.COUNTER_CLOCKWISE, get_polygon_point_order(polygon)) + + def test_counter_clockwise_real3(self): + polygon = create_polygon_from_tuple( + (20.0, -73.0), + (91.0, -73.0), + (91.0, -10.0), + (37.0, 10.0), + (24.0, 10.0), + (20.0, -46.0), + ) + + self.assertEqual(PointOrder.COUNTER_CLOCKWISE, get_polygon_point_order(polygon)) From 7f2d7bd3585c090f6cd1862b928e9188369df340 Mon Sep 17 00:00:00 2001 From: Danila Date: Tue, 1 Apr 2025 23:14:52 +0300 Subject: [PATCH 2/6] refactor: using shutil which instead of distutils --- system/lib/pvr_tex_tool.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/lib/pvr_tex_tool.py b/system/lib/pvr_tex_tool.py index 3340453..6f8bc90 100644 --- a/system/lib/pvr_tex_tool.py +++ b/system/lib/pvr_tex_tool.py @@ -16,10 +16,10 @@ # Note: a solution from # https://stackoverflow.com/questions/11210104/check-if-a-program-exists-from-a-python-script def _get_executable_path(*paths: str) -> str | None: - from distutils.spawn import find_executable + from shutil import which for path in paths: - executable_path = find_executable(path) + executable_path = which(path) if executable_path is not None: return path @@ -27,7 +27,7 @@ def _get_executable_path(*paths: str) -> str | None: _cli_name = "PVRTexToolCLI" -_cli_path = _get_executable_path(_cli_name, f"{_main_dir}/system/bin/{_cli_name}") +_cli_path = _get_executable_path(f"{_main_dir}/system/bin/{_cli_name}", _cli_name) def can_use_pvr_tex_tool() -> bool: From 3c38b4d27531536c1db68374bfd0ac55ffc4bc14 Mon Sep 17 00:00:00 2001 From: Danila Date: Tue, 1 Apr 2025 23:15:37 +0300 Subject: [PATCH 3/6] chore: sc-compression updated to 0.6.5 --- poetry.lock | 674 +++++++++++++++++++++++++++++++++++ pyproject.toml | 25 ++ system/lib/features/files.py | 3 +- system/lib/swf.py | 2 +- 4 files changed, 702 insertions(+), 2 deletions(-) create mode 100644 poetry.lock create mode 100644 pyproject.toml diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..cf09129 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,674 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "black" +version = "24.10.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.9" +files = [ + {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, + {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, + {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, + {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, + {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, + {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, + {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, + {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, + {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, + {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, + {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, + {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, + {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, + {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, + {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, + {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, + {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, + {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, + {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, + {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, + {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, + {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.10)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "click" +version = "8.1.8" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, + {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "distlib" +version = "0.3.9" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, +] + +[[package]] +name = "filelock" +version = "3.18.0" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.9" +files = [ + {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, + {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] +typing = ["typing-extensions (>=4.12.2)"] + +[[package]] +name = "identify" +version = "2.6.9" +description = "File identification library for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "identify-2.6.9-py2.py3-none-any.whl", hash = "sha256:c98b4322da415a8e5a70ff6e51fbc2d2932c015532d77e9f8537b4ba7813b150"}, + {file = "identify-2.6.9.tar.gz", hash = "sha256:d40dfe3142a1421d8518e3d3985ef5ac42890683e32306ad614a29490abeb6bf"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "loguru" +version = "0.7.3" +description = "Python logging made (stupidly) simple" +optional = false +python-versions = "<4.0,>=3.5" +files = [ + {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, + {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["Sphinx (==8.1.3)", "build (==1.2.2)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.5.0)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.13.0)", "mypy (==v1.4.1)", "myst-parser (==4.0.0)", "pre-commit (==4.0.1)", "pytest (==6.1.2)", "pytest (==8.3.2)", "pytest-cov (==2.12.1)", "pytest-cov (==5.0.0)", "pytest-cov (==6.0.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.1.0)", "sphinx-rtd-theme (==3.0.2)", "tox (==3.27.1)", "tox (==4.23.2)", "twine (==6.0.1)"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +description = "Node.js virtual environment builder" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, +] + +[[package]] +name = "packaging" +version = "24.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + +[[package]] +name = "pillow" +version = "10.4.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, + {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, + {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, + {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, + {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, + {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, + {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, + {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, + {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, + {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, + {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, + {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, + {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, + {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, + {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, + {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, + {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, + {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, + {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, + {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + +[[package]] +name = "platformdirs" +version = "4.3.7" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.9" +files = [ + {file = "platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94"}, + {file = "platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] + +[[package]] +name = "pre-commit" +version = "3.8.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"}, + {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "pylzham" +version = "0.1.3" +description = "Python 3 Wrapper for LZHAM Codec" +optional = false +python-versions = "*" +files = [ + {file = "pylzham-0.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:fe877259db418c4a1b11e89a8a972628cac364040de00b3b83d859b93264f236"}, + {file = "pylzham-0.1.3.tar.gz", hash = "sha256:af4828d4b0e158a938550d9299e5da82bdc9fbb375fe6e3da429012839fbade2"}, +] + +[[package]] +name = "pyright" +version = "1.1.398" +description = "Command line wrapper for pyright" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyright-1.1.398-py3-none-any.whl", hash = "sha256:0a70bfd007d9ea7de1cf9740e1ad1a40a122592cfe22a3f6791b06162ad08753"}, + {file = "pyright-1.1.398.tar.gz", hash = "sha256:357a13edd9be8082dc73be51190913e475fa41a6efb6ec0d4b7aab3bc11638d8"}, +] + +[package.dependencies] +nodeenv = ">=1.6.0" +typing-extensions = ">=4.1" + +[package.extras] +all = ["nodejs-wheel-binaries", "twine (>=3.4.1)"] +dev = ["twine (>=3.4.1)"] +nodejs = ["nodejs-wheel-binaries"] + +[[package]] +name = "pyyaml" +version = "6.0.2" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] + +[[package]] +name = "sc-compression" +version = "0.6.5" +description = "SC Compression" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sc_compression-0.6.5-py3-none-any.whl", hash = "sha256:a10c713e0c2bd2cd5f485c99beaad2e9e8c9e20d0e13eb8c2d8ad24ce64773a4"}, + {file = "sc_compression-0.6.5.tar.gz", hash = "sha256:d45da0d64a8b8b9cbadf3354bcf2211e980096fd750217dfd07cfd4563bb127a"}, +] + +[package.dependencies] +zstandard = "*" + +[[package]] +name = "typing-extensions" +version = "4.13.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.13.0-py3-none-any.whl", hash = "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5"}, + {file = "typing_extensions-4.13.0.tar.gz", hash = "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b"}, +] + +[[package]] +name = "virtualenv" +version = "20.30.0" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.8" +files = [ + {file = "virtualenv-20.30.0-py3-none-any.whl", hash = "sha256:e34302959180fca3af42d1800df014b35019490b119eba981af27f2fa486e5d6"}, + {file = "virtualenv-20.30.0.tar.gz", hash = "sha256:800863162bcaa5450a6e4d721049730e7f2dae07720e0902b0e4040bd6f9ada8"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + +[[package]] +name = "win32-setctime" +version = "1.2.0" +description = "A small Python utility to set file creation time on Windows" +optional = false +python-versions = ">=3.5" +files = [ + {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, + {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, +] + +[package.extras] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] + +[[package]] +name = "zstandard" +version = "0.23.0" +description = "Zstandard bindings for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zstandard-0.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9"}, + {file = "zstandard-0.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880"}, + {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77da4c6bfa20dd5ea25cbf12c76f181a8e8cd7ea231c673828d0386b1740b8dc"}, + {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2170c7e0367dde86a2647ed5b6f57394ea7f53545746104c6b09fc1f4223573"}, + {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c16842b846a8d2a145223f520b7e18b57c8f476924bda92aeee3a88d11cfc391"}, + {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:157e89ceb4054029a289fb504c98c6a9fe8010f1680de0201b3eb5dc20aa6d9e"}, + {file = "zstandard-0.23.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:203d236f4c94cd8379d1ea61db2fce20730b4c38d7f1c34506a31b34edc87bdd"}, + {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dc5d1a49d3f8262be192589a4b72f0d03b72dcf46c51ad5852a4fdc67be7b9e4"}, + {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:752bf8a74412b9892f4e5b58f2f890a039f57037f52c89a740757ebd807f33ea"}, + {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80080816b4f52a9d886e67f1f96912891074903238fe54f2de8b786f86baded2"}, + {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:84433dddea68571a6d6bd4fbf8ff398236031149116a7fff6f777ff95cad3df9"}, + {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ab19a2d91963ed9e42b4e8d77cd847ae8381576585bad79dbd0a8837a9f6620a"}, + {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:59556bf80a7094d0cfb9f5e50bb2db27fefb75d5138bb16fb052b61b0e0eeeb0"}, + {file = "zstandard-0.23.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:27d3ef2252d2e62476389ca8f9b0cf2bbafb082a3b6bfe9d90cbcbb5529ecf7c"}, + {file = "zstandard-0.23.0-cp310-cp310-win32.whl", hash = "sha256:5d41d5e025f1e0bccae4928981e71b2334c60f580bdc8345f824e7c0a4c2a813"}, + {file = "zstandard-0.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:519fbf169dfac1222a76ba8861ef4ac7f0530c35dd79ba5727014613f91613d4"}, + {file = "zstandard-0.23.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e"}, + {file = "zstandard-0.23.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23"}, + {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a"}, + {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80a539906390591dd39ebb8d773771dc4db82ace6372c4d41e2d293f8e32b8db"}, + {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:445e4cb5048b04e90ce96a79b4b63140e3f4ab5f662321975679b5f6360b90e2"}, + {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca"}, + {file = "zstandard-0.23.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d20fd853fbb5807c8e84c136c278827b6167ded66c72ec6f9a14b863d809211c"}, + {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ed1708dbf4d2e3a1c5c69110ba2b4eb6678262028afd6c6fbcc5a8dac9cda68e"}, + {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:be9b5b8659dff1f913039c2feee1aca499cfbc19e98fa12bc85e037c17ec6ca5"}, + {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:65308f4b4890aa12d9b6ad9f2844b7ee42c7f7a4fd3390425b242ffc57498f48"}, + {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:98da17ce9cbf3bfe4617e836d561e433f871129e3a7ac16d6ef4c680f13a839c"}, + {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8ed7d27cb56b3e058d3cf684d7200703bcae623e1dcc06ed1e18ecda39fee003"}, + {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:b69bb4f51daf461b15e7b3db033160937d3ff88303a7bc808c67bbc1eaf98c78"}, + {file = "zstandard-0.23.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473"}, + {file = "zstandard-0.23.0-cp311-cp311-win32.whl", hash = "sha256:f2d4380bf5f62daabd7b751ea2339c1a21d1c9463f1feb7fc2bdcea2c29c3160"}, + {file = "zstandard-0.23.0-cp311-cp311-win_amd64.whl", hash = "sha256:62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0"}, + {file = "zstandard-0.23.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094"}, + {file = "zstandard-0.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8"}, + {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1"}, + {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072"}, + {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20"}, + {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373"}, + {file = "zstandard-0.23.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db"}, + {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772"}, + {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105"}, + {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba"}, + {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd"}, + {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a"}, + {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90"}, + {file = "zstandard-0.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35"}, + {file = "zstandard-0.23.0-cp312-cp312-win32.whl", hash = "sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d"}, + {file = "zstandard-0.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b"}, + {file = "zstandard-0.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9"}, + {file = "zstandard-0.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a"}, + {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2"}, + {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5"}, + {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f"}, + {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed"}, + {file = "zstandard-0.23.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea"}, + {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847"}, + {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171"}, + {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840"}, + {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690"}, + {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b"}, + {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057"}, + {file = "zstandard-0.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33"}, + {file = "zstandard-0.23.0-cp313-cp313-win32.whl", hash = "sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd"}, + {file = "zstandard-0.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b"}, + {file = "zstandard-0.23.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2ef3775758346d9ac6214123887d25c7061c92afe1f2b354f9388e9e4d48acfc"}, + {file = "zstandard-0.23.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4051e406288b8cdbb993798b9a45c59a4896b6ecee2f875424ec10276a895740"}, + {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2d1a054f8f0a191004675755448d12be47fa9bebbcffa3cdf01db19f2d30a54"}, + {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f83fa6cae3fff8e98691248c9320356971b59678a17f20656a9e59cd32cee6d8"}, + {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32ba3b5ccde2d581b1e6aa952c836a6291e8435d788f656fe5976445865ae045"}, + {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f146f50723defec2975fb7e388ae3a024eb7151542d1599527ec2aa9cacb152"}, + {file = "zstandard-0.23.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1bfe8de1da6d104f15a60d4a8a768288f66aa953bbe00d027398b93fb9680b26"}, + {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:29a2bc7c1b09b0af938b7a8343174b987ae021705acabcbae560166567f5a8db"}, + {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:61f89436cbfede4bc4e91b4397eaa3e2108ebe96d05e93d6ccc95ab5714be512"}, + {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:53ea7cdc96c6eb56e76bb06894bcfb5dfa93b7adcf59d61c6b92674e24e2dd5e"}, + {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:a4ae99c57668ca1e78597d8b06d5af837f377f340f4cce993b551b2d7731778d"}, + {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:379b378ae694ba78cef921581ebd420c938936a153ded602c4fea612b7eaa90d"}, + {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:50a80baba0285386f97ea36239855f6020ce452456605f262b2d33ac35c7770b"}, + {file = "zstandard-0.23.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:61062387ad820c654b6a6b5f0b94484fa19515e0c5116faf29f41a6bc91ded6e"}, + {file = "zstandard-0.23.0-cp38-cp38-win32.whl", hash = "sha256:b8c0bd73aeac689beacd4e7667d48c299f61b959475cdbb91e7d3d88d27c56b9"}, + {file = "zstandard-0.23.0-cp38-cp38-win_amd64.whl", hash = "sha256:a05e6d6218461eb1b4771d973728f0133b2a4613a6779995df557f70794fd60f"}, + {file = "zstandard-0.23.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa014d55c3af933c1315eb4bb06dd0459661cc0b15cd61077afa6489bec63bb"}, + {file = "zstandard-0.23.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916"}, + {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb2b1ecfef1e67897d336de3a0e3f52478182d6a47eda86cbd42504c5cbd009a"}, + {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:837bb6764be6919963ef41235fd56a6486b132ea64afe5fafb4cb279ac44f259"}, + {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1516c8c37d3a053b01c1c15b182f3b5f5eef19ced9b930b684a73bad121addf4"}, + {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48ef6a43b1846f6025dde6ed9fee0c24e1149c1c25f7fb0a0585572b2f3adc58"}, + {file = "zstandard-0.23.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11e3bf3c924853a2d5835b24f03eeba7fc9b07d8ca499e247e06ff5676461a15"}, + {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2fb4535137de7e244c230e24f9d1ec194f61721c86ebea04e1581d9d06ea1269"}, + {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8c24f21fa2af4bb9f2c492a86fe0c34e6d2c63812a839590edaf177b7398f700"}, + {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a8c86881813a78a6f4508ef9daf9d4995b8ac2d147dcb1a450448941398091c9"}, + {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fe3b385d996ee0822fd46528d9f0443b880d4d05528fd26a9119a54ec3f91c69"}, + {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:82d17e94d735c99621bf8ebf9995f870a6b3e6d14543b99e201ae046dfe7de70"}, + {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c7c517d74bea1a6afd39aa612fa025e6b8011982a0897768a2f7c8ab4ebb78a2"}, + {file = "zstandard-0.23.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fd7e0f1cfb70eb2f95a19b472ee7ad6d9a0a992ec0ae53286870c104ca939e5"}, + {file = "zstandard-0.23.0-cp39-cp39-win32.whl", hash = "sha256:43da0f0092281bf501f9c5f6f3b4c975a8a0ea82de49ba3f7100e64d422a1274"}, + {file = "zstandard-0.23.0-cp39-cp39-win_amd64.whl", hash = "sha256:f8346bfa098532bc1fb6c7ef06783e969d87a99dd1d2a5a18a892c1d7a643c58"}, + {file = "zstandard-0.23.0.tar.gz", hash = "sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09"}, +] + +[package.dependencies] +cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\""} + +[package.extras] +cffi = ["cffi (>=1.11)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "491f7a27807efa3f50c8f5714c180fc4cfcd717e85f405ad82e7e7d73b33cc3c" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..df8be29 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,25 @@ +[tool.poetry] +name = "xcoder" +version = "0.1.0" +description = "" +authors = ["Danila "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.11" +sc-compression = "^0.6.1" +colorama = "^0.4.6" +pylzham = "^0.1.3" +zstandard = "^0.23.0" +pillow = "^10.4.0" +loguru = "^0.7.2" + + +[tool.poetry.group.dev.dependencies] +pyright = "^1.1.376" +black = "^24.8.0" +pre-commit = "^3.8.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/system/lib/features/files.py b/system/lib/features/files.py index ee80b18..a30627d 100644 --- a/system/lib/features/files.py +++ b/system/lib/features/files.py @@ -17,13 +17,14 @@ def write_sc( file_out.write(compress(buffer, signature, version)) # type: ignore -def open_sc(input_filename: os.PathLike | str) -> tuple[bytes, Signatures]: +def open_sc(input_filename: os.PathLike | str) -> tuple[bytes, Signatures, int]: with open(input_filename, "rb") as f: file_data = f.read() try: if b"START" in file_data: file_data = file_data[: file_data.index(b"START")] + return decompress(file_data) except TypeError: logger.info(locale.decompression_error) diff --git a/system/lib/swf.py b/system/lib/swf.py index 675c7ec..2990262 100644 --- a/system/lib/swf.py +++ b/system/lib/swf.py @@ -80,7 +80,7 @@ def _load_internal( logger.info(locale.collecting_inf % self.filename) - decompressed_data, signature = open_sc(filepath) + decompressed_data, signature, version = open_sc(filepath) if signature.name != Signatures.NONE: logger.info(locale.detected_comp % signature.name.upper()) From 06451cb453dc8d6f2064ee80541e10b0c19007c7 Mon Sep 17 00:00:00 2001 From: Danila Date: Tue, 1 Apr 2025 23:18:33 +0300 Subject: [PATCH 4/6] fix: objects bounds rounded now --- .../lib/objects/renderable/renderable_movie_clip.py | 7 +++++++ system/lib/objects/renderable/renderable_shape.py | 7 +++++++ system/lib/objects/shape/region.py | 11 +++++++++-- system/lib/pixel_utils.py | 9 +++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/system/lib/objects/renderable/renderable_movie_clip.py b/system/lib/objects/renderable/renderable_movie_clip.py index 4c4e28b..3f22d5a 100644 --- a/system/lib/objects/renderable/renderable_movie_clip.py +++ b/system/lib/objects/renderable/renderable_movie_clip.py @@ -81,6 +81,13 @@ def calculate_bounds(self, matrix: Matrix2x3) -> Rect: for child in self._frame_children: rect.merge_bounds(child.calculate_bounds(matrix_multiplied)) + rect = Rect( + left=round(rect.left), + top=round(rect.top), + right=round(rect.right), + bottom=round(rect.bottom), + ) + return rect def set_frame(self, frame_index: int): diff --git a/system/lib/objects/renderable/renderable_shape.py b/system/lib/objects/renderable/renderable_shape.py index 598beec..8b762b8 100644 --- a/system/lib/objects/renderable/renderable_shape.py +++ b/system/lib/objects/renderable/renderable_shape.py @@ -43,4 +43,11 @@ def calculate_bounds(self, matrix: Matrix2x3) -> Rect: for region in self._regions: rect.merge_bounds(region.calculate_bounds(matrix_multiplied)) + rect = Rect( + left=round(rect.left), + top=round(rect.top), + right=round(rect.right), + bottom=round(rect.bottom), + ) + return rect diff --git a/system/lib/objects/shape/region.py b/system/lib/objects/shape/region.py index 6f4c3c1..7798409 100644 --- a/system/lib/objects/shape/region.py +++ b/system/lib/objects/shape/region.py @@ -59,7 +59,7 @@ def load(self, swf: SupercellSWF, tag: int): def render(self, matrix: Matrix2x3) -> Image.Image: transformed_points = apply_matrix(self._xy_points, matrix) - rect = get_rect(transformed_points) + rect = self.calculate_bounds(matrix) width, height = max(int(rect.width), 1), max(int(rect.height), 1) rendered_region = self.get_image() @@ -135,4 +135,11 @@ def get_y(self, index: int): return self._xy_points[index].y def calculate_bounds(self, matrix: Matrix2x3 | None = None) -> Rect: - return get_rect(apply_matrix(self._xy_points, matrix)) + rect = get_rect(apply_matrix(self._xy_points, matrix)) + rect = Rect( + left=round(rect.left), + top=round(rect.top), + right=round(rect.right), + bottom=round(rect.bottom), + ) + return rect diff --git a/system/lib/pixel_utils.py b/system/lib/pixel_utils.py index 4a43db5..bf907d3 100644 --- a/system/lib/pixel_utils.py +++ b/system/lib/pixel_utils.py @@ -86,6 +86,15 @@ def _write_rgb5a1(pixel: PixelChannels) -> bytes: return struct.pack("> 7 | b >> 3 << 1 | g >> 3 << 6 | r >> 3 << 11) +# TODO: rewrite with numpy https://qna.habr.com/q/298153 +# rgb888 = numpy.asarray(Image.open(filename)) +# # check that image have 3 color components, each of 8 bits +# assert rgb888.shape[-1] == 3 and rgb888.dtype == numpy.uint8 +# r5 = (rgb888[..., 0] >> 3 & 0x1f).astype(numpy.uint16) +# g6 = (rgb888[..., 1] >> 2 & 0x3f).astype(numpy.uint16) +# b5 = (rgb888[..., 2] >> 3 & 0x1f).astype(numpy.uint16) +# rgb565 = r5 << 11 | g6 << 5 | b5 +# return rgb565.tobytes() def _write_rgb565(pixel: PixelChannels) -> bytes: r, g, b = pixel return struct.pack("> 3 | g >> 2 << 5 | r >> 3 << 11) From c9937f27ee58cf65d79e2044ee94f9b24d8d2096 Mon Sep 17 00:00:00 2001 From: Danila Date: Wed, 2 Apr 2025 00:25:50 +0300 Subject: [PATCH 5/6] chore: dependencies updated, pillow fixed --- .github/workflows/lint.yml | 35 ++-- README.md | 39 ++--- poetry.lock | 231 ++++++++++++++++---------- pyproject.toml | 9 +- requirements.txt | 6 - system/exceptions/__init__.py | 3 + system/languages/en-EU.json | 5 +- system/languages/ru-RU.json | 5 +- system/languages/ua-UA.json | 5 +- system/lib/features/initialization.py | 16 +- system/lib/features/sc/decode.py | 10 +- system/lib/features/sc/encode.py | 2 +- system/lib/features/update/check.py | 18 +- system/lib/images.py | 52 ++++-- system/lib/main_menu.py | 3 +- system/lib/pixel_utils.py | 20 +-- system/lib/pvr_tex_tool.py | 3 +- system/localization.py | 5 +- 18 files changed, 242 insertions(+), 225 deletions(-) delete mode 100644 requirements.txt diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5aa590a..130d61b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,27 +1,38 @@ -name: Lint +name: Lint and test -on: [push, pull_request] +on: [push] jobs: build: - runs-on: ubuntu-latest + runs-on: ${{matrix.os}} + strategy: + matrix: + python: ["3.11", "3.12"] + os: ["ubuntu-latest", "windows-latest"] steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.11 + - uses: actions/checkout@v4 + - name: Set up Python ${{matrix.python}} uses: actions/setup-python@v4 with: - python-version: "3.11" + python-version: ${{matrix.python}} - - name: Install requirements + - name: Install poetry run: | - pip install flake8 pyright - pip install -r requirements.txt + pip install pipx + pipx install poetry - - name: Linting code by flake8 + - name: Install dependencies run: | - flake8 --show-source --statistics + poetry install + + - name: Linting code by ruff + run: | + poetry run ruff check . - name: Check types by pyright run: | - pyright + poetry run pyright . + + - name: Run unit-tests + run: poetry run python -m unittest diff --git a/README.md b/README.md index 100fd82..ecd7395 100644 --- a/README.md +++ b/README.md @@ -15,51 +15,34 @@ Supercell\`s games. ### How to install and use - On Windows: - - Download Python 3.7 or newer version + - Download Python 3.10 or newer version from [official page](https://www.python.org/downloads/); - Install Python. While Installing, enable such parameters as "Add Python to - PATH", "Install pip", "Install py launcher", "Associate files with Python" and " - Add Python to environment variables"; + PATH", "Install pip", "Install py launcher", "Associate files with Python" and "Add Python to environment variables"; - Download XCoder from the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; - Locate the extracted directory and install required modules: - ```pip install -r requirements.txt```; + ```cmd + poetry install + ``` - Execute "main.py" file. - On Linux: - Open Terminal and install Python by executing following command: - ```sudo apt-get update && sudo apt-get install python3 python3-pip```; + ```sudo apt-get update && sudo apt-get install python3 python3-poetry```; - Download XCoder from the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; - Locate the extracted directory and install required modules by executing following command: - ```sudo pip3 install -r requirements.txt```; + ```sh + poetry install + ``` - Execute "main.py" file. -- On Android: - - Download and install PyDroid app - from [Google Play](https://play.google.com/store/apps/details?id=ru.iiec.pydroid3); - - Open PyDroid and wait until Python installs; - - Download XCoder from - the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; - - Install loguru using pip; - - In PyDroid open and execute "main.py" file. - ### Testing -The project supports unit-testing using the unittest module. To run tests by yourself, you can use the command: - -```cmd -python -m unittest -``` - -or - -```sh -python3 -m unittest -``` - -or using the poetry +The project supports unit-testing using the unittest module. To run tests by yourself, +use the command: ```sh poetry run python -m unittest diff --git a/poetry.lock b/poetry.lock index cf09129..51dbf6a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. [[package]] name = "black" @@ -6,6 +6,7 @@ version = "24.10.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, @@ -50,6 +51,8 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "platform_python_implementation == \"PyPy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -129,6 +132,7 @@ version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, @@ -140,6 +144,7 @@ version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, @@ -154,6 +159,7 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -165,6 +171,7 @@ version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, @@ -176,6 +183,7 @@ version = "3.18.0" description = "A platform independent file lock." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, @@ -184,7 +192,7 @@ files = [ [package.extras] docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] [[package]] name = "identify" @@ -192,6 +200,7 @@ version = "2.6.9" description = "File identification library for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "identify-2.6.9-py2.py3-none-any.whl", hash = "sha256:c98b4322da415a8e5a70ff6e51fbc2d2932c015532d77e9f8537b4ba7813b150"}, {file = "identify-2.6.9.tar.gz", hash = "sha256:d40dfe3142a1421d8518e3d3985ef5ac42890683e32306ad614a29490abeb6bf"}, @@ -206,6 +215,7 @@ version = "0.7.3" description = "Python logging made (stupidly) simple" optional = false python-versions = "<4.0,>=3.5" +groups = ["main"] files = [ {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, @@ -216,7 +226,7 @@ colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] -dev = ["Sphinx (==8.1.3)", "build (==1.2.2)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.5.0)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.13.0)", "mypy (==v1.4.1)", "myst-parser (==4.0.0)", "pre-commit (==4.0.1)", "pytest (==6.1.2)", "pytest (==8.3.2)", "pytest-cov (==2.12.1)", "pytest-cov (==5.0.0)", "pytest-cov (==6.0.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.1.0)", "sphinx-rtd-theme (==3.0.2)", "tox (==3.27.1)", "tox (==4.23.2)", "twine (==6.0.1)"] +dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==v0.910) ; python_version < \"3.6\"", "mypy (==v0.971) ; python_version == \"3.6\"", "mypy (==v1.13.0) ; python_version >= \"3.8\"", "mypy (==v1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] [[package]] name = "mypy-extensions" @@ -224,6 +234,7 @@ version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, @@ -235,6 +246,7 @@ version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -246,6 +258,7 @@ version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, @@ -257,6 +270,7 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -264,99 +278,91 @@ files = [ [[package]] name = "pillow" -version = "10.4.0" +version = "11.2.0" description = "Python Imaging Library (Fork)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, - {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, - {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, - {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, - {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, - {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, - {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, - {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, - {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, - {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, - {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, - {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, - {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, - {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, - {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, - {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, - {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, - {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, - {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, - {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, - {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, - {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, - {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, - {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, - {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, - {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, - {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, - {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, - {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, - {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, - {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, - {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, - {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, - {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, - {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, - {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, - {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, - {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, - {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, - {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, - {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, - {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, + {file = "pillow-11.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:38afd040bafe3c2893de4e011557c309a878e8fde07e3303bf3cb0f9832d237c"}, + {file = "pillow-11.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed1f80258bc01a0bc5c5f2eda7e4cbd9bc25060dc69be2f00fe1435ba48f4ff4"}, + {file = "pillow-11.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52ecd8f581cd5aa0fcc29291acc99b38dbaf898272e86e3146ec3996ed370a46"}, + {file = "pillow-11.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10502f9425768a4f9c1c8471a7a3f942da659c727369bab1241b7ae1ff16f93f"}, + {file = "pillow-11.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:d8a9dc58117878e94303dbc32a4c9fe470f6b77f349954d4ae003870c9ac7a83"}, + {file = "pillow-11.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:71733ea2d70a5fc498b7675cb37e7dcfb2b1889d8a08128ec2a62b6843f0660a"}, + {file = "pillow-11.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4846c8efa94eda17832f09c4e8691c9aaeb7eef758c8b622af44e60887fcaf12"}, + {file = "pillow-11.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:54206449613db62c82585bb26ac70f3a1a97654d70ad796b4e05624ef1b08f4e"}, + {file = "pillow-11.2.0-cp310-cp310-win32.whl", hash = "sha256:b92d9059719ec9a718ac9e04039764b10551f2c929db6cd6015e90f9c62f8b34"}, + {file = "pillow-11.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:98cd082d9a523cb0f2f8775ec122e67a5cfd9afc6549d91aafe0c2d75535d008"}, + {file = "pillow-11.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:5c3a8f916c494c0a3dc37daf5a0e7d98480a6f839ad0fa472e9858b667b48268"}, + {file = "pillow-11.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:cb17dc417e951a3af0c5a9ed2641b8b37e7b0e78fe685b91b927de474cddad58"}, + {file = "pillow-11.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f0125a9e668df3e83ff2cfa5800dfe5646591449abae40abf75a1d8b325ddd33"}, + {file = "pillow-11.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d28e47fe5a5e5692ea5d239e8bb6c610cf2dad550fc34c5a32d49b1ffd1c891"}, + {file = "pillow-11.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ec3481f45d9616bb18b5f3b145744dfcdfabea6a23efe233b8a9026852369d1"}, + {file = "pillow-11.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c026e417ebede0e84d9358cc1d9f702356e61a787be882016fbca4fb1248c0d1"}, + {file = "pillow-11.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:92baf77b80de05ede82b14d92bf89a7f0067501b9476df0a162004f3bb015b50"}, + {file = "pillow-11.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ff44a55a650c0337d3db764cec4f85d1324369e5cf10f6daa96c9513182730a9"}, + {file = "pillow-11.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:87c715dd5dc439bde27cf745d59b66af39b2df4355bc57ddd2e51f87f768fb06"}, + {file = "pillow-11.2.0-cp311-cp311-win32.whl", hash = "sha256:b4204996f6a813f5ca8e7d6365e104ec7391315d014780a909eadc19e613fcf9"}, + {file = "pillow-11.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:4d1c229f800addb9158c26661c6ade9cb038ff7bb98e3c0149e8fd3a7b6e6e08"}, + {file = "pillow-11.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:77cea582243e7286ac23ef6315eeb1434f5ccfc710afa16a8999194aa9d1e88a"}, + {file = "pillow-11.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ffcfac194064f4a5bc389b9ef910a60b9bc8573a7e59f081fbc71a59794140f2"}, + {file = "pillow-11.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40f972b6e2a97c633fa25c3c8405d45942747eaf838805d76f7da0363a7696ec"}, + {file = "pillow-11.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b46bd331193a7b223864010e751a30ec48245e5106e00eda94b435e37109de1"}, + {file = "pillow-11.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6581ee02eec144cbcdeb6bef055142129cfda0f52939480d81806ee8d61ab4f3"}, + {file = "pillow-11.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:c2a6700be18335d341ddd12facbc49dcf0febbfeefdda4990e017698a8e66f59"}, + {file = "pillow-11.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b228ae10b25650539d37c056063c8f34c0da4f69419ce03249dfd0adc322d46b"}, + {file = "pillow-11.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:36de59d15a95584fad3758c4bcb992c3bf279ddd86236d3f096dbf696efc2b48"}, + {file = "pillow-11.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:23fedf0def4193848ce5be2f685e3606c1ebf42a033cfa092b729e6cf844d337"}, + {file = "pillow-11.2.0-cp312-cp312-win32.whl", hash = "sha256:290fd44a0b517a48af7660b7586538f9db1fe0656d7d6c97b0aefd2a4ad2b14d"}, + {file = "pillow-11.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:728f2381d178722d008772e57b3252b8c6c0c284cee76e798ffb392ca71e3fd9"}, + {file = "pillow-11.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:65dfab8348a42ba9883141e4fa09a7db6ff2a203d17450717b998fb27f4ba0b4"}, + {file = "pillow-11.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0b46b5ee8443213da50b08caa1b2f7c407233873f6153c6fcf558fab57ac658b"}, + {file = "pillow-11.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:70daf0b69bc9017796cb74a38a597a34e311e4e3e5254d7e4aa42aab3d1d3eac"}, + {file = "pillow-11.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00f8830ac57dc38bfacfb8bb1b7987da7ccbf99131dae0e826bfbaa2c8dfc990"}, + {file = "pillow-11.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:597b629e4d135ebb904f58d0b3328c58dba3ac7bd1f9585e0dddcb250d3f955c"}, + {file = "pillow-11.2.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:106fce029c62ddfed767e4f8cc3396e90ba45320d87df58bf83a73fdbe73f09b"}, + {file = "pillow-11.2.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:676461578f605c8e56ea108c371632e4bf40697996d80b5899c592043432e5f1"}, + {file = "pillow-11.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0f19332b8de08305db8e003272ba86f5a65231b848a44ceef2e9593101637208"}, + {file = "pillow-11.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe61cadf4f0449de64fb6911bca381f1a4c1f04cce3027a0d12ebaba626f97cd"}, + {file = "pillow-11.2.0-cp313-cp313-win32.whl", hash = "sha256:25e533264bec3ca5dc6e1587810dce1c2dda0b9d63ed4e27fa72092cb351cd55"}, + {file = "pillow-11.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:9565b70771a38b096b0f78d830be5338ca9a0b810ea6cbfab54c64f0266f9c72"}, + {file = "pillow-11.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:6fa29d8fcaf8a830ced88f390baffe32ae1ba41873a3f6c8946213d067db7ae0"}, + {file = "pillow-11.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cd635650ddd10be04148e7f2e895afa240d0ea5e810cd10f650adba13f5f93"}, + {file = "pillow-11.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b653372f6b3a7df74cd52abc8c400670ab08dd4473317508ed45668e87df0284"}, + {file = "pillow-11.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e0395313bc32de78309e24a298dc4986f8a93fc917032412f510a272ee9f25"}, + {file = "pillow-11.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47dcb3289613e256c2419242f6d92b1c9ce28368bd337f6a0cf50cddfb8cc69a"}, + {file = "pillow-11.2.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:a32b243b37c060884bd04f6bb709a22d86ec05662374076e6a35c07ac0361477"}, + {file = "pillow-11.2.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4122bb11e4d238ed28ecff24863c620aac22732bc102ab9550e99f6fd6eaf869"}, + {file = "pillow-11.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:be7a73fb992a9cb8e4362220037ea10d3eb52d0804220ca98de4f7d24c1f36c9"}, + {file = "pillow-11.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0d3408815fc6ab70283916e0b058e7a4bbacdd7b5bb71ef81a9a507df4580b9a"}, + {file = "pillow-11.2.0-cp313-cp313t-win32.whl", hash = "sha256:491e11b37e322fc6e80b485f99203e6c4ed69ea170eb6d25e9cb9eb0b92db7e5"}, + {file = "pillow-11.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4202372ccb549a3f12de2cebbafa82b0a3d8e2cb5569fa4b698e7da6b6521687"}, + {file = "pillow-11.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:a9cd300d223efadd1e540521bae1fcdab406ef6c5f2ca6e46370f5671b607f26"}, + {file = "pillow-11.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:20d8f9626c3d48baf14e01aca763e5457508cf4245ef0232ba601a4bfa3d26ce"}, + {file = "pillow-11.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57bc12a7d9175ec13c6e1e2a41532e6ae0f5218988259d1f83dd5f7097369ef8"}, + {file = "pillow-11.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:582c458d766c479ebf5679d582fef698a42b803fa07190e04267280db4f14725"}, + {file = "pillow-11.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:284bcf4d37699a3ca6af2f42ba5e90589802f9c9e0c09e4a1a05732e634e94f1"}, + {file = "pillow-11.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:3a03f96498762c9a6e80282ce43386847e61540011510bf790c48488d834205d"}, + {file = "pillow-11.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:f50edae2624495d3b075e40f65d86bcbf374fa822dfc05f1d9dc995507c410ed"}, + {file = "pillow-11.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c25567ad74526f362b55940d786e70568a05759a7d3b7de1f12aeec6920bc1ae"}, + {file = "pillow-11.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c8a74615674cca471e825392d833e666a945b2bbedfd93299d800f60ae6c495c"}, + {file = "pillow-11.2.0-cp39-cp39-win32.whl", hash = "sha256:d31997b8ddae9db2d93d9fe195b3bae67746419b22cb65dddcfd5d649aa7f26d"}, + {file = "pillow-11.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:f56cd367fb7b5b2779c2b8e5ab2b228ce526b122c21126f4649f9ecd3796efc4"}, + {file = "pillow-11.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:f67f2191773d7a54f8bad94ba781cba88aedf52fed0ff6f6050065f824d201a4"}, + {file = "pillow-11.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:789c65fa7d2a17dc585bb4cc0f08392de5960f7e1a69c6171a82c9f7c5c98b3c"}, + {file = "pillow-11.2.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d516f854dadc0f449f0db7b93009d3169ae126511ee754c954b4a43c432bd9d"}, + {file = "pillow-11.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cade37bde4fbe239b177e809a2599c2772f7e54e3c7a355431de6a25023a50d3"}, + {file = "pillow-11.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afa1718a5ca25d52c766dfaae795d0286363b7adb005965aadfd9eea804fd0b3"}, ] [package.extras] -docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] fpx = ["olefile"] mic = ["olefile"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] -typing = ["typing-extensions"] +test-arrow = ["pyarrow"] +tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "trove-classifiers (>=2024.10.12)"] +typing = ["typing-extensions ; python_version < \"3.10\""] xmp = ["defusedxml"] [[package]] @@ -365,6 +371,7 @@ version = "4.3.7" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94"}, {file = "platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351"}, @@ -381,6 +388,7 @@ version = "3.8.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"}, {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"}, @@ -399,6 +407,8 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "platform_python_implementation == \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -410,6 +420,7 @@ version = "0.1.3" description = "Python 3 Wrapper for LZHAM Codec" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pylzham-0.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:fe877259db418c4a1b11e89a8a972628cac364040de00b3b83d859b93264f236"}, {file = "pylzham-0.1.3.tar.gz", hash = "sha256:af4828d4b0e158a938550d9299e5da82bdc9fbb375fe6e3da429012839fbade2"}, @@ -421,6 +432,7 @@ version = "1.1.398" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pyright-1.1.398-py3-none-any.whl", hash = "sha256:0a70bfd007d9ea7de1cf9740e1ad1a40a122592cfe22a3f6791b06162ad08753"}, {file = "pyright-1.1.398.tar.gz", hash = "sha256:357a13edd9be8082dc73be51190913e475fa41a6efb6ec0d4b7aab3bc11638d8"}, @@ -441,6 +453,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -497,12 +510,41 @@ files = [ {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] +[[package]] +name = "ruff" +version = "0.11.2" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "ruff-0.11.2-py3-none-linux_armv6l.whl", hash = "sha256:c69e20ea49e973f3afec2c06376eb56045709f0212615c1adb0eda35e8a4e477"}, + {file = "ruff-0.11.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2c5424cc1c4eb1d8ecabe6d4f1b70470b4f24a0c0171356290b1953ad8f0e272"}, + {file = "ruff-0.11.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ecf20854cc73f42171eedb66f006a43d0a21bfb98a2523a809931cda569552d9"}, + {file = "ruff-0.11.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c543bf65d5d27240321604cee0633a70c6c25c9a2f2492efa9f6d4b8e4199bb"}, + {file = "ruff-0.11.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20967168cc21195db5830b9224be0e964cc9c8ecf3b5a9e3ce19876e8d3a96e3"}, + {file = "ruff-0.11.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:955a9ce63483999d9f0b8f0b4a3ad669e53484232853054cc8b9d51ab4c5de74"}, + {file = "ruff-0.11.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:86b3a27c38b8fce73bcd262b0de32e9a6801b76d52cdb3ae4c914515f0cef608"}, + {file = "ruff-0.11.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3b66a03b248c9fcd9d64d445bafdf1589326bee6fc5c8e92d7562e58883e30f"}, + {file = "ruff-0.11.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0397c2672db015be5aa3d4dac54c69aa012429097ff219392c018e21f5085147"}, + {file = "ruff-0.11.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:869bcf3f9abf6457fbe39b5a37333aa4eecc52a3b99c98827ccc371a8e5b6f1b"}, + {file = "ruff-0.11.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:2a2b50ca35457ba785cd8c93ebbe529467594087b527a08d487cf0ee7b3087e9"}, + {file = "ruff-0.11.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7c69c74bf53ddcfbc22e6eb2f31211df7f65054bfc1f72288fc71e5f82db3eab"}, + {file = "ruff-0.11.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6e8fb75e14560f7cf53b15bbc55baf5ecbe373dd5f3aab96ff7aa7777edd7630"}, + {file = "ruff-0.11.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:842a472d7b4d6f5924e9297aa38149e5dcb1e628773b70e6387ae2c97a63c58f"}, + {file = "ruff-0.11.2-py3-none-win32.whl", hash = "sha256:aca01ccd0eb5eb7156b324cfaa088586f06a86d9e5314b0eb330cb48415097cc"}, + {file = "ruff-0.11.2-py3-none-win_amd64.whl", hash = "sha256:3170150172a8f994136c0c66f494edf199a0bbea7a409f649e4bc8f4d7084080"}, + {file = "ruff-0.11.2-py3-none-win_arm64.whl", hash = "sha256:52933095158ff328f4c77af3d74f0379e34fd52f175144cefc1b192e7ccd32b4"}, + {file = "ruff-0.11.2.tar.gz", hash = "sha256:ec47591497d5a1050175bdf4e1a4e6272cddff7da88a2ad595e1e326041d8d94"}, +] + [[package]] name = "sc-compression" version = "0.6.5" description = "SC Compression" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "sc_compression-0.6.5-py3-none-any.whl", hash = "sha256:a10c713e0c2bd2cd5f485c99beaad2e9e8c9e20d0e13eb8c2d8ad24ce64773a4"}, {file = "sc_compression-0.6.5.tar.gz", hash = "sha256:d45da0d64a8b8b9cbadf3354bcf2211e980096fd750217dfd07cfd4563bb127a"}, @@ -517,6 +559,7 @@ version = "4.13.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "typing_extensions-4.13.0-py3-none-any.whl", hash = "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5"}, {file = "typing_extensions-4.13.0.tar.gz", hash = "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b"}, @@ -528,6 +571,7 @@ version = "20.30.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "virtualenv-20.30.0-py3-none-any.whl", hash = "sha256:e34302959180fca3af42d1800df014b35019490b119eba981af27f2fa486e5d6"}, {file = "virtualenv-20.30.0.tar.gz", hash = "sha256:800863162bcaa5450a6e4d721049730e7f2dae07720e0902b0e4040bd6f9ada8"}, @@ -540,7 +584,7 @@ platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "win32-setctime" @@ -548,13 +592,15 @@ version = "1.2.0" description = "A small Python utility to set file creation time on Windows" optional = false python-versions = ">=3.5" +groups = ["main"] +markers = "sys_platform == \"win32\"" files = [ {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, ] [package.extras] -dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] +dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] [[package]] name = "zstandard" @@ -562,6 +608,7 @@ version = "0.23.0" description = "Zstandard bindings for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "zstandard-0.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9"}, {file = "zstandard-0.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880"}, @@ -669,6 +716,6 @@ cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\ cffi = ["cffi (>=1.11)"] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "^3.11" -content-hash = "491f7a27807efa3f50c8f5714c180fc4cfcd717e85f405ad82e7e7d73b33cc3c" +content-hash = "eb9cd16ee04b1e9e1d1cd9ef8f34ab0a8d2708b4e72548cd8a85896c81481729" diff --git a/pyproject.toml b/pyproject.toml index df8be29..3463f23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,18 +7,19 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.11" -sc-compression = "^0.6.1" -colorama = "^0.4.6" +sc-compression = "0.6.5" +colorama = "0.4.6" pylzham = "^0.1.3" zstandard = "^0.23.0" -pillow = "^10.4.0" -loguru = "^0.7.2" +pillow = "11.2.0" +loguru = "0.7.3" [tool.poetry.group.dev.dependencies] pyright = "^1.1.376" black = "^24.8.0" pre-commit = "^3.8.0" +ruff = "^0.11.2" [build-system] requires = ["poetry-core"] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 062cc97..0000000 --- a/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -sc-compression -colorama -pylzham -zstandard -pillow -loguru diff --git a/system/exceptions/__init__.py b/system/exceptions/__init__.py index e69de29..21a6432 100644 --- a/system/exceptions/__init__.py +++ b/system/exceptions/__init__.py @@ -0,0 +1,3 @@ +from system.exceptions.tool_not_found import ToolNotFoundException + +__all__ = ["ToolNotFoundException"] diff --git a/system/languages/en-EU.json b/system/languages/en-EU.json index 4ef8972..4116b00 100644 --- a/system/languages/en-EU.json +++ b/system/languages/en-EU.json @@ -42,7 +42,6 @@ "other_features_label": "OTHER", "check_update": "Check for updates", - "check_for_outdated": "Check for outdated packages", "reinit": "Repeat init", "change_language": "Select another language", "clear_directories": "Clear workspace dirs", @@ -64,7 +63,6 @@ "join_pic": "Joining picture...", "png_save": "Saving to png...", "saved": "Saving completed!", - "xcod_not_found": "File '%s.xcod' doesn't exist!", "illegal_size": "Illegal image size! Expected %sx%s but we got %sx%s", "resize_qu": "Would you like to resize an image?", "resizing": "Resizing...", @@ -74,7 +72,8 @@ "compression_error": "Compression failed", "compression_done": "Compression done!", "dir_empty": "Dir '%s' is empty!", - "not_found": "File '%s' not found!", + "texture_not_found": "Texture file for '%s' not found!", + "file_not_found": "File '%s' not found!", "cut_sprites_process": "Cutting sprites... (%d/%d)", "place_sprites_process": "Placing sprites... (%d/%d)", "not_implemented": "This feature will be added in future updates.\nYou can follow XCoder updates here: https://github.com/Vorono4ka/XCoder", diff --git a/system/languages/ru-RU.json b/system/languages/ru-RU.json index e844355..8120e2e 100644 --- a/system/languages/ru-RU.json +++ b/system/languages/ru-RU.json @@ -42,7 +42,6 @@ "other_features_label": "ПРОЧЕЕ", "check_update": "Проверить обновления", - "check_for_outdated": "Проверка устаревших модулей", "reinit": "Повторная инициализация", "change_language": "Выбрать другой язык", "clear_directories": "Очистить рабочие папки", @@ -64,7 +63,6 @@ "join_pic": "Соединяем картинку...", "png_save": "Сохраняем в png...", "saved": "Сохранение прошло успешно!", - "xcod_not_found": "Файл '%s.xcod' не обнаружен!", "illegal_size": "Размер картинки не совпадает с оригиналом! Ожидалось %sx%s, но мы получили %sx%s", "resize_qu": "Хотите изменить размер?", "resizing": "Изменяем размер...", @@ -74,7 +72,8 @@ "compression_error": "Сжатие не удалось", "compression_done": "Сжатие прошло успешно!", "dir_empty": "Папка '%s' пуста!", - "not_found": "Файл '%s' не найден!", + "texture_not_found": "Текстуры для '%s' не найдена!", + "file_not_found": "Файл '%s' не найден!", "cut_sprites_process": "Вырезаем спрайты... (%d/%d)", "place_sprites_process": "Ставим спрайты на место... (%d/%d)", "not_implemented": "Данная возможность будет добавлена в будущих обновлениях.\nЗа обновлениями XCoder вы можете следить здесь: https://github.com/Vorono4ka/XCoder", diff --git a/system/languages/ua-UA.json b/system/languages/ua-UA.json index 47ba54b..94e069d 100644 --- a/system/languages/ua-UA.json +++ b/system/languages/ua-UA.json @@ -42,7 +42,6 @@ "other_features_label": "ІНШЕ", "check_update": "Шукати оновлення", - "check_for_outdated": "Шукати застарілі пакети", "reinit": "Повторити налаштування", "change_language": "Вибрати іншу мову", "clear_directories": "Очистити робочі папки", @@ -64,7 +63,6 @@ "join_pic": "З'єднуємо зоображення...", "png_save": "Зберігаємо PNG...", "saved": "Збереження Виконано!", - "xcod_not_found": "Файл '%s.xcod' не існує!", "illegal_size": "Неможливий розмір картинки! Очікували %sx%s але отримали %sx%s", "resize_qu": "Ти хочеш змінити розмір картинки?", "resizing": "змінюємо розмір...", @@ -74,7 +72,8 @@ "compression_error": "Запаковування не вдалося", "compression_done": "Запаковування виконане!", "dir_empty": "Папка '%s' порожня!", - "not_found": "Файл '%s' не знайдено!", + "texture_not_found": "Текстури для '%s' не знайдено!", + "file_not_found": "Файл '%s' не знайдено!", "cut_sprites_process": "Обрізаємо спрайти... (%d/%d)", "place_sprites_process": "Вставляємо спрайти... (%d/%d)", "not_implemented": "Ця функція буде додана у наступних оновленнях.\nТи можеш сладкувати за оновленнями тут: https://github.com/Vorono4ka/XCoder", diff --git a/system/lib/features/initialization.py b/system/lib/features/initialization.py index 825b806..fdbf1b3 100644 --- a/system/lib/features/initialization.py +++ b/system/lib/features/initialization.py @@ -2,10 +2,10 @@ from loguru import logger -from system import clear, run +from system import clear from system.lib.config import config from system.lib.features.directories import create_directories -from system.lib.features.update.check import get_pip_info, get_tags +from system.lib.features.update.check import get_tags from system.localization import locale @@ -17,18 +17,6 @@ def initialize(first_init=False): logger.info(locale.detected_os % platform.system()) logger.info(locale.installing) - required_packages = [ - pkg.rstrip("\n").lower() for pkg in open("requirements.txt").readlines() - ] - installed_packages = [pkg[0].lower() for pkg in get_pip_info()] - for package in required_packages: - if package in installed_packages: - continue - - if run(f"pip3 install {package}") == 0: - logger.info(locale.installed % package) - else: - logger.info(locale.not_installed % package) logger.info(locale.crt_workspace) create_directories() logger.info(locale.verifying) diff --git a/system/lib/features/sc/decode.py b/system/lib/features/sc/decode.py index e831f74..fe75a1a 100644 --- a/system/lib/features/sc/decode.py +++ b/system/lib/features/sc/decode.py @@ -21,15 +21,15 @@ def decode_textures_only(): files = os.listdir(input_folder) for file in files: + # Note: otherwise both _tex.sc and .sc will be loaded, which is a bug if not file.endswith("_tex.sc"): continue - swf = SupercellSWF() - base_name = os.path.basename(file).rsplit(".", 1)[0] try: + swf = SupercellSWF() texture_loaded, signature = swf.load(f"{input_folder / file}") if not texture_loaded: - logger.error(locale.not_found % f"{base_name}_tex.sc") + logger.error(locale.texture_not_found % file) continue base_name = get_file_basename(swf) @@ -65,12 +65,10 @@ def decode_and_render_objects(): continue try: - base_name = os.path.basename(file).rsplit(".", 1)[0] - swf = SupercellSWF() texture_loaded, signature = swf.load(input_folder / file) if not texture_loaded: - logger.error(locale.not_found % f"{base_name}_tex.sc") + logger.error(locale.texture_not_found % file) continue base_name = get_file_basename(swf) diff --git a/system/lib/features/sc/encode.py b/system/lib/features/sc/encode.py index f95857d..6c52e55 100644 --- a/system/lib/features/sc/encode.py +++ b/system/lib/features/sc/encode.py @@ -57,7 +57,7 @@ def _ensure_metadata_exists(input_folder: Path, file: str) -> Path | None: metadata_file_path = input_folder / metadata_file_name if not os.path.exists(metadata_file_path): - logger.error(locale.not_found % metadata_file_name) + logger.error(locale.file_not_found % metadata_file_name) print() return None diff --git a/system/lib/features/update/check.py b/system/lib/features/update/check.py index a9ceb6c..697831c 100644 --- a/system/lib/features/update/check.py +++ b/system/lib/features/update/check.py @@ -42,11 +42,7 @@ def get_tags(owner: str, repo: str): import urllib.request tags = json.loads( - urllib.request.urlopen( - api_url + "/repos/{owner}/{repo}/tags".format(owner=owner, repo=repo) - ) - .read() - .decode() + urllib.request.urlopen(api_url + f"/repos/{owner}/{repo}/tags").read().decode() ) tags = [ {key: v for key, v in tag.items() if key in ["name", "zipball_url"]} @@ -63,21 +59,9 @@ def check_update(): latest_tag = tags[0] latest_tag_name = latest_tag["name"][1:] # clear char 'v' at string start - check_for_outdated() - logger.info(locale.check_update) if config.version != latest_tag_name: logger.error(locale.not_latest) logger.info(locale.update_downloading) download_update(latest_tag["zipball_url"]) - - -def check_for_outdated(): - logger.info(locale.check_for_outdated) - required_packages = [ - pkg.rstrip("\n").lower() for pkg in open("requirements.txt").readlines() - ] - outdated_packages = [pkg[0].lower() for pkg in get_pip_info(True)] - - return [package for package in required_packages if package in outdated_packages] diff --git a/system/lib/images.py b/system/lib/images.py index abeb7ce..802c65b 100644 --- a/system/lib/images.py +++ b/system/lib/images.py @@ -1,16 +1,19 @@ import math +from typing import TYPE_CHECKING -import PIL.PyAccess from PIL import Image, ImageDraw +if TYPE_CHECKING: + from PIL._imaging import PixelAccess # type: ignore[reportPrivateImportUsage] + from system.bytestream import Reader, Writer from system.lib.console import Console from system.lib.math.point import Point from system.lib.matrices import Matrix2x3 from system.lib.pixel_utils import ( get_channel_count_by_pixel_type, + get_pixel_encode_function, get_read_function, - get_write_function, ) from system.localization import locale @@ -19,14 +22,16 @@ def load_image_from_buffer(img: Image.Image) -> None: width, height = img.size - img_loaded: PIL.PyAccess.PyAccess = img.load() # type: ignore + loaded_image = img.load() + if loaded_image is None: + raise Exception("loaded_image is None") with open("pixel_buffer", "rb") as pixel_buffer: channel_count = int.from_bytes(pixel_buffer.read(1), "little") for y in range(height): for x in range(width): - img_loaded[x, y] = tuple(pixel_buffer.read(channel_count)) + loaded_image[x, y] = tuple(pixel_buffer.read(channel_count)) def join_image(img: Image.Image) -> None: @@ -34,8 +39,9 @@ def join_image(img: Image.Image) -> None: channel_count = int.from_bytes(pixel_buffer.read(1), "little") width, height = img.size - # noinspection PyTypeChecker - loaded_img: PIL.PyAccess.PyAccess = img.load() # type: ignore + loaded_image = img.load() + if loaded_image is None: + raise Exception("loaded_image is None") x_chunks_count = width // CHUNK_SIZE y_chunks_count = height // CHUNK_SIZE @@ -52,22 +58,29 @@ def join_image(img: Image.Image) -> None: if pixel_x >= width: break - loaded_img[pixel_x, pixel_y] = tuple( + loaded_image[pixel_x, pixel_y] = tuple( pixel_buffer.read(channel_count) ) Console.progress_bar(locale.join_pic, y_chunk, y_chunks_count + 1) -def split_image(img: Image.Image) -> None: - def add_pixel(pixel: tuple) -> None: - loaded_image[pixel_index % width, int(pixel_index / width)] = pixel +def _add_pixel( + image: "PixelAccess", pixel_index: int, width: int, color: tuple +) -> None: + image[pixel_index % width, int(pixel_index / width)] = color + +def split_image(img: Image.Image) -> None: width, height = img.size - # noinspection PyTypeChecker - loaded_image: PIL.PyAccess.PyAccess = img.load() # type: ignore - # noinspection PyTypeChecker - loaded_clone: PIL.PyAccess.PyAccess = img.copy().load() # type: ignore + + loaded_image = img.load() + if loaded_image is None: + raise Exception("loaded_image is None") + + loaded_clone = img.copy().load() + if loaded_clone is None: + raise Exception("loaded_clone is None") x_chunks_count = width // CHUNK_SIZE y_chunks_count = height // CHUNK_SIZE @@ -86,7 +99,9 @@ def add_pixel(pixel: tuple) -> None: if pixel_x >= width: break - add_pixel(loaded_clone[pixel_x, pixel_y]) # type: ignore + _add_pixel( + loaded_image, pixel_index, width, loaded_clone[pixel_x, pixel_y] + ) pixel_index += 1 Console.progress_bar(locale.split_pic, y_chunk, y_chunks_count + 1) @@ -139,8 +154,8 @@ def load_texture(reader: Reader, pixel_type: int, img: Image.Image) -> None: def save_texture(writer: Writer, image: Image.Image, pixel_type: int) -> None: - write_pixel = get_write_function(pixel_type) - if write_pixel is None: + encode_pixel = get_pixel_encode_function(pixel_type) + if encode_pixel is None: raise Exception(locale.unknown_pixel_type % pixel_type) width, height = image.size @@ -149,7 +164,8 @@ def save_texture(writer: Writer, image: Image.Image, pixel_type: int) -> None: point = -1 for y in range(height): for x in range(width): - writer.write(write_pixel(pixels[y * width + x])) # type: ignore + # noinspection PyTypeChecker + writer.write(encode_pixel(pixels[y * width + x])) curr = Console.percent(y, height) if curr > point: diff --git a/system/lib/main_menu.py b/system/lib/main_menu.py index 62987ad..da4b713 100644 --- a/system/lib/main_menu.py +++ b/system/lib/main_menu.py @@ -7,7 +7,7 @@ from system.lib.console import Console from system.lib.features.directories import clear_directories from system.lib.features.initialization import initialize -from system.lib.features.update.check import check_for_outdated, check_update, get_tags +from system.lib.features.update.check import check_update, get_tags from system.lib.menu import Menu from system.localization import locale @@ -157,7 +157,6 @@ def refill_menu(): handler=check_update, ) ) - other.add(Menu.Item(name=locale.check_for_outdated, handler=check_for_outdated)) other.add( Menu.Item( name=locale.reinit, diff --git a/system/lib/pixel_utils.py b/system/lib/pixel_utils.py index bf907d3..27d65ec 100644 --- a/system/lib/pixel_utils.py +++ b/system/lib/pixel_utils.py @@ -4,20 +4,16 @@ from system.bytestream import Reader PixelChannels: TypeAlias = tuple[int, ...] -WriteFunction: TypeAlias = Callable[[PixelChannels], bytes] -ReadFunction: TypeAlias = Callable[[Reader], PixelChannels] +EncodeFunction: TypeAlias = Callable[[PixelChannels], bytes] +DecodeFunction: TypeAlias = Callable[[Reader], PixelChannels] -def get_read_function(pixel_type: int) -> ReadFunction | None: - if pixel_type in _read_functions: - return _read_functions[pixel_type] - return None +def get_read_function(pixel_type: int) -> DecodeFunction | None: + return _decode_functions.get(pixel_type, None) -def get_write_function(pixel_type: int) -> WriteFunction | None: - if pixel_type in _write_functions: - return _write_functions[pixel_type] - return None +def get_pixel_encode_function(pixel_type: int) -> EncodeFunction | None: + return _encode_functions.get(pixel_type, None) def get_channel_count_by_pixel_type(pixel_type: int) -> int: @@ -108,7 +104,7 @@ def _write_luminance8(pixel: PixelChannels) -> bytes: return struct.pack("B", pixel) -_write_functions: dict[int, WriteFunction] = { +_encode_functions: dict[int, EncodeFunction] = { 0: _write_rgba8, 1: _write_rgba8, 2: _write_rgba4, @@ -118,7 +114,7 @@ def _write_luminance8(pixel: PixelChannels) -> bytes: 10: _write_luminance8, } -_read_functions: dict[int, ReadFunction] = { +_decode_functions: dict[int, DecodeFunction] = { 0: _read_rgba8, 1: _read_rgba8, 2: _read_rgba4, diff --git a/system/lib/pvr_tex_tool.py b/system/lib/pvr_tex_tool.py index 6f8bc90..bde5aaf 100644 --- a/system/lib/pvr_tex_tool.py +++ b/system/lib/pvr_tex_tool.py @@ -5,7 +5,7 @@ from PIL import Image from system import run -from system.exceptions.tool_not_found import ToolNotFoundException +from system.exceptions import ToolNotFoundException _main_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) _color_space = "sRGB" @@ -19,6 +19,7 @@ def _get_executable_path(*paths: str) -> str | None: from shutil import which for path in paths: + # Fix of https://github.com/xcoder-tool/XCoder/issues/22 executable_path = which(path) if executable_path is not None: return path diff --git a/system/localization.py b/system/localization.py index 1837014..39fe70c 100644 --- a/system/localization.py +++ b/system/localization.py @@ -50,7 +50,6 @@ def __init__(self): self.other_features_label: str = DEFAULT_STRING self.check_update: str = DEFAULT_STRING - self.check_for_outdated: str = DEFAULT_STRING self.reinit: str = DEFAULT_STRING self.change_language: str = DEFAULT_STRING self.clear_directories: str = DEFAULT_STRING @@ -72,7 +71,6 @@ def __init__(self): self.join_pic: str = DEFAULT_STRING self.png_save: str = DEFAULT_STRING self.saved: str = DEFAULT_STRING - self.xcod_not_found: str = DEFAULT_STRING self.illegal_size: str = DEFAULT_STRING self.resize_qu: str = DEFAULT_STRING self.resizing: str = DEFAULT_STRING @@ -82,7 +80,8 @@ def __init__(self): self.compression_error: str = DEFAULT_STRING self.compression_done: str = DEFAULT_STRING self.dir_empty: str = DEFAULT_STRING - self.not_found: str = DEFAULT_STRING + self.texture_not_found: str = DEFAULT_STRING + self.file_not_found: str = DEFAULT_STRING self.cut_sprites_process: str = DEFAULT_STRING self.place_sprites_process: str = DEFAULT_STRING self.not_implemented: str = DEFAULT_STRING From 32dfefddf8e3e93aef50589fb859834ad0f1679e Mon Sep 17 00:00:00 2001 From: Danila Date: Wed, 2 Apr 2025 01:06:39 +0300 Subject: [PATCH 6/6] refactor: main file moved to xcoder package --- .gitignore | 2 +- README.md | 42 ++--- system/exceptions/__init__.py | 3 - system/lib/__init__.py | 20 --- system/lib/config.py | 52 ------ system/lib/math/__init__.py | 0 system/lib/objects/__init__.py | 5 - system/lib/objects/movie_clip/__init__.py | 4 - system/lib/objects/renderable/__init__.py | 0 system/lib/objects/shape/__init__.py | 4 - system/localization.py | 147 ----------------- tests/test_polygon.py | 3 +- {system => xcoder}/__init__.py | 19 +++ main.py => xcoder/__main__.py | 15 +- {system => xcoder}/bytestream.py | 0 xcoder/config.py | 67 ++++++++ {system/lib => xcoder}/console.py | 0 xcoder/exceptions/__init__.py | 3 + .../exceptions/tool_not_found.py | 0 {system/lib => xcoder}/features/__init__.py | 0 .../lib => xcoder}/features/csv/__init__.py | 0 .../lib => xcoder}/features/csv/compress.py | 2 +- .../lib => xcoder}/features/csv/decompress.py | 2 +- {system/lib => xcoder}/features/csv/update.py | 2 +- .../lib => xcoder}/features/cut_sprites.py | 14 +- .../lib => xcoder}/features/directories.py | 0 {system/lib => xcoder}/features/files.py | 2 +- .../lib => xcoder}/features/initialization.py | 12 +- {system/lib => xcoder}/features/ktx.py | 4 +- .../lib => xcoder}/features/place_sprites.py | 10 +- .../lib => xcoder}/features/sc/__init__.py | 12 +- {system/lib => xcoder}/features/sc/decode.py | 8 +- {system/lib => xcoder}/features/sc/encode.py | 8 +- .../features/update/__init__.py | 0 .../lib => xcoder}/features/update/check.py | 10 +- .../features/update/download.py | 16 +- {system/lib => xcoder}/images.py | 12 +- {system => xcoder}/languages/en-EU.json | 2 +- {system => xcoder}/languages/ru-RU.json | 2 +- {system => xcoder}/languages/ua-UA.json | 2 +- xcoder/localization.py | 151 ++++++++++++++++++ {system/lib => xcoder}/main_menu.py | 42 ++--- xcoder/math/__init__.py | 4 + {system/lib => xcoder}/math/point.py | 0 {system/lib => xcoder}/math/polygon.py | 6 +- {system/lib => xcoder}/math/rect.py | 0 {system/lib => xcoder}/matrices/__init__.py | 0 .../matrices/color_transform.py | 0 {system/lib => xcoder}/matrices/matrix2x3.py | 2 +- .../lib => xcoder}/matrices/matrix_bank.py | 4 +- {system/lib => xcoder}/menu.py | 6 +- xcoder/objects/__init__.py | 5 + xcoder/objects/movie_clip/__init__.py | 4 + .../objects/movie_clip/movie_clip.py | 2 +- .../objects/movie_clip/movie_clip_frame.py | 2 +- .../lib => xcoder}/objects/plain_object.py | 2 +- xcoder/objects/renderable/__init__.py | 3 + .../objects/renderable/display_object.py | 4 +- .../objects/renderable/renderable_factory.py | 14 +- .../renderable/renderable_movie_clip.py | 12 +- .../objects/renderable/renderable_shape.py | 8 +- xcoder/objects/shape/__init__.py | 4 + .../lib => xcoder}/objects/shape/region.py | 14 +- {system/lib => xcoder}/objects/shape/shape.py | 6 +- {system/lib => xcoder}/objects/texture.py | 6 +- {system/lib => xcoder}/pixel_utils.py | 2 +- {system/lib => xcoder}/pvr_tex_tool.py | 12 +- {system/lib => xcoder}/swf.py | 12 +- {system/lib => xcoder}/xcod.py | 6 +- 69 files changed, 427 insertions(+), 412 deletions(-) delete mode 100644 system/exceptions/__init__.py delete mode 100644 system/lib/__init__.py delete mode 100644 system/lib/config.py delete mode 100644 system/lib/math/__init__.py delete mode 100644 system/lib/objects/__init__.py delete mode 100644 system/lib/objects/movie_clip/__init__.py delete mode 100644 system/lib/objects/renderable/__init__.py delete mode 100644 system/lib/objects/shape/__init__.py delete mode 100644 system/localization.py rename {system => xcoder}/__init__.py (54%) rename main.py => xcoder/__main__.py (75%) rename {system => xcoder}/bytestream.py (100%) create mode 100644 xcoder/config.py rename {system/lib => xcoder}/console.py (100%) create mode 100644 xcoder/exceptions/__init__.py rename {system => xcoder}/exceptions/tool_not_found.py (100%) rename {system/lib => xcoder}/features/__init__.py (100%) rename {system/lib => xcoder}/features/csv/__init__.py (100%) rename {system/lib => xcoder}/features/csv/compress.py (95%) rename {system/lib => xcoder}/features/csv/decompress.py (95%) rename {system/lib => xcoder}/features/csv/update.py (95%) rename {system/lib => xcoder}/features/cut_sprites.py (90%) rename {system/lib => xcoder}/features/directories.py (100%) rename {system/lib => xcoder}/features/files.py (95%) rename {system/lib => xcoder}/features/initialization.py (59%) rename {system/lib => xcoder}/features/ktx.py (90%) rename {system/lib => xcoder}/features/place_sprites.py (92%) rename {system/lib => xcoder}/features/sc/__init__.py (84%) rename {system/lib => xcoder}/features/sc/decode.py (95%) rename {system/lib => xcoder}/features/sc/encode.py (91%) rename {system/lib => xcoder}/features/update/__init__.py (100%) rename {system/lib => xcoder}/features/update/check.py (86%) rename {system/lib => xcoder}/features/update/download.py (73%) rename {system/lib => xcoder}/images.py (96%) rename {system => xcoder}/languages/en-EU.json (98%) rename {system => xcoder}/languages/ru-RU.json (98%) rename {system => xcoder}/languages/ua-UA.json (98%) create mode 100644 xcoder/localization.py rename {system/lib => xcoder}/main_menu.py (87%) create mode 100644 xcoder/math/__init__.py rename {system/lib => xcoder}/math/point.py (100%) rename {system/lib => xcoder}/math/polygon.py (95%) rename {system/lib => xcoder}/math/rect.py (100%) rename {system/lib => xcoder}/matrices/__init__.py (100%) rename {system/lib => xcoder}/matrices/color_transform.py (100%) rename {system/lib => xcoder}/matrices/matrix2x3.py (98%) rename {system/lib => xcoder}/matrices/matrix_bank.py (85%) rename {system/lib => xcoder}/menu.py (95%) create mode 100644 xcoder/objects/__init__.py create mode 100644 xcoder/objects/movie_clip/__init__.py rename {system/lib => xcoder}/objects/movie_clip/movie_clip.py (98%) rename {system/lib => xcoder}/objects/movie_clip/movie_clip_frame.py (94%) rename {system/lib => xcoder}/objects/plain_object.py (84%) create mode 100644 xcoder/objects/renderable/__init__.py rename {system/lib => xcoder}/objects/renderable/display_object.py (86%) rename {system/lib => xcoder}/objects/renderable/renderable_factory.py (62%) rename {system/lib => xcoder}/objects/renderable/renderable_movie_clip.py (90%) rename {system/lib => xcoder}/objects/renderable/renderable_shape.py (87%) create mode 100644 xcoder/objects/shape/__init__.py rename {system/lib => xcoder}/objects/shape/region.py (92%) rename {system/lib => xcoder}/objects/shape/shape.py (86%) rename {system/lib => xcoder}/objects/texture.py (93%) rename {system/lib => xcoder}/pixel_utils.py (98%) rename {system/lib => xcoder}/pvr_tex_tool.py (87%) rename {system/lib => xcoder}/swf.py (96%) rename {system/lib => xcoder}/xcod.py (95%) diff --git a/.gitignore b/.gitignore index c1b990f..c2c2c6e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ /SC/ # Configuration files -system/config.json +xcoder/config.json # Python compiled files *.pyc diff --git a/README.md b/README.md index ecd7395..65baa5d 100644 --- a/README.md +++ b/README.md @@ -9,35 +9,41 @@ Supercell\`s games. ### Features: -- SC compile / decompile; -- Compression and decompression. +- SC compile / decompile +- Compression and decompression ### How to install and use - On Windows: - Download Python 3.10 or newer version - from [official page](https://www.python.org/downloads/); + from [official page](https://www.python.org/downloads/) - Install Python. While Installing, enable such parameters as "Add Python to - PATH", "Install pip", "Install py launcher", "Associate files with Python" and "Add Python to environment variables"; - - Download XCoder from - the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; + PATH", "Install pip", "Install py launcher", "Associate files with Python" and "Add Python to environment variables" + - Download XCoder from the [releases page](https://github.com/xcoder-tool/XCoder/releases) and extract it - Locate the extracted directory and install required modules: ```cmd poetry install ``` - - Execute "main.py" file. + - Run program with + ```cmd + poetry run python -m xcoder + ``` - On Linux: - - Open Terminal and install Python by executing following command: - ```sudo apt-get update && sudo apt-get install python3 python3-poetry```; - - Download XCoder from - the [releases page](https://github.com/Vorono4ka/XCoder/releases) and extract it; - - Locate the extracted directory and install required modules by executing following - command: - ```sh - poetry install - ``` - - Execute "main.py" file. + - Open Terminal and install Python by executing following command: + ```sh + sudo apt-get update && sudo apt-get install python3 python3-poetry + ``` + - Download XCoder from the [releases page](https://github.com/xcoder-tool/XCoder/releases) and extract it + - Locate the extracted directory and install required modules by executing following + command: + ```sh + poetry install + ``` + - Run program with + ```cmd + poetry run python -m xcoder + ``` ### Testing @@ -58,7 +64,7 @@ perform this step.** To enable the KTX module, you need to get the "PVRTexToolCLI" binary from the official site: https://developer.imaginationtech.com/pvrtextool/. -Then it is necessary to put CLI in "system/bin/" folder in the main script folder. +Then it is necessary to put CLI in "bin/" folder in the main script folder. ### In the plans: diff --git a/system/exceptions/__init__.py b/system/exceptions/__init__.py deleted file mode 100644 index 21a6432..0000000 --- a/system/exceptions/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from system.exceptions.tool_not_found import ToolNotFoundException - -__all__ = ["ToolNotFoundException"] diff --git a/system/lib/__init__.py b/system/lib/__init__.py deleted file mode 100644 index 97bbcc3..0000000 --- a/system/lib/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys - -from loguru import logger - -logger.remove() -logger.add( - "./logs/info/{time:YYYY-MM-DD}.log", - format="[{time:HH:mm:ss}] [{level}]: {message}", - encoding="utf8", - level="INFO", -) -logger.add( - "./logs/errors/{time:YYYY-MM-DD}.log", - format="[{time:HH:mm:ss}] [{level}]: {message}", - backtrace=True, - diagnose=True, - encoding="utf8", - level="ERROR", -) -logger.add(sys.stdout, format="[{level}] {message}", level="INFO") diff --git a/system/lib/config.py b/system/lib/config.py deleted file mode 100644 index eefee68..0000000 --- a/system/lib/config.py +++ /dev/null @@ -1,52 +0,0 @@ -import json -import os - - -class Config: - DEFAULT_LANGUAGE = "en-EU" - - config_path = "./system/config.json" - inited: bool - - def __init__(self): - self.config_items = ( - "initialized", - "version", - "language", - "has_update", - "last_update", - "auto_update", - "should_render_movie_clips", - ) - - self.initialized: bool = False - self.version = None - self.language: str = Config.DEFAULT_LANGUAGE - self.has_update: bool = False - self.last_update: int = -1 - self.auto_update: bool = False - self.should_render_movie_clips: bool = False - - self.load() - - def toggle_auto_update(self): - self.auto_update = not self.auto_update - self.dump() - - def change_language(self, language): - self.language = language - self.dump() - - def load(self): - if os.path.isfile(self.config_path): - for key, value in json.load(open(self.config_path)).items(): - setattr(self, key, value) - - def dump(self): - json.dump( - {item: getattr(self, item) for item in self.config_items}, - open(self.config_path, "w"), - ) - - -config = Config() diff --git a/system/lib/math/__init__.py b/system/lib/math/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/system/lib/objects/__init__.py b/system/lib/objects/__init__.py deleted file mode 100644 index 2174ad1..0000000 --- a/system/lib/objects/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from system.lib.objects.movie_clip import MovieClip -from system.lib.objects.shape import Shape -from system.lib.objects.texture import SWFTexture - -__all__ = ["Shape", "MovieClip", "SWFTexture"] diff --git a/system/lib/objects/movie_clip/__init__.py b/system/lib/objects/movie_clip/__init__.py deleted file mode 100644 index bcb10e4..0000000 --- a/system/lib/objects/movie_clip/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -__all__ = ["MovieClip", "MovieClipFrame"] - -from system.lib.objects.movie_clip.movie_clip import MovieClip -from system.lib.objects.movie_clip.movie_clip_frame import MovieClipFrame diff --git a/system/lib/objects/renderable/__init__.py b/system/lib/objects/renderable/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/system/lib/objects/shape/__init__.py b/system/lib/objects/shape/__init__.py deleted file mode 100644 index 841f84e..0000000 --- a/system/lib/objects/shape/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -__all__ = ["Shape", "Region"] - -from system.lib.objects.shape.region import Region -from system.lib.objects.shape.shape import Shape diff --git a/system/localization.py b/system/localization.py deleted file mode 100644 index 39fe70c..0000000 --- a/system/localization.py +++ /dev/null @@ -1,147 +0,0 @@ -import json -import os - -from system.lib.config import config - -DEFAULT_STRING = "NO LOCALE" - - -class Locale: - def __init__(self): - self.xcoder_header: str = DEFAULT_STRING - self.detected_os: str = DEFAULT_STRING - self.installing: str = DEFAULT_STRING - self.update_downloading: str = DEFAULT_STRING - self.crt_workspace: str = DEFAULT_STRING - self.verifying: str = DEFAULT_STRING - self.installed: str = DEFAULT_STRING - self.update_done: str = DEFAULT_STRING - self.not_installed: str = DEFAULT_STRING - self.clear_qu: str = DEFAULT_STRING - self.done: str = DEFAULT_STRING - self.done_qu: str = DEFAULT_STRING - self.choice: str = DEFAULT_STRING - self.to_continue: str = DEFAULT_STRING - self.experimental: str = DEFAULT_STRING - - self.sc_label: str = DEFAULT_STRING - self.decode_sc: str = DEFAULT_STRING - self.encode_sc: str = DEFAULT_STRING - self.decode_by_parts: str = DEFAULT_STRING - self.encode_by_parts: str = DEFAULT_STRING - self.overwrite_by_parts: str = DEFAULT_STRING - self.decode_sc_description: str = DEFAULT_STRING - self.encode_sc_description: str = DEFAULT_STRING - self.decode_by_parts_description: str = DEFAULT_STRING - self.encode_by_parts_description: str = DEFAULT_STRING - self.overwrite_by_parts_description: str = DEFAULT_STRING - - self.csv_label: str = DEFAULT_STRING - self.decompress_csv: str = DEFAULT_STRING - self.compress_csv: str = DEFAULT_STRING - self.decompress_csv_description: str = DEFAULT_STRING - self.compress_csv_description: str = DEFAULT_STRING - - self.ktx_label: str = DEFAULT_STRING - self.ktx_from_png_label: str = DEFAULT_STRING - self.png_from_ktx_label: str = DEFAULT_STRING - self.ktx_from_png_description: str = DEFAULT_STRING - self.png_from_ktx_description: str = DEFAULT_STRING - - self.other_features_label: str = DEFAULT_STRING - self.check_update: str = DEFAULT_STRING - self.reinit: str = DEFAULT_STRING - self.change_language: str = DEFAULT_STRING - self.clear_directories: str = DEFAULT_STRING - self.toggle_update_auto_checking: str = DEFAULT_STRING - self.exit: str = DEFAULT_STRING - self.version: str = DEFAULT_STRING - self.reinit_description: str = DEFAULT_STRING - self.change_lang_description: str = DEFAULT_STRING - self.clean_dirs_description: str = DEFAULT_STRING - - self.not_latest: str = DEFAULT_STRING - self.collecting_inf: str = DEFAULT_STRING - self.about_sc: str = DEFAULT_STRING - self.skip_not_installed: str = DEFAULT_STRING - self.decompression_error: str = DEFAULT_STRING - self.detected_comp: str = DEFAULT_STRING - self.unknown_pixel_type: str = DEFAULT_STRING - self.crt_pic: str = DEFAULT_STRING - self.join_pic: str = DEFAULT_STRING - self.png_save: str = DEFAULT_STRING - self.saved: str = DEFAULT_STRING - self.illegal_size: str = DEFAULT_STRING - self.resize_qu: str = DEFAULT_STRING - self.resizing: str = DEFAULT_STRING - self.split_pic: str = DEFAULT_STRING - self.writing_pic: str = DEFAULT_STRING - self.compressing_with: str = DEFAULT_STRING - self.compression_error: str = DEFAULT_STRING - self.compression_done: str = DEFAULT_STRING - self.dir_empty: str = DEFAULT_STRING - self.texture_not_found: str = DEFAULT_STRING - self.file_not_found: str = DEFAULT_STRING - self.cut_sprites_process: str = DEFAULT_STRING - self.place_sprites_process: str = DEFAULT_STRING - self.not_implemented: str = DEFAULT_STRING - self.error: str = DEFAULT_STRING - - # new - self.e1sc1: str = DEFAULT_STRING - self.cgl: str = DEFAULT_STRING - self.upd_av: str = DEFAULT_STRING - self.upd_qu: str = DEFAULT_STRING - self.upd: str = DEFAULT_STRING - self.upd_ck: str = DEFAULT_STRING - self.bkp: str = DEFAULT_STRING - self.stp: str = DEFAULT_STRING - - self.enabled: str = DEFAULT_STRING - self.disabled: str = DEFAULT_STRING - - self.install_to_unlock: str = DEFAULT_STRING - - def load(self, language: str): - language_filepath = "./system/languages/" + language + ".json" - english_language_filepath = "./system/languages/en-EU.json" - - loaded_locale = {} - if os.path.exists(language_filepath): - loaded_locale = json.load(open(language_filepath, encoding="utf-8")) # Any - english_locale = json.load(open(english_language_filepath)) # English - - for key in self.__dict__: - if key in loaded_locale: - setattr(self, key, loaded_locale[key]) - continue - setattr(self, key, english_locale[key]) - - def change(self): - language_files = os.listdir("./system/languages/") - - print("Select Language\nВыберите язык\nВиберіть Мову\n") - - for file_index in range(len(language_files)): - language_path = "./system/languages/" + language_files[file_index] - language_name = json.load(open(language_path, encoding="utf-8"))["name"] - - print(f"{file_index + 1} - {language_name}") - - language_index = input("\n>>> ") - try: - language_index = int(language_index) - 1 - if language_index >= 0: - if language_index < len(language_files): - language = ".".join(language_files[language_index].split(".")[:-1]) - self.load(language) - - return language - except ValueError: - pass - - return self.change() - - -locale = Locale() -locale.load(config.language) diff --git a/tests/test_polygon.py b/tests/test_polygon.py index e9b2d3b..bdb4b6f 100644 --- a/tests/test_polygon.py +++ b/tests/test_polygon.py @@ -1,7 +1,6 @@ from unittest import TestCase -from system.lib.math.point import Point -from system.lib.math.polygon import PointOrder, Polygon, get_polygon_point_order +from xcoder.math import Point, PointOrder, Polygon, get_polygon_point_order def create_polygon_from_tuple(*polygon: tuple[float, float]) -> Polygon: diff --git a/system/__init__.py b/xcoder/__init__.py similarity index 54% rename from system/__init__.py rename to xcoder/__init__.py index 9e263f9..ec764f5 100644 --- a/system/__init__.py +++ b/xcoder/__init__.py @@ -1,5 +1,6 @@ import os import platform +import sys from loguru import logger @@ -27,3 +28,21 @@ def clear(): def clear(): os.system("clear") + + +logger.remove() +logger.add( + "./logs/info/{time:YYYY-MM-DD}.log", + format="[{time:HH:mm:ss}] [{level}]: {message}", + encoding="utf8", + level="INFO", +) +logger.add( + "./logs/errors/{time:YYYY-MM-DD}.log", + format="[{time:HH:mm:ss}] [{level}]: {message}", + backtrace=True, + diagnose=True, + encoding="utf8", + level="ERROR", +) +logger.add(sys.stdout, format="[{level}] {message}", level="INFO") diff --git a/main.py b/xcoder/__main__.py similarity index 75% rename from main.py rename to xcoder/__main__.py index 0a12752..ae69b56 100644 --- a/main.py +++ b/xcoder/__main__.py @@ -1,21 +1,16 @@ import time -from system.lib.config import config -from system.lib.main_menu import ( - check_auto_update, - check_files_updated, - menu, - refill_menu, -) -from system.localization import locale +from xcoder.config import config +from xcoder.localization import locale +from xcoder.main_menu import check_auto_update, check_files_updated, menu, refill_menu try: from loguru import logger except ImportError: raise RuntimeError("Please, install loguru using pip") -from system import clear -from system.lib.features.initialization import initialize +from xcoder import clear +from xcoder.features.initialization import initialize def main(): diff --git a/system/bytestream.py b/xcoder/bytestream.py similarity index 100% rename from system/bytestream.py rename to xcoder/bytestream.py diff --git a/xcoder/config.py b/xcoder/config.py new file mode 100644 index 0000000..38be027 --- /dev/null +++ b/xcoder/config.py @@ -0,0 +1,67 @@ +import json +import os +from pathlib import Path +from typing import LiteralString + +_LIBRARY_DIRECTORY = Path(__file__).parent + + +class Config: + DEFAULT_LANGUAGE: LiteralString = "en-EU" + + REPO_OWNER: LiteralString = "xcoder-tool" + REPO_NAME: LiteralString = "xcoder" + + config_path = _LIBRARY_DIRECTORY / "config.json" + + def __init__(self): + self.config_items = ( + "initialized", + "repo_owner", + "repo_name", + "version", + "language", + "has_update", + "last_update", + "auto_update", + "should_render_movie_clips", + ) + + self.initialized: bool = False + self.repo_owner: str = Config.REPO_OWNER + self.repo_name: str = Config.REPO_NAME + self.version = None + self.language: str = Config.DEFAULT_LANGUAGE + self.has_update: bool = False + self.last_update: int = -1 + self.auto_update: bool = False + self.should_render_movie_clips: bool = False + + self.load() + + def toggle_auto_update(self) -> None: + self.auto_update = not self.auto_update + self.dump() + + def change_language(self, language: str) -> None: + self.language = language + self.dump() + + def load(self) -> None: + if os.path.isfile(self.config_path): + with open(self.config_path) as config_file: + config_data = json.load(config_file) + for key, value in config_data.items(): + setattr(self, key, value) + + def dump(self) -> None: + with open(self.config_path, "w") as config_file: + json.dump( + {item: getattr(self, item) for item in self.config_items}, config_file + ) + + def get_repo_url(self) -> str: + return f"https://github.com/{self.repo_owner}/{self.repo_name}" + + +config = Config() diff --git a/system/lib/console.py b/xcoder/console.py similarity index 100% rename from system/lib/console.py rename to xcoder/console.py diff --git a/xcoder/exceptions/__init__.py b/xcoder/exceptions/__init__.py new file mode 100644 index 0000000..5d97ceb --- /dev/null +++ b/xcoder/exceptions/__init__.py @@ -0,0 +1,3 @@ +from xcoder.exceptions.tool_not_found import ToolNotFoundException + +__all__ = ["ToolNotFoundException"] diff --git a/system/exceptions/tool_not_found.py b/xcoder/exceptions/tool_not_found.py similarity index 100% rename from system/exceptions/tool_not_found.py rename to xcoder/exceptions/tool_not_found.py diff --git a/system/lib/features/__init__.py b/xcoder/features/__init__.py similarity index 100% rename from system/lib/features/__init__.py rename to xcoder/features/__init__.py diff --git a/system/lib/features/csv/__init__.py b/xcoder/features/csv/__init__.py similarity index 100% rename from system/lib/features/csv/__init__.py rename to xcoder/features/csv/__init__.py diff --git a/system/lib/features/csv/compress.py b/xcoder/features/csv/compress.py similarity index 95% rename from system/lib/features/csv/compress.py rename to xcoder/features/csv/compress.py index 8ce6629..d6c1742 100644 --- a/system/lib/features/csv/compress.py +++ b/xcoder/features/csv/compress.py @@ -3,7 +3,7 @@ from loguru import logger from sc_compression import compress -from system.localization import locale +from xcoder.localization import locale def compress_csv(): diff --git a/system/lib/features/csv/decompress.py b/xcoder/features/csv/decompress.py similarity index 95% rename from system/lib/features/csv/decompress.py rename to xcoder/features/csv/decompress.py index 5b20788..bdedb32 100644 --- a/system/lib/features/csv/decompress.py +++ b/xcoder/features/csv/decompress.py @@ -3,7 +3,7 @@ from loguru import logger from sc_compression import decompress -from system.localization import locale +from xcoder.localization import locale def decompress_csv(): diff --git a/system/lib/features/csv/update.py b/xcoder/features/csv/update.py similarity index 95% rename from system/lib/features/csv/update.py rename to xcoder/features/csv/update.py index 9f6400c..0d2e9d0 100644 --- a/system/lib/features/csv/update.py +++ b/xcoder/features/csv/update.py @@ -3,7 +3,7 @@ from loguru import logger from sc_compression import compress -from system.localization import locale +from xcoder.localization import locale def update_csv(): diff --git a/system/lib/features/cut_sprites.py b/xcoder/features/cut_sprites.py similarity index 90% rename from system/lib/features/cut_sprites.py rename to xcoder/features/cut_sprites.py index 82829e4..85f8c81 100644 --- a/system/lib/features/cut_sprites.py +++ b/xcoder/features/cut_sprites.py @@ -1,14 +1,12 @@ import os from pathlib import Path -from system.lib.config import config -from system.lib.console import Console -from system.lib.matrices import Matrix2x3 -from system.lib.objects.renderable.renderable_factory import ( - create_renderable_from_plain, -) -from system.lib.swf import SupercellSWF -from system.localization import locale +from xcoder.config import config +from xcoder.console import Console +from xcoder.localization import locale +from xcoder.matrices import Matrix2x3 +from xcoder.objects.renderable.renderable_factory import create_renderable_from_plain +from xcoder.swf import SupercellSWF def render_objects(swf: SupercellSWF, output_folder: Path): diff --git a/system/lib/features/directories.py b/xcoder/features/directories.py similarity index 100% rename from system/lib/features/directories.py rename to xcoder/features/directories.py diff --git a/system/lib/features/files.py b/xcoder/features/files.py similarity index 95% rename from system/lib/features/files.py rename to xcoder/features/files.py index a30627d..ebd2d92 100644 --- a/system/lib/features/files.py +++ b/xcoder/features/files.py @@ -4,7 +4,7 @@ from sc_compression import compress, decompress from sc_compression.signatures import Signatures -from system.localization import locale +from xcoder.localization import locale def write_sc( diff --git a/system/lib/features/initialization.py b/xcoder/features/initialization.py similarity index 59% rename from system/lib/features/initialization.py rename to xcoder/features/initialization.py index fdbf1b3..d1be8de 100644 --- a/system/lib/features/initialization.py +++ b/xcoder/features/initialization.py @@ -2,11 +2,11 @@ from loguru import logger -from system import clear -from system.lib.config import config -from system.lib.features.directories import create_directories -from system.lib.features.update.check import get_tags -from system.localization import locale +from xcoder import clear +from xcoder.config import config +from xcoder.features.directories import create_directories +from xcoder.features.update.check import get_tags +from xcoder.localization import locale @logger.catch() @@ -22,7 +22,7 @@ def initialize(first_init=False): logger.info(locale.verifying) config.initialized = True - config.version = get_tags("vorono4ka", "xcoder")[0]["name"][1:] + config.version = get_tags(config.repo_owner, config.repo_name)[0]["name"][1:] config.dump() if first_init: diff --git a/system/lib/features/ktx.py b/xcoder/features/ktx.py similarity index 90% rename from system/lib/features/ktx.py rename to xcoder/features/ktx.py index 22eb4cb..5e24980 100644 --- a/system/lib/features/ktx.py +++ b/xcoder/features/ktx.py @@ -3,8 +3,8 @@ from loguru import logger -from system.lib.pvr_tex_tool import convert_ktx_to_png, convert_png_to_ktx -from system.localization import locale +from xcoder.localization import locale +from xcoder.pvr_tex_tool import convert_ktx_to_png, convert_png_to_ktx IN_PNG_PATH = Path("./TEX/In-PNG") IN_KTX_PATH = Path("./TEX/In-KTX") diff --git a/system/lib/features/place_sprites.py b/xcoder/features/place_sprites.py similarity index 92% rename from system/lib/features/place_sprites.py rename to xcoder/features/place_sprites.py index 753f1ac..747a7f3 100644 --- a/system/lib/features/place_sprites.py +++ b/xcoder/features/place_sprites.py @@ -3,11 +3,11 @@ from PIL import Image -from system.lib.console import Console -from system.lib.images import create_filled_polygon_image, get_format_by_pixel_type -from system.lib.math.polygon import get_rect -from system.lib.xcod import FileInfo -from system.localization import locale +from xcoder.console import Console +from xcoder.images import create_filled_polygon_image, get_format_by_pixel_type +from xcoder.localization import locale +from xcoder.math.polygon import get_rect +from xcoder.xcod import FileInfo MASK_COLOR = 255 diff --git a/system/lib/features/sc/__init__.py b/xcoder/features/sc/__init__.py similarity index 84% rename from system/lib/features/sc/__init__.py rename to xcoder/features/sc/__init__.py index efb8969..cccde9f 100644 --- a/system/lib/features/sc/__init__.py +++ b/xcoder/features/sc/__init__.py @@ -4,12 +4,12 @@ from loguru import logger from PIL import Image -from system.bytestream import Writer -from system.lib.console import Console -from system.lib.features.files import write_sc -from system.lib.images import get_byte_count_by_pixel_type, save_texture, split_image -from system.lib.xcod import FileInfo -from system.localization import locale +from xcoder.bytestream import Writer +from xcoder.console import Console +from xcoder.features.files import write_sc +from xcoder.images import get_byte_count_by_pixel_type, save_texture, split_image +from xcoder.localization import locale +from xcoder.xcod import FileInfo def compile_sc( diff --git a/system/lib/features/sc/decode.py b/xcoder/features/sc/decode.py similarity index 95% rename from system/lib/features/sc/decode.py rename to xcoder/features/sc/decode.py index fe75a1a..a1d7597 100644 --- a/system/lib/features/sc/decode.py +++ b/xcoder/features/sc/decode.py @@ -5,10 +5,10 @@ from loguru import logger from sc_compression import Signatures -from system.bytestream import Writer -from system.lib.features.cut_sprites import render_objects -from system.lib.swf import SupercellSWF -from system.localization import locale +from xcoder.bytestream import Writer +from xcoder.features.cut_sprites import render_objects +from xcoder.localization import locale +from xcoder.swf import SupercellSWF IN_COMPRESSED_PATH = Path("./SC/In-Compressed") OUT_DECOMPRESSED = Path("./SC/Out-Decompressed") diff --git a/system/lib/features/sc/encode.py b/xcoder/features/sc/encode.py similarity index 91% rename from system/lib/features/sc/encode.py rename to xcoder/features/sc/encode.py index 6c52e55..df36b96 100644 --- a/system/lib/features/sc/encode.py +++ b/xcoder/features/sc/encode.py @@ -4,10 +4,10 @@ from loguru import logger from PIL import Image -from system.lib.features.place_sprites import place_sprites -from system.lib.features.sc import compile_sc -from system.lib.xcod import parse_info -from system.localization import locale +from xcoder.features.place_sprites import place_sprites +from xcoder.features.sc import compile_sc +from xcoder.localization import locale +from xcoder.xcod import parse_info OUT_COMPRESSED_PATH = Path("./SC/Out-Compressed") IN_DECOMPRESSED_PATH = Path("./SC/In-Decompressed") diff --git a/system/lib/features/update/__init__.py b/xcoder/features/update/__init__.py similarity index 100% rename from system/lib/features/update/__init__.py rename to xcoder/features/update/__init__.py diff --git a/system/lib/features/update/check.py b/xcoder/features/update/check.py similarity index 86% rename from system/lib/features/update/check.py rename to xcoder/features/update/check.py index 697831c..5f80973 100644 --- a/system/lib/features/update/check.py +++ b/xcoder/features/update/check.py @@ -3,10 +3,10 @@ from loguru import logger -from system import run -from system.lib.config import config -from system.lib.features.update.download import download_update -from system.localization import locale +from xcoder import run +from xcoder.config import config +from xcoder.features.update.download import download_update +from xcoder.localization import locale def get_run_output(command: str): @@ -53,7 +53,7 @@ def get_tags(owner: str, repo: str): def check_update(): - tags = get_tags("vorono4ka", "xcoder") + tags = get_tags(config.repo_owner, config.repo_name) if len(tags) > 0: latest_tag = tags[0] diff --git a/system/lib/features/update/download.py b/xcoder/features/update/download.py similarity index 73% rename from system/lib/features/update/download.py rename to xcoder/features/update/download.py index 2c19504..0949224 100644 --- a/system/lib/features/update/download.py +++ b/xcoder/features/update/download.py @@ -3,21 +3,11 @@ from loguru import logger -from system import run -from system.lib.config import config -from system.localization import locale +from xcoder.config import config +from xcoder.localization import locale -def update_outdated(outdated): - for package in outdated: - update_package(package) - - -def update_package(package): - run(f"pip3 install --upgrade {package}") - - -def download_update(zip_url): +def download_update(zip_url: str) -> None: if not os.path.exists("updates"): os.mkdir("updates") diff --git a/system/lib/images.py b/xcoder/images.py similarity index 96% rename from system/lib/images.py rename to xcoder/images.py index 802c65b..fb524d6 100644 --- a/system/lib/images.py +++ b/xcoder/images.py @@ -6,16 +6,16 @@ if TYPE_CHECKING: from PIL._imaging import PixelAccess # type: ignore[reportPrivateImportUsage] -from system.bytestream import Reader, Writer -from system.lib.console import Console -from system.lib.math.point import Point -from system.lib.matrices import Matrix2x3 -from system.lib.pixel_utils import ( +from .bytestream import Reader, Writer +from .console import Console +from .localization import locale +from .math.point import Point +from .matrices import Matrix2x3 +from .pixel_utils import ( get_channel_count_by_pixel_type, get_pixel_encode_function, get_read_function, ) -from system.localization import locale CHUNK_SIZE = 32 diff --git a/system/languages/en-EU.json b/xcoder/languages/en-EU.json similarity index 98% rename from system/languages/en-EU.json rename to xcoder/languages/en-EU.json index 4116b00..3d1ba74 100644 --- a/system/languages/en-EU.json +++ b/xcoder/languages/en-EU.json @@ -76,7 +76,7 @@ "file_not_found": "File '%s' not found!", "cut_sprites_process": "Cutting sprites... (%d/%d)", "place_sprites_process": "Placing sprites... (%d/%d)", - "not_implemented": "This feature will be added in future updates.\nYou can follow XCoder updates here: https://github.com/Vorono4ka/XCoder", + "not_implemented": "This feature will be added in future updates.\nYou can follow XCoder updates here: {repo_url}", "error": "ERROR! (%s.%s: %s)", "e1sc1": "Overwrite SC sprites", "cgl": "Changelog:\n%s", diff --git a/system/languages/ru-RU.json b/xcoder/languages/ru-RU.json similarity index 98% rename from system/languages/ru-RU.json rename to xcoder/languages/ru-RU.json index 8120e2e..51aabcc 100644 --- a/system/languages/ru-RU.json +++ b/xcoder/languages/ru-RU.json @@ -76,7 +76,7 @@ "file_not_found": "Файл '%s' не найден!", "cut_sprites_process": "Вырезаем спрайты... (%d/%d)", "place_sprites_process": "Ставим спрайты на место... (%d/%d)", - "not_implemented": "Данная возможность будет добавлена в будущих обновлениях.\nЗа обновлениями XCoder вы можете следить здесь: https://github.com/Vorono4ka/XCoder", + "not_implemented": "Данная возможность будет добавлена в будущих обновлениях.\nЗа обновлениями XCoder вы можете следить здесь: {repo_url}", "error": "ОШИБКА! (%s.%s: %s)", "e1sc1": "Перезапись спрайтов", "cgl": "Список изменений: \n%s", diff --git a/system/languages/ua-UA.json b/xcoder/languages/ua-UA.json similarity index 98% rename from system/languages/ua-UA.json rename to xcoder/languages/ua-UA.json index 94e069d..689f5f7 100644 --- a/system/languages/ua-UA.json +++ b/xcoder/languages/ua-UA.json @@ -76,7 +76,7 @@ "file_not_found": "Файл '%s' не знайдено!", "cut_sprites_process": "Обрізаємо спрайти... (%d/%d)", "place_sprites_process": "Вставляємо спрайти... (%d/%d)", - "not_implemented": "Ця функція буде додана у наступних оновленнях.\nТи можеш сладкувати за оновленнями тут: https://github.com/Vorono4ka/XCoder", + "not_implemented": "Ця функція буде додана у наступних оновленнях.\nТи можеш сладкувати за оновленнями тут: {repo_url}", "error": "Помилка! (%s.%s: %s)", "e1sc1": "Переписати SC спрайти", "cgl": "Список змін:\n%s", diff --git a/xcoder/localization.py b/xcoder/localization.py new file mode 100644 index 0000000..56a44ea --- /dev/null +++ b/xcoder/localization.py @@ -0,0 +1,151 @@ +import json +import os +from pathlib import Path + +from xcoder.config import config + +_DEFAULT_STRING = "NO LOCALE" +_LIBRARY_DIRECTORY = Path(__file__).parent +_LOCALES_DIRECTORY = _LIBRARY_DIRECTORY / "languages" + + +class Locale: + def __init__(self): + self.xcoder_header: str = _DEFAULT_STRING + self.detected_os: str = _DEFAULT_STRING + self.installing: str = _DEFAULT_STRING + self.update_downloading: str = _DEFAULT_STRING + self.crt_workspace: str = _DEFAULT_STRING + self.verifying: str = _DEFAULT_STRING + self.installed: str = _DEFAULT_STRING + self.update_done: str = _DEFAULT_STRING + self.not_installed: str = _DEFAULT_STRING + self.clear_qu: str = _DEFAULT_STRING + self.done: str = _DEFAULT_STRING + self.done_qu: str = _DEFAULT_STRING + self.choice: str = _DEFAULT_STRING + self.to_continue: str = _DEFAULT_STRING + self.experimental: str = _DEFAULT_STRING + + self.sc_label: str = _DEFAULT_STRING + self.decode_sc: str = _DEFAULT_STRING + self.encode_sc: str = _DEFAULT_STRING + self.decode_by_parts: str = _DEFAULT_STRING + self.encode_by_parts: str = _DEFAULT_STRING + self.overwrite_by_parts: str = _DEFAULT_STRING + self.decode_sc_description: str = _DEFAULT_STRING + self.encode_sc_description: str = _DEFAULT_STRING + self.decode_by_parts_description: str = _DEFAULT_STRING + self.encode_by_parts_description: str = _DEFAULT_STRING + self.overwrite_by_parts_description: str = _DEFAULT_STRING + + self.csv_label: str = _DEFAULT_STRING + self.decompress_csv: str = _DEFAULT_STRING + self.compress_csv: str = _DEFAULT_STRING + self.decompress_csv_description: str = _DEFAULT_STRING + self.compress_csv_description: str = _DEFAULT_STRING + + self.ktx_label: str = _DEFAULT_STRING + self.ktx_from_png_label: str = _DEFAULT_STRING + self.png_from_ktx_label: str = _DEFAULT_STRING + self.ktx_from_png_description: str = _DEFAULT_STRING + self.png_from_ktx_description: str = _DEFAULT_STRING + + self.other_features_label: str = _DEFAULT_STRING + self.check_update: str = _DEFAULT_STRING + self.reinit: str = _DEFAULT_STRING + self.change_language: str = _DEFAULT_STRING + self.clear_directories: str = _DEFAULT_STRING + self.toggle_update_auto_checking: str = _DEFAULT_STRING + self.exit: str = _DEFAULT_STRING + self.version: str = _DEFAULT_STRING + self.reinit_description: str = _DEFAULT_STRING + self.change_lang_description: str = _DEFAULT_STRING + self.clean_dirs_description: str = _DEFAULT_STRING + + self.not_latest: str = _DEFAULT_STRING + self.collecting_inf: str = _DEFAULT_STRING + self.about_sc: str = _DEFAULT_STRING + self.skip_not_installed: str = _DEFAULT_STRING + self.decompression_error: str = _DEFAULT_STRING + self.detected_comp: str = _DEFAULT_STRING + self.unknown_pixel_type: str = _DEFAULT_STRING + self.crt_pic: str = _DEFAULT_STRING + self.join_pic: str = _DEFAULT_STRING + self.png_save: str = _DEFAULT_STRING + self.saved: str = _DEFAULT_STRING + self.illegal_size: str = _DEFAULT_STRING + self.resize_qu: str = _DEFAULT_STRING + self.resizing: str = _DEFAULT_STRING + self.split_pic: str = _DEFAULT_STRING + self.writing_pic: str = _DEFAULT_STRING + self.compressing_with: str = _DEFAULT_STRING + self.compression_error: str = _DEFAULT_STRING + self.compression_done: str = _DEFAULT_STRING + self.dir_empty: str = _DEFAULT_STRING + self.texture_not_found: str = _DEFAULT_STRING + self.file_not_found: str = _DEFAULT_STRING + self.cut_sprites_process: str = _DEFAULT_STRING + self.place_sprites_process: str = _DEFAULT_STRING + self.not_implemented: str = _DEFAULT_STRING + self.error: str = _DEFAULT_STRING + + self.e1sc1: str = _DEFAULT_STRING + self.cgl: str = _DEFAULT_STRING + self.upd_av: str = _DEFAULT_STRING + self.upd_qu: str = _DEFAULT_STRING + self.upd: str = _DEFAULT_STRING + self.upd_ck: str = _DEFAULT_STRING + self.bkp: str = _DEFAULT_STRING + self.stp: str = _DEFAULT_STRING + + self.enabled: str = _DEFAULT_STRING + self.disabled: str = _DEFAULT_STRING + + self.install_to_unlock: str = _DEFAULT_STRING + + def load(self, language: str): + language_filepath = _LOCALES_DIRECTORY / (language + ".json") + default_locale_filepath = _LOCALES_DIRECTORY / ( + config.DEFAULT_LANGUAGE + ".json" + ) + + loaded_locale = {} + if os.path.exists(language_filepath): + loaded_locale = json.load(open(language_filepath, encoding="utf-8")) # Any + english_locale = json.load(open(default_locale_filepath)) # English + + for key in self.__dict__: + if key in loaded_locale: + setattr(self, key, loaded_locale[key]) + continue + setattr(self, key, english_locale[key]) + + def change(self): + language_files = os.listdir(_LOCALES_DIRECTORY) + + print("Select Language\nВыберите язык\nВиберіть Мову\n") + + for file_index, language_file in enumerate(language_files): + language_path = _LOCALES_DIRECTORY / language_file + language_name = json.load(open(language_path, encoding="utf-8"))["name"] + + print(f"{file_index + 1} - {language_name}") + + language_index = input("\n>>> ") + try: + language_index = int(language_index) - 1 + if language_index >= 0: + if language_index < len(language_files): + language = ".".join(language_files[language_index].split(".")[:-1]) + self.load(language) + + return language + except ValueError: + pass + + return self.change() + + +locale = Locale() +locale.load(config.language) diff --git a/system/lib/main_menu.py b/xcoder/main_menu.py similarity index 87% rename from system/lib/main_menu.py rename to xcoder/main_menu.py index da4b713..a5974be 100644 --- a/system/lib/main_menu.py +++ b/xcoder/main_menu.py @@ -2,14 +2,14 @@ from loguru import logger -from system import clear -from system.lib.config import config -from system.lib.console import Console -from system.lib.features.directories import clear_directories -from system.lib.features.initialization import initialize -from system.lib.features.update.check import check_update, get_tags -from system.lib.menu import Menu -from system.localization import locale +from xcoder import clear +from xcoder.config import config +from xcoder.console import Console +from xcoder.features.directories import clear_directories +from xcoder.features.initialization import initialize +from xcoder.features.update.check import check_update, get_tags +from xcoder.localization import locale +from xcoder.menu import Menu menu = Menu() @@ -25,7 +25,7 @@ def check_files_updated(): if config.has_update: logger.opt(colors=True).info(f'{locale.update_done % ""}') if Console.question(locale.done_qu): - latest_tag = get_tags("vorono4ka", "xcoder")[0] + latest_tag = get_tags(config.repo_owner, config.repo_name)[0] latest_tag_name = latest_tag["name"][1:] config.has_update = False @@ -58,8 +58,8 @@ def refill_menu(): except ImportError: logger.warning(locale.install_to_unlock % "sc-compression") else: - from system.lib.features.csv.compress import compress_csv - from system.lib.features.csv.decompress import decompress_csv + from xcoder.features.csv.compress import compress_csv + from xcoder.features.csv.decompress import decompress_csv try: import PIL @@ -68,11 +68,11 @@ def refill_menu(): except ImportError: logger.warning(locale.install_to_unlock % "PILLOW") else: - from system.lib.features.sc.decode import ( + from xcoder.features.sc.decode import ( decode_and_render_objects, decode_textures_only, ) - from system.lib.features.sc.encode import ( + from xcoder.features.sc.encode import ( collect_objects_and_encode, encode_textures_only, ) @@ -113,25 +113,25 @@ def refill_menu(): ) ) - from system.lib.features.ktx import ( + from xcoder.features.ktx import ( convert_ktx_textures_to_png, convert_png_textures_to_ktx, ) - from system.lib.pvr_tex_tool import can_use_pvr_tex_tool + from xcoder.pvr_tex_tool import can_use_pvr_tex_tool if can_use_pvr_tex_tool(): ktx_category.add( Menu.Item( - name=locale.ktx_from_png_label, - description=locale.ktx_from_png_description, - handler=convert_png_textures_to_ktx, + name=locale.png_from_ktx_label, + description=locale.png_from_ktx_description, + handler=convert_ktx_textures_to_png, ) ) ktx_category.add( Menu.Item( - name=locale.png_from_ktx_label, - description=locale.png_from_ktx_description, - handler=convert_ktx_textures_to_png, + name=locale.ktx_from_png_label, + description=locale.ktx_from_png_description, + handler=convert_png_textures_to_ktx, ) ) diff --git a/xcoder/math/__init__.py b/xcoder/math/__init__.py new file mode 100644 index 0000000..0ad2624 --- /dev/null +++ b/xcoder/math/__init__.py @@ -0,0 +1,4 @@ +from .point import Point +from .polygon import PointOrder, Polygon, get_polygon_point_order + +__all__ = ["Point", "PointOrder", "Polygon", "get_polygon_point_order"] diff --git a/system/lib/math/point.py b/xcoder/math/point.py similarity index 100% rename from system/lib/math/point.py rename to xcoder/math/point.py diff --git a/system/lib/math/polygon.py b/xcoder/math/polygon.py similarity index 95% rename from system/lib/math/polygon.py rename to xcoder/math/polygon.py index 596c71e..84ab433 100644 --- a/system/lib/math/polygon.py +++ b/xcoder/math/polygon.py @@ -2,9 +2,9 @@ from math import atan2, degrees from typing import TypeAlias -from system.lib.math.point import Point -from system.lib.math.rect import Rect -from system.lib.matrices import Matrix2x3 +from xcoder.math.point import Point +from xcoder.math.rect import Rect +from xcoder.matrices import Matrix2x3 Polygon: TypeAlias = list[Point] diff --git a/system/lib/math/rect.py b/xcoder/math/rect.py similarity index 100% rename from system/lib/math/rect.py rename to xcoder/math/rect.py diff --git a/system/lib/matrices/__init__.py b/xcoder/matrices/__init__.py similarity index 100% rename from system/lib/matrices/__init__.py rename to xcoder/matrices/__init__.py diff --git a/system/lib/matrices/color_transform.py b/xcoder/matrices/color_transform.py similarity index 100% rename from system/lib/matrices/color_transform.py rename to xcoder/matrices/color_transform.py diff --git a/system/lib/matrices/matrix2x3.py b/xcoder/matrices/matrix2x3.py similarity index 98% rename from system/lib/matrices/matrix2x3.py rename to xcoder/matrices/matrix2x3.py index 9bbba4e..802f1f5 100644 --- a/system/lib/matrices/matrix2x3.py +++ b/xcoder/matrices/matrix2x3.py @@ -1,7 +1,7 @@ from math import atan2, cos, degrees, hypot, sin from typing import Self -from system.bytestream import Reader +from xcoder.bytestream import Reader DEFAULT_MULTIPLIER = 1024 PRECISE_MULTIPLIER = 65535 diff --git a/system/lib/matrices/matrix_bank.py b/xcoder/matrices/matrix_bank.py similarity index 85% rename from system/lib/matrices/matrix_bank.py rename to xcoder/matrices/matrix_bank.py index a1e045b..aca94d4 100644 --- a/system/lib/matrices/matrix_bank.py +++ b/xcoder/matrices/matrix_bank.py @@ -1,5 +1,5 @@ -from system.lib.matrices.color_transform import ColorTransform -from system.lib.matrices.matrix2x3 import Matrix2x3 +from xcoder.matrices.color_transform import ColorTransform +from xcoder.matrices.matrix2x3 import Matrix2x3 class MatrixBank: diff --git a/system/lib/menu.py b/xcoder/menu.py similarity index 95% rename from system/lib/menu.py rename to xcoder/menu.py index 4eac6de..d715057 100644 --- a/system/lib/menu.py +++ b/xcoder/menu.py @@ -4,8 +4,8 @@ import colorama -from system.lib.config import config -from system.localization import locale +from xcoder.config import config +from xcoder.localization import locale def print_feature( @@ -73,7 +73,7 @@ def choice(self): + colorama.Style.RESET_ALL ).center(console_width + 12) ) - print("https://github.com/Vorono4ka/XCoder".center(console_width - 1)) + print(config.get_repo_url().center(console_width - 1)) self._print_divider_line(console_width) for category in self.categories: diff --git a/xcoder/objects/__init__.py b/xcoder/objects/__init__.py new file mode 100644 index 0000000..c768d56 --- /dev/null +++ b/xcoder/objects/__init__.py @@ -0,0 +1,5 @@ +from .movie_clip import MovieClip +from .shape import Shape +from .texture import SWFTexture + +__all__ = ["Shape", "MovieClip", "SWFTexture"] diff --git a/xcoder/objects/movie_clip/__init__.py b/xcoder/objects/movie_clip/__init__.py new file mode 100644 index 0000000..1dd7067 --- /dev/null +++ b/xcoder/objects/movie_clip/__init__.py @@ -0,0 +1,4 @@ +__all__ = ["MovieClip", "MovieClipFrame"] + +from xcoder.objects.movie_clip.movie_clip import MovieClip +from xcoder.objects.movie_clip.movie_clip_frame import MovieClipFrame diff --git a/system/lib/objects/movie_clip/movie_clip.py b/xcoder/objects/movie_clip/movie_clip.py similarity index 98% rename from system/lib/objects/movie_clip/movie_clip.py rename to xcoder/objects/movie_clip/movie_clip.py index 661e467..86f7304 100644 --- a/system/lib/objects/movie_clip/movie_clip.py +++ b/xcoder/objects/movie_clip/movie_clip.py @@ -6,7 +6,7 @@ from .movie_clip_frame import MovieClipFrame if TYPE_CHECKING: - from system.lib.swf import SupercellSWF + from xcoder.swf import SupercellSWF CACHE = {} diff --git a/system/lib/objects/movie_clip/movie_clip_frame.py b/xcoder/objects/movie_clip/movie_clip_frame.py similarity index 94% rename from system/lib/objects/movie_clip/movie_clip_frame.py rename to xcoder/objects/movie_clip/movie_clip_frame.py index 0e92108..0329ca9 100644 --- a/system/lib/objects/movie_clip/movie_clip_frame.py +++ b/xcoder/objects/movie_clip/movie_clip_frame.py @@ -1,4 +1,4 @@ -from system.bytestream import Reader +from xcoder.bytestream import Reader class MovieClipFrame: diff --git a/system/lib/objects/plain_object.py b/xcoder/objects/plain_object.py similarity index 84% rename from system/lib/objects/plain_object.py rename to xcoder/objects/plain_object.py index 86d3e7b..033b694 100644 --- a/system/lib/objects/plain_object.py +++ b/xcoder/objects/plain_object.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from system.lib.swf import SupercellSWF + from xcoder.swf import SupercellSWF class PlainObject(ABC): diff --git a/xcoder/objects/renderable/__init__.py b/xcoder/objects/renderable/__init__.py new file mode 100644 index 0000000..67d9248 --- /dev/null +++ b/xcoder/objects/renderable/__init__.py @@ -0,0 +1,3 @@ +from xcoder.objects.renderable.renderable_factory import create_renderable_from_plain + +__all__ = ["create_renderable_from_plain"] diff --git a/system/lib/objects/renderable/display_object.py b/xcoder/objects/renderable/display_object.py similarity index 86% rename from system/lib/objects/renderable/display_object.py rename to xcoder/objects/renderable/display_object.py index c089e48..b79db36 100644 --- a/system/lib/objects/renderable/display_object.py +++ b/xcoder/objects/renderable/display_object.py @@ -4,8 +4,8 @@ from PIL import Image -from system.lib.math.rect import Rect -from system.lib.matrices import ColorTransform, Matrix2x3 +from xcoder.math.rect import Rect +from xcoder.matrices import ColorTransform, Matrix2x3 class DisplayObject(ABC): diff --git a/system/lib/objects/renderable/renderable_factory.py b/xcoder/objects/renderable/renderable_factory.py similarity index 62% rename from system/lib/objects/renderable/renderable_factory.py rename to xcoder/objects/renderable/renderable_factory.py index c351939..cfb8568 100644 --- a/system/lib/objects/renderable/renderable_factory.py +++ b/xcoder/objects/renderable/renderable_factory.py @@ -1,10 +1,10 @@ -from system.lib.objects import Shape -from system.lib.objects.movie_clip.movie_clip import MovieClip -from system.lib.objects.plain_object import PlainObject -from system.lib.objects.renderable.display_object import DisplayObject -from system.lib.objects.renderable.renderable_movie_clip import RenderableMovieClip -from system.lib.objects.renderable.renderable_shape import RenderableShape -from system.lib.swf import SupercellSWF +from xcoder.objects import Shape +from xcoder.objects.movie_clip.movie_clip import MovieClip +from xcoder.objects.plain_object import PlainObject +from xcoder.objects.renderable.display_object import DisplayObject +from xcoder.objects.renderable.renderable_movie_clip import RenderableMovieClip +from xcoder.objects.renderable.renderable_shape import RenderableShape +from xcoder.swf import SupercellSWF def create_renderable_from_plain( diff --git a/system/lib/objects/renderable/renderable_movie_clip.py b/xcoder/objects/renderable/renderable_movie_clip.py similarity index 90% rename from system/lib/objects/renderable/renderable_movie_clip.py rename to xcoder/objects/renderable/renderable_movie_clip.py index 3f22d5a..3576e87 100644 --- a/system/lib/objects/renderable/renderable_movie_clip.py +++ b/xcoder/objects/renderable/renderable_movie_clip.py @@ -4,14 +4,14 @@ from PIL import Image -from system.lib.math.rect import Rect -from system.lib.matrices import ColorTransform, Matrix2x3, MatrixBank -from system.lib.objects.movie_clip.movie_clip import MovieClip -from system.lib.objects.movie_clip.movie_clip_frame import MovieClipFrame -from system.lib.objects.renderable.display_object import DisplayObject +from xcoder.math.rect import Rect +from xcoder.matrices import ColorTransform, Matrix2x3, MatrixBank +from xcoder.objects.movie_clip.movie_clip import MovieClip +from xcoder.objects.movie_clip.movie_clip_frame import MovieClipFrame +from xcoder.objects.renderable.display_object import DisplayObject if TYPE_CHECKING: - from system.lib.swf import SupercellSWF + from xcoder.swf import SupercellSWF class RenderableMovieClip(DisplayObject): diff --git a/system/lib/objects/renderable/renderable_shape.py b/xcoder/objects/renderable/renderable_shape.py similarity index 87% rename from system/lib/objects/renderable/renderable_shape.py rename to xcoder/objects/renderable/renderable_shape.py index 8b762b8..f61aa1f 100644 --- a/system/lib/objects/renderable/renderable_shape.py +++ b/xcoder/objects/renderable/renderable_shape.py @@ -2,10 +2,10 @@ from PIL import Image -from system.lib.math.rect import Rect -from system.lib.matrices import Matrix2x3 -from system.lib.objects import Shape -from system.lib.objects.renderable.display_object import DisplayObject +from xcoder.math.rect import Rect +from xcoder.matrices import Matrix2x3 +from xcoder.objects import Shape +from xcoder.objects.renderable.display_object import DisplayObject class RenderableShape(DisplayObject): diff --git a/xcoder/objects/shape/__init__.py b/xcoder/objects/shape/__init__.py new file mode 100644 index 0000000..2322fcf --- /dev/null +++ b/xcoder/objects/shape/__init__.py @@ -0,0 +1,4 @@ +__all__ = ["Shape", "Region"] + +from .region import Region +from .shape import Shape diff --git a/system/lib/objects/shape/region.py b/xcoder/objects/shape/region.py similarity index 92% rename from system/lib/objects/shape/region.py rename to xcoder/objects/shape/region.py index 7798409..0d2a085 100644 --- a/system/lib/objects/shape/region.py +++ b/xcoder/objects/shape/region.py @@ -4,15 +4,15 @@ from PIL import Image -from system.lib.images import create_filled_polygon_image -from system.lib.math.point import Point -from system.lib.math.polygon import apply_matrix, compare_polygons, get_rect -from system.lib.math.rect import Rect -from system.lib.matrices import Matrix2x3 +from xcoder.images import create_filled_polygon_image +from xcoder.math.point import Point +from xcoder.math.polygon import apply_matrix, compare_polygons, get_rect +from xcoder.math.rect import Rect +from xcoder.matrices import Matrix2x3 if TYPE_CHECKING: - from system.lib.objects import SWFTexture - from system.lib.swf import SupercellSWF + from xcoder.objects import SWFTexture + from xcoder.swf import SupercellSWF class Region: diff --git a/system/lib/objects/shape/shape.py b/xcoder/objects/shape/shape.py similarity index 86% rename from system/lib/objects/shape/shape.py rename to xcoder/objects/shape/shape.py index 5dfed07..26a9418 100644 --- a/system/lib/objects/shape/shape.py +++ b/xcoder/objects/shape/shape.py @@ -2,11 +2,11 @@ from typing import TYPE_CHECKING -from system.lib.objects.plain_object import PlainObject -from system.lib.objects.shape import Region +from xcoder.objects.plain_object import PlainObject +from xcoder.objects.shape import Region if TYPE_CHECKING: - from system.lib.swf import SupercellSWF + from xcoder.swf import SupercellSWF class Shape(PlainObject): diff --git a/system/lib/objects/texture.py b/xcoder/objects/texture.py similarity index 93% rename from system/lib/objects/texture.py rename to xcoder/objects/texture.py index fb700e7..d490e20 100644 --- a/system/lib/objects/texture.py +++ b/xcoder/objects/texture.py @@ -6,16 +6,16 @@ import zstandard from PIL import Image -from system.lib.images import ( +from xcoder.images import ( get_format_by_pixel_type, join_image, load_image_from_buffer, load_texture, ) -from system.lib.pvr_tex_tool import get_image_from_ktx_data +from xcoder.pvr_tex_tool import get_image_from_ktx_data if TYPE_CHECKING: - from system.lib.swf import SupercellSWF + from xcoder.swf import SupercellSWF class SWFTexture: diff --git a/system/lib/pixel_utils.py b/xcoder/pixel_utils.py similarity index 98% rename from system/lib/pixel_utils.py rename to xcoder/pixel_utils.py index 27d65ec..9199c0a 100644 --- a/system/lib/pixel_utils.py +++ b/xcoder/pixel_utils.py @@ -1,7 +1,7 @@ import struct from typing import Callable, TypeAlias -from system.bytestream import Reader +from xcoder.bytestream import Reader PixelChannels: TypeAlias = tuple[int, ...] EncodeFunction: TypeAlias = Callable[[PixelChannels], bytes] diff --git a/system/lib/pvr_tex_tool.py b/xcoder/pvr_tex_tool.py similarity index 87% rename from system/lib/pvr_tex_tool.py rename to xcoder/pvr_tex_tool.py index bde5aaf..f84feeb 100644 --- a/system/lib/pvr_tex_tool.py +++ b/xcoder/pvr_tex_tool.py @@ -4,10 +4,10 @@ from PIL import Image -from system import run -from system.exceptions import ToolNotFoundException +from xcoder import run +from xcoder.exceptions import ToolNotFoundException -_main_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) +_main_dir = Path(__file__).parent _color_space = "sRGB" _format = "ETC1,UBN,lRGB" _quality = "etcfast" @@ -15,7 +15,9 @@ # Note: a solution from # https://stackoverflow.com/questions/11210104/check-if-a-program-exists-from-a-python-script -def _get_executable_path(*paths: str) -> str | None: +def _get_executable_path( + *paths: os.PathLike[str] | str, +) -> os.PathLike[str] | str | None: from shutil import which for path in paths: @@ -28,7 +30,7 @@ def _get_executable_path(*paths: str) -> str | None: _cli_name = "PVRTexToolCLI" -_cli_path = _get_executable_path(f"{_main_dir}/system/bin/{_cli_name}", _cli_name) +_cli_path = _get_executable_path(_main_dir / f"bin/{_cli_name}", _cli_name) def can_use_pvr_tex_tool() -> bool: diff --git a/system/lib/swf.py b/xcoder/swf.py similarity index 96% rename from system/lib/swf.py rename to xcoder/swf.py index 2990262..cee103c 100644 --- a/system/lib/swf.py +++ b/xcoder/swf.py @@ -4,12 +4,12 @@ from loguru import logger from sc_compression import Signatures -from system.bytestream import Reader, Writer -from system.lib.features.files import open_sc -from system.lib.matrices.matrix_bank import MatrixBank -from system.lib.objects import MovieClip, Shape, SWFTexture -from system.lib.objects.plain_object import PlainObject -from system.localization import locale +from xcoder.bytestream import Reader, Writer +from xcoder.features.files import open_sc +from xcoder.localization import locale +from xcoder.matrices.matrix_bank import MatrixBank +from xcoder.objects import MovieClip, Shape, SWFTexture +from xcoder.objects.plain_object import PlainObject DEFAULT_HIGHRES_SUFFIX = "_highres" DEFAULT_LOWRES_SUFFIX = "_lowres" diff --git a/system/lib/xcod.py b/xcoder/xcod.py similarity index 95% rename from system/lib/xcod.py rename to xcoder/xcod.py index 1b27806..83c70c8 100644 --- a/system/lib/xcod.py +++ b/xcoder/xcod.py @@ -7,9 +7,9 @@ from loguru import logger from sc_compression import Signatures -from system.bytestream import Reader -from system.lib.math.point import Point -from system.localization import locale +from xcoder.bytestream import Reader +from xcoder.localization import locale +from xcoder.math.point import Point @dataclass