pyupdator 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyupdator-0.1.0/PKG-INFO +165 -0
- pyupdator-0.1.0/README.md +138 -0
- pyupdator-0.1.0/examples/basic_usage.py +66 -0
- pyupdator-0.1.0/pyproject.toml +52 -0
- pyupdator-0.1.0/pyupdator/__init__.py +410 -0
- pyupdator-0.1.0/pyupdator/core/__init__.py +74 -0
- pyupdator-0.1.0/pyupdator/core/backend_manager.py +264 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/__init__.py +26 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/aria2_dl.py +281 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/base.py +108 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/http_dl.py +832 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/http_zip_delta.py +2070 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/libtorrent_dl.py +383 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/manual_dl.py +141 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/qbittorrent_dl.py +935 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/transmission_dl.py +154 -0
- pyupdator-0.1.0/pyupdator/core/downloaders/utorrent_dl.py +245 -0
- pyupdator-0.1.0/pyupdator/core/torrent.py +1103 -0
- pyupdator-0.1.0/pyupdator/core/zip_engine.py +630 -0
- pyupdator-0.1.0/pyupdator/utils/__init__.py +38 -0
- pyupdator-0.1.0/pyupdator/utils/helpers.py +186 -0
- pyupdator-0.1.0/pyupdator.egg-info/PKG-INFO +165 -0
- pyupdator-0.1.0/pyupdator.egg-info/SOURCES.txt +45 -0
- pyupdator-0.1.0/pyupdator.egg-info/dependency_links.txt +1 -0
- pyupdator-0.1.0/pyupdator.egg-info/entry_points.txt +2 -0
- pyupdator-0.1.0/pyupdator.egg-info/requires.txt +8 -0
- pyupdator-0.1.0/pyupdator.egg-info/top_level.txt +4 -0
- pyupdator-0.1.0/pyupdator_gui/__init__.py +52 -0
- pyupdator-0.1.0/pyupdator_gui/main_window.py +1072 -0
- pyupdator-0.1.0/setup.cfg +4 -0
- pyupdator-0.1.0/tests/cdc_test_server.py +211 -0
- pyupdator-0.1.0/tests/test_cdc_delta.py +405 -0
- pyupdator-0.1.0/tests/test_comprehensive.py +240 -0
- pyupdator-0.1.0/tests/test_final_qbittorrent_fix.py +171 -0
- pyupdator-0.1.0/tests/test_html_manifest_fallback.py +474 -0
- pyupdator-0.1.0/tests/test_libtorrent_virtual.py +292 -0
- pyupdator-0.1.0/tests/test_qbittorrent.py +60 -0
- pyupdator-0.1.0/tests/test_qbittorrent_api.py +73 -0
- pyupdator-0.1.0/tests/test_qbittorrent_endpoints.py +63 -0
- pyupdator-0.1.0/tests/test_qbittorrent_fix.py +184 -0
- pyupdator-0.1.0/tests/test_qbittorrent_fix_fixed.py +184 -0
- pyupdator-0.1.0/tests/test_qbittorrent_info.py +39 -0
- pyupdator-0.1.0/tests/test_qbittorrent_new_logic.py +168 -0
- pyupdator-0.1.0/tests/test_qbittorrent_pause.py +48 -0
- pyupdator-0.1.0/tests/test_zip_block_delta.py +368 -0
- pyupdator-0.1.0/tests/test_zip_delta.py +329 -0
- pyupdator-0.1.0/tests/test_zip_root_detect.py +257 -0
pyupdator-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyupdator
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Delta updater for games (Torrent and HTTP Zip support)
|
|
5
|
+
Author: pyupdator
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: delta,updater,game,torrent,http,zip,cdc
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Topic :: System :: Software Distribution
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Provides-Extra: gui
|
|
22
|
+
Requires-Dist: customtkinter>=5.2.0; extra == "gui"
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
25
|
+
Requires-Dist: build; extra == "dev"
|
|
26
|
+
Requires-Dist: twine; extra == "dev"
|
|
27
|
+
|
|
28
|
+
# pyupdator
|
|
29
|
+
|
|
30
|
+
**Delta updater for games (Torrent and HTTP Zip support).**
|
|
31
|
+
|
|
32
|
+
`pyupdator` is an independent, pip-installable Python library that lets a game
|
|
33
|
+
launcher (or any host application) update installed game files without
|
|
34
|
+
downloading the entire new release. It supports:
|
|
35
|
+
|
|
36
|
+
- **BitTorrent piece-level delta** (via `libtorrent`, optional) — download only
|
|
37
|
+
the missing SHA-1 pieces of a `.torrent`.
|
|
38
|
+
- **HTTP ZIP delta** — read a remote ZIP's Central Directory over HTTP Range
|
|
39
|
+
requests and download only the changed files.
|
|
40
|
+
- **Content-Defined Chunking (CDC)** via Gear/FastCDC hashing — download only
|
|
41
|
+
the changed byte ranges of a single HTTP-hosted file.
|
|
42
|
+
|
|
43
|
+
The library core (`pyupdator/`) contains **no** `tkinter`, `customtkinter`, or
|
|
44
|
+
GUI code. A separate optional package (`pyupdator_gui/`) provides a
|
|
45
|
+
Tkinter/customtkinter launcher window and is installed with
|
|
46
|
+
`pip install pyupdator[gui]`.
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Library core only (no GUI)
|
|
52
|
+
pip install pyupdator
|
|
53
|
+
|
|
54
|
+
# Library + optional GUI
|
|
55
|
+
pip install pyupdator[gui]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Quick start
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from pyupdator import Updater
|
|
62
|
+
|
|
63
|
+
updater = Updater(install_dir="C:/Oyun", source="oyun.torrent")
|
|
64
|
+
plan = updater.analyze()
|
|
65
|
+
print("Plan:", plan)
|
|
66
|
+
|
|
67
|
+
updater.update(progress_callback=my_progress_func)
|
|
68
|
+
|
|
69
|
+
# Optional verification
|
|
70
|
+
result = updater.verify()
|
|
71
|
+
print("Verified:", result)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
See `examples/basic_usage.py` for a complete GUI-free example.
|
|
75
|
+
|
|
76
|
+
## Project layout
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
pyupdator/ # library core (no GUI imports)
|
|
80
|
+
__init__.py # public API: Updater, UpdaterError, logging helpers
|
|
81
|
+
core/
|
|
82
|
+
__init__.py
|
|
83
|
+
torrent.py # .torrent parse, recheck, delta plan, apply, verify
|
|
84
|
+
zip_engine.py # HTTP ZIP delta + CDC chunker
|
|
85
|
+
backend_manager.py# download backend detection & selection
|
|
86
|
+
utils/
|
|
87
|
+
__init__.py
|
|
88
|
+
helpers.py # UpdaterError, hashing, safe_join, config, ...
|
|
89
|
+
pyupdator_gui/ # optional Tkinter/customtkinter GUI
|
|
90
|
+
__init__.py
|
|
91
|
+
main_window.py # MainWindow ported from gui.py
|
|
92
|
+
examples/
|
|
93
|
+
basic_usage.py # GUI-free usage example
|
|
94
|
+
tests/ # existing test suite moved here
|
|
95
|
+
pyproject.toml
|
|
96
|
+
README.md
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Updater API contract
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from pyupdator import Updater
|
|
103
|
+
|
|
104
|
+
updater = Updater(install_dir="C:/Oyun", source="oyun.torrent")
|
|
105
|
+
plan = updater.analyze() # returns a plan dict
|
|
106
|
+
updater.update(progress_callback=my_func) # applies the update
|
|
107
|
+
updater.verify() # verifies installed files against source
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Logging
|
|
111
|
+
|
|
112
|
+
`pyupdator` uses the standard `logging` module (logger name `"pyupdator"`).
|
|
113
|
+
The host launcher can forward logs to its own console or GUI:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import logging
|
|
117
|
+
from pyupdator import add_log_handler, set_log_level
|
|
118
|
+
|
|
119
|
+
handler = logging.StreamHandler()
|
|
120
|
+
add_log_handler(handler)
|
|
121
|
+
set_log_level(logging.DEBUG)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Backends
|
|
125
|
+
|
|
126
|
+
| Backend | Capability | Notes |
|
|
127
|
+
|--------------|----------------|------------------------------------|
|
|
128
|
+
| libtorrent | PIECE_LEVEL | Optional; true piece-level delta |
|
|
129
|
+
| aria2 | FILE_LEVEL | aria2c JSON-RPC |
|
|
130
|
+
| qBittorrent | FILE_LEVEL | Web API v2 |
|
|
131
|
+
| uTorrent | FILE_LEVEL | Web UI, best effort |
|
|
132
|
+
| Transmission | FILE_LEVEL | RPC |
|
|
133
|
+
| manual | FILE_LEVEL | Manual/local source |
|
|
134
|
+
| http_zip | CHUNK_LEVEL | HTTP ZIP delta / CDC |
|
|
135
|
+
|
|
136
|
+
`libtorrent` is often unavailable on Windows + Python 3.13; the library falls
|
|
137
|
+
back to FILE_LEVEL backends and reports this clearly.
|
|
138
|
+
|
|
139
|
+
## Tests
|
|
140
|
+
|
|
141
|
+
Run the test suite:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
python -m pytest tests/
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Individual test scripts can also be run directly:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
python tests/test_cdc_delta.py
|
|
151
|
+
python tests/test_zip_delta.py
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## PyPI publishing
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
pip install build twine
|
|
158
|
+
python -m build
|
|
159
|
+
twine upload dist/*
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
If a PyPI token is required, set `TWINE_USERNAME` and `TWINE_PASSWORD` (or use
|
|
163
|
+
`~/.pypirc`). If `twine upload` returns `400 Bad Request` because the name
|
|
164
|
+
`pyupdator` collides with an existing package (e.g. `pyupdater`), rename the
|
|
165
|
+
project in `pyproject.toml` and republish.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# pyupdator
|
|
2
|
+
|
|
3
|
+
**Delta updater for games (Torrent and HTTP Zip support).**
|
|
4
|
+
|
|
5
|
+
`pyupdator` is an independent, pip-installable Python library that lets a game
|
|
6
|
+
launcher (or any host application) update installed game files without
|
|
7
|
+
downloading the entire new release. It supports:
|
|
8
|
+
|
|
9
|
+
- **BitTorrent piece-level delta** (via `libtorrent`, optional) — download only
|
|
10
|
+
the missing SHA-1 pieces of a `.torrent`.
|
|
11
|
+
- **HTTP ZIP delta** — read a remote ZIP's Central Directory over HTTP Range
|
|
12
|
+
requests and download only the changed files.
|
|
13
|
+
- **Content-Defined Chunking (CDC)** via Gear/FastCDC hashing — download only
|
|
14
|
+
the changed byte ranges of a single HTTP-hosted file.
|
|
15
|
+
|
|
16
|
+
The library core (`pyupdator/`) contains **no** `tkinter`, `customtkinter`, or
|
|
17
|
+
GUI code. A separate optional package (`pyupdator_gui/`) provides a
|
|
18
|
+
Tkinter/customtkinter launcher window and is installed with
|
|
19
|
+
`pip install pyupdator[gui]`.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Library core only (no GUI)
|
|
25
|
+
pip install pyupdator
|
|
26
|
+
|
|
27
|
+
# Library + optional GUI
|
|
28
|
+
pip install pyupdator[gui]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from pyupdator import Updater
|
|
35
|
+
|
|
36
|
+
updater = Updater(install_dir="C:/Oyun", source="oyun.torrent")
|
|
37
|
+
plan = updater.analyze()
|
|
38
|
+
print("Plan:", plan)
|
|
39
|
+
|
|
40
|
+
updater.update(progress_callback=my_progress_func)
|
|
41
|
+
|
|
42
|
+
# Optional verification
|
|
43
|
+
result = updater.verify()
|
|
44
|
+
print("Verified:", result)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
See `examples/basic_usage.py` for a complete GUI-free example.
|
|
48
|
+
|
|
49
|
+
## Project layout
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
pyupdator/ # library core (no GUI imports)
|
|
53
|
+
__init__.py # public API: Updater, UpdaterError, logging helpers
|
|
54
|
+
core/
|
|
55
|
+
__init__.py
|
|
56
|
+
torrent.py # .torrent parse, recheck, delta plan, apply, verify
|
|
57
|
+
zip_engine.py # HTTP ZIP delta + CDC chunker
|
|
58
|
+
backend_manager.py# download backend detection & selection
|
|
59
|
+
utils/
|
|
60
|
+
__init__.py
|
|
61
|
+
helpers.py # UpdaterError, hashing, safe_join, config, ...
|
|
62
|
+
pyupdator_gui/ # optional Tkinter/customtkinter GUI
|
|
63
|
+
__init__.py
|
|
64
|
+
main_window.py # MainWindow ported from gui.py
|
|
65
|
+
examples/
|
|
66
|
+
basic_usage.py # GUI-free usage example
|
|
67
|
+
tests/ # existing test suite moved here
|
|
68
|
+
pyproject.toml
|
|
69
|
+
README.md
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Updater API contract
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from pyupdator import Updater
|
|
76
|
+
|
|
77
|
+
updater = Updater(install_dir="C:/Oyun", source="oyun.torrent")
|
|
78
|
+
plan = updater.analyze() # returns a plan dict
|
|
79
|
+
updater.update(progress_callback=my_func) # applies the update
|
|
80
|
+
updater.verify() # verifies installed files against source
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Logging
|
|
84
|
+
|
|
85
|
+
`pyupdator` uses the standard `logging` module (logger name `"pyupdator"`).
|
|
86
|
+
The host launcher can forward logs to its own console or GUI:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
import logging
|
|
90
|
+
from pyupdator import add_log_handler, set_log_level
|
|
91
|
+
|
|
92
|
+
handler = logging.StreamHandler()
|
|
93
|
+
add_log_handler(handler)
|
|
94
|
+
set_log_level(logging.DEBUG)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Backends
|
|
98
|
+
|
|
99
|
+
| Backend | Capability | Notes |
|
|
100
|
+
|--------------|----------------|------------------------------------|
|
|
101
|
+
| libtorrent | PIECE_LEVEL | Optional; true piece-level delta |
|
|
102
|
+
| aria2 | FILE_LEVEL | aria2c JSON-RPC |
|
|
103
|
+
| qBittorrent | FILE_LEVEL | Web API v2 |
|
|
104
|
+
| uTorrent | FILE_LEVEL | Web UI, best effort |
|
|
105
|
+
| Transmission | FILE_LEVEL | RPC |
|
|
106
|
+
| manual | FILE_LEVEL | Manual/local source |
|
|
107
|
+
| http_zip | CHUNK_LEVEL | HTTP ZIP delta / CDC |
|
|
108
|
+
|
|
109
|
+
`libtorrent` is often unavailable on Windows + Python 3.13; the library falls
|
|
110
|
+
back to FILE_LEVEL backends and reports this clearly.
|
|
111
|
+
|
|
112
|
+
## Tests
|
|
113
|
+
|
|
114
|
+
Run the test suite:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
python -m pytest tests/
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Individual test scripts can also be run directly:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
python tests/test_cdc_delta.py
|
|
124
|
+
python tests/test_zip_delta.py
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## PyPI publishing
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
pip install build twine
|
|
131
|
+
python -m build
|
|
132
|
+
twine upload dist/*
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
If a PyPI token is required, set `TWINE_USERNAME` and `TWINE_PASSWORD` (or use
|
|
136
|
+
`~/.pypirc`). If `twine upload` returns `400 Bad Request` because the name
|
|
137
|
+
`pyupdator` collides with an existing package (e.g. `pyupdater`), rename the
|
|
138
|
+
project in `pyproject.toml` and republish.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
examples/basic_usage.py — GUI-free example showing how to use pyupdator.
|
|
3
|
+
|
|
4
|
+
This is the canonical example for a game launcher or other host project.
|
|
5
|
+
|
|
6
|
+
pip install pyupdator
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python examples/basic_usage.py
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
# Ensure the local pyupdator package is importable when running from the repo.
|
|
19
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
20
|
+
|
|
21
|
+
from pyupdator import Updater, UpdaterError, human_bytes
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def progress_callback(done: int, total: int, message: str = "") -> None:
|
|
25
|
+
"""Host-provided progress callback."""
|
|
26
|
+
if total:
|
|
27
|
+
pct = done / total * 100
|
|
28
|
+
print(f"[{pct:6.2f}%] {message} ({human_bytes(done)} / {human_bytes(total)})")
|
|
29
|
+
else:
|
|
30
|
+
print(f"{message} ({human_bytes(done)})")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main() -> int:
|
|
34
|
+
logging.basicConfig(
|
|
35
|
+
level=logging.INFO,
|
|
36
|
+
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# The host launcher decides install_dir and source.
|
|
40
|
+
install_dir = Path("C:/Oyun") # <-- change to your game folder
|
|
41
|
+
source = "oyun.torrent" # <-- change to your .torrent or HTTP URL
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
updater = Updater(install_dir=str(install_dir), source=source)
|
|
45
|
+
|
|
46
|
+
# 1) Analyze what needs to be downloaded / verified.
|
|
47
|
+
plan = updater.analyze()
|
|
48
|
+
print("Analiz tamamlandı. Plan:", plan)
|
|
49
|
+
|
|
50
|
+
# 2) Apply the update, reporting progress back to the host.
|
|
51
|
+
updater.update(progress_callback=progress_callback)
|
|
52
|
+
print("Güncelleme tamamlandı.")
|
|
53
|
+
|
|
54
|
+
# 3) (Optional) verify the installed files against the torrent.
|
|
55
|
+
result = updater.verify()
|
|
56
|
+
print("Doğrulama sonucu:", result)
|
|
57
|
+
|
|
58
|
+
except UpdaterError as exc:
|
|
59
|
+
print(f"Hata: {exc}", file=sys.stderr)
|
|
60
|
+
return 1
|
|
61
|
+
|
|
62
|
+
return 0
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pyupdator"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Delta updater for games (Torrent and HTTP Zip support)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [{name = "pyupdator"}]
|
|
13
|
+
keywords = ["delta", "updater", "game", "torrent", "http", "zip", "cdc"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Topic :: System :: Software Distribution",
|
|
25
|
+
"Topic :: Utilities",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
# Optional dependencies — GUI requires customtkinter.
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
gui = ["customtkinter>=5.2.0"]
|
|
31
|
+
dev = [
|
|
32
|
+
"pytest>=7.0",
|
|
33
|
+
"build",
|
|
34
|
+
"twine",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
pyupdator-gui = "pyupdator_gui.__init__:run"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages.find]
|
|
41
|
+
include = ["pyupdator*", "pyupdator_gui*", "examples*", "tests*"]
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.package-data]
|
|
44
|
+
pyupdator = ["*.json", "*.cfg"]
|
|
45
|
+
pyupdator_gui = ["*.json"]
|
|
46
|
+
|
|
47
|
+
[tool.black]
|
|
48
|
+
line-length = 100
|
|
49
|
+
target-version = ["py310"]
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
line-length = 100
|