doctopdf 2.0.5b0__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.
@@ -0,0 +1,573 @@
1
+ Metadata-Version: 2.4
2
+ Name: doctopdf
3
+ Version: 2.0.5b0
4
+ Summary: Offline batch .doc/.docx → PDF converter using Microsoft Word on macOS
5
+ Author: DocToPDF Team
6
+ License: MIT
7
+ Keywords: docx,doc,pdf,converter,microsoft-word,macos
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: End Users/Desktop
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: MacOS :: MacOS X
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Office/Business :: Office Suites
19
+ Classifier: Topic :: Text Processing
20
+ Classifier: Topic :: Text Editors :: Word Processors
21
+ Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest; extra == "dev"
26
+ Requires-Dist: pytest-cov; extra == "dev"
27
+ Requires-Dist: ruff; extra == "dev"
28
+ Requires-Dist: mypy; extra == "dev"
29
+
30
+ # DocToPDF — Offline macOS Batch Document Converter
31
+
32
+ <div align="center">
33
+
34
+ ![Python 3.9+](https://img.shields.io/badge/Python-3.9+-blue?logo=python&logoColor=white)
35
+ ![Platform: macOS](https://img.shields.io/badge/Platform-macOS-lightgrey?logo=apple&logoColor=black)
36
+ ![Automation: AppleScript](https://img.shields.io/badge/Automation-AppleScript%20%2F%20JXA-purple)
37
+ ![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)
38
+ ![Version: 1.2.0](https://img.shields.io/badge/version-1.2.0-brightgreen)
39
+ ![CI](https://github.com/HarryW00/doctopdf/actions/workflows/lint.yml/badge.svg)
40
+
41
+ </div>
42
+
43
+ <div align="center">
44
+
45
+ <!-- TODO: Add demo GIF — terminal recording showing batch conversion workflow (e.g. asciinema or QuickTime screen recording). Save to docs/images/demo.gif -->
46
+
47
+ </div>
48
+
49
+ **Convert .doc and .docx files to PDF using Microsoft Word as the rendering engine.**
50
+ Runs entirely offline with zero cloud dependencies.
51
+
52
+ ## How It Works
53
+
54
+ ```
55
+ Input (.doc/.docx) ──→ Microsoft Word (JXA automation) ──→ Output (.pdf)
56
+ ```
57
+
58
+ The tool uses AppleScript/JXA (JavaScript for Automation) to tell Microsoft Word to open each document and export it as PDF. This guarantees **maximum formatting fidelity** — the PDF looks exactly as it would if you manually opened the file in Word and chose File → Export as PDF.
59
+
60
+ ## Requirements (what you need before starting)
61
+
62
+ Before you can use this tool, make sure you have everything listed below:
63
+
64
+ | Requirement | Why you need it | How to check you have it |
65
+ |---|---|---|
66
+ | **macOS 11 (Big Sur) or newer** | Only runs on Mac | Click the Apple menu  → About This Mac → look at macOS version |
67
+ | **Python 3.9 or later** | The tool is written in Python | Open Terminal and type `python3 --version`. You should see `Python 3.9.x` or higher. If you don't have Python, see the note below. |
68
+ | **Microsoft Word for Mac** | This is the engine that actually converts the files to PDF. You need Word 2019, Microsoft 365, or any newer version. | Open Word and go to Word menu → About Microsoft Word |
69
+ | **Automation permission** | macOS needs your permission before this tool can talk to Word. You'll be prompted on first use. | You don't need to check this in advance — see the Permissions section below. |
70
+
71
+ > **No Python?** macOS usually comes with Python 3 pre-installed. If `python3 --version` gives an error, install Python from [python.org](https://www.python.org/downloads/). Download the macOS installer, run it, and follow the steps.
72
+
73
+ ## Installation (step by step)
74
+
75
+ There are **three ways** to use this tool. Choose whichever is easiest for you:
76
+
77
+ | Option | Method | Best for |
78
+ |--------|--------|----------|
79
+ | **A** | [Homebrew](https://brew.sh) — `brew install harryw00/doctopdf/doctopdf` | Everyone with Homebrew installed |
80
+ | **B** | pip — `pip3 install .` (from source) | Users who prefer pip / don't have Homebrew |
81
+ | **C** | Run without install — `python3 -m doctopdf` | Quick test, no installation wanted |
82
+
83
+ ---
84
+
85
+ ### Option A: Install via Homebrew (easiest)
86
+
87
+ If you have [Homebrew](https://brew.sh) installed, this is the one-command way:
88
+
89
+ ```bash
90
+ brew install harryw00/doctopdf/doctopdf
91
+ ```
92
+
93
+ Homebrew automatically sets up all paths — no `cd`, no `pip`, no PATH fixes needed.
94
+ It also keeps `doctopdf` up-to-date when you run `brew update && brew upgrade`.
95
+
96
+ #### Verify it worked
97
+
98
+ ```bash
99
+ convert-word-pdf --check
100
+ ```
101
+
102
+ ---
103
+
104
+ ### Option B: Install via pip
105
+
106
+ > **📦 PyPI package pending** — Once published, you'll be able to run `pip3 install doctopdf`.
107
+ > For now, install from the source checkout.
108
+
109
+ #### Step 1: Open Terminal
110
+
111
+ - Press **Cmd + Space** → type **"Terminal"** → Enter
112
+
113
+ #### Step 2: Get the source
114
+
115
+ ```bash
116
+ git clone https://github.com/HarryW00/doctopdf.git
117
+ cd doctopdf
118
+ ```
119
+
120
+ *(Or download the ZIP from GitHub and extract it.)*
121
+
122
+ #### Step 3: Install
123
+
124
+ ```bash
125
+ pip3 install .
126
+ ```
127
+
128
+ > **⚠️ You may see a warning like this:**
129
+ > ```
130
+ > WARNING: The script convert-word-pdf is installed in
131
+ > '/Users/yourname/Library/Python/3.9/bin' which is not on PATH.
132
+ > ```
133
+ > This is normal on macOS — Python's install folder isn't on your `PATH` by default.
134
+ > See the **Troubleshooting** section below to fix this in one minute.
135
+
136
+ #### Step 4: Verify it worked
137
+
138
+ ```bash
139
+ convert-word-pdf --check
140
+ ```
141
+
142
+ You should see:
143
+
144
+ ```
145
+ ✓ Microsoft Word is installed (version: 16.72)
146
+ The automation bridge is operational.
147
+ ```
148
+
149
+ ---
150
+
151
+ ### Option C: Run directly (no installation)
152
+
153
+ If you'd rather not install anything, run the tool straight from the project folder:
154
+
155
+ ```bash
156
+ cd path/to/doctopdf
157
+ python3 -m doctopdf --check
158
+ ```
159
+
160
+ Use `python3 -m doctopdf` wherever the docs say `convert-word-pdf`:
161
+
162
+ | Instead of this | Use this |
163
+ |-----------------|----------|
164
+ | `convert-word-pdf --check` | `python3 -m doctopdf --check` |
165
+ | `convert-word-pdf -i ./docs -o ./pdfs` | `python3 -m doctopdf -i ./docs -o ./pdfs` |
166
+ | `convert-word-pdf --version` | `python3 -m doctopdf --version` |
167
+
168
+ ---
169
+
170
+ ### After installing (all options)
171
+
172
+ Run the check to make sure Word is detected:
173
+
174
+ ```bash
175
+ # Installed (Option A or B)
176
+ convert-word-pdf --check
177
+
178
+ # Direct run (Option C)
179
+ python3 -m doctopdf --check
180
+ ```
181
+
182
+ **Expected output:**
183
+
184
+ ```
185
+ ✓ Microsoft Word is installed (version: 16.72)
186
+ The automation bridge is operational.
187
+ ```
188
+
189
+ **If you see "Word is NOT installed":**
190
+ 1. Make sure Microsoft Word is actually installed (open it from Applications)
191
+ 2. If Word opens but the check still fails, close Word completely (Word menu → Quit Microsoft Word) and try again
192
+ 3. If you just installed Word, restart your Mac and try again
193
+
194
+ **If you see a permission error (-1743):**
195
+ This means macOS hasn't granted Automation permission yet. Run the command a second time — macOS should show a permission dialog. Click **Allow**. See the **macOS Permissions** section below if this doesn't happen.
196
+
197
+ > **⚠️ Data Safety — Important**
198
+ >
199
+ > DocToPDF is a **batch automation tool**. If you accidentally point it at the wrong folder or a file gets corrupted during conversion, documents could be lost or damaged.
200
+ >
201
+ > **Before running your first conversion:**
202
+ > 1. **Back up your documents** — copy your `.doc` / `.docx` files to a separate backup folder, or ensure you have Time Machine or cloud backup running
203
+ > 2. **Use a dedicated input folder** — copy the files you want to convert into a new folder rather than pointing the tool at your master document directory
204
+ > 3. **Try a dry run first** — add `--dry-run` to see which files will be processed before any conversion happens:
205
+ > ```bash
206
+ > convert-word-pdf -i ./docs -o ./pdfs --dry-run
207
+ > ```
208
+
209
+ ## Quick Start
210
+
211
+ ```bash
212
+ # Convert all .doc/.docx files in ~/Documents/reports recursively
213
+ convert-word-pdf --input ~/Documents/reports --output ~/Documents/pdfs
214
+
215
+ # Same, but with abbreviated flags
216
+ convert-word-pdf -i ./docs -o ./pdfs -r
217
+
218
+ # Flat output (all PDFs in one folder)
219
+ convert-word-pdf -i ./docs -o ./pdfs --flat
220
+
221
+ # Top-level only (no subdirectory recursion)
222
+ convert-word-pdf -i ./docs -o ./pdfs --no-recursive
223
+
224
+ # Dry run — see what would be converted without doing it
225
+ convert-word-pdf -i ./docs -o ./pdfs --dry-run
226
+
227
+ # Custom timeout and retry for large/complex documents
228
+ convert-word-pdf -i ./docs -o ./pdfs --timeout 120 --retry 3
229
+
230
+ # Export results to a structured log
231
+ convert-word-pdf -i ./docs -o ./pdfs --log-file ./conversion-log.json
232
+ ```
233
+
234
+ ## Output Structure
235
+
236
+ ### Mirrored Tree (Default)
237
+
238
+ The input directory structure is preserved under the output folder:
239
+
240
+ ```
241
+ Input: Output:
242
+ ./docs/ ./pdfs/
243
+ ├── report.docx ──→ ├── report.pdf
244
+ ├── subdir/ ├── subdir/
245
+ │ ├── notes.docx ──→ │ ├── notes.pdf
246
+ │ └── deep/ │ └── deep/
247
+ │ └── final.docx ──→ │ └── final.pdf
248
+ ```
249
+
250
+ ### Flat Mode (`--flat`)
251
+
252
+ All PDFs are written directly into the output folder. If filenames collide, a `_1`, `_2`, etc. suffix is appended.
253
+
254
+ ```
255
+ ./pdfs/
256
+ ├── report.pdf
257
+ ├── notes.pdf
258
+ ├── notes_1.pdf
259
+ ```
260
+
261
+ ## CLI Reference
262
+
263
+ | Argument | Short | Default | Description |
264
+ |---|---|---|---|
265
+ | `--input` | `-i` | — | Input directory (`.doc`/`.docx` files) |
266
+ | `--output` | `-o` | — | Output directory for PDFs |
267
+ | `--recursive` | `-r` | `True` | Scan subdirectories |
268
+ | `--no-recursive` | — | — | Top-level scan only |
269
+ | `--flat` | — | `False` | Flat output (no mirrored tree) |
270
+ | `--timeout` | — | `60` | Seconds per document before timeout |
271
+ | `--retry` | — | `2` | Retries per failed conversion |
272
+ | `--restart-every` | — | `0` | Restart Word every N conversions (0 = never). Use for 100+ file batches |
273
+ | `--dry-run` | `-n` | `False` | Scan only, no conversion |
274
+ | `--log-file` | — | — | Export log to `.json` or `.csv` |
275
+ | `--quiet` | `-q` | `False` | Suppress per-file status |
276
+ | `--check` | — | — | Probe for Word installation |
277
+ | `--version` | `-v` | — | Show version |
278
+
279
+ ## Error Handling
280
+
281
+ | Problem | What Happens | User Action |
282
+ |---|---|---|
283
+ | **Word not installed** | Clear error on startup | Install Microsoft Word |
284
+ | **Permission denied (-1743)** | Error with fix instructions | System Settings → Automation |
285
+ | **File locked / open in Word** | Retries 2×, then skips | Close the file in Word |
286
+ | **Corrupt document** | Skips with error message | Repair the source file |
287
+ | **Export failure** | Retries 2×, then skips | Try converting manually in Word |
288
+ | **Timeout** | Skips after `--timeout` seconds | Increase `--timeout` for large files |
289
+ | **File not writable** | Error with path details | Check output directory permissions |
290
+ | **Word crashes** | Detects crash, restarts Word, retries | Rare; check for Word updates |
291
+
292
+ ### Retry Policy
293
+
294
+ The converter retries only **recoverable errors** (timeouts, transient export failures, Word crashes). It does **not** retry:
295
+ - Corrupt/unreadable documents (will always fail)
296
+ - Permission errors (user must fix)
297
+ - File access errors (disk or path issues)
298
+
299
+ ## macOS Permissions
300
+
301
+ ### Automation Permission
302
+
303
+ The first time you run the tool (or the Automator Quick Action), macOS will show a dialog:
304
+
305
+ > **"Terminal" wants access to control "Microsoft Word".**
306
+ > [Deny] [Allow]
307
+
308
+ <!-- TODO: Add screenshot — macOS Automation Permission dialog ("Terminal" wants access to control "Microsoft Word"). Save to docs/images/automation-permission-dialog.png -->
309
+
310
+ Click **Allow**. If you accidentally deny, fix it:
311
+
312
+ 1. Open **System Settings** (or System Preferences)
313
+ 2. Go to **Privacy & Security → Automation**
314
+ 3. Find **Terminal** (or your app — e.g., iTerm2, Automator)
315
+ 4. Toggle **ON** the checkbox next to **"Microsoft Word"**
316
+
317
+ ### File Access
318
+
319
+ The tool needs read access to the input directory and write access to the output directory. Standard macOS file permissions apply. For directories under `~/Documents`, your terminal app typically already has access.
320
+
321
+ When Microsoft Word opens a document from a folder it hasn't accessed before, macOS may show a **"Grant File Access"** dialog:
322
+
323
+ <!-- TODO: Add screenshot — see docs/images/file-access-dialog.png -->
324
+ ```
325
+ Microsoft Word wants to access files in your "Downloads" folder.
326
+ [Deny] [Allow]
327
+ ```
328
+
329
+ Click **Allow** so Word can read the source document and write the PDF. If you click Deny by accident, the conversion will fail with a file-access error — just re-run the tool and macOS will prompt again.
330
+
331
+ ### No Network/Accessibility Permissions
332
+
333
+ This tool requires:
334
+ - ✅ Automation (Terminal → Microsoft Word)
335
+ - ❌ No network/Internet access
336
+ - ❌ No Accessibility/Screen Recording permissions
337
+ - ❌ No Full Disk Access
338
+
339
+ ## Automator Quick Action (Finder Right-Click)
340
+
341
+ Create a macOS Finder right-click service that converts documents to PDF without opening Terminal. See the [full setup guide](docs/automator.md) for step-by-step instructions.
342
+
343
+ ## Comparison with Other Tools
344
+
345
+ | Dimension | DocToPDF (Word) | LibreOffice | Pandoc | python-docx |
346
+ |---|---|---|---|---|
347
+ | **Rendering fidelity** | ★★★★★ (Word's engine) | ★★★★ (good, minor diffs) | ★★ (markdown-centric) | ★ (no layout engine) |
348
+ | **Speed** | ★★★ (Word launch overhead) | ★★★★ (fast headless) | ★★★★★ | ★★★★★ |
349
+ | **License cost** | Requires Microsoft Word | Free | Free | Free |
350
+ | **Offline** | ✅ Fully | ✅ Fully | ✅ Fully | ✅ Fully |
351
+ | **VBA macros** | ✅ Executed | ⚠️ Partial | ❌ | ❌ |
352
+ | **Complex formatting** | ✅ Full Word fidelity | ⚠️ Minor regressions | ❌ | ❌ |
353
+ | **PDF bookmarks/TOC** | ✅ Word-native | ⚠️ Varies | ❌ | ❌ |
354
+ | **Batch-friendly** | ✅ Sequential | ✅ Parallel-capable | ✅ | ✅ |
355
+ | **macOS native** | ✅ AppleScript/JXA | ⚠️ X11 or headless | ✅ | ✅ |
356
+
357
+ ### When to Use This Tool
358
+
359
+ - **Fidelity matters**: Legal documents, official submissions, contracts, academic papers
360
+ - **Complex formatting**: Multi-column layouts, embedded fonts, tracked changes, SmartArt
361
+ - **Security constraints**: The environment blocks cloud uploads and web APIs
362
+ - **Workflow integration**: You want a Finder right-click option
363
+
364
+ ### When to Use LibreOffice Instead
365
+
366
+ - You don't have a Microsoft Word license
367
+ - You need to run headless on a server (Linux/CI)
368
+ - You need parallel batch conversion for hundreds of files
369
+ - Minor rendering differences are acceptable
370
+
371
+ ## Performance Notes
372
+
373
+ ### Expected Conversion Times
374
+
375
+ | File Type | Size | Typical Time |
376
+ |---|---|---|
377
+ | Simple text (.docx) | ~50 KB | 3–8 s |
378
+ | With images/tables | ~5 MB | 8–20 s |
379
+ | Large legacy (.doc) | ~20 MB | 15–45 s |
380
+ | Very large + complex | ~100 MB | 60–120 s |
381
+
382
+ **Cold start** (first conversion): includes Word launch time (+3–8s).
383
+ **Subsequent conversions** are faster (2–5s typical) because Word stays warm.
384
+
385
+ ### Keep Word Warm Strategy
386
+
387
+ The converter **never restarts Word between conversions** by default. This is deliberate — keeping Word running for the entire batch eliminates the 5–15s relaunch penalty and avoids the reliability issues that come with killing and restarting the application.
388
+
389
+ For very large batches (100+ files), use `--restart-every N` to periodically restart Word and prevent any accumulated state degradation. A good rule of thumb is `--restart-every 50`.
390
+
391
+ ### No Parallelism
392
+
393
+ Microsoft Word on macOS is a single-instance application. Running parallel conversions would create race conditions on Word's internal state. This tool processes files **one at a time**, which is the reliable default.
394
+
395
+ ### Batch Size
396
+
397
+ Tested with batches of 100+ files. For very large batches (1000+), consider splitting into smaller groups and running sequentially.
398
+
399
+ ## Project Structure
400
+
401
+ ```
402
+ doctopdf/
403
+ ├── pyproject.toml # Package build configuration
404
+ ├── DESIGN.md # Architecture design document
405
+ ├── README.md # This file
406
+ └── doctopdf/ # Python package
407
+ ├── __init__.py # Package metadata
408
+ ├── __main__.py # `python -m doctopdf` entry
409
+ ├── cli.py # CLI argument parsing and dispatch
410
+ ├── config.py # Constants and defaults
411
+ ├── converter.py # Word automation bridge (JXA)
412
+ ├── errors.py # Exception hierarchy
413
+ ├── logger.py # Structured logging
414
+ ├── orchestrator.py # Batch coordination
415
+ ├── scanner.py # File discovery and path mapping
416
+ └── applescript/ # JXA/AppleScript bridge files
417
+ ├── check_word.applescript
418
+ └── export_document.js
419
+ ```
420
+
421
+ ## Development
422
+
423
+ ```bash
424
+ # Install in development mode
425
+ pip install -e .
426
+
427
+ # Run directly
428
+ python -m doctopdf --check
429
+ python -m doctopdf -i ./test_docs -o ./test_pdfs --dry-run
430
+
431
+ # Test with real files
432
+ python -m doctopdf -i ./test_docs -o ./test_pdfs
433
+ ```
434
+
435
+ ## Logging
436
+
437
+ ### Per-file output (stdout)
438
+ ```
439
+ ✓ report.docx → report.pdf [4.2s]
440
+ ✓ notes.docx → notes.pdf [3.1s]
441
+ ✗ broken.docx → broken.pdf [5.0s] — Corrupt document: File format error
442
+ ```
443
+
444
+ ### Summary (end of run)
445
+ ```
446
+ ── Summary ──────────────────────────────────
447
+ Total processed: 15
448
+ Successful: 14 (62.3s spent on successful conversions)
449
+ Errors: 1
450
+ Average: 4.4s per file
451
+ Total wall time: 67.8s
452
+
453
+ Failed files (1):
454
+ ✗ broken.docx: Corrupt document — File format error
455
+ ```
456
+
457
+ ### Structured log (--log-file)
458
+ Use `--log-file results.json` or `--log-file results.csv` for post-hoc analysis.
459
+
460
+ ## Troubleshooting
461
+
462
+ ### "convert-word-pdf: command not found" after installation
463
+
464
+ This is the most common issue on macOS. Here is what happened and how to fix it.
465
+
466
+ **Why this happens:** When you run `pip3 install .`, Python installs the
467
+ `convert-word-pdf` command into a folder like:
468
+
469
+ ```
470
+ /Users/yourname/Library/Python/3.9/bin
471
+ ```
472
+
473
+ That folder is a standard install location used by Python's `pip` on macOS.
474
+ However, macOS does not include this folder in your terminal's search path
475
+ (the technical term is `PATH`) by default. So even though the tool is
476
+ installed, your terminal doesn't know where to find it.
477
+
478
+ **How to fix it (two ways):**
479
+
480
+ #### Fix A: Add the folder to your PATH (do this once)
481
+
482
+ 1. Find out which Python version you have:
483
+
484
+ ```bash
485
+ python3 --version
486
+ ```
487
+
488
+ This will show something like `Python 3.9.x`. Note the **major.minor**
489
+ version number (e.g. `3.9`).
490
+
491
+ 2. Open your shell configuration file:
492
+
493
+ - If you use **zsh** (default on macOS Catalina and newer):
494
+
495
+ ```bash
496
+ nano ~/.zshrc
497
+ ```
498
+
499
+ - If you use **bash** (older macOS versions):
500
+
501
+ ```bash
502
+ nano ~/.bash_profile
503
+ ```
504
+
505
+ 3. Add this line at the bottom of the file (replace `3.9` with the Python
506
+ version you saw in step 1):
507
+
508
+ ```bash
509
+ export PATH="$HOME/Library/Python/3.9/bin:$PATH"
510
+ ```
511
+
512
+ **What this does:** It tells your terminal to look in the Python bin
513
+ folder whenever you type a command, so it can find `convert-word-pdf`.
514
+
515
+ 4. Save the file:
516
+ - Press **Ctrl + O** → **Enter** to save
517
+ - Press **Ctrl + X** to exit nano
518
+
519
+ 5. Reload your configuration:
520
+
521
+ ```bash
522
+ source ~/.zshrc
523
+ ```
524
+
525
+ (If you used `~/.bash_profile` instead, run `source ~/.bash_profile`.)
526
+
527
+ 6. Verify it worked:
528
+
529
+ ```bash
530
+ convert-word-pdf --version
531
+ ```
532
+
533
+ You should see `convert-word-pdf 1.0.0` instead of "command not found."
534
+
535
+ #### Fix B: Skip PATH entirely — use Option C instead
536
+
537
+ If you don't want to edit configuration files, don't install the tool at
538
+ all. Run it directly from the project folder instead:
539
+
540
+ ```bash
541
+ cd ~/Documents/doctopdf
542
+ python3 -m doctopdf --check
543
+ ```
544
+
545
+ See **Option C** in the Installation section above for full instructions.
546
+ The tool works identically either way — you just type a slightly longer
547
+ command.
548
+
549
+ ### Check which Python is active
550
+
551
+ If you have multiple Python versions installed, `pip3 install` and
552
+ `python3 -m doctopdf` might use different Python installations, causing
553
+ confusion. Verify they match:
554
+
555
+ ```bash
556
+ pip3 --version
557
+ python3 --version
558
+ ```
559
+
560
+ Both should reference the same Python version (e.g. `Python 3.9.x`).
561
+ If they don't, use the full path to your desired Python, for example:
562
+
563
+ ```bash
564
+ /usr/local/bin/python3 -m doctopdf --check
565
+ ```
566
+
567
+ ### Permission errors with osascript (-1743)
568
+
569
+ See the **macOS Permissions** section earlier in this document.
570
+
571
+ ## License
572
+
573
+ MIT