morphconv 1.0.2__tar.gz → 1.0.4__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 (55) hide show
  1. {morphconv-1.0.2 → morphconv-1.0.4}/LICENSE +1 -1
  2. morphconv-1.0.4/PKG-INFO +350 -0
  3. morphconv-1.0.4/README.md +292 -0
  4. {morphconv-1.0.2 → morphconv-1.0.4}/morph/cli.py +328 -7
  5. morphconv-1.0.4/morph/converters/archives.py +188 -0
  6. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/images.py +71 -0
  7. morphconv-1.0.4/morph/converters/legacy_office.py +153 -0
  8. morphconv-1.0.4/morph/converters/notebooks.py +165 -0
  9. morphconv-1.0.4/morph/converters/pdf.py +576 -0
  10. morphconv-1.0.4/morph/converters/qrcode.py +172 -0
  11. morphconv-1.0.4/morph/converters/raw_photo.py +145 -0
  12. morphconv-1.0.4/morph/converters/subtitles.py +145 -0
  13. morphconv-1.0.4/morph/converters/toml.py +72 -0
  14. morphconv-1.0.4/morph/converters/weasyprint_pdf.py +92 -0
  15. morphconv-1.0.4/morph/converters/web.py +153 -0
  16. {morphconv-1.0.2 → morphconv-1.0.4}/morph/deps.py +29 -9
  17. {morphconv-1.0.2 → morphconv-1.0.4}/morph/history.py +60 -0
  18. morphconv-1.0.4/morphconv.egg-info/PKG-INFO +350 -0
  19. {morphconv-1.0.2 → morphconv-1.0.4}/morphconv.egg-info/SOURCES.txt +8 -0
  20. {morphconv-1.0.2 → morphconv-1.0.4}/morphconv.egg-info/requires.txt +25 -3
  21. {morphconv-1.0.2 → morphconv-1.0.4}/pyproject.toml +26 -4
  22. morphconv-1.0.2/PKG-INFO +0 -396
  23. morphconv-1.0.2/README.md +0 -357
  24. morphconv-1.0.2/morph/converters/archives.py +0 -85
  25. morphconv-1.0.2/morph/converters/web.py +0 -92
  26. morphconv-1.0.2/morphconv.egg-info/PKG-INFO +0 -396
  27. {morphconv-1.0.2 → morphconv-1.0.4}/morph/__init__.py +0 -0
  28. {morphconv-1.0.2 → morphconv-1.0.4}/morph/batch.py +0 -0
  29. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/__init__.py +0 -0
  30. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/audio.py +0 -0
  31. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/csv_json.py +0 -0
  32. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/csv_to_xlsx.py +0 -0
  33. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/documents.py +0 -0
  34. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/ebooks.py +0 -0
  35. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/fonts.py +0 -0
  36. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/json_yaml.py +0 -0
  37. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/models_3d.py +0 -0
  38. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/ocr.py +0 -0
  39. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/pandas_extra.py +0 -0
  40. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/svg.py +0 -0
  41. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/video.py +0 -0
  42. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/vtracer_converter.py +0 -0
  43. {morphconv-1.0.2 → morphconv-1.0.4}/morph/converters/xlsx_to_csv.py +0 -0
  44. {morphconv-1.0.2 → morphconv-1.0.4}/morph/ffmpeg_utils.py +0 -0
  45. {morphconv-1.0.2 → morphconv-1.0.4}/morph/progress.py +0 -0
  46. {morphconv-1.0.2 → morphconv-1.0.4}/morph/registry.py +0 -0
  47. {morphconv-1.0.2 → morphconv-1.0.4}/morph/tui.py +0 -0
  48. {morphconv-1.0.2 → morphconv-1.0.4}/morphconv.egg-info/dependency_links.txt +0 -0
  49. {morphconv-1.0.2 → morphconv-1.0.4}/morphconv.egg-info/entry_points.txt +0 -0
  50. {morphconv-1.0.2 → morphconv-1.0.4}/morphconv.egg-info/top_level.txt +0 -0
  51. {morphconv-1.0.2 → morphconv-1.0.4}/setup.cfg +0 -0
  52. {morphconv-1.0.2 → morphconv-1.0.4}/tests/test_cli.py +0 -0
  53. {morphconv-1.0.2 → morphconv-1.0.4}/tests/test_converters.py +0 -0
  54. {morphconv-1.0.2 → morphconv-1.0.4}/tests/test_registry.py +0 -0
  55. {morphconv-1.0.2 → morphconv-1.0.4}/tests/test_web.py +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 morph contributors
