downctl 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 (103) hide show
  1. downctl-0.1.0/.gitignore +44 -0
  2. downctl-0.1.0/CHANGELOG.md +130 -0
  3. downctl-0.1.0/LICENSE +21 -0
  4. downctl-0.1.0/PKG-INFO +702 -0
  5. downctl-0.1.0/README.en.md +106 -0
  6. downctl-0.1.0/README.md +635 -0
  7. downctl-0.1.0/docs/cli.md +154 -0
  8. downctl-0.1.0/docs/cli.zh.md +112 -0
  9. downctl-0.1.0/docs/design.md +157 -0
  10. downctl-0.1.0/docs/design.zh.md +262 -0
  11. downctl-0.1.0/docs/index.md +136 -0
  12. downctl-0.1.0/docs/index.zh.md +135 -0
  13. downctl-0.1.0/docs/plugins.md +133 -0
  14. downctl-0.1.0/docs/plugins.zh.md +125 -0
  15. downctl-0.1.0/examples/plugins/README.md +29 -0
  16. downctl-0.1.0/examples/plugins/example_source.py +35 -0
  17. downctl-0.1.0/pyproject.toml +163 -0
  18. downctl-0.1.0/src/downctl/__init__.py +13 -0
  19. downctl-0.1.0/src/downctl/__main__.py +8 -0
  20. downctl-0.1.0/src/downctl/app.py +732 -0
  21. downctl-0.1.0/src/downctl/builtin/__init__.py +48 -0
  22. downctl-0.1.0/src/downctl/builtin/hooks/__init__.py +10 -0
  23. downctl-0.1.0/src/downctl/builtin/hooks/archive_hook.py +144 -0
  24. downctl-0.1.0/src/downctl/builtin/hooks/logfile_hook.py +32 -0
  25. downctl-0.1.0/src/downctl/builtin/hooks/manifest_hook.py +76 -0
  26. downctl-0.1.0/src/downctl/builtin/hooks/webhook_hook.py +70 -0
  27. downctl-0.1.0/src/downctl/builtin/reporters/__init__.py +9 -0
  28. downctl-0.1.0/src/downctl/builtin/reporters/json_reporter.py +62 -0
  29. downctl-0.1.0/src/downctl/builtin/reporters/quiet_reporter.py +27 -0
  30. downctl-0.1.0/src/downctl/builtin/reporters/tqdm_reporter.py +91 -0
  31. downctl-0.1.0/src/downctl/builtin/routers/__init__.py +7 -0
  32. downctl-0.1.0/src/downctl/builtin/routers/mirror_router.py +27 -0
  33. downctl-0.1.0/src/downctl/builtin/sinks/__init__.py +7 -0
  34. downctl-0.1.0/src/downctl/builtin/sinks/filesystem_sink.py +36 -0
  35. downctl-0.1.0/src/downctl/builtin/sources/__init__.py +19 -0
  36. downctl-0.1.0/src/downctl/builtin/sources/_sigv4.py +107 -0
  37. downctl-0.1.0/src/downctl/builtin/sources/file_source.py +67 -0
  38. downctl-0.1.0/src/downctl/builtin/sources/github_source.py +120 -0
  39. downctl-0.1.0/src/downctl/builtin/sources/huggingface_source.py +140 -0
  40. downctl-0.1.0/src/downctl/builtin/sources/s3_source.py +226 -0
  41. downctl-0.1.0/src/downctl/builtin/sources/sftp_source.py +135 -0
  42. downctl-0.1.0/src/downctl/builtin/sources/url_source.py +47 -0
  43. downctl-0.1.0/src/downctl/builtin/transports/__init__.py +9 -0
  44. downctl-0.1.0/src/downctl/builtin/transports/_sftp.py +77 -0
  45. downctl-0.1.0/src/downctl/builtin/transports/file_transport.py +101 -0
  46. downctl-0.1.0/src/downctl/builtin/transports/http_transport.py +77 -0
  47. downctl-0.1.0/src/downctl/builtin/transports/sftp_transport.py +139 -0
  48. downctl-0.1.0/src/downctl/builtin/verifiers/__init__.py +7 -0
  49. downctl-0.1.0/src/downctl/builtin/verifiers/sha256_verifier.py +31 -0
  50. downctl-0.1.0/src/downctl/cli.py +213 -0
  51. downctl-0.1.0/src/downctl/config.py +153 -0
  52. downctl-0.1.0/src/downctl/console.py +87 -0
  53. downctl-0.1.0/src/downctl/core/__init__.py +30 -0
  54. downctl-0.1.0/src/downctl/core/context.py +48 -0
  55. downctl-0.1.0/src/downctl/core/engine.py +265 -0
  56. downctl-0.1.0/src/downctl/core/errors.py +56 -0
  57. downctl-0.1.0/src/downctl/core/locks.py +67 -0
  58. downctl-0.1.0/src/downctl/core/pieces.py +258 -0
  59. downctl-0.1.0/src/downctl/core/ratelimit.py +34 -0
  60. downctl-0.1.0/src/downctl/core/task.py +30 -0
  61. downctl-0.1.0/src/downctl/core/transfer.py +381 -0
  62. downctl-0.1.0/src/downctl/core/watchdog.py +53 -0
  63. downctl-0.1.0/src/downctl/platform_utils.py +166 -0
  64. downctl-0.1.0/src/downctl/plugin/__init__.py +42 -0
  65. downctl-0.1.0/src/downctl/plugin/hooks.py +65 -0
  66. downctl-0.1.0/src/downctl/plugin/loader.py +92 -0
  67. downctl-0.1.0/src/downctl/plugin/protocols.py +145 -0
  68. downctl-0.1.0/src/downctl/plugin/registry.py +75 -0
  69. downctl-0.1.0/src/downctl/probe.py +44 -0
  70. downctl-0.1.0/src/downctl/py.typed +0 -0
  71. downctl-0.1.0/src/downctl/session.py +50 -0
  72. downctl-0.1.0/tests/conftest.py +10 -0
  73. downctl-0.1.0/tests/integration/conftest.py +118 -0
  74. downctl-0.1.0/tests/integration/test_cli_get.py +152 -0
  75. downctl-0.1.0/tests/integration/test_engine.py +91 -0
  76. downctl-0.1.0/tests/integration/test_file_source.py +81 -0
  77. downctl-0.1.0/tests/integration/test_github_source.py +148 -0
  78. downctl-0.1.0/tests/integration/test_huggingface.py +144 -0
  79. downctl-0.1.0/tests/integration/test_s3_source.py +166 -0
  80. downctl-0.1.0/tests/integration/test_sftp_source.py +110 -0
  81. downctl-0.1.0/tests/integration/test_smoke.py +27 -0
  82. downctl-0.1.0/tests/integration/test_transfer.py +135 -0
  83. downctl-0.1.0/tests/integration/test_webhook_hook.py +81 -0
  84. downctl-0.1.0/tests/unit/test_archive_hook.py +80 -0
  85. downctl-0.1.0/tests/unit/test_builtins.py +47 -0
  86. downctl-0.1.0/tests/unit/test_clean.py +70 -0
  87. downctl-0.1.0/tests/unit/test_cli.py +70 -0
  88. downctl-0.1.0/tests/unit/test_config.py +38 -0
  89. downctl-0.1.0/tests/unit/test_console.py +69 -0
  90. downctl-0.1.0/tests/unit/test_failed_log.py +34 -0
  91. downctl-0.1.0/tests/unit/test_github_source_unit.py +29 -0
  92. downctl-0.1.0/tests/unit/test_hooks.py +38 -0
  93. downctl-0.1.0/tests/unit/test_huggingface_source.py +62 -0
  94. downctl-0.1.0/tests/unit/test_manifest_hook.py +46 -0
  95. downctl-0.1.0/tests/unit/test_pieces.py +108 -0
  96. downctl-0.1.0/tests/unit/test_platform_utils.py +64 -0
  97. downctl-0.1.0/tests/unit/test_plugins.py +60 -0
  98. downctl-0.1.0/tests/unit/test_review_fixes.py +149 -0
  99. downctl-0.1.0/tests/unit/test_session.py +22 -0
  100. downctl-0.1.0/tests/unit/test_sigv4.py +68 -0
  101. downctl-0.1.0/tests/unit/test_status.py +59 -0
  102. downctl-0.1.0/tests/unit/test_tqdm_reporter.py +42 -0
  103. downctl-0.1.0/tests/unit/test_watchdog.py +38 -0
