polytool 0.2.9__tar.gz → 0.2.11__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.
- polytool-0.2.11/PKG-INFO +295 -0
- polytool-0.2.11/README.md +196 -0
- {polytool-0.2.9 → polytool-0.2.11}/docs/README.md +1 -1
- {polytool-0.2.9 → polytool-0.2.11}/pyproject.toml +3 -3
- polytool-0.2.11/src/polytool/__init__.py +4 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/__init__.py +6 -3
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/dl.py +4 -16
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/gen.py +3 -2
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/img.py +8 -9
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/pdf.py +12 -2
- polytool-0.2.9/PKG-INFO +0 -260
- polytool-0.2.9/README.md +0 -159
- polytool-0.2.9/src/polytool/__init__.py +0 -4
- {polytool-0.2.9 → polytool-0.2.11}/.gitignore +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/LICENSE +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/__main__.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/clip.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/color.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/convert.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/cron.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/data.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/enc.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/file.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/net.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/qr.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/shot.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/text.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/cli/vid.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/__init__.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/browsers.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/config.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/console.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/errors.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/ffmpeg.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/io.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/lazy.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/progress.py +0 -0
- {polytool-0.2.9 → polytool-0.2.11}/src/polytool/core/runtime.py +0 -0
polytool-0.2.11/PKG-INFO
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: polytool
|
|
3
|
+
Version: 0.2.11
|
|
4
|
+
Summary: One CLI with 60+ everyday commands — image/video/PDF conversion, background removal, OCR, QR codes, hashing, downloads, and more
|
|
5
|
+
Project-URL: Homepage, https://github.com/k6w/polytool
|
|
6
|
+
Project-URL: Repository, https://github.com/k6w/polytool
|
|
7
|
+
Project-URL: Issues, https://github.com/k6w/polytool/issues
|
|
8
|
+
Author: polytool contributors
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: background-removal,cli,convert,ffmpeg,image,ocr,pdf,qr,swiss-army-knife,utility,video,yt-dlp
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.13
|
|
23
|
+
Requires-Dist: cron-descriptor>=1.4
|
|
24
|
+
Requires-Dist: croniter>=2
|
|
25
|
+
Requires-Dist: faker>=25
|
|
26
|
+
Requires-Dist: httpx>=0.27
|
|
27
|
+
Requires-Dist: markdown-it-py>=3
|
|
28
|
+
Requires-Dist: pint>=0.24
|
|
29
|
+
Requires-Dist: pyjwt>=2.8
|
|
30
|
+
Requires-Dist: pyperclip>=1.8
|
|
31
|
+
Requires-Dist: python-dateutil>=2.9
|
|
32
|
+
Requires-Dist: python-slugify>=8
|
|
33
|
+
Requires-Dist: rich>=13
|
|
34
|
+
Requires-Dist: ruamel-yaml>=0.18
|
|
35
|
+
Requires-Dist: segno>=1.6
|
|
36
|
+
Requires-Dist: tomli-w>=1.0
|
|
37
|
+
Requires-Dist: typer>=0.12
|
|
38
|
+
Requires-Dist: xmltodict>=0.13
|
|
39
|
+
Requires-Dist: xxhash>=3.4
|
|
40
|
+
Provides-Extra: ai
|
|
41
|
+
Requires-Dist: rembg[cpu]>=2.0; extra == 'ai'
|
|
42
|
+
Provides-Extra: archive
|
|
43
|
+
Requires-Dist: py7zr>=0.21; extra == 'archive'
|
|
44
|
+
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: basedpyright>=1.13; extra == 'dev'
|
|
46
|
+
Requires-Dist: pre-commit>=3.7; extra == 'dev'
|
|
47
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
48
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
49
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
50
|
+
Provides-Extra: dl
|
|
51
|
+
Requires-Dist: yt-dlp[default]>=2026.8.19; extra == 'dl'
|
|
52
|
+
Provides-Extra: full
|
|
53
|
+
Requires-Dist: ascii-magic>=2; extra == 'full'
|
|
54
|
+
Requires-Dist: colorthief>=0.2; extra == 'full'
|
|
55
|
+
Requires-Dist: easyocr>=1.7; extra == 'full'
|
|
56
|
+
Requires-Dist: ffmpeg-python>=0.2; extra == 'full'
|
|
57
|
+
Requires-Dist: imageio-ffmpeg>=0.5; extra == 'full'
|
|
58
|
+
Requires-Dist: mss>=9; extra == 'full'
|
|
59
|
+
Requires-Dist: pdfplumber>=0.11; extra == 'full'
|
|
60
|
+
Requires-Dist: piexif>=1.1; extra == 'full'
|
|
61
|
+
Requires-Dist: pikepdf>=8; extra == 'full'
|
|
62
|
+
Requires-Dist: pillow-avif-plugin>=1.4; extra == 'full'
|
|
63
|
+
Requires-Dist: pillow-heif>=0.18; extra == 'full'
|
|
64
|
+
Requires-Dist: pillow>=10; extra == 'full'
|
|
65
|
+
Requires-Dist: playwright>=1.44; extra == 'full'
|
|
66
|
+
Requires-Dist: py7zr>=0.21; extra == 'full'
|
|
67
|
+
Requires-Dist: pymupdf>=1.24; extra == 'full'
|
|
68
|
+
Requires-Dist: pypdf>=4; extra == 'full'
|
|
69
|
+
Requires-Dist: pytesseract>=0.3; extra == 'full'
|
|
70
|
+
Requires-Dist: pyzbar>=0.1; extra == 'full'
|
|
71
|
+
Requires-Dist: rembg[cpu]>=2.0; extra == 'full'
|
|
72
|
+
Requires-Dist: resvg-py>=0.1; extra == 'full'
|
|
73
|
+
Requires-Dist: yt-dlp[default]>=2026.8.19; extra == 'full'
|
|
74
|
+
Provides-Extra: img
|
|
75
|
+
Requires-Dist: ascii-magic>=2; extra == 'img'
|
|
76
|
+
Requires-Dist: colorthief>=0.2; extra == 'img'
|
|
77
|
+
Requires-Dist: piexif>=1.1; extra == 'img'
|
|
78
|
+
Requires-Dist: pillow-avif-plugin>=1.4; extra == 'img'
|
|
79
|
+
Requires-Dist: pillow-heif>=0.18; extra == 'img'
|
|
80
|
+
Requires-Dist: pillow>=10; extra == 'img'
|
|
81
|
+
Requires-Dist: resvg-py>=0.1; extra == 'img'
|
|
82
|
+
Provides-Extra: ocr
|
|
83
|
+
Requires-Dist: easyocr>=1.7; extra == 'ocr'
|
|
84
|
+
Requires-Dist: pytesseract>=0.3; extra == 'ocr'
|
|
85
|
+
Provides-Extra: pdf
|
|
86
|
+
Requires-Dist: pdfplumber>=0.11; extra == 'pdf'
|
|
87
|
+
Requires-Dist: pikepdf>=8; extra == 'pdf'
|
|
88
|
+
Requires-Dist: pymupdf>=1.24; extra == 'pdf'
|
|
89
|
+
Requires-Dist: pypdf>=4; extra == 'pdf'
|
|
90
|
+
Provides-Extra: qr-decode
|
|
91
|
+
Requires-Dist: pyzbar>=0.1; extra == 'qr-decode'
|
|
92
|
+
Provides-Extra: shot
|
|
93
|
+
Requires-Dist: mss>=9; extra == 'shot'
|
|
94
|
+
Requires-Dist: playwright>=1.44; extra == 'shot'
|
|
95
|
+
Provides-Extra: vid
|
|
96
|
+
Requires-Dist: ffmpeg-python>=0.2; extra == 'vid'
|
|
97
|
+
Requires-Dist: imageio-ffmpeg>=0.5; extra == 'vid'
|
|
98
|
+
Description-Content-Type: text/markdown
|
|
99
|
+
|
|
100
|
+
# polytool
|
|
101
|
+
|
|
102
|
+
**The command line toolbox for everything that is not worth installing another app for.**
|
|
103
|
+
|
|
104
|
+
`polytool` puts 60+ practical commands behind one memorable interface: `pt`. Convert
|
|
105
|
+
images, trim video, clean PDFs, remove backgrounds, run OCR, generate QR codes,
|
|
106
|
+
download media, transform data, hash files, inspect networks, and automate the
|
|
107
|
+
small tasks that normally turn into a tab-hunting expedition.
|
|
108
|
+
|
|
109
|
+
[](https://github.com/k6w/polytool/actions/workflows/ci.yml)
|
|
110
|
+
[](https://pypi.org/project/polytool/)
|
|
111
|
+
[](LICENSE)
|
|
112
|
+
|
|
113
|
+
## See the real thing
|
|
114
|
+
|
|
115
|
+
These are direct captures from the installed CLI and its generated artifacts—not
|
|
116
|
+
mockups or a web demo.
|
|
117
|
+
|
|
118
|
+

|
|
119
|
+
|
|
120
|
+
One Terminal window can handle text, color, units, data, security, generators,
|
|
121
|
+
images, QR, OCR, audio, and PDF work:
|
|
122
|
+
|
|
123
|
+

|
|
124
|
+
|
|
125
|
+
Real AI background removal, with the original and transparent result shown in Preview:
|
|
126
|
+
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+
Live YouTube metadata and download through the `pt` wrapper:
|
|
130
|
+
|
|
131
|
+

|
|
132
|
+
|
|
133
|
+
## Why people reach for `pt`
|
|
134
|
+
|
|
135
|
+
- **One install, a broad surface.** Stop collecting tiny single-purpose utilities.
|
|
136
|
+
- **Discoverable by design.** Every command has focused help and runnable examples.
|
|
137
|
+
- **Pipelines-first.** Text commands use stdout; file commands choose sensible output names.
|
|
138
|
+
- **Fast startup.** Heavy dependencies load only when the relevant command runs.
|
|
139
|
+
- **Helpful failure modes.** Missing optional tools produce an actionable install hint.
|
|
140
|
+
- **Local by default.** Media, documents, data, hashes, and OCR stay on your machine unless a command explicitly accesses a network service.
|
|
141
|
+
- **Flexible footprint.** Install the lightweight core or opt into only the extras you need.
|
|
142
|
+
|
|
143
|
+
## Install in seconds
|
|
144
|
+
|
|
145
|
+
`uv` is the recommended installer because it manages Python and keeps the command isolated:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# macOS / Linux
|
|
149
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
150
|
+
uv tool install polytool
|
|
151
|
+
|
|
152
|
+
# Windows PowerShell
|
|
153
|
+
irm https://astral.sh/uv/install.ps1 | iex
|
|
154
|
+
uv tool install polytool
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
That gives you the fast core: data, encoding, generators, color, units, text,
|
|
158
|
+
QR generation, cron, networking, clipboard, and file operations.
|
|
159
|
+
|
|
160
|
+
For the complete toolbox:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
uv tool install 'polytool[full]'
|
|
164
|
+
pt setup -y # install Deno and Chromium for external integrations
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Both `polytool` and the shorter `pt` command are installed. PowerShell users
|
|
168
|
+
should keep the quotes around extras because brackets are shell glob characters.
|
|
169
|
+
|
|
170
|
+
## A five-minute tour
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Make a shareable QR code
|
|
174
|
+
pt qr gen "https://github.com/k6w/polytool" -o qr.png
|
|
175
|
+
|
|
176
|
+
# Prepare an image for the web
|
|
177
|
+
pt img convert photo.heic -o photo.jpg
|
|
178
|
+
pt img resize photo.jpg --width 1600
|
|
179
|
+
pt img compress photo.jpg --quality 75
|
|
180
|
+
|
|
181
|
+
# Turn media into something useful
|
|
182
|
+
pt vid gif clip.mp4 --width 480
|
|
183
|
+
pt vid extract-audio recording.mp4 -o recording.mp3
|
|
184
|
+
|
|
185
|
+
# Clean up documents
|
|
186
|
+
pt pdf merge cover.pdf report.pdf -o release.pdf
|
|
187
|
+
pt pdf to-images release.pdf --dpi 200
|
|
188
|
+
|
|
189
|
+
# Download public media and inspect it first
|
|
190
|
+
pt dl info 'https://www.youtube.com/watch?v=...'
|
|
191
|
+
pt dl get 'https://www.youtube.com/watch?v=...'
|
|
192
|
+
|
|
193
|
+
# Make data and developer chores boring
|
|
194
|
+
pt data convert config.yaml --to json
|
|
195
|
+
pt enc hash sha256 release.zip
|
|
196
|
+
pt enc base64 encode README.md
|
|
197
|
+
pt gen password --length 32
|
|
198
|
+
pt gen uuid v7
|
|
199
|
+
pt color convert '#3366ff'
|
|
200
|
+
pt convert unit '100 km' --to mi
|
|
201
|
+
pt text slugify 'Hello, World!'
|
|
202
|
+
pt cron explain '0 9 * * MON-FRI'
|
|
203
|
+
pt file dedupe ./Downloads
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Run `pt --help`, then `pt <group> --help`. You can also pipe text into commands
|
|
207
|
+
that accept stdin and compose them with standard Unix tools.
|
|
208
|
+
|
|
209
|
+
## Everything inside
|
|
210
|
+
|
|
211
|
+
| Group | What it unlocks |
|
|
212
|
+
|---|---|
|
|
213
|
+
| `pt img` | Convert, resize, compress, watermark, palette, EXIF, ASCII, background removal, OCR |
|
|
214
|
+
| `pt vid` | Convert, trim, extract audio, animated GIF |
|
|
215
|
+
| `pt pdf` | Merge, split, compress, extract text, render, build from images, OCR |
|
|
216
|
+
| `pt dl` | YouTube and 1000+ site downloads, metadata, audio-only mode, browser cookies |
|
|
217
|
+
| `pt data` | JSON, YAML, TOML, CSV, XML conversion, pretty-printing, validation |
|
|
218
|
+
| `pt enc` | SHA/Blake2/xxhash, Base64, URL/HTML escaping, JWT decode and verify |
|
|
219
|
+
| `pt qr` | PNG, SVG, PDF, EPS, terminal, Wi-Fi QR generation, decode |
|
|
220
|
+
| `pt gen` | Passwords, UUID v1/v3/v4/v5/v7, lorem ipsum |
|
|
221
|
+
| `pt file` | Batch rename, duplicate detection, largest files, organizing, archives |
|
|
222
|
+
| `pt net` | Port checks, IP information, HTTP requests |
|
|
223
|
+
| `pt text` | Diff, word counts, case conversion, slugify, Markdown HTML/preview |
|
|
224
|
+
| `pt convert` | Units, timestamps, number bases |
|
|
225
|
+
| `pt color` | Hex, RGB, HSL, HSV, CMYK conversion |
|
|
226
|
+
| `pt cron` | Human explanations and next firing times |
|
|
227
|
+
| `pt clip` / `pt shot` | Clipboard operations and screen/web screenshots |
|
|
228
|
+
|
|
229
|
+
## Install only what you need
|
|
230
|
+
|
|
231
|
+
The base package stays intentionally small. Add capabilities à la carte:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
uv tool install 'polytool[img]' # Pillow, HEIC/AVIF/SVG, palette, ASCII
|
|
235
|
+
uv tool install 'polytool[vid]' # ffmpeg-backed media conversion
|
|
236
|
+
uv tool install 'polytool[pdf]' # PDF manipulation and rendering
|
|
237
|
+
uv tool install 'polytool[dl]' # yt-dlp and matched EJS scripts
|
|
238
|
+
uv tool install 'polytool[shot]' # mss and Playwright
|
|
239
|
+
uv tool install 'polytool[ai]' # rembg background removal
|
|
240
|
+
uv tool install 'polytool[ocr]' # Tesseract wrapper and EasyOCR
|
|
241
|
+
uv tool install 'polytool[qr-decode]' # QR decoding (also needs native zbar)
|
|
242
|
+
uv tool install 'polytool[archive]' # 7z support
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
`[full]` combines every extra. The first use of some commands also downloads
|
|
246
|
+
runtime assets: Deno for YouTube challenge solving, Chromium for web captures,
|
|
247
|
+
the U2-Net model for background removal, or language/model data for OCR.
|
|
248
|
+
|
|
249
|
+
Platform notes:
|
|
250
|
+
|
|
251
|
+
- macOS QR decoding: `brew install zbar`
|
|
252
|
+
- Debian/Ubuntu QR decoding: `sudo apt install libzbar0`
|
|
253
|
+
- macOS OCR: `brew install tesseract`
|
|
254
|
+
- Windows OCR: install Tesseract from UB Mannheim
|
|
255
|
+
- Video commands use a system `ffmpeg` when available and otherwise fall back to the bundled binary
|
|
256
|
+
|
|
257
|
+
If an optional dependency is missing, `pt` explains the exact extra to install.
|
|
258
|
+
|
|
259
|
+
## Trust the plumbing
|
|
260
|
+
|
|
261
|
+
The project is tested as a CLI, not only as a collection of importable functions:
|
|
262
|
+
|
|
263
|
+
- 143 automated tests covering happy paths, invalid input, integrations, and file outputs
|
|
264
|
+
- Ruff lint and formatting checks
|
|
265
|
+
- basedpyright static analysis
|
|
266
|
+
- Cross-platform CI configuration for macOS, Linux, and Windows
|
|
267
|
+
- Lazy imports so `pt --help` remains quick
|
|
268
|
+
- MIT licensed and straightforward to extend
|
|
269
|
+
|
|
270
|
+
## Documentation
|
|
271
|
+
|
|
272
|
+
Start with the [full command index](docs/README.md), or jump directly to:
|
|
273
|
+
|
|
274
|
+
[Install](docs/install.md) · [Images](docs/img.md) · [Video](docs/vid.md) ·
|
|
275
|
+
[PDF](docs/pdf.md) · [Downloads](docs/dl.md) · [Data](docs/data.md) ·
|
|
276
|
+
[Encoding](docs/enc.md) · [QR](docs/qr.md) · [Files](docs/file.md) ·
|
|
277
|
+
[Text](docs/text.md) · [Troubleshooting](docs/troubleshooting.md)
|
|
278
|
+
|
|
279
|
+
## Build from source
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
git clone https://github.com/k6w/polytool
|
|
283
|
+
cd polytool
|
|
284
|
+
uv sync --extra dev --extra img --extra vid --extra pdf --extra dl --extra shot --extra archive --extra qr-decode
|
|
285
|
+
uv run pytest
|
|
286
|
+
uv run ruff check .
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Contributions use conventional commits (`feat:`, `fix:`, `docs:`, `test:`, and so on).
|
|
290
|
+
Every user-facing command should ship help examples, a happy-path test, and an
|
|
291
|
+
error-path test. See [architecture.md](docs/architecture.md) before adding a new group.
|
|
292
|
+
|
|
293
|
+
## License
|
|
294
|
+
|
|
295
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# polytool
|
|
2
|
+
|
|
3
|
+
**The command line toolbox for everything that is not worth installing another app for.**
|
|
4
|
+
|
|
5
|
+
`polytool` puts 60+ practical commands behind one memorable interface: `pt`. Convert
|
|
6
|
+
images, trim video, clean PDFs, remove backgrounds, run OCR, generate QR codes,
|
|
7
|
+
download media, transform data, hash files, inspect networks, and automate the
|
|
8
|
+
small tasks that normally turn into a tab-hunting expedition.
|
|
9
|
+
|
|
10
|
+
[](https://github.com/k6w/polytool/actions/workflows/ci.yml)
|
|
11
|
+
[](https://pypi.org/project/polytool/)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
|
|
14
|
+
## See the real thing
|
|
15
|
+
|
|
16
|
+
These are direct captures from the installed CLI and its generated artifacts—not
|
|
17
|
+
mockups or a web demo.
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
One Terminal window can handle text, color, units, data, security, generators,
|
|
22
|
+
images, QR, OCR, audio, and PDF work:
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
Real AI background removal, with the original and transparent result shown in Preview:
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
Live YouTube metadata and download through the `pt` wrapper:
|
|
31
|
+
|
|
32
|
+

|
|
33
|
+
|
|
34
|
+
## Why people reach for `pt`
|
|
35
|
+
|
|
36
|
+
- **One install, a broad surface.** Stop collecting tiny single-purpose utilities.
|
|
37
|
+
- **Discoverable by design.** Every command has focused help and runnable examples.
|
|
38
|
+
- **Pipelines-first.** Text commands use stdout; file commands choose sensible output names.
|
|
39
|
+
- **Fast startup.** Heavy dependencies load only when the relevant command runs.
|
|
40
|
+
- **Helpful failure modes.** Missing optional tools produce an actionable install hint.
|
|
41
|
+
- **Local by default.** Media, documents, data, hashes, and OCR stay on your machine unless a command explicitly accesses a network service.
|
|
42
|
+
- **Flexible footprint.** Install the lightweight core or opt into only the extras you need.
|
|
43
|
+
|
|
44
|
+
## Install in seconds
|
|
45
|
+
|
|
46
|
+
`uv` is the recommended installer because it manages Python and keeps the command isolated:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# macOS / Linux
|
|
50
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
51
|
+
uv tool install polytool
|
|
52
|
+
|
|
53
|
+
# Windows PowerShell
|
|
54
|
+
irm https://astral.sh/uv/install.ps1 | iex
|
|
55
|
+
uv tool install polytool
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
That gives you the fast core: data, encoding, generators, color, units, text,
|
|
59
|
+
QR generation, cron, networking, clipboard, and file operations.
|
|
60
|
+
|
|
61
|
+
For the complete toolbox:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv tool install 'polytool[full]'
|
|
65
|
+
pt setup -y # install Deno and Chromium for external integrations
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Both `polytool` and the shorter `pt` command are installed. PowerShell users
|
|
69
|
+
should keep the quotes around extras because brackets are shell glob characters.
|
|
70
|
+
|
|
71
|
+
## A five-minute tour
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Make a shareable QR code
|
|
75
|
+
pt qr gen "https://github.com/k6w/polytool" -o qr.png
|
|
76
|
+
|
|
77
|
+
# Prepare an image for the web
|
|
78
|
+
pt img convert photo.heic -o photo.jpg
|
|
79
|
+
pt img resize photo.jpg --width 1600
|
|
80
|
+
pt img compress photo.jpg --quality 75
|
|
81
|
+
|
|
82
|
+
# Turn media into something useful
|
|
83
|
+
pt vid gif clip.mp4 --width 480
|
|
84
|
+
pt vid extract-audio recording.mp4 -o recording.mp3
|
|
85
|
+
|
|
86
|
+
# Clean up documents
|
|
87
|
+
pt pdf merge cover.pdf report.pdf -o release.pdf
|
|
88
|
+
pt pdf to-images release.pdf --dpi 200
|
|
89
|
+
|
|
90
|
+
# Download public media and inspect it first
|
|
91
|
+
pt dl info 'https://www.youtube.com/watch?v=...'
|
|
92
|
+
pt dl get 'https://www.youtube.com/watch?v=...'
|
|
93
|
+
|
|
94
|
+
# Make data and developer chores boring
|
|
95
|
+
pt data convert config.yaml --to json
|
|
96
|
+
pt enc hash sha256 release.zip
|
|
97
|
+
pt enc base64 encode README.md
|
|
98
|
+
pt gen password --length 32
|
|
99
|
+
pt gen uuid v7
|
|
100
|
+
pt color convert '#3366ff'
|
|
101
|
+
pt convert unit '100 km' --to mi
|
|
102
|
+
pt text slugify 'Hello, World!'
|
|
103
|
+
pt cron explain '0 9 * * MON-FRI'
|
|
104
|
+
pt file dedupe ./Downloads
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Run `pt --help`, then `pt <group> --help`. You can also pipe text into commands
|
|
108
|
+
that accept stdin and compose them with standard Unix tools.
|
|
109
|
+
|
|
110
|
+
## Everything inside
|
|
111
|
+
|
|
112
|
+
| Group | What it unlocks |
|
|
113
|
+
|---|---|
|
|
114
|
+
| `pt img` | Convert, resize, compress, watermark, palette, EXIF, ASCII, background removal, OCR |
|
|
115
|
+
| `pt vid` | Convert, trim, extract audio, animated GIF |
|
|
116
|
+
| `pt pdf` | Merge, split, compress, extract text, render, build from images, OCR |
|
|
117
|
+
| `pt dl` | YouTube and 1000+ site downloads, metadata, audio-only mode, browser cookies |
|
|
118
|
+
| `pt data` | JSON, YAML, TOML, CSV, XML conversion, pretty-printing, validation |
|
|
119
|
+
| `pt enc` | SHA/Blake2/xxhash, Base64, URL/HTML escaping, JWT decode and verify |
|
|
120
|
+
| `pt qr` | PNG, SVG, PDF, EPS, terminal, Wi-Fi QR generation, decode |
|
|
121
|
+
| `pt gen` | Passwords, UUID v1/v3/v4/v5/v7, lorem ipsum |
|
|
122
|
+
| `pt file` | Batch rename, duplicate detection, largest files, organizing, archives |
|
|
123
|
+
| `pt net` | Port checks, IP information, HTTP requests |
|
|
124
|
+
| `pt text` | Diff, word counts, case conversion, slugify, Markdown HTML/preview |
|
|
125
|
+
| `pt convert` | Units, timestamps, number bases |
|
|
126
|
+
| `pt color` | Hex, RGB, HSL, HSV, CMYK conversion |
|
|
127
|
+
| `pt cron` | Human explanations and next firing times |
|
|
128
|
+
| `pt clip` / `pt shot` | Clipboard operations and screen/web screenshots |
|
|
129
|
+
|
|
130
|
+
## Install only what you need
|
|
131
|
+
|
|
132
|
+
The base package stays intentionally small. Add capabilities à la carte:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
uv tool install 'polytool[img]' # Pillow, HEIC/AVIF/SVG, palette, ASCII
|
|
136
|
+
uv tool install 'polytool[vid]' # ffmpeg-backed media conversion
|
|
137
|
+
uv tool install 'polytool[pdf]' # PDF manipulation and rendering
|
|
138
|
+
uv tool install 'polytool[dl]' # yt-dlp and matched EJS scripts
|
|
139
|
+
uv tool install 'polytool[shot]' # mss and Playwright
|
|
140
|
+
uv tool install 'polytool[ai]' # rembg background removal
|
|
141
|
+
uv tool install 'polytool[ocr]' # Tesseract wrapper and EasyOCR
|
|
142
|
+
uv tool install 'polytool[qr-decode]' # QR decoding (also needs native zbar)
|
|
143
|
+
uv tool install 'polytool[archive]' # 7z support
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`[full]` combines every extra. The first use of some commands also downloads
|
|
147
|
+
runtime assets: Deno for YouTube challenge solving, Chromium for web captures,
|
|
148
|
+
the U2-Net model for background removal, or language/model data for OCR.
|
|
149
|
+
|
|
150
|
+
Platform notes:
|
|
151
|
+
|
|
152
|
+
- macOS QR decoding: `brew install zbar`
|
|
153
|
+
- Debian/Ubuntu QR decoding: `sudo apt install libzbar0`
|
|
154
|
+
- macOS OCR: `brew install tesseract`
|
|
155
|
+
- Windows OCR: install Tesseract from UB Mannheim
|
|
156
|
+
- Video commands use a system `ffmpeg` when available and otherwise fall back to the bundled binary
|
|
157
|
+
|
|
158
|
+
If an optional dependency is missing, `pt` explains the exact extra to install.
|
|
159
|
+
|
|
160
|
+
## Trust the plumbing
|
|
161
|
+
|
|
162
|
+
The project is tested as a CLI, not only as a collection of importable functions:
|
|
163
|
+
|
|
164
|
+
- 143 automated tests covering happy paths, invalid input, integrations, and file outputs
|
|
165
|
+
- Ruff lint and formatting checks
|
|
166
|
+
- basedpyright static analysis
|
|
167
|
+
- Cross-platform CI configuration for macOS, Linux, and Windows
|
|
168
|
+
- Lazy imports so `pt --help` remains quick
|
|
169
|
+
- MIT licensed and straightforward to extend
|
|
170
|
+
|
|
171
|
+
## Documentation
|
|
172
|
+
|
|
173
|
+
Start with the [full command index](docs/README.md), or jump directly to:
|
|
174
|
+
|
|
175
|
+
[Install](docs/install.md) · [Images](docs/img.md) · [Video](docs/vid.md) ·
|
|
176
|
+
[PDF](docs/pdf.md) · [Downloads](docs/dl.md) · [Data](docs/data.md) ·
|
|
177
|
+
[Encoding](docs/enc.md) · [QR](docs/qr.md) · [Files](docs/file.md) ·
|
|
178
|
+
[Text](docs/text.md) · [Troubleshooting](docs/troubleshooting.md)
|
|
179
|
+
|
|
180
|
+
## Build from source
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
git clone https://github.com/k6w/polytool
|
|
184
|
+
cd polytool
|
|
185
|
+
uv sync --extra dev --extra img --extra vid --extra pdf --extra dl --extra shot --extra archive --extra qr-decode
|
|
186
|
+
uv run pytest
|
|
187
|
+
uv run ruff check .
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Contributions use conventional commits (`feat:`, `fix:`, `docs:`, `test:`, and so on).
|
|
191
|
+
Every user-facing command should ship help examples, a happy-path test, and an
|
|
192
|
+
error-path test. See [architecture.md](docs/architecture.md) before adding a new group.
|
|
193
|
+
|
|
194
|
+
## License
|
|
195
|
+
|
|
196
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Detailed reference for every command in `polytool` (binary `pt`).
|
|
4
4
|
|
|
5
|
-
`pt` is built around 16 subcommand groups
|
|
5
|
+
`pt` is built around 16 subcommand groups with more than 60 commands. Every command is documented below with argument types, defaults, flags, exit behavior, and runnable examples.
|
|
6
6
|
|
|
7
7
|
## Quick links
|
|
8
8
|
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "polytool"
|
|
7
|
-
version = "0.2.
|
|
8
|
-
description = "One
|
|
7
|
+
version = "0.2.11"
|
|
8
|
+
description = "One CLI with 60+ everyday commands — image/video/PDF conversion, background removal, OCR, QR codes, hashing, downloads, and more"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13"
|
|
11
11
|
license = { text = "MIT" }
|
|
@@ -58,7 +58,7 @@ img = [
|
|
|
58
58
|
]
|
|
59
59
|
vid = ["ffmpeg-python>=0.2", "imageio-ffmpeg>=0.5"]
|
|
60
60
|
pdf = ["pypdf>=4", "pikepdf>=8", "pdfplumber>=0.11", "pymupdf>=1.24"]
|
|
61
|
-
dl = ["yt-dlp>=
|
|
61
|
+
dl = ["yt-dlp[default]>=2026.8.19"]
|
|
62
62
|
ocr = ["pytesseract>=0.3", "easyocr>=1.7"]
|
|
63
63
|
ai = ["rembg[cpu]>=2.0"]
|
|
64
64
|
qr-decode = ["pyzbar>=0.1"]
|
|
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
import subprocess
|
|
11
11
|
import sys
|
|
12
|
+
from io import TextIOWrapper
|
|
12
13
|
from typing import Annotated
|
|
13
14
|
|
|
14
15
|
import typer
|
|
@@ -38,7 +39,7 @@ from polytool.core.errors import PolytoolError, render_panel
|
|
|
38
39
|
|
|
39
40
|
app = typer.Typer(
|
|
40
41
|
name="polytool",
|
|
41
|
-
help="polytool — one
|
|
42
|
+
help="polytool — one CLI with 60+ everyday commands (pt for short).",
|
|
42
43
|
no_args_is_help=True,
|
|
43
44
|
add_completion=False,
|
|
44
45
|
rich_markup_mode="rich",
|
|
@@ -56,7 +57,9 @@ def _force_utf8_io() -> None:
|
|
|
56
57
|
import contextlib
|
|
57
58
|
|
|
58
59
|
for stream in (sys.stdout, sys.stderr):
|
|
59
|
-
|
|
60
|
+
if not isinstance(stream, TextIOWrapper):
|
|
61
|
+
continue
|
|
62
|
+
with contextlib.suppress(OSError):
|
|
60
63
|
stream.reconfigure(encoding="utf-8", errors="replace")
|
|
61
64
|
|
|
62
65
|
|
|
@@ -91,7 +94,7 @@ def main(
|
|
|
91
94
|
help="Show version and exit.",
|
|
92
95
|
),
|
|
93
96
|
) -> None:
|
|
94
|
-
"""polytool — one
|
|
97
|
+
"""polytool — one CLI with 60+ everyday commands."""
|
|
95
98
|
|
|
96
99
|
|
|
97
100
|
@app.command("setup")
|
|
@@ -653,14 +653,9 @@ def cmd_get(
|
|
|
653
653
|
"noprogress": True, # we render a Rich progress bar
|
|
654
654
|
"logger": logger,
|
|
655
655
|
"progress_hooks": [_make_progress_hook(progress, state)],
|
|
656
|
-
#
|
|
657
|
-
#
|
|
658
|
-
#
|
|
659
|
-
"extractor_args": {
|
|
660
|
-
"youtube": {
|
|
661
|
-
"player_client": ["web", "web_safari", "mweb", "android", "ios", "tv"],
|
|
662
|
-
}
|
|
663
|
-
},
|
|
656
|
+
# Let current yt-dlp select the appropriate YouTube client. Forcing a
|
|
657
|
+
# broad client list causes duplicate requests and noisy SABR warnings,
|
|
658
|
+
# and tends to age badly as YouTube changes its APIs.
|
|
664
659
|
}
|
|
665
660
|
if audio_only:
|
|
666
661
|
opts["format"] = "bestaudio/best"
|
|
@@ -716,9 +711,7 @@ def cmd_get(
|
|
|
716
711
|
f"({_human_size(size)} in {_human_duration(elapsed)})[/dim]"
|
|
717
712
|
)
|
|
718
713
|
else:
|
|
719
|
-
console.print(
|
|
720
|
-
f" [dim]({_human_size(size)} in {_human_duration(elapsed)})[/dim]"
|
|
721
|
-
)
|
|
714
|
+
console.print(f" [dim]({_human_size(size)} in {_human_duration(elapsed)})[/dim]")
|
|
722
715
|
|
|
723
716
|
|
|
724
717
|
@app.command("info")
|
|
@@ -775,11 +768,6 @@ def cmd_info(
|
|
|
775
768
|
"quiet": True,
|
|
776
769
|
"no_warnings": True,
|
|
777
770
|
"logger": logger,
|
|
778
|
-
"extractor_args": {
|
|
779
|
-
"youtube": {
|
|
780
|
-
"player_client": ["web", "web_safari", "mweb", "android", "ios", "tv"],
|
|
781
|
-
}
|
|
782
|
-
},
|
|
783
771
|
}
|
|
784
772
|
_apply_cookie_opts(opts, cookies_from_browser, cookies_file)
|
|
785
773
|
if username is not None:
|
|
@@ -76,8 +76,9 @@ def cmd_uuid(
|
|
|
76
76
|
typer.echo(str(_uuid.uuid4()))
|
|
77
77
|
elif v == "7":
|
|
78
78
|
# Python 3.13 added uuid.uuid7
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
uuid7 = getattr(_uuid, "uuid7", None)
|
|
80
|
+
if uuid7 is not None:
|
|
81
|
+
typer.echo(str(uuid7()))
|
|
81
82
|
else:
|
|
82
83
|
# Manual v7 fallback (won't be hit on 3.13+, but defensive)
|
|
83
84
|
import os
|
|
@@ -246,11 +246,9 @@ def cmd_exif(
|
|
|
246
246
|
# Fallback: re-encode without EXIF via Pillow
|
|
247
247
|
from PIL import Image
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
clean
|
|
252
|
-
clean.putdata(data)
|
|
253
|
-
clean.save(out)
|
|
249
|
+
with Image.open(source) as img:
|
|
250
|
+
clean = img.copy()
|
|
251
|
+
clean.save(out, exif=b"")
|
|
254
252
|
console.print(f"[green]Stripped[/green] EXIF -> {out}")
|
|
255
253
|
|
|
256
254
|
|
|
@@ -293,7 +291,7 @@ def cmd_watermark(
|
|
|
293
291
|
str,
|
|
294
292
|
typer.Option(
|
|
295
293
|
"--position",
|
|
296
|
-
help="
|
|
294
|
+
help="top-left | top-right | bottom-left | bottom-right | center",
|
|
297
295
|
),
|
|
298
296
|
] = "bottomright",
|
|
299
297
|
size: Annotated[int, typer.Option("--size", help="Font size (px)")] = 48,
|
|
@@ -328,12 +326,13 @@ def cmd_watermark(
|
|
|
328
326
|
"bottomright": (w - tw - pad, h - th - pad),
|
|
329
327
|
"center": ((w - tw) // 2, (h - th) // 2),
|
|
330
328
|
}
|
|
331
|
-
|
|
329
|
+
position_key = position.lower().replace("-", "").replace("_", "")
|
|
330
|
+
if position_key not in positions:
|
|
332
331
|
raise PolytoolError(
|
|
333
332
|
f"Unknown position {position!r}",
|
|
334
|
-
hint=
|
|
333
|
+
hint="One of: top-left, top-right, bottom-left, bottom-right, center",
|
|
335
334
|
)
|
|
336
|
-
x, y = positions[
|
|
335
|
+
x, y = positions[position_key]
|
|
337
336
|
alpha = int(255 * max(0.0, min(1.0, opacity)))
|
|
338
337
|
draw.text((x, y), text, font=font, fill=(255, 255, 255, alpha))
|
|
339
338
|
out_img = Image.alpha_composite(img, overlay)
|
|
@@ -229,12 +229,22 @@ def cmd_from_images(
|
|
|
229
229
|
from polytool.core.lazy import require_extra
|
|
230
230
|
|
|
231
231
|
PIL_Image = require_extra("PIL.Image", extra="img")
|
|
232
|
+
# Pillow loads encoders lazily. A fresh CLI process that opens only PNGs
|
|
233
|
+
# has not registered JPEG yet, but Pillow's PDF writer uses it internally.
|
|
234
|
+
require_extra("PIL.JpegImagePlugin", extra="img")
|
|
232
235
|
|
|
233
236
|
if not inputs:
|
|
234
237
|
raise PolytoolError("No input images")
|
|
235
|
-
imgs = [
|
|
238
|
+
imgs = []
|
|
239
|
+
for path in inputs:
|
|
240
|
+
with PIL_Image.open(path) as image:
|
|
241
|
+
imgs.append(image.convert("RGB"))
|
|
236
242
|
head, *rest = imgs
|
|
237
|
-
|
|
243
|
+
try:
|
|
244
|
+
head.save(output, save_all=True, append_images=rest)
|
|
245
|
+
finally:
|
|
246
|
+
for image in imgs:
|
|
247
|
+
image.close()
|
|
238
248
|
console.print(f"[green]Wrote[/green] {output} ({len(inputs)} pages)")
|
|
239
249
|
|
|
240
250
|
|
polytool-0.2.9/PKG-INFO
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: polytool
|
|
3
|
-
Version: 0.2.9
|
|
4
|
-
Summary: One-binary CLI bundling 26 everyday utilities — image/video/PDF conversion, background removal, OCR, QR codes, hashing, downloads, and more
|
|
5
|
-
Project-URL: Homepage, https://github.com/k6w/polytool
|
|
6
|
-
Project-URL: Repository, https://github.com/k6w/polytool
|
|
7
|
-
Project-URL: Issues, https://github.com/k6w/polytool/issues
|
|
8
|
-
Author: polytool contributors
|
|
9
|
-
License: MIT
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
Keywords: background-removal,cli,convert,ffmpeg,image,ocr,pdf,qr,swiss-army-knife,utility,video,yt-dlp
|
|
12
|
-
Classifier: Development Status :: 3 - Alpha
|
|
13
|
-
Classifier: Environment :: Console
|
|
14
|
-
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
-
Classifier: Operating System :: OS Independent
|
|
18
|
-
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
-
Classifier: Topic :: Multimedia :: Graphics
|
|
21
|
-
Classifier: Topic :: Utilities
|
|
22
|
-
Requires-Python: >=3.13
|
|
23
|
-
Requires-Dist: cron-descriptor>=1.4
|
|
24
|
-
Requires-Dist: croniter>=2
|
|
25
|
-
Requires-Dist: faker>=25
|
|
26
|
-
Requires-Dist: httpx>=0.27
|
|
27
|
-
Requires-Dist: markdown-it-py>=3
|
|
28
|
-
Requires-Dist: pint>=0.24
|
|
29
|
-
Requires-Dist: pyjwt>=2.8
|
|
30
|
-
Requires-Dist: pyperclip>=1.8
|
|
31
|
-
Requires-Dist: python-dateutil>=2.9
|
|
32
|
-
Requires-Dist: python-slugify>=8
|
|
33
|
-
Requires-Dist: rich>=13
|
|
34
|
-
Requires-Dist: ruamel-yaml>=0.18
|
|
35
|
-
Requires-Dist: segno>=1.6
|
|
36
|
-
Requires-Dist: tomli-w>=1.0
|
|
37
|
-
Requires-Dist: typer>=0.12
|
|
38
|
-
Requires-Dist: xmltodict>=0.13
|
|
39
|
-
Requires-Dist: xxhash>=3.4
|
|
40
|
-
Provides-Extra: ai
|
|
41
|
-
Requires-Dist: rembg[cpu]>=2.0; extra == 'ai'
|
|
42
|
-
Provides-Extra: archive
|
|
43
|
-
Requires-Dist: py7zr>=0.21; extra == 'archive'
|
|
44
|
-
Provides-Extra: dev
|
|
45
|
-
Requires-Dist: basedpyright>=1.13; extra == 'dev'
|
|
46
|
-
Requires-Dist: pre-commit>=3.7; extra == 'dev'
|
|
47
|
-
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
48
|
-
Requires-Dist: pytest>=8; extra == 'dev'
|
|
49
|
-
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
50
|
-
Provides-Extra: dl
|
|
51
|
-
Requires-Dist: yt-dlp-ejs>=0.8; extra == 'dl'
|
|
52
|
-
Requires-Dist: yt-dlp>=2024.5; extra == 'dl'
|
|
53
|
-
Provides-Extra: full
|
|
54
|
-
Requires-Dist: ascii-magic>=2; extra == 'full'
|
|
55
|
-
Requires-Dist: colorthief>=0.2; extra == 'full'
|
|
56
|
-
Requires-Dist: easyocr>=1.7; extra == 'full'
|
|
57
|
-
Requires-Dist: ffmpeg-python>=0.2; extra == 'full'
|
|
58
|
-
Requires-Dist: imageio-ffmpeg>=0.5; extra == 'full'
|
|
59
|
-
Requires-Dist: mss>=9; extra == 'full'
|
|
60
|
-
Requires-Dist: pdfplumber>=0.11; extra == 'full'
|
|
61
|
-
Requires-Dist: piexif>=1.1; extra == 'full'
|
|
62
|
-
Requires-Dist: pikepdf>=8; extra == 'full'
|
|
63
|
-
Requires-Dist: pillow-avif-plugin>=1.4; extra == 'full'
|
|
64
|
-
Requires-Dist: pillow-heif>=0.18; extra == 'full'
|
|
65
|
-
Requires-Dist: pillow>=10; extra == 'full'
|
|
66
|
-
Requires-Dist: playwright>=1.44; extra == 'full'
|
|
67
|
-
Requires-Dist: py7zr>=0.21; extra == 'full'
|
|
68
|
-
Requires-Dist: pymupdf>=1.24; extra == 'full'
|
|
69
|
-
Requires-Dist: pypdf>=4; extra == 'full'
|
|
70
|
-
Requires-Dist: pytesseract>=0.3; extra == 'full'
|
|
71
|
-
Requires-Dist: pyzbar>=0.1; extra == 'full'
|
|
72
|
-
Requires-Dist: rembg[cpu]>=2.0; extra == 'full'
|
|
73
|
-
Requires-Dist: resvg-py>=0.1; extra == 'full'
|
|
74
|
-
Requires-Dist: yt-dlp-ejs>=0.8; extra == 'full'
|
|
75
|
-
Requires-Dist: yt-dlp>=2024.5; extra == 'full'
|
|
76
|
-
Provides-Extra: img
|
|
77
|
-
Requires-Dist: ascii-magic>=2; extra == 'img'
|
|
78
|
-
Requires-Dist: colorthief>=0.2; extra == 'img'
|
|
79
|
-
Requires-Dist: piexif>=1.1; extra == 'img'
|
|
80
|
-
Requires-Dist: pillow-avif-plugin>=1.4; extra == 'img'
|
|
81
|
-
Requires-Dist: pillow-heif>=0.18; extra == 'img'
|
|
82
|
-
Requires-Dist: pillow>=10; extra == 'img'
|
|
83
|
-
Requires-Dist: resvg-py>=0.1; extra == 'img'
|
|
84
|
-
Provides-Extra: ocr
|
|
85
|
-
Requires-Dist: easyocr>=1.7; extra == 'ocr'
|
|
86
|
-
Requires-Dist: pytesseract>=0.3; extra == 'ocr'
|
|
87
|
-
Provides-Extra: pdf
|
|
88
|
-
Requires-Dist: pdfplumber>=0.11; extra == 'pdf'
|
|
89
|
-
Requires-Dist: pikepdf>=8; extra == 'pdf'
|
|
90
|
-
Requires-Dist: pymupdf>=1.24; extra == 'pdf'
|
|
91
|
-
Requires-Dist: pypdf>=4; extra == 'pdf'
|
|
92
|
-
Provides-Extra: qr-decode
|
|
93
|
-
Requires-Dist: pyzbar>=0.1; extra == 'qr-decode'
|
|
94
|
-
Provides-Extra: shot
|
|
95
|
-
Requires-Dist: mss>=9; extra == 'shot'
|
|
96
|
-
Requires-Dist: playwright>=1.44; extra == 'shot'
|
|
97
|
-
Provides-Extra: vid
|
|
98
|
-
Requires-Dist: ffmpeg-python>=0.2; extra == 'vid'
|
|
99
|
-
Requires-Dist: imageio-ffmpeg>=0.5; extra == 'vid'
|
|
100
|
-
Description-Content-Type: text/markdown
|
|
101
|
-
|
|
102
|
-
# polytool
|
|
103
|
-
|
|
104
|
-
> One CLI, 26 everyday utilities. Image format conversion, background removal, video/audio conversion, PDF tooling, OCR, QR codes, hashing, downloads, and more — all behind one binary called `pt`.
|
|
105
|
-
|
|
106
|
-
[](https://github.com/k6w/polytool/actions/workflows/ci.yml)
|
|
107
|
-
|
|
108
|
-
## Install
|
|
109
|
-
|
|
110
|
-
The fastest way (no Python prerequisite — `uv` brings its own):
|
|
111
|
-
|
|
112
|
-
```powershell
|
|
113
|
-
# 1. install uv (Windows PowerShell)
|
|
114
|
-
irm https://astral.sh/uv/install.ps1 | iex
|
|
115
|
-
|
|
116
|
-
# 2. install polytool (slim — fast, ~80 MB)
|
|
117
|
-
uv tool install polytool
|
|
118
|
-
|
|
119
|
-
# or, install everything (image/video/PDF/yt-dlp/screenshots/AI background removal)
|
|
120
|
-
uv tool install 'polytool[full]'
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
# macOS / Linux
|
|
125
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
126
|
-
uv tool install 'polytool[full]'
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
> **Note for PowerShell users:** quote `'polytool[full]'` — the brackets are shell glob characters.
|
|
130
|
-
|
|
131
|
-
After install, both `polytool` and the short alias `pt` are on your PATH.
|
|
132
|
-
|
|
133
|
-
## Quick start
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
pt qr gen "https://github.com/k6w/polytool" -o qr.png
|
|
137
|
-
pt img convert photo.heic -o photo.jpg
|
|
138
|
-
pt img bg-remove portrait.jpg # transparent PNG
|
|
139
|
-
pt vid gif clip.mp4 # animated gif
|
|
140
|
-
pt vid extract-audio movie.mp4 # mp3
|
|
141
|
-
pt pdf merge a.pdf b.pdf -o merged.pdf
|
|
142
|
-
pt pdf to-images doc.pdf --dpi 200
|
|
143
|
-
pt dl get 'https://www.youtube.com/watch?v=...'
|
|
144
|
-
pt enc hash sha256 release.zip
|
|
145
|
-
pt enc base64 encode README.md
|
|
146
|
-
pt data convert config.yaml --to json
|
|
147
|
-
pt gen password --length 32
|
|
148
|
-
pt gen uuid v7
|
|
149
|
-
pt color convert "#3366ff"
|
|
150
|
-
pt convert unit "100 km" --to mi
|
|
151
|
-
pt convert timestamp 1715200000
|
|
152
|
-
pt text slugify "Hello, World!"
|
|
153
|
-
pt cron explain "0 9 * * MON"
|
|
154
|
-
pt net http GET https://api.github.com
|
|
155
|
-
pt file dedupe ./Downloads
|
|
156
|
-
pt file archive ./project -o project.7z
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
Run `pt --help` to see all groups, or `pt <group> --help` for any group's verbs (each verb's help has runnable Examples).
|
|
160
|
-
|
|
161
|
-
## Documentation
|
|
162
|
-
|
|
163
|
-
Full reference for every verb, argument, and option lives in **[docs/](docs/README.md)**:
|
|
164
|
-
|
|
165
|
-
- **[Install guide](docs/install.md)** — slim vs full, all extras, Windows quoting
|
|
166
|
-
- **Per-group reference** — [img](docs/img.md) · [vid](docs/vid.md) · [pdf](docs/pdf.md) · [dl](docs/dl.md) · [shot](docs/shot.md) · [qr](docs/qr.md) · [data](docs/data.md) · [enc](docs/enc.md) · [text](docs/text.md) · [convert](docs/convert.md) · [color](docs/color.md) · [cron](docs/cron.md) · [file](docs/file.md) · [gen](docs/gen.md) · [net](docs/net.md) · [clip](docs/clip.md)
|
|
167
|
-
- **[Architecture](docs/architecture.md)** — package layout, lazy imports, error model, how to add a verb
|
|
168
|
-
- **[Troubleshooting](docs/troubleshooting.md)** — every common error with a fix
|
|
169
|
-
|
|
170
|
-
## Feature reference (all 26 verbs)
|
|
171
|
-
|
|
172
|
-
| Group | Verbs |
|
|
173
|
-
|---|---|
|
|
174
|
-
| `pt img` | `convert` (png/jpg/webp/avif/heic/svg/bmp/tiff), `resize`, `compress`, `bg-remove`, `watermark`, `ascii`, `exif`, `palette`, `ocr` |
|
|
175
|
-
| `pt vid` | `convert`, `trim`, `extract-audio`, `gif` |
|
|
176
|
-
| `pt pdf` | `merge`, `split`, `compress`, `extract-text`, `to-images`, `from-images`, `ocr` |
|
|
177
|
-
| `pt dl` | `get` (yt-dlp wrapper, audio-only mode), `info` |
|
|
178
|
-
| `pt data` | `convert` (json↔yaml↔toml↔csv↔xml), `pretty`, `validate` |
|
|
179
|
-
| `pt enc` | `hash` (md5/sha1/sha256/sha512/blake2b/xxhash), `base64`, `url`, `html`, `jwt-decode`, `jwt-verify` |
|
|
180
|
-
| `pt qr` | `gen` (png/svg/pdf/eps/terminal), `wifi` (Wi-Fi join code), `decode` |
|
|
181
|
-
| `pt gen` | `password`, `uuid` (v1/v3/v4/v5/v7), `lorem` |
|
|
182
|
-
| `pt file` | `rename`, `dedupe`, `bigfiles`, `organize`, `archive` (zip/tar/tar.gz/7z) |
|
|
183
|
-
| `pt net` | `port-check`, `ip-info`, `http` |
|
|
184
|
-
| `pt clip` | `copy`, `paste` |
|
|
185
|
-
| `pt shot` | `screen`, `web` (Playwright), `install` |
|
|
186
|
-
| `pt color` | `convert` (hex/rgb/hsl/hsv/cmyk) |
|
|
187
|
-
| `pt convert` | `unit`, `timestamp`, `base` |
|
|
188
|
-
| `pt text` | `diff`, `wc`, `case` (snake/kebab/camel/pascal/...), `slugify`, `md-to-html`, `md-preview` |
|
|
189
|
-
| `pt cron` | `explain`, `next` |
|
|
190
|
-
|
|
191
|
-
## Slim vs full install
|
|
192
|
-
|
|
193
|
-
The default install ships only lightweight utilities (data, enc, gen, color, convert, text, qr-gen, cron, net, clip, file). Heavy/optional features are grouped behind extras so you only pull what you need:
|
|
194
|
-
|
|
195
|
-
| Extra | Adds | Approx. size |
|
|
196
|
-
|---|---|---|
|
|
197
|
-
| `[img]` | Pillow + HEIC/AVIF/SVG plugins, EXIF, palette, ASCII, watermark | ~50 MB |
|
|
198
|
-
| `[vid]` | `ffmpeg-python` + bundled `ffmpeg` (auto-downloaded) | ~70 MB on first use |
|
|
199
|
-
| `[pdf]` | pypdf, pikepdf, pdfplumber, PyMuPDF | ~80 MB |
|
|
200
|
-
| `[dl]` | yt-dlp | ~10 MB |
|
|
201
|
-
| `[shot]` | mss, Playwright (Chromium installed via `pt shot install`) | ~150 MB |
|
|
202
|
-
| `[ai]` | rembg + ONNX runtime (170 MB U2-Net model on first run) | ~250 MB |
|
|
203
|
-
| `[ocr]` | pytesseract / easyocr (PyTorch) | ~1 GB if easyocr |
|
|
204
|
-
| `[qr-decode]` | pyzbar (system `libzbar` on Linux) | ~5 MB |
|
|
205
|
-
| `[archive]` | py7zr | ~5 MB |
|
|
206
|
-
| `[full]` | all of the above | ~1.5 GB |
|
|
207
|
-
|
|
208
|
-
Verbs that need an extra you haven't installed print a friendly hint:
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
This command needs the 'ai' extra.
|
|
212
|
-
Install with: uv tool install 'polytool[ai]'
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## Troubleshooting
|
|
216
|
-
|
|
217
|
-
### `pt img convert *.svg` fails on Windows
|
|
218
|
-
We use `resvg-py` (a pre-built Rust wheel) instead of `cairosvg` precisely to avoid the Cairo DLL pain. Reinstall the `[img]` extra to pull it in.
|
|
219
|
-
|
|
220
|
-
### `pt vid` wants ffmpeg
|
|
221
|
-
We prefer a system `ffmpeg` if it's on PATH, and fall back to `imageio-ffmpeg`'s bundled binary (auto-downloads ~70 MB on first call). Install ffmpeg system-wide with [`winget install ffmpeg`](https://learn.microsoft.com/windows/package-manager/) / `brew install ffmpeg` / `apt install ffmpeg` to skip the bundled download.
|
|
222
|
-
|
|
223
|
-
### `pt img bg-remove` is downloading something
|
|
224
|
-
First run pulls the U2-Net ONNX model (~170 MB) into `~/.u2net/`. Set `U2NET_HOME` to relocate.
|
|
225
|
-
|
|
226
|
-
### `pt qr decode` says pyzbar missing
|
|
227
|
-
On Linux, install the system library: `sudo apt-get install libzbar0` (Debian/Ubuntu) or `sudo dnf install zbar` (Fedora). Then reinstall `[qr-decode]`.
|
|
228
|
-
|
|
229
|
-
### `pt shot web` fails on first run
|
|
230
|
-
Chromium isn't installed yet. Run `pt shot install` (which is shorthand for `python -m playwright install chromium`).
|
|
231
|
-
|
|
232
|
-
### `pt img ocr` says Tesseract not found
|
|
233
|
-
The default `tesseract` engine needs the system Tesseract binary. Either install it (`winget install --id UB-Mannheim.TesseractOCR` on Windows, `brew install tesseract`, `apt install tesseract-ocr`) or pass `--engine easyocr` to use a self-contained PyTorch OCR.
|
|
234
|
-
|
|
235
|
-
### Brackets in `uv tool install 'polytool[full]'`
|
|
236
|
-
PowerShell parses unquoted brackets — always wrap the spec in single quotes.
|
|
237
|
-
|
|
238
|
-
## Contributing
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
git clone https://github.com/k6w/polytool
|
|
242
|
-
cd polytool
|
|
243
|
-
uv sync --extra dev --extra img --extra vid --extra pdf --extra dl --extra shot --extra archive --extra qr-decode
|
|
244
|
-
uv run pre-commit install
|
|
245
|
-
uv run pytest
|
|
246
|
-
uv run ruff check .
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Conventional Commits required (`feat:`, `fix:`, `chore:`, `docs:`, `test:`, `ci:`, `build:`).
|
|
250
|
-
|
|
251
|
-
Each user-facing verb must:
|
|
252
|
-
- Include a runnable `Examples:` block in its `--help`.
|
|
253
|
-
- Read from path or stdin (`-`) where it's semantic.
|
|
254
|
-
- Default `--output` to next-to-source for files, stdout for text.
|
|
255
|
-
- Raise `PolytoolError(msg, hint=...)` on user errors (rendered as a red panel).
|
|
256
|
-
- Ship at least one happy-path and one error-path test.
|
|
257
|
-
|
|
258
|
-
## License
|
|
259
|
-
|
|
260
|
-
MIT — see [LICENSE](LICENSE).
|
polytool-0.2.9/README.md
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
# polytool
|
|
2
|
-
|
|
3
|
-
> One CLI, 26 everyday utilities. Image format conversion, background removal, video/audio conversion, PDF tooling, OCR, QR codes, hashing, downloads, and more — all behind one binary called `pt`.
|
|
4
|
-
|
|
5
|
-
[](https://github.com/k6w/polytool/actions/workflows/ci.yml)
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
The fastest way (no Python prerequisite — `uv` brings its own):
|
|
10
|
-
|
|
11
|
-
```powershell
|
|
12
|
-
# 1. install uv (Windows PowerShell)
|
|
13
|
-
irm https://astral.sh/uv/install.ps1 | iex
|
|
14
|
-
|
|
15
|
-
# 2. install polytool (slim — fast, ~80 MB)
|
|
16
|
-
uv tool install polytool
|
|
17
|
-
|
|
18
|
-
# or, install everything (image/video/PDF/yt-dlp/screenshots/AI background removal)
|
|
19
|
-
uv tool install 'polytool[full]'
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
# macOS / Linux
|
|
24
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
25
|
-
uv tool install 'polytool[full]'
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
> **Note for PowerShell users:** quote `'polytool[full]'` — the brackets are shell glob characters.
|
|
29
|
-
|
|
30
|
-
After install, both `polytool` and the short alias `pt` are on your PATH.
|
|
31
|
-
|
|
32
|
-
## Quick start
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
pt qr gen "https://github.com/k6w/polytool" -o qr.png
|
|
36
|
-
pt img convert photo.heic -o photo.jpg
|
|
37
|
-
pt img bg-remove portrait.jpg # transparent PNG
|
|
38
|
-
pt vid gif clip.mp4 # animated gif
|
|
39
|
-
pt vid extract-audio movie.mp4 # mp3
|
|
40
|
-
pt pdf merge a.pdf b.pdf -o merged.pdf
|
|
41
|
-
pt pdf to-images doc.pdf --dpi 200
|
|
42
|
-
pt dl get 'https://www.youtube.com/watch?v=...'
|
|
43
|
-
pt enc hash sha256 release.zip
|
|
44
|
-
pt enc base64 encode README.md
|
|
45
|
-
pt data convert config.yaml --to json
|
|
46
|
-
pt gen password --length 32
|
|
47
|
-
pt gen uuid v7
|
|
48
|
-
pt color convert "#3366ff"
|
|
49
|
-
pt convert unit "100 km" --to mi
|
|
50
|
-
pt convert timestamp 1715200000
|
|
51
|
-
pt text slugify "Hello, World!"
|
|
52
|
-
pt cron explain "0 9 * * MON"
|
|
53
|
-
pt net http GET https://api.github.com
|
|
54
|
-
pt file dedupe ./Downloads
|
|
55
|
-
pt file archive ./project -o project.7z
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Run `pt --help` to see all groups, or `pt <group> --help` for any group's verbs (each verb's help has runnable Examples).
|
|
59
|
-
|
|
60
|
-
## Documentation
|
|
61
|
-
|
|
62
|
-
Full reference for every verb, argument, and option lives in **[docs/](docs/README.md)**:
|
|
63
|
-
|
|
64
|
-
- **[Install guide](docs/install.md)** — slim vs full, all extras, Windows quoting
|
|
65
|
-
- **Per-group reference** — [img](docs/img.md) · [vid](docs/vid.md) · [pdf](docs/pdf.md) · [dl](docs/dl.md) · [shot](docs/shot.md) · [qr](docs/qr.md) · [data](docs/data.md) · [enc](docs/enc.md) · [text](docs/text.md) · [convert](docs/convert.md) · [color](docs/color.md) · [cron](docs/cron.md) · [file](docs/file.md) · [gen](docs/gen.md) · [net](docs/net.md) · [clip](docs/clip.md)
|
|
66
|
-
- **[Architecture](docs/architecture.md)** — package layout, lazy imports, error model, how to add a verb
|
|
67
|
-
- **[Troubleshooting](docs/troubleshooting.md)** — every common error with a fix
|
|
68
|
-
|
|
69
|
-
## Feature reference (all 26 verbs)
|
|
70
|
-
|
|
71
|
-
| Group | Verbs |
|
|
72
|
-
|---|---|
|
|
73
|
-
| `pt img` | `convert` (png/jpg/webp/avif/heic/svg/bmp/tiff), `resize`, `compress`, `bg-remove`, `watermark`, `ascii`, `exif`, `palette`, `ocr` |
|
|
74
|
-
| `pt vid` | `convert`, `trim`, `extract-audio`, `gif` |
|
|
75
|
-
| `pt pdf` | `merge`, `split`, `compress`, `extract-text`, `to-images`, `from-images`, `ocr` |
|
|
76
|
-
| `pt dl` | `get` (yt-dlp wrapper, audio-only mode), `info` |
|
|
77
|
-
| `pt data` | `convert` (json↔yaml↔toml↔csv↔xml), `pretty`, `validate` |
|
|
78
|
-
| `pt enc` | `hash` (md5/sha1/sha256/sha512/blake2b/xxhash), `base64`, `url`, `html`, `jwt-decode`, `jwt-verify` |
|
|
79
|
-
| `pt qr` | `gen` (png/svg/pdf/eps/terminal), `wifi` (Wi-Fi join code), `decode` |
|
|
80
|
-
| `pt gen` | `password`, `uuid` (v1/v3/v4/v5/v7), `lorem` |
|
|
81
|
-
| `pt file` | `rename`, `dedupe`, `bigfiles`, `organize`, `archive` (zip/tar/tar.gz/7z) |
|
|
82
|
-
| `pt net` | `port-check`, `ip-info`, `http` |
|
|
83
|
-
| `pt clip` | `copy`, `paste` |
|
|
84
|
-
| `pt shot` | `screen`, `web` (Playwright), `install` |
|
|
85
|
-
| `pt color` | `convert` (hex/rgb/hsl/hsv/cmyk) |
|
|
86
|
-
| `pt convert` | `unit`, `timestamp`, `base` |
|
|
87
|
-
| `pt text` | `diff`, `wc`, `case` (snake/kebab/camel/pascal/...), `slugify`, `md-to-html`, `md-preview` |
|
|
88
|
-
| `pt cron` | `explain`, `next` |
|
|
89
|
-
|
|
90
|
-
## Slim vs full install
|
|
91
|
-
|
|
92
|
-
The default install ships only lightweight utilities (data, enc, gen, color, convert, text, qr-gen, cron, net, clip, file). Heavy/optional features are grouped behind extras so you only pull what you need:
|
|
93
|
-
|
|
94
|
-
| Extra | Adds | Approx. size |
|
|
95
|
-
|---|---|---|
|
|
96
|
-
| `[img]` | Pillow + HEIC/AVIF/SVG plugins, EXIF, palette, ASCII, watermark | ~50 MB |
|
|
97
|
-
| `[vid]` | `ffmpeg-python` + bundled `ffmpeg` (auto-downloaded) | ~70 MB on first use |
|
|
98
|
-
| `[pdf]` | pypdf, pikepdf, pdfplumber, PyMuPDF | ~80 MB |
|
|
99
|
-
| `[dl]` | yt-dlp | ~10 MB |
|
|
100
|
-
| `[shot]` | mss, Playwright (Chromium installed via `pt shot install`) | ~150 MB |
|
|
101
|
-
| `[ai]` | rembg + ONNX runtime (170 MB U2-Net model on first run) | ~250 MB |
|
|
102
|
-
| `[ocr]` | pytesseract / easyocr (PyTorch) | ~1 GB if easyocr |
|
|
103
|
-
| `[qr-decode]` | pyzbar (system `libzbar` on Linux) | ~5 MB |
|
|
104
|
-
| `[archive]` | py7zr | ~5 MB |
|
|
105
|
-
| `[full]` | all of the above | ~1.5 GB |
|
|
106
|
-
|
|
107
|
-
Verbs that need an extra you haven't installed print a friendly hint:
|
|
108
|
-
|
|
109
|
-
```
|
|
110
|
-
This command needs the 'ai' extra.
|
|
111
|
-
Install with: uv tool install 'polytool[ai]'
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Troubleshooting
|
|
115
|
-
|
|
116
|
-
### `pt img convert *.svg` fails on Windows
|
|
117
|
-
We use `resvg-py` (a pre-built Rust wheel) instead of `cairosvg` precisely to avoid the Cairo DLL pain. Reinstall the `[img]` extra to pull it in.
|
|
118
|
-
|
|
119
|
-
### `pt vid` wants ffmpeg
|
|
120
|
-
We prefer a system `ffmpeg` if it's on PATH, and fall back to `imageio-ffmpeg`'s bundled binary (auto-downloads ~70 MB on first call). Install ffmpeg system-wide with [`winget install ffmpeg`](https://learn.microsoft.com/windows/package-manager/) / `brew install ffmpeg` / `apt install ffmpeg` to skip the bundled download.
|
|
121
|
-
|
|
122
|
-
### `pt img bg-remove` is downloading something
|
|
123
|
-
First run pulls the U2-Net ONNX model (~170 MB) into `~/.u2net/`. Set `U2NET_HOME` to relocate.
|
|
124
|
-
|
|
125
|
-
### `pt qr decode` says pyzbar missing
|
|
126
|
-
On Linux, install the system library: `sudo apt-get install libzbar0` (Debian/Ubuntu) or `sudo dnf install zbar` (Fedora). Then reinstall `[qr-decode]`.
|
|
127
|
-
|
|
128
|
-
### `pt shot web` fails on first run
|
|
129
|
-
Chromium isn't installed yet. Run `pt shot install` (which is shorthand for `python -m playwright install chromium`).
|
|
130
|
-
|
|
131
|
-
### `pt img ocr` says Tesseract not found
|
|
132
|
-
The default `tesseract` engine needs the system Tesseract binary. Either install it (`winget install --id UB-Mannheim.TesseractOCR` on Windows, `brew install tesseract`, `apt install tesseract-ocr`) or pass `--engine easyocr` to use a self-contained PyTorch OCR.
|
|
133
|
-
|
|
134
|
-
### Brackets in `uv tool install 'polytool[full]'`
|
|
135
|
-
PowerShell parses unquoted brackets — always wrap the spec in single quotes.
|
|
136
|
-
|
|
137
|
-
## Contributing
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
git clone https://github.com/k6w/polytool
|
|
141
|
-
cd polytool
|
|
142
|
-
uv sync --extra dev --extra img --extra vid --extra pdf --extra dl --extra shot --extra archive --extra qr-decode
|
|
143
|
-
uv run pre-commit install
|
|
144
|
-
uv run pytest
|
|
145
|
-
uv run ruff check .
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
Conventional Commits required (`feat:`, `fix:`, `chore:`, `docs:`, `test:`, `ci:`, `build:`).
|
|
149
|
-
|
|
150
|
-
Each user-facing verb must:
|
|
151
|
-
- Include a runnable `Examples:` block in its `--help`.
|
|
152
|
-
- Read from path or stdin (`-`) where it's semantic.
|
|
153
|
-
- Default `--output` to next-to-source for files, stdout for text.
|
|
154
|
-
- Raise `PolytoolError(msg, hint=...)` on user errors (rendered as a red panel).
|
|
155
|
-
- Ship at least one happy-path and one error-path test.
|
|
156
|
-
|
|
157
|
-
## License
|
|
158
|
-
|
|
159
|
-
MIT — see [LICENSE](LICENSE).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|