3
+ Copyright (c) 2026 Hariharen S S
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,350 @@
1
+ Metadata-Version: 2.4
2
+ Name: morphconv
3
+ Version: 1.0.4
4
+ Summary: morph — convert anything to anything, from the CLI
5
+ License: MIT
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: pandas>=2.2.0
10
+ Requires-Dist: openpyxl>=3.1.2
11
+ Requires-Dist: xlsxwriter>=3.2.0
12
+ Requires-Dist: xlrd>=2.0.1
13
+ Requires-Dist: pyarrow>=15.0.0
14
+ Requires-Dist: odfpy>=1.4.1
15
+ Requires-Dist: lxml>=5.1.0
16
+ Requires-Dist: SQLAlchemy>=2.0.0
17
+ Requires-Dist: rich>=13.7.0
18
+ Requires-Dist: typer>=0.12.0
19
+ Requires-Dist: chardet>=5.2.0
20
+ Requires-Dist: python-dateutil>=2.9.0
21
+ Requires-Dist: click>=8.1.7
22
+ Requires-Dist: pyyaml>=6.0.1
23
+ Requires-Dist: textual>=0.60.0
24
+ Requires-Dist: Pillow>=10.0.0
25
+ Requires-Dist: pillow-heif>=0.15.0
26
+ Requires-Dist: pillow-avif-plugin>=1.4.3
27
+ Requires-Dist: cairosvg>=2.7.1
28
+ Requires-Dist: fonttools[woff]>=4.50.0
29
+ Requires-Dist: pytesseract>=0.3.10
30
+ Requires-Dist: trafilatura>=1.8.0
31
+ Requires-Dist: vtracer>=0.6.0
32
+ Requires-Dist: yt-dlp>=2024.03.10
33
+ Requires-Dist: pymupdf>=1.24.0
34
+ Requires-Dist: pdfplumber>=0.11.0
35
+ Requires-Dist: pdf2docx>=0.5.8
36
+ Requires-Dist: py7zr>=0.21.0
37
+ Requires-Dist: rarfile>=4.1
38
+ Requires-Dist: pysubs2>=1.6.0
39
+ Requires-Dist: tomlkit>=0.12.0
40
+ Requires-Dist: nbconvert>=7.0.0
41
+ Requires-Dist: img2pdf>=0.5.0
42
+ Requires-Dist: rawpy>=0.19.0
43
+ Requires-Dist: qrcode[pil]>=7.4.0
44
+ Requires-Dist: pyzbar>=0.1.9
45
+ Requires-Dist: markdownify>=0.13.0
46
+ Requires-Dist: weasyprint>=62.0
47
+ Provides-Extra: dev
48
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
49
+ Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
50
+ Provides-Extra: 3d
51
+ Requires-Dist: bpy>=5.0.0; python_version < "3.13" and extra == "3d"
52
+ Provides-Extra: web
53
+ Requires-Dist: crawl4ai>=0.4.0; extra == "web"
54
+ Requires-Dist: playwright>=1.40.0; extra == "web"
55
+ Provides-Extra: all
56
+ Requires-Dist: morphconv[3d,web]; extra == "all"
57
+ Dynamic: license-file
58
+
59
+ <div align="center">
60
+
61
+ # 🦋 MORPH
62
+
63
+ **The Universal File Converter for the Command Line.**
64
+
65
+ *One command. No format-specific tools to remember. No cloud upload. No API keys.*
66
+ *Convert anything, to anything.*
67
+
68
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
69
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
70
+ [![Built with Typer](https://img.shields.io/badge/CLI-Typer-6C47FF.svg)](https://typer.tiangolo.com/)
71
+ [![Powered by Rich](https://img.shields.io/badge/output-Rich-8A2BE2.svg)](https://github.com/Textualize/rich)
72
+ [![TUI: Textual](https://img.shields.io/badge/TUI-Textual-4B0082.svg)](https://textual.textualize.io/)
73
+
74
+ ```bash
75
+ morph report.docx report.pdf
76
+ morph data.csv data.xlsx --table-style TableStyleMedium2 --header-bg 2E7D32
77
+ morph logo.png logo.svg --mode spline
78
+ morph batch '*.mp4' mp3 --workers 4
79
+ morph pack '*.png' photos/ doc.pdf archive.zip
80
+ ```
81
+
82
+ </div>
83
+
84
+ ---
85
+
86
+ ## ⚡ Why `morph` exists
87
+
88
+ `ffmpeg` converts media. `pandoc` converts documents. `ImageMagick` converts images. Each is an incredible piece of software, but using them together is a nightmare of different flag dialects, mental models, and obscure syntax errors.
89
+
90
+ **`morph` doesn't reinvent codecs or file formats — it orchestrates the best tool for each job behind a single, predictable, and beautiful interface.**
91
+
92
+ Whether you are rendering a 3D `.blend` file to a `.png`, scraping a Wikipedia article into a Markdown file, vectorizing a `.jpg` into an `.svg`, or converting a batch of `.csv` files to `.parquet`, `morph` calculates the route, fetches the dependencies, and executes the job.
93
+
94
+ ## ✨ Features
95
+
96
+ - **One Universal Verb.** `morph <input> <output>`. That's it. Omit the output, and `morph` acts as a wizard, presenting you with an interactive menu of all possible destination formats.
97
+ - **Undo.** Made a mistake? Convert a massive 1,000-file directory by accident? Just type `morph undo` and watch it instantly delete the generated files and revert your history.
98
+ - **Smart Multi-Hop Graph Routing.** No direct `csv → yaml` converter? `morph` automatically finds the `csv → json → yaml` route. When crossing wild paradigms (e.g. Markdown → SQLite), `morph` explicitly hints its logic (like `extracts tabular data only`).
99
+ - **Contextual Intelligence.** Run `morph data.csv data.xlsx --help` and you'll *only* see flags relevant to that specific pair (like `--table-style` or `--freeze-cols`). Run it on a video file, and you'll see bitrate and framerate controls instead.
100
+ - **Output Verification.** Pass the `--verify` flag to calculate and display the exact SHA-256 checksum of the resulting file right alongside the success message.
101
+ - **Transparent Remote Downloads.** Pass any `http://` link and `morph` handles the rest. It uses `trafilatura` to scrape web articles into clean Markdown, or `yt-dlp` to natively download high-quality media (`morph <url> --audio`).
102
+ - **Batch Processing Engine.** `morph batch '*.mp4' mp3` converts files concurrently with a live progress table, smart skip logic (`--newer-only`, `--skip-existing`), and output structure mirroring.
103
+ - **Pack Command.** Run `morph pack *.png output.zip` to collect any number of files, globs, or directories into a single archive (zip/7z/tar.gz), with auto-stripped common paths.
104
+ - **Interactive TUI.** Type `morph` with no arguments to launch a stunning, keyboard-driven Textual UI. Navigate your filesystem, preview conversion options, and watch live progress bars without touching your mouse.
105
+ - **Automated Dependency Management.** Missing `ffmpeg` or `pandoc`? `morph` detects your OS and package manager (brew/apt/winget/etc.), shows you the exact install command, and asks before running it. Massive dependencies (like 3D rendering engines) are cleanly isolated as optional extras!
106
+ - **Pluggable Architecture.** Drop a Python script in `morph/converters/`, add a `@register` decorator, and it's instantly live in the routing graph.
107
+ - **Local-First & Private.** No cloud uploads. No API keys. Everything runs on your machine.
108
+
109
+ ---
110
+
111
+ ## 📦 Installation
112
+
113
+ `morph` is natively distributed across all major operating systems. You do not need Python installed to use the standalone binaries!
114
+
115
+ ### Windows
116
+ ```powershell
117
+ # via Winget (Recommended)
118
+ winget install hariharen.morph
119
+
120
+ # via Scoop
121
+ scoop bucket add morph https://github.com/hariharen9/scoop-bucket.git
122
+ scoop install morph
123
+ ```
124
+
125
+ ### macOS & Linux
126
+ ```bash
127
+ # via Homebrew
128
+ brew tap hariharen9/homebrew-tap
129
+ brew install morph
130
+ ```
131
+
132
+ ### Python Ecosystem (PyPI)
133
+ If you prefer managing via `pip` (or `pipx`), install it globally:
134
+ ```bash
135
+ pipx install morphconv
136
+ ```
137
+
138
+ ### Development (Source)
139
+ ```bash
140
+ git clone https://github.com/hariharen9/morph.git
141
+ cd morph
142
+ pip install -e .
143
+ ```
144
+
145
+ `morph` relies on native Python libraries for data, web, and archives. For massive specialized packages, `morph` uses optional extras to keep your base installation blazing fast. If you need them, simply install them:
146
+ ```bash
147
+ pip install -e ".[3d]" # Installs bpy (Blender) for 3D conversions
148
+ pip install -e ".[web]" # Installs crawl4ai and playwright for heavy JS rendering
149
+ ```
150
+
151
+ For domain-specific external binaries (e.g., `ffmpeg`, `pandoc`), you don't need to install these upfront — `morph` will intelligently prompt you to install them the first time they are needed.
152
+
153
+ To see your current system dependencies at any time:
154
+ ```bash
155
+ morph deps
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 🚀 Quickstart & Real-World Examples
161
+
162
+ ### 📊 Data Processing
163
+ Switch between analytical formats effortlessly.
164
+
165
+ ```bash
166
+ morph data.csv data.xlsx
167
+ morph data.json data.yaml
168
+ morph database.sqlite data.csv
169
+ ```
170
+
171
+ ### 📄 Documents & Ebooks
172
+ ```bash
173
+ morph notes.md notes.docx
174
+ morph report.docx report.pdf
175
+ morph book.epub book.mobi
176
+ ```
177
+
178
+ ### 🖼️ Images & Vectorization
179
+ Raster conversions, plus advanced raster-to-vector tracing.
180
+
181
+ ```bash
182
+ # Standard image processing
183
+ morph photo.png photo.webp --quality 80 --resize 1200x
184
+ morph icon.png icon.ico
185
+
186
+ # Raster to Vector (via vtracer)
187
+ morph logo.png logo.svg --mode spline --hierarchical stacked
188
+ ```
189
+
190
+ ### 🎬 Audio & Video (via `ffmpeg`)
191
+ Media manipulation with real-time progress bars parsed directly from ffmpeg.
192
+
193
+ ```bash
194
+ morph song.wav song.mp3 --bitrate 192k
195
+ morph clip.mp4 clip.gif --fps 10 --width 480
196
+ morph clip.mkv clip.mp3 # Extract audio
197
+ ```
198
+
199
+ ### 🌐 Web & Remote Files
200
+ Fetch data directly from the internet and transform it locally in one step. `morph` natively embeds `yt-dlp` to download almost any media from the web.
201
+
202
+ ```bash
203
+ # Natively download video from YouTube, Twitter, etc.
204
+ morph https://youtube.com/watch?v=... video.mp4
205
+
206
+ # Extract audio only from a remote video with metadata embedded
207
+ morph https://youtube.com/watch?v=... audio.mp3 --audio
208
+
209
+ # Scrape an article into clean Markdown (via trafilatura)
210
+ morph https://en.wikipedia.org/wiki/Graph_theory graph_theory.md
211
+
212
+ # Download a remote CSV and style it as an Excel workbook natively
213
+ morph https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/latest/owid-covid-latest.csv covid.xlsx --table-style TableStyleMedium2
214
+
215
+ # Scrape a JavaScript-heavy page (requires morphconv[web])
216
+ morph https://example.com/dynamic-article doc.pdf --js
217
+ ```
218
+
219
+ ### 🧊 3D Models & Rendering (Powered by Blender/`bpy`)
220
+ Seamlessly convert between 3D formats, or utilize headless rendering to generate images of your models.
221
+
222
+ ```bash
223
+ # Format conversion
224
+ morph character.fbx character.glb
225
+ morph scene.obj scene.blend
226
+
227
+ # Headless 3D rendering (automatically places lights and cameras)
228
+ morph character.gltf character.png
229
+ ```
230
+
231
+ ---
232
+
233
+ ## 🏎️ Batch Operations
234
+
235
+ Convert hundreds of files concurrently with a beautiful terminal dashboard.
236
+
237
+ ```bash
238
+ # All MP4s to MP3 using 4 parallel workers
239
+ morph batch '*.mp4' mp3 --workers 4
240
+
241
+ # Recursively convert a whole directory and mirror its structure in an output folder
242
+ morph batch ./raw_footage/ mp3 --recursive --out-dir ./audio_only/ --mirror
243
+
244
+ # Skip files that have already been converted
245
+ morph batch '*.flac' mp3 --skip-existing
246
+ ```
247
+
248
+ During batch conversions, `morph` displays a live status table:
249
+
250
+ ```text
251
+ ╭─ morph batch — 8 files → mp3 ─────────────────────────────────────╮
252
+ │ Status File Time Size │
253
+ │ ✓ done concert_01.flac 0:00:04 8.3MB → 4.1MB │
254
+ │ ✓ done concert_02.flac 0:00:03 7.9MB → 3.8MB │
255
+ │ ▶ converting… concert_03.flac 0:00:01 │
256
+ │ · waiting concert_04.wav │
257
+ │ │
258
+ │ Overall ████████░░░░░░░░ 2/8 [0:00:07] │
259
+ ╰──────────────────────────────────────────────────────────────────────╯
260
+ ```
261
+
262
+ ---
263
+
264
+ ## 🗂️ Supported Formats
265
+
266
+ | Domain | Formats | Backend |
267
+ |---|---|---|
268
+ | **Data** | `csv`, `xlsx`, `json`, `yaml`, `toml`, `parquet`, `feather`, `ods`, `xml`, `html`, `sqlite` | Native (`pandas` / `tomlkit`) |
269
+ | **Documents** | `md`, `html`, `docx`, `odt`, `rtf`, `epub`, `latex`, `rst`, `txt`, `pptx`, `adoc`, `org`, `opml`, `man` | `pandoc` |
270
+ | **Legacy Office** | `doc`, `xls`, `ppt` | `LibreOffice (soffice)` |
271
+ | **Notebooks** | `ipynb` | `nbconvert` (executes & renders outputs) |
272
+ | **PDF** | `pdf` (real text, layout, tables, generation) | `pymupdf` / `pdfplumber` / `pdf2docx` |
273
+ | **Images (Raster)** | `png`, `jpg/jpeg`, `webp`, `bmp`, `gif`, `tiff`, `ico`, `heic`, `avif`, `icns` | `Pillow` / `cairosvg` |
274
+ | **Vectorization** | `png`/`jpg`/etc. → `svg` | `vtracer` |
275
+ | **3D Models** | `obj`, `stl`, `fbx`, `gltf`, `glb`, `blend`, `any → png` (Render) | `bpy` (Blender) |
276
+ | **Web Extraction** | `url` → `md`, `txt`, `xml`, `html` | `trafilatura` / `crawl4ai` |
277
+ | **Audio** | `mp3`, `wav`, `flac`, `ogg`, `aac`, `m4a`, `opus`, `wma` | `ffmpeg` |
278
+ | **Video** | `mp4`, `mkv`, `mov`, `webm`, `avi`, `flv`, `wmv`, `mpeg` | `ffmpeg` |
279
+ | **Subtitles** | `srt`, `vtt`, `ass`, `ssa`, `sub`, `sami` | `pysubs2` |
280
+ | **Ebooks** | `epub`, `mobi`, `azw3` | `ebook-convert` |
281
+ | **Fonts** | `ttf`, `otf`, `woff`, `woff2` | `fontTools` |
282
+ | **OCR** | `png`, `jpg`, `webp`, `pdf`, etc. → `txt` | `tesseract` |
283
+ | **Archives** | `zip`, `7z`, `tar`, `tar.gz`, `tar.bz2`, `tar.xz`, `rar`* | Python stdlib / `py7zr` / `rarfile` |
284
+
285
+ *\* Note: RAR is an extract-only format (RAR creation requires proprietary tools).*
286
+
287
+ ---
288
+
289
+ ## 🛠️ Architecture & Under the Hood
290
+
291
+ The magic of `morph` lies in its modular graph architecture.
292
+
293
+ ```text
294
+ morph/
295
+ ├── cli.py # Command dispatch (run, batch, formats, history, deps)
296
+ ├── registry.py # BFS Routing graph & registration logic
297
+ ├── tui.py # Textual keyboard-driven TUI
298
+ └── converters/
299
+ ├── __init__.py # Auto-discovers all modules
300
+ ├── documents.py # pandoc engine
301
+ ├── images.py # Pillow engine
302
+ ├── models_3d.py # Blender/bpy engine
303
+ ├── web.py # trafilatura / crawl4ai engine
304
+ └── vtracer_converter.py # Raster-to-SVG vectorization
305
+ ```
306
+
307
+ ### Adding a new conversion is trivial
308
+
309
+ Drop a file in `morph/converters/` and use the `@register` decorator. No central registry, no CLI parsers to update.
310
+
311
+ ```python
312
+ from pathlib import Path
313
+ from ..registry import ConversionResult, OptionSpec, register
314
+
315
+ @register("foo", "bar", backend="mytool", family="image")
316
+ def foo_to_bar(input_path: Path, output_path: Path, **kwargs) -> ConversionResult:
317
+ # Do the conversion...
318
+ return ConversionResult(output=output_path)
319
+ ```
320
+
321
+ Because of `morph`'s graph routing, once `foo → bar` is registered, if a path exists from `bar → baz`, `morph` immediately knows how to convert `foo → baz`.
322
+
323
+ ---
324
+
325
+ ## 📜 History & Transparency
326
+
327
+ Every conversion is automatically logged. You can review your execution history at any time.
328
+
329
+ ```bash
330
+ morph history
331
+ ```
332
+
333
+ ```text
334
+ ┌──────────┬──────┬──────┬────────────────┬────────┬────────────┐
335
+ │ When │ From │ To │ File │ Mode │ Status │
336
+ ├──────────┼──────┼──────┼────────────────┼────────┼────────────┤
337
+ │ 2m ago │ md │ docx │ README.md │ single │ ✓ 1.8s │
338
+ │ 1h ago │ mp4 │ mp3 │ intro.mp4 │ batch │ ✓ 4.2s │
339
+ └──────────┴──────┴──────┴────────────────┴────────┴────────────┘
340
+ ```
341
+
342
+ ---
343
+
344
+ ## 🤝 Contributing
345
+
346
+ PRs are highly encouraged! If you are adding a new conversion, simply add the file in the `converters/` directory.
347
+
348
+ ## ⚖️ License
349
+
350
+ Released under the [MIT License](LICENSE).
@@ -0,0 +1,292 @@
1
+ <div align="center">
2
+
3
+ # 🦋 MORPH
4
+
5
+ **The Universal File Converter for the Command Line.**
6
+
7
+ *One command. No format-specific tools to remember. No cloud upload. No API keys.*
8
+ *Convert anything, to anything.*
9
+
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
11
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
12
+ [![Built with Typer](https://img.shields.io/badge/CLI-Typer-6C47FF.svg)](https://typer.tiangolo.com/)
13
+ [![Powered by Rich](https://img.shields.io/badge/output-Rich-8A2BE2.svg)](https://github.com/Textualize/rich)
14
+ [![TUI: Textual](https://img.shields.io/badge/TUI-Textual-4B0082.svg)](https://textual.textualize.io/)
15
+
16
+ ```bash
17
+ morph report.docx report.pdf
18
+ morph data.csv data.xlsx --table-style TableStyleMedium2 --header-bg 2E7D32
19
+ morph logo.png logo.svg --mode spline
20
+ morph batch '*.mp4' mp3 --workers 4
21
+ morph pack '*.png' photos/ doc.pdf archive.zip
22
+ ```
23
+
24
+ </div>
25
+
26
+ ---
27
+
28
+ ## ⚡ Why `morph` exists
29
+
30
+ `ffmpeg` converts media. `pandoc` converts documents. `ImageMagick` converts images. Each is an incredible piece of software, but using them together is a nightmare of different flag dialects, mental models, and obscure syntax errors.
31
+
32
+ **`morph` doesn't reinvent codecs or file formats — it orchestrates the best tool for each job behind a single, predictable, and beautiful interface.**
33
+
34
+ Whether you are rendering a 3D `.blend` file to a `.png`, scraping a Wikipedia article into a Markdown file, vectorizing a `.jpg` into an `.svg`, or converting a batch of `.csv` files to `.parquet`, `morph` calculates the route, fetches the dependencies, and executes the job.
35
+
36
+ ## ✨ Features
37
+
38
+ - **One Universal Verb.** `morph <input> <output>`. That's it. Omit the output, and `morph` acts as a wizard, presenting you with an interactive menu of all possible destination formats.
39
+ - **Undo.** Made a mistake? Convert a massive 1,000-file directory by accident? Just type `morph undo` and watch it instantly delete the generated files and revert your history.
40
+ - **Smart Multi-Hop Graph Routing.** No direct `csv → yaml` converter? `morph` automatically finds the `csv → json → yaml` route. When crossing wild paradigms (e.g. Markdown → SQLite), `morph` explicitly hints its logic (like `extracts tabular data only`).
41
+ - **Contextual Intelligence.** Run `morph data.csv data.xlsx --help` and you'll *only* see flags relevant to that specific pair (like `--table-style` or `--freeze-cols`). Run it on a video file, and you'll see bitrate and framerate controls instead.
42
+ - **Output Verification.** Pass the `--verify` flag to calculate and display the exact SHA-256 checksum of the resulting file right alongside the success message.
43
+ - **Transparent Remote Downloads.** Pass any `http://` link and `morph` handles the rest. It uses `trafilatura` to scrape web articles into clean Markdown, or `yt-dlp` to natively download high-quality media (`morph <url> --audio`).
44
+ - **Batch Processing Engine.** `morph batch '*.mp4' mp3` converts files concurrently with a live progress table, smart skip logic (`--newer-only`, `--skip-existing`), and output structure mirroring.
45
+ - **Pack Command.** Run `morph pack *.png output.zip` to collect any number of files, globs, or directories into a single archive (zip/7z/tar.gz), with auto-stripped common paths.
46
+ - **Interactive TUI.** Type `morph` with no arguments to launch a stunning, keyboard-driven Textual UI. Navigate your filesystem, preview conversion options, and watch live progress bars without touching your mouse.
47
+ - **Automated Dependency Management.** Missing `ffmpeg` or `pandoc`? `morph` detects your OS and package manager (brew/apt/winget/etc.), shows you the exact install command, and asks before running it. Massive dependencies (like 3D rendering engines) are cleanly isolated as optional extras!
48
+ - **Pluggable Architecture.** Drop a Python script in `morph/converters/`, add a `@register` decorator, and it's instantly live in the routing graph.
49
+ - **Local-First & Private.** No cloud uploads. No API keys. Everything runs on your machine.
50
+
51
+ ---
52
+
53
+ ## 📦 Installation
54
+
55
+ `morph` is natively distributed across all major operating systems. You do not need Python installed to use the standalone binaries!
56
+
57
+ ### Windows
58
+ ```powershell
59
+ # via Winget (Recommended)
60
+ winget install hariharen.morph
61
+
62
+ # via Scoop
63
+ scoop bucket add morph https://github.com/hariharen9/scoop-bucket.git
64
+ scoop install morph
65
+ ```
66
+
67
+ ### macOS & Linux
68
+ ```bash
69
+ # via Homebrew
70
+ brew tap hariharen9/homebrew-tap
71
+ brew install morph
72
+ ```
73
+
74
+ ### Python Ecosystem (PyPI)
75
+ If you prefer managing via `pip` (or `pipx`), install it globally:
76
+ ```bash
77
+ pipx install morphconv
78
+ ```
79
+
80
+ ### Development (Source)
81
+ ```bash
82
+ git clone https://github.com/hariharen9/morph.git
83
+ cd morph
84
+ pip install -e .
85
+ ```
86
+
87
+ `morph` relies on native Python libraries for data, web, and archives. For massive specialized packages, `morph` uses optional extras to keep your base installation blazing fast. If you need them, simply install them:
88
+ ```bash
89
+ pip install -e ".[3d]" # Installs bpy (Blender) for 3D conversions
90
+ pip install -e ".[web]" # Installs crawl4ai and playwright for heavy JS rendering
91
+ ```
92
+
93
+ For domain-specific external binaries (e.g., `ffmpeg`, `pandoc`), you don't need to install these upfront — `morph` will intelligently prompt you to install them the first time they are needed.
94
+
95
+ To see your current system dependencies at any time:
96
+ ```bash
97
+ morph deps
98
+ ```
99
+
100
+ ---
101
+
102
+ ## 🚀 Quickstart & Real-World Examples
103
+
104
+ ### 📊 Data Processing
105
+ Switch between analytical formats effortlessly.
106
+
107
+ ```bash
108
+ morph data.csv data.xlsx
109
+ morph data.json data.yaml
110
+ morph database.sqlite data.csv
111
+ ```
112
+
113
+ ### 📄 Documents & Ebooks
114
+ ```bash
115
+ morph notes.md notes.docx
116
+ morph report.docx report.pdf
117
+ morph book.epub book.mobi
118
+ ```
119
+
120
+ ### 🖼️ Images & Vectorization
121
+ Raster conversions, plus advanced raster-to-vector tracing.
122
+
123
+ ```bash
124
+ # Standard image processing
125
+ morph photo.png photo.webp --quality 80 --resize 1200x
126
+ morph icon.png icon.ico
127
+
128
+ # Raster to Vector (via vtracer)
129
+ morph logo.png logo.svg --mode spline --hierarchical stacked
130
+ ```
131
+
132
+ ### 🎬 Audio & Video (via `ffmpeg`)
133
+ Media manipulation with real-time progress bars parsed directly from ffmpeg.
134
+
135
+ ```bash
136
+ morph song.wav song.mp3 --bitrate 192k
137
+ morph clip.mp4 clip.gif --fps 10 --width 480
138
+ morph clip.mkv clip.mp3 # Extract audio
139
+ ```
140
+
141
+ ### 🌐 Web & Remote Files
142
+ Fetch data directly from the internet and transform it locally in one step. `morph` natively embeds `yt-dlp` to download almost any media from the web.
143
+
144
+ ```bash
145
+ # Natively download video from YouTube, Twitter, etc.
146
+ morph https://youtube.com/watch?v=... video.mp4
147
+
148
+ # Extract audio only from a remote video with metadata embedded
149
+ morph https://youtube.com/watch?v=... audio.mp3 --audio
150
+
151
+ # Scrape an article into clean Markdown (via trafilatura)
152
+ morph https://en.wikipedia.org/wiki/Graph_theory graph_theory.md
153
+
154
+ # Download a remote CSV and style it as an Excel workbook natively
155
+ morph https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/latest/owid-covid-latest.csv covid.xlsx --table-style TableStyleMedium2
156
+
157
+ # Scrape a JavaScript-heavy page (requires morphconv[web])
158
+ morph https://example.com/dynamic-article doc.pdf --js
159
+ ```
160
+
161
+ ### 🧊 3D Models & Rendering (Powered by Blender/`bpy`)
162
+ Seamlessly convert between 3D formats, or utilize headless rendering to generate images of your models.
163
+
164
+ ```bash
165
+ # Format conversion
166
+ morph character.fbx character.glb
167
+ morph scene.obj scene.blend
168
+
169
+ # Headless 3D rendering (automatically places lights and cameras)
170
+ morph character.gltf character.png
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 🏎️ Batch Operations
176
+
177
+ Convert hundreds of files concurrently with a beautiful terminal dashboard.
178
+
179
+ ```bash
180
+ # All MP4s to MP3 using 4 parallel workers
181
+ morph batch '*.mp4' mp3 --workers 4
182
+
183
+ # Recursively convert a whole directory and mirror its structure in an output folder
184
+ morph batch ./raw_footage/ mp3 --recursive --out-dir ./audio_only/ --mirror
185
+
186
+ # Skip files that have already been converted
187
+ morph batch '*.flac' mp3 --skip-existing
188
+ ```
189
+
190
+ During batch conversions, `morph` displays a live status table:
191
+
192
+ ```text
193
+ ╭─ morph batch — 8 files → mp3 ─────────────────────────────────────╮
194
+ │ Status File Time Size │
195
+ │ ✓ done concert_01.flac 0:00:04 8.3MB → 4.1MB │
196
+ │ ✓ done concert_02.flac 0:00:03 7.9MB → 3.8MB │
197
+ │ ▶ converting… concert_03.flac 0:00:01 │
198
+ │ · waiting concert_04.wav │
199
+ │ │
200
+ │ Overall ████████░░░░░░░░ 2/8 [0:00:07] │
201
+ ╰──────────────────────────────────────────────────────────────────────╯
202
+ ```
203
+
204
+ ---
205
+
206
+ ## 🗂️ Supported Formats
207
+
208
+ | Domain | Formats | Backend |
209
+ |---|---|---|
210
+ | **Data** | `csv`, `xlsx`, `json`, `yaml`, `toml`, `parquet`, `feather`, `ods`, `xml`, `html`, `sqlite` | Native (`pandas` / `tomlkit`) |
211
+ | **Documents** | `md`, `html`, `docx`, `odt`, `rtf`, `epub`, `latex`, `rst`, `txt`, `pptx`, `adoc`, `org`, `opml`, `man` | `pandoc` |
212
+ | **Legacy Office** | `doc`, `xls`, `ppt` | `LibreOffice (soffice)` |
213
+ | **Notebooks** | `ipynb` | `nbconvert` (executes & renders outputs) |
214
+ | **PDF** | `pdf` (real text, layout, tables, generation) | `pymupdf` / `pdfplumber` / `pdf2docx` |
215
+ | **Images (Raster)** | `png`, `jpg/jpeg`, `webp`, `bmp`, `gif`, `tiff`, `ico`, `heic`, `avif`, `icns` | `Pillow` / `cairosvg` |
216
+ | **Vectorization** | `png`/`jpg`/etc. → `svg` | `vtracer` |
217
+ | **3D Models** | `obj`, `stl`, `fbx`, `gltf`, `glb`, `blend`, `any → png` (Render) | `bpy` (Blender) |
218
+ | **Web Extraction** | `url` → `md`, `txt`, `xml`, `html` | `trafilatura` / `crawl4ai` |
219
+ | **Audio** | `mp3`, `wav`, `flac`, `ogg`, `aac`, `m4a`, `opus`, `wma` | `ffmpeg` |
220
+ | **Video** | `mp4`, `mkv`, `mov`, `webm`, `avi`, `flv`, `wmv`, `mpeg` | `ffmpeg` |
221
+ | **Subtitles** | `srt`, `vtt`, `ass`, `ssa`, `sub`, `sami` | `pysubs2` |
222
+ | **Ebooks** | `epub`, `mobi`, `azw3` | `ebook-convert` |
223
+ | **Fonts** | `ttf`, `otf`, `woff`, `woff2` | `fontTools` |
224
+ | **OCR** | `png`, `jpg`, `webp`, `pdf`, etc. → `txt` | `tesseract` |
225
+ | **Archives** | `zip`, `7z`, `tar`, `tar.gz`, `tar.bz2`, `tar.xz`, `rar`* | Python stdlib / `py7zr` / `rarfile` |
226
+
227
+ *\* Note: RAR is an extract-only format (RAR creation requires proprietary tools).*
228
+
229
+ ---
230
+
231
+ ## 🛠️ Architecture & Under the Hood
232
+
233
+ The magic of `morph` lies in its modular graph architecture.
234
+
235
+ ```text
236
+ morph/
237
+ ├── cli.py # Command dispatch (run, batch, formats, history, deps)
238
+ ├── registry.py # BFS Routing graph & registration logic
239
+ ├── tui.py # Textual keyboard-driven TUI
240
+ └── converters/
241
+ ├── __init__.py # Auto-discovers all modules
242
+ ├── documents.py # pandoc engine
243
+ ├── images.py # Pillow engine
244
+ ├── models_3d.py # Blender/bpy engine
245
+ ├── web.py # trafilatura / crawl4ai engine
246
+ └── vtracer_converter.py # Raster-to-SVG vectorization
247
+ ```
248
+
249
+ ### Adding a new conversion is trivial
250
+
251
+ Drop a file in `morph/converters/` and use the `@register` decorator. No central registry, no CLI parsers to update.
252
+
253
+ ```python
254
+ from pathlib import Path
255
+ from ..registry import ConversionResult, OptionSpec, register
256
+
257
+ @register("foo", "bar", backend="mytool", family="image")
258
+ def foo_to_bar(input_path: Path, output_path: Path, **kwargs) -> ConversionResult:
259
+ # Do the conversion...
260
+ return ConversionResult(output=output_path)
261
+ ```
262
+
263
+ Because of `morph`'s graph routing, once `foo → bar` is registered, if a path exists from `bar → baz`, `morph` immediately knows how to convert `foo → baz`.
264
+
265
+ ---
266
+
267
+ ## 📜 History & Transparency
268
+
269
+ Every conversion is automatically logged. You can review your execution history at any time.
270
+
271
+ ```bash
272
+ morph history
273
+ ```
274
+
275
+ ```text
276
+ ┌──────────┬──────┬──────┬────────────────┬────────┬────────────┐
277
+ │ When │ From │ To │ File │ Mode │ Status │
278
+ ├──────────┼──────┼──────┼────────────────┼────────┼────────────┤
279
+ │ 2m ago │ md │ docx │ README.md │ single │ ✓ 1.8s │
280
+ │ 1h ago │ mp4 │ mp3 │ intro.mp4 │ batch │ ✓ 4.2s │
281
+ └──────────┴──────┴──────┴────────────────┴────────┴────────────┘
282
+ ```
283
+
284
+ ---
285
+
286
+ ## 🤝 Contributing
287
+
288
+ PRs are highly encouraged! If you are adding a new conversion, simply add the file in the `converters/` directory.
289
+
290
+ ## ⚖️ License
291
+
292
+ Released under the [MIT License](LICENSE).