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.
Files changed (47) hide show
  1. pyupdator-0.1.0/PKG-INFO +165 -0
  2. pyupdator-0.1.0/README.md +138 -0
  3. pyupdator-0.1.0/examples/basic_usage.py +66 -0
  4. pyupdator-0.1.0/pyproject.toml +52 -0
  5. pyupdator-0.1.0/pyupdator/__init__.py +410 -0
  6. pyupdator-0.1.0/pyupdator/core/__init__.py +74 -0
  7. pyupdator-0.1.0/pyupdator/core/backend_manager.py +264 -0
  8. pyupdator-0.1.0/pyupdator/core/downloaders/__init__.py +26 -0
  9. pyupdator-0.1.0/pyupdator/core/downloaders/aria2_dl.py +281 -0
  10. pyupdator-0.1.0/pyupdator/core/downloaders/base.py +108 -0
  11. pyupdator-0.1.0/pyupdator/core/downloaders/http_dl.py +832 -0
  12. pyupdator-0.1.0/pyupdator/core/downloaders/http_zip_delta.py +2070 -0
  13. pyupdator-0.1.0/pyupdator/core/downloaders/libtorrent_dl.py +383 -0
  14. pyupdator-0.1.0/pyupdator/core/downloaders/manual_dl.py +141 -0
  15. pyupdator-0.1.0/pyupdator/core/downloaders/qbittorrent_dl.py +935 -0
  16. pyupdator-0.1.0/pyupdator/core/downloaders/transmission_dl.py +154 -0
  17. pyupdator-0.1.0/pyupdator/core/downloaders/utorrent_dl.py +245 -0
  18. pyupdator-0.1.0/pyupdator/core/torrent.py +1103 -0
  19. pyupdator-0.1.0/pyupdator/core/zip_engine.py +630 -0
  20. pyupdator-0.1.0/pyupdator/utils/__init__.py +38 -0
  21. pyupdator-0.1.0/pyupdator/utils/helpers.py +186 -0
  22. pyupdator-0.1.0/pyupdator.egg-info/PKG-INFO +165 -0
  23. pyupdator-0.1.0/pyupdator.egg-info/SOURCES.txt +45 -0
  24. pyupdator-0.1.0/pyupdator.egg-info/dependency_links.txt +1 -0
  25. pyupdator-0.1.0/pyupdator.egg-info/entry_points.txt +2 -0
  26. pyupdator-0.1.0/pyupdator.egg-info/requires.txt +8 -0
  27. pyupdator-0.1.0/pyupdator.egg-info/top_level.txt +4 -0
  28. pyupdator-0.1.0/pyupdator_gui/__init__.py +52 -0
  29. pyupdator-0.1.0/pyupdator_gui/main_window.py +1072 -0
  30. pyupdator-0.1.0/setup.cfg +4 -0
  31. pyupdator-0.1.0/tests/cdc_test_server.py +211 -0
  32. pyupdator-0.1.0/tests/test_cdc_delta.py +405 -0
  33. pyupdator-0.1.0/tests/test_comprehensive.py +240 -0
  34. pyupdator-0.1.0/tests/test_final_qbittorrent_fix.py +171 -0
  35. pyupdator-0.1.0/tests/test_html_manifest_fallback.py +474 -0
  36. pyupdator-0.1.0/tests/test_libtorrent_virtual.py +292 -0
  37. pyupdator-0.1.0/tests/test_qbittorrent.py +60 -0
  38. pyupdator-0.1.0/tests/test_qbittorrent_api.py +73 -0
  39. pyupdator-0.1.0/tests/test_qbittorrent_endpoints.py +63 -0
  40. pyupdator-0.1.0/tests/test_qbittorrent_fix.py +184 -0
  41. pyupdator-0.1.0/tests/test_qbittorrent_fix_fixed.py +184 -0
  42. pyupdator-0.1.0/tests/test_qbittorrent_info.py +39 -0
  43. pyupdator-0.1.0/tests/test_qbittorrent_new_logic.py +168 -0
  44. pyupdator-0.1.0/tests/test_qbittorrent_pause.py +48 -0
  45. pyupdator-0.1.0/tests/test_zip_block_delta.py +368 -0
  46. pyupdator-0.1.0/tests/test_zip_delta.py +329 -0
  47. pyupdator-0.1.0/tests/test_zip_root_detect.py +257 -0
@@ -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