@@ -0,0 +1,44 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ build/
8
+ dist/
9
+ site/
10
+ *.egg-info/
11
+ *.egg
12
+ .eggs/
13
+ wheels/
14
+
15
+ # Virtual environments
16
+ .venv/
17
+ venv/
18
+ env/
19
+
20
+ # Test / coverage
21
+ .pytest_cache/
22
+ .mypy_cache/
23
+ .ruff_cache/
24
+ .coverage
25
+ .coverage.*
26
+ htmlcov/
27
+ coverage.xml
28
+ .tox/
29
+ .nox/
30
+
31
+ # Editors / OS
32
+ .idea/
33
+ .vscode/
34
+ *.swp
35
+ .DS_Store
36
+ Thumbs.db
37
+
38
+ # downctl runtime artifacts
39
+ *.downctl-pieces
40
+ *.lock/
41
+ downctl.log
42
+
43
+ # Legacy single-file script (not part of this project)
44
+ hf-download.py
@@ -0,0 +1,130 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.0] - 2026-10-17
8
+
9
+ First release.
10
+
11
+ ### Added
12
+
13
+ - P1 skeleton: package layout, plugin contracts (7 categories), plugin
14
+ registry/loader/event bus, CLI surface, TOML configuration, packaging and
15
+ CI.
16
+ - P2 core engine:
17
+ - resumable piece bitmap (`core.pieces`) with authoritative out-of-order
18
+ resume, `fsync`-backed ledger, atomic save and hole-detection guards
19
+ - multi-connection transfer (`core.transfer`) with stall watchdog, single
20
+ stream fallback for unknown sizes and Range-less servers
21
+ - download orchestration (`core.engine`) with retries, disk pre-flight,
22
+ file locking, checksum verification and a concurrent task runner
23
+ - transport contract now exposes a streaming `Response`; the HTTP transport
24
+ maps aiohttp errors onto the downctl exception hierarchy so the core is
25
+ HTTP-library agnostic
26
+ - integration tests with a controllable local HTTP server (full download,
27
+ out-of-order resume, Range fallback, unknown size, stall-then-resume)
28
+ - P4/P5 usable CLI and built-in plugins:
29
+ - `downctl get` resolves targets through source plugins, probes sizes,
30
+ applies mirror rewrites and runs the engine with a chosen reporter
31
+ - `downctl probe`, `plugin list|info`, `config init|show|path`, `doctor`
32
+ and `wizard` are implemented
33
+ - options: `-d/-o/-j/-t/-r/-p`, `--checksum`, `--mirror`, `--source`,
34
+ `--reporter`, `--include/--exclude`, `--dry-run`, `--retry-failed`,
35
+ `-l/--list`, `--local-plugins`
36
+ - failed-target log (`.downctl.failed`) with `--retry-failed`
37
+ - session factory, TOML config wiring and `DOWNCTL_CONFIG` override
38
+ - integration tests drive the real CLI flow against a local server
39
+ - HuggingFace source plugin:
40
+ - expands `hf://org/name[@revision]` (and bare `org/name`) for models and
41
+ datasets via the Hub API
42
+ - honours `--include`/`--exclude`, `--revision` and the
43
+ `[plugins.huggingface]` mirror/token options; verifies LFS sha256
44
+ - integration tests against a fake Hub plus real-world verification
45
+ - Docs and repository tooling:
46
+ - `py.typed` marker (PEP 561) and inline types
47
+ - docs site config (`mkdocs.yml`) plus CLI and plugin guides
48
+ - issue/PR templates, Dependabot config and `RELEASING.md`
49
+ - GitHub Releases source plugin (`gh://owner/repo[@tag]`):
50
+ - lists release assets via the REST API, honours `--include`/`--exclude`
51
+ - uses asset `sha256` digests for verification; `[plugins.github]` api/token
52
+ - integration tests against a fake API plus end-to-end download
53
+ - configurable `connections` and `stall` (config and `--connections`/
54
+ `--stall`), threaded through the engine
55
+ - S3 source plugin (`s3://bucket/key` and prefixes):
56
+ - SigV4 query-string presigning (no extra dependency), so the HTTP
57
+ transport fetches S3 objects incl. ranged transfers
58
+ - prefix listing via ListObjectsV2 with pagination; `[plugins.s3]`
59
+ endpoint/region/credentials/path_style; object size via presigned HEAD
60
+ - tests against a fake S3 endpoint plus SigV4 unit tests
61
+ - resume and failure handling:
62
+ - failed log v2 stores the resolved URL, target path, checksum and size,
63
+ so `--retry-failed` restores repo subpaths and verification
64
+ - `--continue` skips targets that fail to resolve or probe instead of
65
+ aborting the whole run
66
+ - unified console output with `-q/--quiet` and `-v/--verbose`; quiet mode
67
+ also switches to the `quiet` reporter; tqdm progress bar polished
68
+ - `downctl status` scans a directory for in-progress (piece bitmap) and
69
+ failed downloads
70
+ - hook plugins can be enabled with `--hook NAME` or `[core] hooks = [...]`
71
+ - `--user-agent` for a custom HTTP User-Agent
72
+ - Dockerfile (multi-stage, wheel-based) and `.dockerignore`
73
+ - aggregate progress: the tqdm reporter shows an overall bar across files
74
+ - `archive` hook extracts zip/tar archives on completion (path-traversal and
75
+ link-safe); `keep`/`into` options
76
+ - `--checksums FILE` verifies downloads against a `sha256sum`-style file
77
+ - SFTP source and transport (`sftp://[user@]host[:port]/path`), optional
78
+ `asyncssh` dependency (`downctl[sftp]`); supports directory listing and
79
+ ranged (multi-connection) transfers
80
+ - `webhook` hook POSTs selected lifecycle events as JSON
81
+ - `manifest` hook writes a `sha256sum` manifest of completed downloads
82
+ - coverage gate (75%) in the test configuration and CI
83
+ - documentation: the primary `README.md` is now a detailed Chinese guide
84
+ (install, usage, sources, configuration, plugins, troubleshooting); the
85
+ English version lives at `README.en.md`
86
+ - global rate limiting: the `--limit-rate` budget is now shared across all
87
+ concurrent files (previously each file was limited independently)
88
+ - `-H/--header` (repeatable) and `-u/--user USER:PASS` for custom headers and
89
+ HTTP Basic auth
90
+ - `downctl clean [DIR]` removes leftover bitmaps, the failed log and stale
91
+ lock directories
92
+ - `file://` source and transport for local files/directories (recursive,
93
+ ranged); console warnings/errors are now colored on a TTY
94
+ - concurrent downloads (job > 1) show an overall progress bar with a
95
+ completed-files count; optional shell completion via `argcomplete`
96
+ (`downctl[completion]`)
97
+ - docs site published to GitHub Pages (Actions-based, keeping a single
98
+ master branch) with a generated coverage badge; CI gains a `pip-audit`
99
+ dependency-vulnerability job
100
+
101
+ ### Fixed
102
+
103
+ - webhook hook now flushes in-flight POSTs at shutdown (via an event-bus
104
+ `aclose`), so late events such as `on_task_finish`/`on_finish` are no
105
+ longer dropped
106
+ - the CLI reports network/library errors as clean messages instead of
107
+ dumping a traceback (use `-v` for the traceback)
108
+ - single-stream downloads no longer cancel the read generator to poll for
109
+ progress (which could look like a clean EOF and truncate the file); a
110
+ watchdog task aborts instead
111
+ - reject piece bitmaps whose length does not match the piece count
112
+ - confine source-provided relative targets to the destination directory
113
+ (mitigates `..`/percent-encoded path traversal from remote metadata)
114
+ - lock acquisition treats a missing pid file as held (avoids a takeover race)
115
+ - a file that cannot be opened for writing fails instead of retrying forever
116
+ - an unknown checksum algorithm now fails the file instead of silently passing
117
+ - checksum give-up discards the bad file so it is not trusted on the next run
118
+ - SFTP: guard connection creation with a lock, key the cache by credentials,
119
+ evict broken connections, and never leak inline credentials across hosts
120
+ - archive hook normalizes backslashes (Windows traversal) and extracts off the
121
+ event loop; `logfile`/SFTP key paths expand `~`; manifest uses POSIX
122
+ separators; GitHub tag is URL-quoted and private assets carry the token;
123
+ JSON reporter throttles progress; HTTP 408/425 are retried
124
+
125
+ ### Changed
126
+
127
+ - version is now dynamic, sourced from `src/downctl/__init__.py`
128
+ - the docs site is bilingual (English + 简体中文) via `mkdocs-static-i18n`
129
+
130
+ [0.1.0]: https://github.com/ThzxxArt/downctl/releases/tag/v0.1.0
downctl-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ThzxxArt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.