vexy-pdf-werk 1.1.2.dev0__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.
- vexy_pdf_werk-1.1.2.dev0/.gitignore +195 -0
- vexy_pdf_werk-1.1.2.dev0/LICENSE +21 -0
- vexy_pdf_werk-1.1.2.dev0/PKG-INFO +267 -0
- vexy_pdf_werk-1.1.2.dev0/README.md +225 -0
- vexy_pdf_werk-1.1.2.dev0/pyproject.toml +448 -0
- vexy_pdf_werk-1.1.2.dev0/src/vexy_pdf_werk/_version.py +2 -0
- vexy_pdf_werk-1.1.2.dev0/src/vexy_pdf_werk/py.typed +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
__pypackages__/
|
|
3
|
+
__version__.py
|
|
4
|
+
_deps
|
|
5
|
+
_dev/
|
|
6
|
+
_private/
|
|
7
|
+
_version.py
|
|
8
|
+
!.env.example
|
|
9
|
+
!.env.template
|
|
10
|
+
!.vscode/*.code-snippets
|
|
11
|
+
!.vscode/extensions.json
|
|
12
|
+
!.vscode/launch.json
|
|
13
|
+
!.vscode/settings.json
|
|
14
|
+
!.vscode/tasks.json
|
|
15
|
+
!build/.gitkeep
|
|
16
|
+
!dist/.gitkeep
|
|
17
|
+
._*
|
|
18
|
+
.\#*
|
|
19
|
+
.apdisk
|
|
20
|
+
.AppleDB
|
|
21
|
+
.AppleDesktop
|
|
22
|
+
.AppleDouble
|
|
23
|
+
.atom/
|
|
24
|
+
.benchmarks/
|
|
25
|
+
.cache
|
|
26
|
+
.com.apple.timemachine.donotpresent
|
|
27
|
+
.conda/
|
|
28
|
+
.coverage
|
|
29
|
+
.coverage.*
|
|
30
|
+
.dmypy.json
|
|
31
|
+
.DocumentRevisions-V100
|
|
32
|
+
.DS_Store
|
|
33
|
+
.eggs/
|
|
34
|
+
.env
|
|
35
|
+
.env*
|
|
36
|
+
.fseventsd
|
|
37
|
+
.hatch/
|
|
38
|
+
.history/
|
|
39
|
+
.hypothesis/
|
|
40
|
+
.idea/
|
|
41
|
+
.installed.cfg
|
|
42
|
+
.ionide/
|
|
43
|
+
.ipynb_checkpoints
|
|
44
|
+
.LSOverride
|
|
45
|
+
.mypy_cache/
|
|
46
|
+
.nox/
|
|
47
|
+
.pdm-build/
|
|
48
|
+
.pdm-python
|
|
49
|
+
.pdm.toml
|
|
50
|
+
.pybuilder/
|
|
51
|
+
.pyre/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
.Python
|
|
54
|
+
.python-version
|
|
55
|
+
.pytype/
|
|
56
|
+
.ropeproject
|
|
57
|
+
.ruff_cache/
|
|
58
|
+
.scrapy
|
|
59
|
+
.Spotlight-V100
|
|
60
|
+
.spyderproject
|
|
61
|
+
.spyproject
|
|
62
|
+
.TemporaryItems
|
|
63
|
+
.tox/
|
|
64
|
+
.Trashes
|
|
65
|
+
.uv/
|
|
66
|
+
.venv
|
|
67
|
+
.vimrc.local
|
|
68
|
+
.VolumeIcon.icns
|
|
69
|
+
.vscode/
|
|
70
|
+
.webassets-cache
|
|
71
|
+
*.backup
|
|
72
|
+
*.bak
|
|
73
|
+
*.cover
|
|
74
|
+
*.crt
|
|
75
|
+
*.csr
|
|
76
|
+
*.egg
|
|
77
|
+
*.egg-info/
|
|
78
|
+
*.elc
|
|
79
|
+
*.key
|
|
80
|
+
*.log
|
|
81
|
+
*.make
|
|
82
|
+
*.manifest
|
|
83
|
+
*.mo
|
|
84
|
+
*.p12
|
|
85
|
+
*.pem
|
|
86
|
+
*.pfx
|
|
87
|
+
*.pot
|
|
88
|
+
*.prof
|
|
89
|
+
*.profile
|
|
90
|
+
*.py,cover
|
|
91
|
+
*.py[cod]
|
|
92
|
+
*.sage.py
|
|
93
|
+
*.secret
|
|
94
|
+
*.so
|
|
95
|
+
*.spec
|
|
96
|
+
*.sublime-workspace
|
|
97
|
+
*.swo
|
|
98
|
+
*.swp
|
|
99
|
+
*.temp
|
|
100
|
+
*.tmp
|
|
101
|
+
*~
|
|
102
|
+
*$py.class
|
|
103
|
+
/.emacs.desktop
|
|
104
|
+
/.emacs.desktop.lock
|
|
105
|
+
/site
|
|
106
|
+
\#*\#
|
|
107
|
+
$RECYCLE.BIN/
|
|
108
|
+
artifacts/
|
|
109
|
+
auto-save-list
|
|
110
|
+
autom4te.cache/
|
|
111
|
+
benchmark_results/
|
|
112
|
+
benchmarks/results/
|
|
113
|
+
build/
|
|
114
|
+
celerybeat-schedule
|
|
115
|
+
celerybeat.pid
|
|
116
|
+
cmake_install.cmake
|
|
117
|
+
CMakeCache.txt
|
|
118
|
+
CMakeFiles/
|
|
119
|
+
config.local.*
|
|
120
|
+
config.log
|
|
121
|
+
config.status
|
|
122
|
+
configure
|
|
123
|
+
cover/
|
|
124
|
+
coverage.xml
|
|
125
|
+
CTestTestfile.cmake
|
|
126
|
+
cython_debug/
|
|
127
|
+
db.sqlite3
|
|
128
|
+
db.sqlite3-journal
|
|
129
|
+
Desktop.ini
|
|
130
|
+
dev/
|
|
131
|
+
develop-eggs/
|
|
132
|
+
dist/
|
|
133
|
+
dmypy.json
|
|
134
|
+
docs/_build/
|
|
135
|
+
docs/build/
|
|
136
|
+
downloads/
|
|
137
|
+
eggs/
|
|
138
|
+
ehthumbs_vista.db
|
|
139
|
+
ehthumbs.db
|
|
140
|
+
env.bak/
|
|
141
|
+
env/
|
|
142
|
+
ENV/
|
|
143
|
+
external/
|
|
144
|
+
htmlcov/
|
|
145
|
+
Icon
|
|
146
|
+
instance/
|
|
147
|
+
ipython_config.py
|
|
148
|
+
lib/
|
|
149
|
+
lib64/
|
|
150
|
+
local_config.*
|
|
151
|
+
local_settings.py
|
|
152
|
+
log/
|
|
153
|
+
logs/
|
|
154
|
+
Makefile
|
|
155
|
+
Makefile.in
|
|
156
|
+
MANIFEST
|
|
157
|
+
Network Trash Folder
|
|
158
|
+
node_modules/
|
|
159
|
+
nosetests.xml
|
|
160
|
+
npm-debug.log*
|
|
161
|
+
outputs/
|
|
162
|
+
package-lock.json
|
|
163
|
+
parts/
|
|
164
|
+
pip-delete-this-directory.txt
|
|
165
|
+
pip-log.txt
|
|
166
|
+
Pipfile.lock
|
|
167
|
+
poetry.lock
|
|
168
|
+
private/
|
|
169
|
+
prof/
|
|
170
|
+
profile_default/
|
|
171
|
+
profiles/
|
|
172
|
+
results/
|
|
173
|
+
sdist/
|
|
174
|
+
secret.*
|
|
175
|
+
secrets/
|
|
176
|
+
share/python-wheels/
|
|
177
|
+
src/*/__version__.py
|
|
178
|
+
src/*/_version.py
|
|
179
|
+
src/*/version.py
|
|
180
|
+
target/
|
|
181
|
+
temp/
|
|
182
|
+
Temporary Items
|
|
183
|
+
Thumbs.db
|
|
184
|
+
Thumbs.db:encryptable
|
|
185
|
+
tmp/
|
|
186
|
+
tramp
|
|
187
|
+
uv.lock
|
|
188
|
+
var/
|
|
189
|
+
vendor/
|
|
190
|
+
venv.bak/
|
|
191
|
+
venv/
|
|
192
|
+
wheels/
|
|
193
|
+
yarn-debug.log*
|
|
194
|
+
yarn-error.log*
|
|
195
|
+
yarn.lock
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Fontlab Ltd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vexy-pdf-werk
|
|
3
|
+
Version: 1.1.2.dev0
|
|
4
|
+
Project-URL: Documentation, https://github.com/vexyart/vexy-pdf-werk#readme
|
|
5
|
+
Project-URL: Issues, https://github.com/vexyart/vexy-pdf-werk/issues
|
|
6
|
+
Project-URL: Source, https://github.com/vexyart/vexy-pdf-werk
|
|
7
|
+
Author-email: Fontlab Ltd <opensource@vexy.art>
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Provides-Extra: all
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: absolufy-imports>=0.3.1; extra == 'dev'
|
|
24
|
+
Requires-Dist: isort>=6.0.1; extra == 'dev'
|
|
25
|
+
Requires-Dist: mypy>=1.15.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pre-commit>=4.1.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pyupgrade>=3.19.1; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.9.7; extra == 'dev'
|
|
29
|
+
Provides-Extra: docs
|
|
30
|
+
Requires-Dist: myst-parser>=3.0.0; extra == 'docs'
|
|
31
|
+
Requires-Dist: sphinx-autodoc-typehints>=2.0.0; extra == 'docs'
|
|
32
|
+
Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == 'docs'
|
|
33
|
+
Requires-Dist: sphinx>=7.2.6; extra == 'docs'
|
|
34
|
+
Provides-Extra: test
|
|
35
|
+
Requires-Dist: coverage[toml]>=7.6.12; extra == 'test'
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.25.3; extra == 'test'
|
|
37
|
+
Requires-Dist: pytest-benchmark[histogram]>=5.1.0; extra == 'test'
|
|
38
|
+
Requires-Dist: pytest-cov>=6.0.0; extra == 'test'
|
|
39
|
+
Requires-Dist: pytest-xdist>=3.6.1; extra == 'test'
|
|
40
|
+
Requires-Dist: pytest>=8.3.4; extra == 'test'
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
# this_file: README.md
|
|
44
|
+
|
|
45
|
+
# Vexy PDF Werk
|
|
46
|
+
|
|
47
|
+
**Transform PDFs into high-quality, accessible formats with AI-enhanced processing**
|
|
48
|
+
|
|
49
|
+
Vexy PDF Werk (VPW) is a Python package that converts PDF documents into multiple high-quality formats using modern tools and optional AI enhancement. Transform your PDFs into PDF/A archives, paginated Markdown, ePub books, and structured bibliographic metadata.
|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
🔧 **Modern PDF Processing**
|
|
54
|
+
- PDF/A conversion for long-term archival
|
|
55
|
+
- OCR enhancement using OCRmyPDF
|
|
56
|
+
- Quality optimization with qpdf
|
|
57
|
+
|
|
58
|
+
📚 **Multiple Output Formats**
|
|
59
|
+
- Paginated Markdown documents with smart naming
|
|
60
|
+
- ePub generation from Markdown
|
|
61
|
+
- Structured bibliographic YAML metadata
|
|
62
|
+
- Preserves original PDF alongside enhanced versions
|
|
63
|
+
|
|
64
|
+
🤖 **Optional AI Enhancement**
|
|
65
|
+
- Text correction using Claude or Gemini CLI
|
|
66
|
+
- Content structure optimization
|
|
67
|
+
- Fallback to proven traditional methods
|
|
68
|
+
|
|
69
|
+
⚙️ **Flexible Architecture**
|
|
70
|
+
- Multiple conversion backends (Marker, MarkItDown, Docling, basic)
|
|
71
|
+
- Platform-appropriate configuration storage
|
|
72
|
+
- Robust error handling with graceful fallbacks
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
### Installation
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Install from PyPI
|
|
80
|
+
pip install vexy-pdf-werk
|
|
81
|
+
|
|
82
|
+
# Or install in development mode
|
|
83
|
+
git clone https://github.com/vexyart/vexy-pdf-werk
|
|
84
|
+
cd vexy-pdf-werk
|
|
85
|
+
pip install -e .
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Basic Usage
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import vexy_pdf_werk
|
|
92
|
+
|
|
93
|
+
# Process a PDF with default settings
|
|
94
|
+
config = vexy_pdf_werk.Config(name="default", value="process")
|
|
95
|
+
result = vexy_pdf_werk.process_data(["document.pdf"], config=config)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### CLI Usage (Coming Soon)
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Process a PDF into all formats
|
|
102
|
+
vpw process document.pdf
|
|
103
|
+
|
|
104
|
+
# Process with specific formats only
|
|
105
|
+
vpw process document.pdf --formats pdfa,markdown
|
|
106
|
+
|
|
107
|
+
# Enable AI enhancement
|
|
108
|
+
vpw process document.pdf --ai-enabled --ai-provider claude
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Output Structure
|
|
112
|
+
|
|
113
|
+
VPW creates organized output with consistent naming:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
output/
|
|
117
|
+
├── document_enhanced.pdf # PDF/A version
|
|
118
|
+
├── 000--introduction.md # Paginated Markdown files
|
|
119
|
+
├── 001--chapter-one.md
|
|
120
|
+
├── 002--conclusions.md
|
|
121
|
+
├── document.epub # Generated ePub
|
|
122
|
+
└── metadata.yaml # Bibliographic data
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## System Requirements
|
|
126
|
+
|
|
127
|
+
### Required Dependencies
|
|
128
|
+
- Python 3.10+
|
|
129
|
+
- tesseract-ocr
|
|
130
|
+
- qpdf
|
|
131
|
+
- ghostscript
|
|
132
|
+
|
|
133
|
+
### Optional Dependencies
|
|
134
|
+
- pandoc (for ePub generation)
|
|
135
|
+
- marker-pdf (advanced PDF conversion)
|
|
136
|
+
- markitdown (Microsoft's document converter)
|
|
137
|
+
- docling (IBM's document understanding)
|
|
138
|
+
|
|
139
|
+
### Installation Commands
|
|
140
|
+
|
|
141
|
+
**Ubuntu/Debian:**
|
|
142
|
+
```bash
|
|
143
|
+
sudo apt-get update
|
|
144
|
+
sudo apt-get install tesseract-ocr tesseract-ocr-eng qpdf ghostscript pandoc
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**macOS:**
|
|
148
|
+
```bash
|
|
149
|
+
brew install tesseract tesseract-lang qpdf ghostscript pandoc
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Windows:**
|
|
153
|
+
```bash
|
|
154
|
+
choco install tesseract qpdf ghostscript pandoc
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Configuration
|
|
158
|
+
|
|
159
|
+
VPW stores configuration in platform-appropriate directories:
|
|
160
|
+
|
|
161
|
+
- **Linux/macOS**: `~/.config/vexy-pdf-werk/config.toml`
|
|
162
|
+
- **Windows**: `%APPDATA%\\vexy-pdf-werk\\config.toml`
|
|
163
|
+
|
|
164
|
+
### Example Configuration
|
|
165
|
+
|
|
166
|
+
```toml
|
|
167
|
+
[processing]
|
|
168
|
+
ocr_language = "eng"
|
|
169
|
+
pdf_quality = "high"
|
|
170
|
+
force_ocr = false
|
|
171
|
+
|
|
172
|
+
[conversion]
|
|
173
|
+
markdown_backend = "auto" # auto, marker, markitdown, docling, basic
|
|
174
|
+
paginate_markdown = true
|
|
175
|
+
include_images = true
|
|
176
|
+
|
|
177
|
+
[ai]
|
|
178
|
+
enabled = false
|
|
179
|
+
provider = "claude" # claude, gemini
|
|
180
|
+
correction_enabled = false
|
|
181
|
+
|
|
182
|
+
[output]
|
|
183
|
+
formats = ["pdfa", "markdown", "epub", "yaml"]
|
|
184
|
+
preserve_original = true
|
|
185
|
+
output_directory = "./output"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Development
|
|
189
|
+
|
|
190
|
+
This project uses modern Python tooling:
|
|
191
|
+
|
|
192
|
+
- **Package Management**: uv + hatch
|
|
193
|
+
- **Code Quality**: ruff + mypy
|
|
194
|
+
- **Testing**: pytest
|
|
195
|
+
- **Version Control**: git-tag-based semver with hatch-vcs
|
|
196
|
+
|
|
197
|
+
### Development Setup
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# Install uv and hatch
|
|
201
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
202
|
+
pip install hatch
|
|
203
|
+
|
|
204
|
+
# Clone and setup
|
|
205
|
+
git clone https://github.com/vexyart/vexy-pdf-werk
|
|
206
|
+
cd vexy-pdf-werk
|
|
207
|
+
|
|
208
|
+
# Run tests using hatch (automatically manages environment)
|
|
209
|
+
hatch run test
|
|
210
|
+
|
|
211
|
+
# Run linting and formatting
|
|
212
|
+
hatch run lint
|
|
213
|
+
|
|
214
|
+
# Type checking
|
|
215
|
+
hatch run type-check
|
|
216
|
+
|
|
217
|
+
# Or run individual commands
|
|
218
|
+
hatch run python -c "import vexy_pdf_werk; print(vexy_pdf_werk.__version__)"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Architecture
|
|
222
|
+
|
|
223
|
+
VPW follows a modular pipeline architecture:
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
PDF Input → Analysis → OCR Enhancement → Content Extraction → Format Generation → Multi-Format Output
|
|
227
|
+
↓
|
|
228
|
+
Optional AI Enhancement
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Core Components
|
|
232
|
+
|
|
233
|
+
- **PDF Processor**: Handles OCR and PDF/A conversion
|
|
234
|
+
- **Content Extractors**: Multiple backends for PDF-to-Markdown
|
|
235
|
+
- **Format Generators**: Creates ePub and metadata outputs
|
|
236
|
+
- **AI Integrations**: Optional LLM enhancement services
|
|
237
|
+
- **Configuration System**: Platform-aware settings management
|
|
238
|
+
|
|
239
|
+
## Contributing
|
|
240
|
+
|
|
241
|
+
1. Fork the repository
|
|
242
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
243
|
+
3. Make your changes following the code quality standards
|
|
244
|
+
4. Run tests and linting
|
|
245
|
+
5. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
246
|
+
6. Push to the branch (`git push origin feature/amazing-feature`)
|
|
247
|
+
7. Open a Pull Request
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
252
|
+
|
|
253
|
+
## Authors
|
|
254
|
+
|
|
255
|
+
- **Fontlab Ltd** - *Initial work* - [Vexy Art](https://vexy.art)
|
|
256
|
+
|
|
257
|
+
## Acknowledgments
|
|
258
|
+
|
|
259
|
+
- Built on proven tools: qpdf, OCRmyPDF, tesseract
|
|
260
|
+
- Integration with cutting-edge AI services
|
|
261
|
+
- Inspired by the need for better PDF accessibility and archival
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
**Project Status**: Under active development
|
|
266
|
+
|
|
267
|
+
For detailed implementation specifications, see the [spec/](spec/) directory.
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# this_file: README.md
|
|
2
|
+
|
|
3
|
+
# Vexy PDF Werk
|
|
4
|
+
|
|
5
|
+
**Transform PDFs into high-quality, accessible formats with AI-enhanced processing**
|
|
6
|
+
|
|
7
|
+
Vexy PDF Werk (VPW) is a Python package that converts PDF documents into multiple high-quality formats using modern tools and optional AI enhancement. Transform your PDFs into PDF/A archives, paginated Markdown, ePub books, and structured bibliographic metadata.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
🔧 **Modern PDF Processing**
|
|
12
|
+
- PDF/A conversion for long-term archival
|
|
13
|
+
- OCR enhancement using OCRmyPDF
|
|
14
|
+
- Quality optimization with qpdf
|
|
15
|
+
|
|
16
|
+
📚 **Multiple Output Formats**
|
|
17
|
+
- Paginated Markdown documents with smart naming
|
|
18
|
+
- ePub generation from Markdown
|
|
19
|
+
- Structured bibliographic YAML metadata
|
|
20
|
+
- Preserves original PDF alongside enhanced versions
|
|
21
|
+
|
|
22
|
+
🤖 **Optional AI Enhancement**
|
|
23
|
+
- Text correction using Claude or Gemini CLI
|
|
24
|
+
- Content structure optimization
|
|
25
|
+
- Fallback to proven traditional methods
|
|
26
|
+
|
|
27
|
+
⚙️ **Flexible Architecture**
|
|
28
|
+
- Multiple conversion backends (Marker, MarkItDown, Docling, basic)
|
|
29
|
+
- Platform-appropriate configuration storage
|
|
30
|
+
- Robust error handling with graceful fallbacks
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
### Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Install from PyPI
|
|
38
|
+
pip install vexy-pdf-werk
|
|
39
|
+
|
|
40
|
+
# Or install in development mode
|
|
41
|
+
git clone https://github.com/vexyart/vexy-pdf-werk
|
|
42
|
+
cd vexy-pdf-werk
|
|
43
|
+
pip install -e .
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Basic Usage
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import vexy_pdf_werk
|
|
50
|
+
|
|
51
|
+
# Process a PDF with default settings
|
|
52
|
+
config = vexy_pdf_werk.Config(name="default", value="process")
|
|
53
|
+
result = vexy_pdf_werk.process_data(["document.pdf"], config=config)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### CLI Usage (Coming Soon)
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Process a PDF into all formats
|
|
60
|
+
vpw process document.pdf
|
|
61
|
+
|
|
62
|
+
# Process with specific formats only
|
|
63
|
+
vpw process document.pdf --formats pdfa,markdown
|
|
64
|
+
|
|
65
|
+
# Enable AI enhancement
|
|
66
|
+
vpw process document.pdf --ai-enabled --ai-provider claude
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Output Structure
|
|
70
|
+
|
|
71
|
+
VPW creates organized output with consistent naming:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
output/
|
|
75
|
+
├── document_enhanced.pdf # PDF/A version
|
|
76
|
+
├── 000--introduction.md # Paginated Markdown files
|
|
77
|
+
├── 001--chapter-one.md
|
|
78
|
+
├── 002--conclusions.md
|
|
79
|
+
├── document.epub # Generated ePub
|
|
80
|
+
└── metadata.yaml # Bibliographic data
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## System Requirements
|
|
84
|
+
|
|
85
|
+
### Required Dependencies
|
|
86
|
+
- Python 3.10+
|
|
87
|
+
- tesseract-ocr
|
|
88
|
+
- qpdf
|
|
89
|
+
- ghostscript
|
|
90
|
+
|
|
91
|
+
### Optional Dependencies
|
|
92
|
+
- pandoc (for ePub generation)
|
|
93
|
+
- marker-pdf (advanced PDF conversion)
|
|
94
|
+
- markitdown (Microsoft's document converter)
|
|
95
|
+
- docling (IBM's document understanding)
|
|
96
|
+
|
|
97
|
+
### Installation Commands
|
|
98
|
+
|
|
99
|
+
**Ubuntu/Debian:**
|
|
100
|
+
```bash
|
|
101
|
+
sudo apt-get update
|
|
102
|
+
sudo apt-get install tesseract-ocr tesseract-ocr-eng qpdf ghostscript pandoc
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**macOS:**
|
|
106
|
+
```bash
|
|
107
|
+
brew install tesseract tesseract-lang qpdf ghostscript pandoc
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Windows:**
|
|
111
|
+
```bash
|
|
112
|
+
choco install tesseract qpdf ghostscript pandoc
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Configuration
|
|
116
|
+
|
|
117
|
+
VPW stores configuration in platform-appropriate directories:
|
|
118
|
+
|
|
119
|
+
- **Linux/macOS**: `~/.config/vexy-pdf-werk/config.toml`
|
|
120
|
+
- **Windows**: `%APPDATA%\\vexy-pdf-werk\\config.toml`
|
|
121
|
+
|
|
122
|
+
### Example Configuration
|
|
123
|
+
|
|
124
|
+
```toml
|
|
125
|
+
[processing]
|
|
126
|
+
ocr_language = "eng"
|
|
127
|
+
pdf_quality = "high"
|
|
128
|
+
force_ocr = false
|
|
129
|
+
|
|
130
|
+
[conversion]
|
|
131
|
+
markdown_backend = "auto" # auto, marker, markitdown, docling, basic
|
|
132
|
+
paginate_markdown = true
|
|
133
|
+
include_images = true
|
|
134
|
+
|
|
135
|
+
[ai]
|
|
136
|
+
enabled = false
|
|
137
|
+
provider = "claude" # claude, gemini
|
|
138
|
+
correction_enabled = false
|
|
139
|
+
|
|
140
|
+
[output]
|
|
141
|
+
formats = ["pdfa", "markdown", "epub", "yaml"]
|
|
142
|
+
preserve_original = true
|
|
143
|
+
output_directory = "./output"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Development
|
|
147
|
+
|
|
148
|
+
This project uses modern Python tooling:
|
|
149
|
+
|
|
150
|
+
- **Package Management**: uv + hatch
|
|
151
|
+
- **Code Quality**: ruff + mypy
|
|
152
|
+
- **Testing**: pytest
|
|
153
|
+
- **Version Control**: git-tag-based semver with hatch-vcs
|
|
154
|
+
|
|
155
|
+
### Development Setup
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Install uv and hatch
|
|
159
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
160
|
+
pip install hatch
|
|
161
|
+
|
|
162
|
+
# Clone and setup
|
|
163
|
+
git clone https://github.com/vexyart/vexy-pdf-werk
|
|
164
|
+
cd vexy-pdf-werk
|
|
165
|
+
|
|
166
|
+
# Run tests using hatch (automatically manages environment)
|
|
167
|
+
hatch run test
|
|
168
|
+
|
|
169
|
+
# Run linting and formatting
|
|
170
|
+
hatch run lint
|
|
171
|
+
|
|
172
|
+
# Type checking
|
|
173
|
+
hatch run type-check
|
|
174
|
+
|
|
175
|
+
# Or run individual commands
|
|
176
|
+
hatch run python -c "import vexy_pdf_werk; print(vexy_pdf_werk.__version__)"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Architecture
|
|
180
|
+
|
|
181
|
+
VPW follows a modular pipeline architecture:
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
PDF Input → Analysis → OCR Enhancement → Content Extraction → Format Generation → Multi-Format Output
|
|
185
|
+
↓
|
|
186
|
+
Optional AI Enhancement
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Core Components
|
|
190
|
+
|
|
191
|
+
- **PDF Processor**: Handles OCR and PDF/A conversion
|
|
192
|
+
- **Content Extractors**: Multiple backends for PDF-to-Markdown
|
|
193
|
+
- **Format Generators**: Creates ePub and metadata outputs
|
|
194
|
+
- **AI Integrations**: Optional LLM enhancement services
|
|
195
|
+
- **Configuration System**: Platform-aware settings management
|
|
196
|
+
|
|
197
|
+
## Contributing
|
|
198
|
+
|
|
199
|
+
1. Fork the repository
|
|
200
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
201
|
+
3. Make your changes following the code quality standards
|
|
202
|
+
4. Run tests and linting
|
|
203
|
+
5. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
204
|
+
6. Push to the branch (`git push origin feature/amazing-feature`)
|
|
205
|
+
7. Open a Pull Request
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
210
|
+
|
|
211
|
+
## Authors
|
|
212
|
+
|
|
213
|
+
- **Fontlab Ltd** - *Initial work* - [Vexy Art](https://vexy.art)
|
|
214
|
+
|
|
215
|
+
## Acknowledgments
|
|
216
|
+
|
|
217
|
+
- Built on proven tools: qpdf, OCRmyPDF, tesseract
|
|
218
|
+
- Integration with cutting-edge AI services
|
|
219
|
+
- Inspired by the need for better PDF accessibility and archival
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
**Project Status**: Under active development
|
|
224
|
+
|
|
225
|
+
For detailed implementation specifications, see the [spec/](spec/) directory.
|
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
# this_file: pyproject.toml
|
|
2
|
+
#==============================================================================
|
|
3
|
+
# VEXY-PDF-WERK PACKAGE CONFIGURATION
|
|
4
|
+
# This pyproject.toml defines the package metadata, dependencies, build system,
|
|
5
|
+
# and development environment for the vexy-pdf-werk package.
|
|
6
|
+
#==============================================================================
|
|
7
|
+
|
|
8
|
+
#------------------------------------------------------------------------------
|
|
9
|
+
# PROJECT METADATA
|
|
10
|
+
# Core package information used by PyPI and package managers.
|
|
11
|
+
#------------------------------------------------------------------------------
|
|
12
|
+
[project]
|
|
13
|
+
name = 'vexy-pdf-werk' # Package name on PyPI
|
|
14
|
+
description = '' # Short description
|
|
15
|
+
readme = 'README.md' # Path to README file
|
|
16
|
+
requires-python = '>=3.10' # Minimum Python version
|
|
17
|
+
keywords = [
|
|
18
|
+
] # Keywords for PyPI search
|
|
19
|
+
dynamic = ["version"] # Fields set dynamically at build time
|
|
20
|
+
|
|
21
|
+
# PyPI classifiers for package categorization
|
|
22
|
+
classifiers = [
|
|
23
|
+
'Development Status :: 4 - Beta', # Package maturity level
|
|
24
|
+
'Programming Language :: Python',
|
|
25
|
+
'Programming Language :: Python :: 3.10',
|
|
26
|
+
'Programming Language :: Python :: 3.11',
|
|
27
|
+
'Programming Language :: Python :: 3.12',
|
|
28
|
+
'Programming Language :: Python :: Implementation :: CPython',
|
|
29
|
+
'Programming Language :: Python :: Implementation :: PyPy',
|
|
30
|
+
'Operating System :: OS Independent',
|
|
31
|
+
'License :: OSI Approved :: MIT License',
|
|
32
|
+
'Intended Audience :: Developers',
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
dependencies = [
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
# Author information
|
|
39
|
+
[[project.authors]]
|
|
40
|
+
name = 'Fontlab Ltd'
|
|
41
|
+
email = 'opensource@vexy.art'
|
|
42
|
+
|
|
43
|
+
# License information
|
|
44
|
+
[project.license]
|
|
45
|
+
text = 'MIT'
|
|
46
|
+
|
|
47
|
+
# Project URLs
|
|
48
|
+
[project.urls]
|
|
49
|
+
Documentation = 'https://github.com/vexyart/vexy-pdf-werk#readme'
|
|
50
|
+
Issues = 'https://github.com/vexyart/vexy-pdf-werk/issues'
|
|
51
|
+
Source = 'https://github.com/vexyart/vexy-pdf-werk'
|
|
52
|
+
|
|
53
|
+
#------------------------------------------------------------------------------
|
|
54
|
+
# OPTIONAL DEPENDENCIES
|
|
55
|
+
# Additional dependencies for optional features, development, and testing.
|
|
56
|
+
#------------------------------------------------------------------------------
|
|
57
|
+
[project.optional-dependencies]
|
|
58
|
+
|
|
59
|
+
# Development tools
|
|
60
|
+
dev = [
|
|
61
|
+
'pre-commit>=4.1.0', # Pre-commit hook manager - Keep pre-commit as is, update if newer pre-commit version is required
|
|
62
|
+
'ruff>=0.9.7', # Linting and formatting - Keep ruff as is, update if newer ruff version is required
|
|
63
|
+
'mypy>=1.15.0', # Type checking - Keep mypy as is, update if newer mypy version is required
|
|
64
|
+
'absolufy-imports>=0.3.1', # Convert relative imports to absolute - Keep absolufy-imports as is, update if newer absolufy-imports version is required
|
|
65
|
+
'pyupgrade>=3.19.1', # Upgrade Python syntax - Keep pyupgrade as is, update if newer pyupgrade version is required
|
|
66
|
+
'isort>=6.0.1', # Sort imports - Keep isort as is, update if newer isort version is required
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
# Testing tools and frameworks
|
|
70
|
+
test = [
|
|
71
|
+
'pytest>=8.3.4', # Testing framework - Keep pytest as is, update if newer pytest version is required
|
|
72
|
+
'pytest-cov>=6.0.0', # Coverage plugin for pytest - Keep pytest-cov as is, update if newer pytest-cov version is required
|
|
73
|
+
'pytest-xdist>=3.6.1', # Parallel test execution - Keep pytest-xdist as is, update if newer pytest-xdist version is required
|
|
74
|
+
'pytest-benchmark[histogram]>=5.1.0', # Benchmarking plugin - Keep pytest-benchmark as is, update if newer pytest-benchmark version is required
|
|
75
|
+
'pytest-asyncio>=0.25.3', # Async test support - Keep pytest-asyncio as is, update if newer pytest-asyncio version is required
|
|
76
|
+
'coverage[toml]>=7.6.12',
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
docs = [
|
|
80
|
+
"sphinx>=7.2.6",
|
|
81
|
+
"sphinx-rtd-theme>=2.0.0",
|
|
82
|
+
"sphinx-autodoc-typehints>=2.0.0",
|
|
83
|
+
"myst-parser>=3.0.0", # Markdown support in Sphinx
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
# All optional dependencies combined
|
|
87
|
+
all = [
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
#------------------------------------------------------------------------------
|
|
91
|
+
# COMMAND-LINE SCRIPTS
|
|
92
|
+
# Entry points for command-line executables installed with the package.
|
|
93
|
+
#------------------------------------------------------------------------------
|
|
94
|
+
[project.scripts]
|
|
95
|
+
vpw = "vexy_pdf_werk.cli:main"
|
|
96
|
+
|
|
97
|
+
#------------------------------------------------------------------------------
|
|
98
|
+
# BUILD SYSTEM CONFIGURATION
|
|
99
|
+
# Defines the tools required to build the package and the build backend.
|
|
100
|
+
#------------------------------------------------------------------------------
|
|
101
|
+
[build-system]
|
|
102
|
+
# Hatchling is a modern build backend for Python packaging
|
|
103
|
+
# hatch-vcs integrates with version control systems for versioning
|
|
104
|
+
requires = [
|
|
105
|
+
'hatchling>=1.27.0', # Keep hatchling as is, update if newer hatchling version is required
|
|
106
|
+
'hatch-vcs>=0.4.0', # Keep hatch-vcs as is, update if newer hatch-vcs version is required
|
|
107
|
+
]
|
|
108
|
+
build-backend = 'hatchling.build' # Specifies Hatchling as the build backend
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
#------------------------------------------------------------------------------
|
|
112
|
+
# HATCH BUILD CONFIGURATION
|
|
113
|
+
# Configures the build process, specifying which packages to include and
|
|
114
|
+
# how to handle versioning.
|
|
115
|
+
#------------------------------------------------------------------------------
|
|
116
|
+
[tool.hatch.build]
|
|
117
|
+
# Include package data files
|
|
118
|
+
include = [
|
|
119
|
+
"src/vexy_pdf_werk/py.typed", # For better type checking support
|
|
120
|
+
"src/vexy_pdf_werk/data/**/*", # Include data files if any
|
|
121
|
+
|
|
122
|
+
]
|
|
123
|
+
exclude = ["**/__pycache__", "**/.pytest_cache", "**/.mypy_cache"]
|
|
124
|
+
|
|
125
|
+
[tool.hatch.build.targets.wheel]
|
|
126
|
+
only-include = ["src/vexy_pdf_werk"]
|
|
127
|
+
sources = ["src"]
|
|
128
|
+
reproducible = true
|
|
129
|
+
|
|
130
|
+
# Version control system hook configuration
|
|
131
|
+
# Automatically updates the version file from git tags
|
|
132
|
+
[tool.hatch.build.hooks.vcs]
|
|
133
|
+
version-file = "src/vexy_pdf_werk/_version.py"
|
|
134
|
+
template = '''
|
|
135
|
+
__version__ = "{version}"
|
|
136
|
+
__version_tuple__ = {version_tuple}
|
|
137
|
+
'''
|
|
138
|
+
|
|
139
|
+
# Version source configuration
|
|
140
|
+
[tool.hatch.version]
|
|
141
|
+
source = 'vcs' # Get version from git tags or other VCS info
|
|
142
|
+
raw-options = { local_scheme = "no-local-version" } # Clean version format without local identifiers
|
|
143
|
+
|
|
144
|
+
# Metadata handling configuration
|
|
145
|
+
[tool.hatch.metadata]
|
|
146
|
+
allow-direct-references = true # Allow direct references in metadata (useful for local dependencies)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
#------------------------------------------------------------------------------
|
|
150
|
+
# DEVELOPMENT ENVIRONMENTS
|
|
151
|
+
|
|
152
|
+
[tool.hatch.envs.default]
|
|
153
|
+
features = ['dev', 'test', 'all']
|
|
154
|
+
installer = "uv" # Use uv for fast dependency resolution and installation
|
|
155
|
+
dependencies = []
|
|
156
|
+
dev-mode = true
|
|
157
|
+
python = "3.12"
|
|
158
|
+
|
|
159
|
+
# Commands available in the default environment
|
|
160
|
+
[tool.hatch.envs.default.scripts]
|
|
161
|
+
# Run tests with optional arguments
|
|
162
|
+
test = 'pytest {args:tests}'
|
|
163
|
+
# Run tests with coverage reporting
|
|
164
|
+
test-cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=src/vexy_pdf_werk --cov=tests {args:tests}"
|
|
165
|
+
# Run type checking
|
|
166
|
+
type-check = "mypy src/vexy_pdf_werk tests"
|
|
167
|
+
# Run linting and formatting
|
|
168
|
+
lint = ["ruff check src/vexy_pdf_werk tests", "ruff format --respect-gitignore src/vexy_pdf_werk tests"]
|
|
169
|
+
# Format and fix style issues
|
|
170
|
+
fmt = ["ruff format --respect-gitignore src/vexy_pdf_werk tests", "ruff check --fix src/vexy_pdf_werk tests"]
|
|
171
|
+
fix = ["ruff check --fix --unsafe-fixes src/vexy_pdf_werk tests", "ruff format --respect-gitignore src/vexy_pdf_werk tests"]
|
|
172
|
+
|
|
173
|
+
# Matrix configuration to test across multiple Python versions
|
|
174
|
+
|
|
175
|
+
[[tool.hatch.envs.all.matrix]]
|
|
176
|
+
python = ["3.10", "3.11", "3.12"]
|
|
177
|
+
|
|
178
|
+
#------------------------------------------------------------------------------
|
|
179
|
+
# SPECIALIZED ENVIRONMENTS
|
|
180
|
+
# Additional environments for specific development tasks.
|
|
181
|
+
#------------------------------------------------------------------------------
|
|
182
|
+
|
|
183
|
+
# Dedicated environment for linting and code quality checks
|
|
184
|
+
[tool.hatch.envs.lint]
|
|
185
|
+
detached = true # Create a separate, isolated environment
|
|
186
|
+
installer = "uv" # Use uv for fast dependency resolution
|
|
187
|
+
features = ['dev'] # Use dev extras dependencies
|
|
188
|
+
|
|
189
|
+
# Linting environment commands
|
|
190
|
+
[tool.hatch.envs.lint.scripts]
|
|
191
|
+
# Type checking with automatic type installation
|
|
192
|
+
typing = "mypy --install-types --non-interactive {args:src/vexy_pdf_werk tests}"
|
|
193
|
+
# Check style and format code
|
|
194
|
+
style = ["ruff check {args:.}", "ruff format --respect-gitignore {args:.}"]
|
|
195
|
+
# Format and fix style issues
|
|
196
|
+
fmt = ["ruff format --respect-gitignore {args:.}", "ruff check --fix {args:.}"]
|
|
197
|
+
fix = ["ruff check --fix --unsafe-fixes {args:.}", "ruff format --respect-gitignore {args:.}"]
|
|
198
|
+
# Run all ops
|
|
199
|
+
all = ["style", "typing", "fix"]
|
|
200
|
+
|
|
201
|
+
# Dedicated environment for testing
|
|
202
|
+
[tool.hatch.envs.test]
|
|
203
|
+
features = ['test'] # Use test extras as dependencies
|
|
204
|
+
installer = "uv" # Use uv for fast dependency resolution
|
|
205
|
+
dev-mode = true
|
|
206
|
+
python = "3.12"
|
|
207
|
+
|
|
208
|
+
# Testing environment commands
|
|
209
|
+
[tool.hatch.envs.test.scripts]
|
|
210
|
+
# Run tests in parallel
|
|
211
|
+
test = "python -m pytest -n auto {args:tests}"
|
|
212
|
+
# Run tests with coverage in parallel
|
|
213
|
+
test-cov = "python -m pytest -n auto --cov-report=term-missing --cov-config=pyproject.toml --cov=src/vexy_pdf_werk --cov=tests {args:tests}"
|
|
214
|
+
# Run benchmarks
|
|
215
|
+
bench = "python -m pytest -v -p no:briefcase tests/test_benchmark.py --benchmark-only"
|
|
216
|
+
# Run benchmarks and save results
|
|
217
|
+
bench-save = "python -m pytest -v -p no:briefcase tests/test_benchmark.py --benchmark-only --benchmark-json=benchmark/results.json"
|
|
218
|
+
|
|
219
|
+
# Documentation environment
|
|
220
|
+
[tool.hatch.envs.docs]
|
|
221
|
+
features = ['docs']
|
|
222
|
+
installer = "uv" # Use uv for fast dependency resolution
|
|
223
|
+
|
|
224
|
+
# Documentation environment commands
|
|
225
|
+
[tool.hatch.envs.docs.scripts]
|
|
226
|
+
build = "sphinx-build -b html docs/source docs/build"
|
|
227
|
+
|
|
228
|
+
# GitHub Actions workflow configuration
|
|
229
|
+
[tool.hatch.envs.ci]
|
|
230
|
+
features = ['test']
|
|
231
|
+
installer = "uv" # Use uv for fast dependency resolution
|
|
232
|
+
dev-mode = true
|
|
233
|
+
python = "3.12"
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
[tool.hatch.envs.ci.scripts]
|
|
237
|
+
test = "pytest --cov=src/vexy_pdf_werk --cov-report=xml"
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
#------------------------------------------------------------------------------
|
|
241
|
+
# CODE QUALITY TOOLS
|
|
242
|
+
# Configuration for linting, formatting, and code quality enforcement.
|
|
243
|
+
#------------------------------------------------------------------------------
|
|
244
|
+
|
|
245
|
+
#------------------------------------------------------------------------------
|
|
246
|
+
# COVERAGE CONFIGURATION
|
|
247
|
+
# Settings for test coverage measurement and reporting.
|
|
248
|
+
#------------------------------------------------------------------------------
|
|
249
|
+
|
|
250
|
+
# Path mapping for coverage in different environments
|
|
251
|
+
[tool.coverage.paths]
|
|
252
|
+
vexy_pdf_werk = ["src/vexy_pdf_werk", "*/vexy-pdf-werk/src/vexy_pdf_werk"]
|
|
253
|
+
tests = ["tests", "*/vexy-pdf-werk/tests"]
|
|
254
|
+
|
|
255
|
+
# Coverage report configuration
|
|
256
|
+
[tool.coverage.report]
|
|
257
|
+
# Lines to exclude from coverage reporting
|
|
258
|
+
exclude_lines = [
|
|
259
|
+
'no cov', # Custom marker to skip coverage
|
|
260
|
+
'if __name__ == .__main__.:', # Script execution guard
|
|
261
|
+
'if TYPE_CHECKING:', # Type checking imports and code
|
|
262
|
+
'pass', # Empty pass statements
|
|
263
|
+
'raise NotImplementedError', # Unimplemented method placeholders
|
|
264
|
+
'raise ImportError', # Import error handling
|
|
265
|
+
'except ImportError', # Import error handling
|
|
266
|
+
'except KeyError', # Common error handling
|
|
267
|
+
'except AttributeError', # Common error handling
|
|
268
|
+
'except NotImplementedError', # Common error handling
|
|
269
|
+
]
|
|
270
|
+
|
|
271
|
+
[tool.coverage.run]
|
|
272
|
+
source_pkgs = ["vexy_pdf_werk", "tests"]
|
|
273
|
+
branch = true # Measure branch coverage (if/else statements)
|
|
274
|
+
parallel = true # Support parallel test execution
|
|
275
|
+
omit = [
|
|
276
|
+
"src/vexy_pdf_werk/_version.py",
|
|
277
|
+
]
|
|
278
|
+
|
|
279
|
+
#------------------------------------------------------------------------------
|
|
280
|
+
# MYPY CONFIGURATION
|
|
281
|
+
# Configuration for type checking with mypy.
|
|
282
|
+
#------------------------------------------------------------------------------
|
|
283
|
+
|
|
284
|
+
[tool.mypy]
|
|
285
|
+
python_version = "3.10"
|
|
286
|
+
strict = true # Enable all strict checks
|
|
287
|
+
warn_return_any = true
|
|
288
|
+
warn_unused_configs = true
|
|
289
|
+
warn_redundant_casts = true
|
|
290
|
+
warn_unused_ignores = true
|
|
291
|
+
warn_no_return = true
|
|
292
|
+
warn_unreachable = true
|
|
293
|
+
show_error_codes = true
|
|
294
|
+
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
|
|
295
|
+
|
|
296
|
+
[[tool.mypy.overrides]]
|
|
297
|
+
module = ["tests.*"]
|
|
298
|
+
disallow_untyped_defs = false
|
|
299
|
+
disallow_incomplete_defs = false
|
|
300
|
+
|
|
301
|
+
#------------------------------------------------------------------------------
|
|
302
|
+
# PYTEST CONFIGURATION
|
|
303
|
+
# Configuration for pytest, including markers, options, and benchmark settings.
|
|
304
|
+
#------------------------------------------------------------------------------
|
|
305
|
+
|
|
306
|
+
[tool.pytest.ini_options]
|
|
307
|
+
addopts = "-v --durations=10 -p no:briefcase"
|
|
308
|
+
asyncio_mode = "auto"
|
|
309
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
310
|
+
console_output_style = "progress"
|
|
311
|
+
filterwarnings = ["ignore::DeprecationWarning", "ignore::UserWarning"]
|
|
312
|
+
log_cli = true
|
|
313
|
+
log_cli_level = "INFO"
|
|
314
|
+
markers = [
|
|
315
|
+
"benchmark: marks tests as benchmarks (select with '-m benchmark')",
|
|
316
|
+
"unit: mark a test as a unit test",
|
|
317
|
+
"integration: mark a test as an integration test",
|
|
318
|
+
"permutation: tests for permutation functionality",
|
|
319
|
+
"parameter: tests for parameter parsing",
|
|
320
|
+
"prompt: tests for prompt parsing",
|
|
321
|
+
]
|
|
322
|
+
norecursedirs = [
|
|
323
|
+
".*",
|
|
324
|
+
"build",
|
|
325
|
+
"dist",
|
|
326
|
+
"venv",
|
|
327
|
+
"__pycache__",
|
|
328
|
+
"*.egg-info",
|
|
329
|
+
"_private",
|
|
330
|
+
]
|
|
331
|
+
python_classes = ["Test*"]
|
|
332
|
+
python_files = ["test_*.py"]
|
|
333
|
+
python_functions = ["test_*"]
|
|
334
|
+
testpaths = ["tests"]
|
|
335
|
+
pythonpath = ["src"]
|
|
336
|
+
|
|
337
|
+
[tool.pytest-benchmark]
|
|
338
|
+
min_rounds = 100
|
|
339
|
+
min_time = 0.1
|
|
340
|
+
histogram = true
|
|
341
|
+
storage = "file"
|
|
342
|
+
save-data = true
|
|
343
|
+
compare = [
|
|
344
|
+
"min", # Minimum time
|
|
345
|
+
"max", # Maximum time
|
|
346
|
+
"mean", # Mean time
|
|
347
|
+
"stddev", # Standard deviation
|
|
348
|
+
"median", # Median time
|
|
349
|
+
"iqr", # Inter-quartile range
|
|
350
|
+
"ops", # Operations per second
|
|
351
|
+
"rounds", # Number of rounds
|
|
352
|
+
]
|
|
353
|
+
|
|
354
|
+
#------------------------------------------------------------------------------
|
|
355
|
+
# RUFF CONFIGURATION
|
|
356
|
+
# Configuration for Ruff, including linter and formatter settings.
|
|
357
|
+
#------------------------------------------------------------------------------
|
|
358
|
+
|
|
359
|
+
# Ruff linter and formatter configuration
|
|
360
|
+
[tool.ruff]
|
|
361
|
+
target-version = "py310"
|
|
362
|
+
line-length = 120
|
|
363
|
+
|
|
364
|
+
# Linting rules configuration
|
|
365
|
+
[tool.ruff.lint]
|
|
366
|
+
# Rule sets to enable, organized by category
|
|
367
|
+
select = [
|
|
368
|
+
# flake8 plugins and extensions
|
|
369
|
+
'A', # flake8-builtins: checks for shadowed builtins
|
|
370
|
+
'ARG', # flake8-unused-arguments: checks for unused function arguments
|
|
371
|
+
'ASYNC', # flake8-async: checks for async/await issues
|
|
372
|
+
'B', # flake8-bugbear: finds likely bugs and design problems
|
|
373
|
+
'C', # flake8-comprehensions: helps write better list/dict comprehensions
|
|
374
|
+
'DTZ', # flake8-datetimez: checks for datetime timezone issues
|
|
375
|
+
'E', # pycodestyle errors: PEP 8 style guide errors
|
|
376
|
+
'EM', # flake8-errmsg: checks for better error messages
|
|
377
|
+
'F', # pyflakes: detects various errors
|
|
378
|
+
'FBT', # flake8-boolean-trap: checks for boolean traps in function signatures
|
|
379
|
+
'I', # isort: sorts imports
|
|
380
|
+
'ICN', # flake8-import-conventions: checks for import conventions
|
|
381
|
+
'ISC', # flake8-implicit-str-concat: checks for implicit string concatenation
|
|
382
|
+
'LOG', # flake8-logging: checks for logging issues
|
|
383
|
+
'N', # pep8-naming: checks naming conventions
|
|
384
|
+
'PLC', # pylint convention: checks for convention issues
|
|
385
|
+
'PLE', # pylint error: checks for errors
|
|
386
|
+
'PLR', # pylint refactor: suggests refactors
|
|
387
|
+
'PLW', # pylint warning: checks for suspicious code
|
|
388
|
+
'PT', # flake8-pytest-style: checks pytest-specific style
|
|
389
|
+
'PTH', # flake8-use-pathlib: checks for stdlib path usage vs pathlib
|
|
390
|
+
'PYI', # flake8-pyi: checks stub files
|
|
391
|
+
'RET', # flake8-return: checks return statement consistency
|
|
392
|
+
'RSE', # flake8-raise: checks raise statements
|
|
393
|
+
'RUF', # Ruff-specific rules
|
|
394
|
+
'S', # flake8-bandit: checks for security issues
|
|
395
|
+
'SIM', # flake8-simplify: checks for code simplification opportunities
|
|
396
|
+
'T', # flake8-print: checks for print statements
|
|
397
|
+
'TCH', # flake8-type-checking: helps with type-checking
|
|
398
|
+
'TID', # flake8-tidy-imports: checks for tidy import statements
|
|
399
|
+
'UP', # pyupgrade: checks for opportunities to use newer Python features
|
|
400
|
+
'W', # pycodestyle warnings: PEP 8 style guide warnings
|
|
401
|
+
'YTT', # flake8-2020: checks for misuse of sys.version or sys.version_info
|
|
402
|
+
|
|
403
|
+
]
|
|
404
|
+
# Rules to ignore (with reasons)
|
|
405
|
+
ignore = [
|
|
406
|
+
'B027', # Empty method in abstract base class - sometimes needed for interfaces
|
|
407
|
+
'C901', # Function is too complex - sometimes complexity is necessary
|
|
408
|
+
'FBT003', # Boolean positional argument in function definition - sometimes unavoidable
|
|
409
|
+
'PLR0911', # Too many return statements - sometimes needed for readability
|
|
410
|
+
'PLR0912', # Too many branches - sometimes needed for complex logic
|
|
411
|
+
'PLR0913', # Too many arguments - sometimes needed in APIs
|
|
412
|
+
'PLR0915', # Too many statements - sometimes needed for comprehensive functions
|
|
413
|
+
'PLR1714', # Consider merging multiple comparisons - sometimes less readable
|
|
414
|
+
'PLW0603', # Using the global statement - sometimes necessary
|
|
415
|
+
'PT013', # Pytest explicit test parameter - sometimes clearer
|
|
416
|
+
'PTH123', # Path traversal - sometimes needed
|
|
417
|
+
'PYI056', # Calling open() in pyi file - sometimes needed in type stubs
|
|
418
|
+
'S105', # Possible hardcoded password - often false positives
|
|
419
|
+
'S106', # Possible hardcoded password - often false positives
|
|
420
|
+
'S107', # Possible hardcoded password - often false positives
|
|
421
|
+
'S110', # try-except-pass - sometimes valid for suppressing exceptions
|
|
422
|
+
'SIM102', # Nested if statements - sometimes more readable than combined conditions
|
|
423
|
+
]
|
|
424
|
+
# Rules that should not be automatically fixed
|
|
425
|
+
unfixable = [
|
|
426
|
+
'F401', # Don't automatically remove unused imports - may be needed later
|
|
427
|
+
|
|
428
|
+
]
|
|
429
|
+
# Configure exclude to ignore specific directories
|
|
430
|
+
exclude = [".git", ".venv", "venv", "dist", "build"]
|
|
431
|
+
|
|
432
|
+
# isort configuration within Ruff
|
|
433
|
+
[tool.ruff.lint.isort]
|
|
434
|
+
known-first-party = ['vexy_pdf_werk'] # Treat as first-party imports for sorting
|
|
435
|
+
|
|
436
|
+
# flake8-tidy-imports configuration within Ruff
|
|
437
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
438
|
+
ban-relative-imports = 'all' # Ban all relative imports for consistency
|
|
439
|
+
|
|
440
|
+
# Per-file rule exceptions
|
|
441
|
+
[tool.ruff.lint.per-file-ignores]
|
|
442
|
+
# Tests can use magic values, assertions, and relative imports
|
|
443
|
+
'tests/**/*' = [
|
|
444
|
+
'PLR2004', # Allow magic values in tests for readability
|
|
445
|
+
'S101', # Allow assertions in tests
|
|
446
|
+
'TID252'
|
|
447
|
+
# Allow relative imports in tests for convenience
|
|
448
|
+
]
|
|
File without changes
|