pdfdancer-client-python 0.1.1__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.

Potentially problematic release.


This version of pdfdancer-client-python might be problematic. Click here for more details.

Files changed (40) hide show
  1. pdfdancer_client_python-0.1.1/.gitignore +7 -0
  2. pdfdancer_client_python-0.1.1/CLAUDE.md +121 -0
  3. pdfdancer_client_python-0.1.1/PKG-INFO +308 -0
  4. pdfdancer_client_python-0.1.1/README.md +281 -0
  5. pdfdancer_client_python-0.1.1/demo.py +365 -0
  6. pdfdancer_client_python-0.1.1/docs/openapi.yml +1190 -0
  7. pdfdancer_client_python-0.1.1/pyproject.toml +52 -0
  8. pdfdancer_client_python-0.1.1/requirements-dev.txt +17 -0
  9. pdfdancer_client_python-0.1.1/requirements.txt +4 -0
  10. pdfdancer_client_python-0.1.1/setup.cfg +4 -0
  11. pdfdancer_client_python-0.1.1/src/pdfdancer/__init__.py +40 -0
  12. pdfdancer_client_python-0.1.1/src/pdfdancer/client_v1.py +675 -0
  13. pdfdancer_client_python-0.1.1/src/pdfdancer/exceptions.py +57 -0
  14. pdfdancer_client_python-0.1.1/src/pdfdancer/models.py +417 -0
  15. pdfdancer_client_python-0.1.1/src/pdfdancer/paragraph_builder.py +267 -0
  16. pdfdancer_client_python-0.1.1/src/pdfdancer_client_python.egg-info/PKG-INFO +308 -0
  17. pdfdancer_client_python-0.1.1/src/pdfdancer_client_python.egg-info/SOURCES.txt +38 -0
  18. pdfdancer_client_python-0.1.1/src/pdfdancer_client_python.egg-info/dependency_links.txt +1 -0
  19. pdfdancer_client_python-0.1.1/src/pdfdancer_client_python.egg-info/requires.txt +10 -0
  20. pdfdancer_client_python-0.1.1/src/pdfdancer_client_python.egg-info/top_level.txt +1 -0
  21. pdfdancer_client_python-0.1.1/test.py +455 -0
  22. pdfdancer_client_python-0.1.1/tests/__init__.py +1 -0
  23. pdfdancer_client_python-0.1.1/tests/e2e/__init__.py +46 -0
  24. pdfdancer_client_python-0.1.1/tests/e2e/test_form.py +33 -0
  25. pdfdancer_client_python-0.1.1/tests/e2e/test_image.py +84 -0
  26. pdfdancer_client_python-0.1.1/tests/e2e/test_line.py +92 -0
  27. pdfdancer_client_python-0.1.1/tests/e2e/test_page.py +29 -0
  28. pdfdancer_client_python-0.1.1/tests/e2e/test_paragraph.py +172 -0
  29. pdfdancer_client_python-0.1.1/tests/e2e/test_path.py +56 -0
  30. pdfdancer_client_python-0.1.1/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
  31. pdfdancer_client_python-0.1.1/tests/fixtures/ObviouslyAwesome.pdf +0 -0
  32. pdfdancer_client_python-0.1.1/tests/fixtures/basic-paths.pdf +0 -0
  33. pdfdancer_client_python-0.1.1/tests/fixtures/logo-80.png +0 -0
  34. pdfdancer_client_python-0.1.1/tests/fixtures/mixed-form-types.pdf +0 -0
  35. pdfdancer_client_python-0.1.1/tests/test_client_v1.py +444 -0
  36. pdfdancer_client_python-0.1.1/tests/test_error_extraction.py +117 -0
  37. pdfdancer_client_python-0.1.1/tests/test_exception_suppression.py +53 -0
  38. pdfdancer_client_python-0.1.1/tests/test_models.py +303 -0
  39. pdfdancer_client_python-0.1.1/tests/test_openapi_compliance.py +108 -0
  40. pdfdancer_client_python-0.1.1/tests/test_paragraph_builder.py +324 -0
@@ -0,0 +1,7 @@
1
+ output.pdf
2
+ .idea
3
+ comprehensive_output.pdf
4
+ jwt-token-mlahr-20250829-160417.txt
5
+ dist/
6
+ src/pdfdancer_python.egg-info
7
+ .aider*
@@ -0,0 +1,121 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with the PDFDancer Python client.
4
+
5
+ ## Project Overview
6
+
7
+ This is a **Python client library** for the PDFDancer PDF manipulation API. It uses a **100% manual implementation** that:
8
+
9
+ - **Mirrors Java client structure exactly** - Same methods, validation, and patterns
10
+ - **Pure Python implementation** - Uses `requests` for HTTP calls, no code generation
11
+ - **Pythonic conventions** - Snake_case methods, type hints, context managers
12
+ - **Strict validation** - Matches Java client validation exactly
13
+
14
+ ## Essential Commands
15
+
16
+ ### Development
17
+ - `python -m venv venv` - Create virtual environment
18
+ - `venv/bin/pip install -e .` - Install in development mode
19
+ - `venv/bin/pip install -r requirements-dev.txt` - Install dev dependencies
20
+
21
+ ### Testing
22
+ - `venv/bin/python -m pytest tests/ -v` - Run all tests (77 tests)
23
+ - `venv/bin/python -m pytest tests/test_client_v1.py -v` - Run client tests
24
+ - `venv/bin/python -m pytest tests/test_paragraph_builder.py -v` - Run builder tests
25
+
26
+ ### Building & Publishing
27
+ - `venv/bin/python -m build` - Build distribution packages
28
+ - `venv/bin/python -m twine check dist/*` - Validate packages
29
+ - `venv/bin/python -m twine upload dist/*` - Publish to PyPI
30
+
31
+ ## Architecture
32
+
33
+ ### Manual Implementation
34
+ The client is a pure manual implementation that closely mirrors the Java client:
35
+
36
+ ```python
37
+ # Java-like API with Python conventions
38
+ client = ClientV1(token="jwt-token", pdf_data="document.pdf")
39
+
40
+ # Find operations (mirrors Java findParagraphs, findImages, etc.)
41
+ paragraphs = client.find_paragraphs(position)
42
+ images = client.find_images(position)
43
+
44
+ # Manipulation operations (mirrors Java delete, move, etc.)
45
+ client.delete(paragraphs[0])
46
+ client.move(images[0], new_position)
47
+
48
+ # Builder pattern (mirrors Java ParagraphBuilder)
49
+ paragraph = (client.paragraph_builder()
50
+ .from_string("Text content")
51
+ .with_font(Font("Arial", 12))
52
+ .with_position(Position.on_page_coordinates(0, 100, 200))
53
+ .build())
54
+
55
+ # Context manager support (Python enhancement)
56
+ with ClientV1(token="jwt-token", pdf_data=pdf_file) as client:
57
+ client.save_pdf("output.pdf")
58
+ ```
59
+
60
+ ### Package Structure
61
+ - `src/pdfdancer/` - Main package
62
+ - `client_v1.py` - Main ClientV1 class (mirrors Java Client class)
63
+ - `paragraph_builder.py` - ParagraphBuilder for fluent construction
64
+ - `models.py` - All model classes (ObjectRef, Position, Font, etc.)
65
+ - `exceptions.py` - Exception hierarchy matching Java client
66
+
67
+ ### Key Features
68
+ - **Session-based operations**: Constructor creates session automatically
69
+ - **Strict validation**: All validation matches Java client exactly
70
+ - **Builder pattern**: ParagraphBuilder with fluent interface
71
+ - **Exception handling**: FontNotFoundException, ValidationException, etc.
72
+ - **Type safety**: Full type hints throughout
73
+ - **Context manager**: Python enhancement for resource management
74
+
75
+ ## Java Client Mapping
76
+
77
+ ### Constructor Patterns
78
+ ```python
79
+ # Java: new Client(token, pdfFile)
80
+ client = ClientV1(token="jwt-token", pdf_data="document.pdf")
81
+
82
+ # Java: new Client(token, bytesPDF, httpClient)
83
+ client = ClientV1(token="jwt-token", pdf_data=pdf_bytes, base_url="http://api.server")
84
+ ```
85
+
86
+ ### Method Mapping
87
+ - `find()` → `find()`
88
+ - `findParagraphs()` → `find_paragraphs()`
89
+ - `findImages()` → `find_images()`
90
+ - `delete()` → `delete()`
91
+ - `move()` → `move()`
92
+ - `addParagraph()` → `add_paragraph()`
93
+ - `getPDFFile()` → `get_pdf_file()`
94
+ - `savePDF()` → `save_pdf()`
95
+ - `paragraphBuilder()` → `paragraph_builder()`
96
+
97
+ ### Validation Matching
98
+ All validation matches Java client exactly:
99
+ - Null checks become None checks
100
+ - IllegalArgumentException becomes ValidationException
101
+ - FontNotFoundException preserved exactly
102
+ - Page number validation (must be positive)
103
+ - File existence and readability checks
104
+
105
+ ## Development Notes
106
+
107
+ - **Python 3.8+ compatibility**
108
+ - **Uses `requests` library** for all HTTP communication
109
+ - **No code generation** - pure manual implementation
110
+ - **Virtual environment auto-setup** via parent Makefile
111
+ - **No code formatter configured** - follow existing style
112
+ - **Comprehensive tests** - 77 tests covering all functionality
113
+
114
+ ## Important Instructions
115
+
116
+ - **ALWAYS mirror Java client behavior exactly** - same validation, same patterns
117
+ - **Use snake_case for method names** but preserve Java logic
118
+ - **Maintain strict validation** - don't be more lenient than Java client
119
+ - **Follow existing test patterns** when adding new functionality
120
+ - **Keep exception hierarchy matching Java client**
121
+ - **Preserve builder pattern fluent interface**
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.4
2
+ Name: pdfdancer-client-python
3
+ Version: 0.1.1
4
+ Summary: Python client for PDFDancer API
5
+ Author-email: TFC <info@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/tfc/pdfdancer-python
8
+ Project-URL: Repository, https://github.com/tfc/pdfdancer-python.git
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: requests>=2.25.0
19
+ Requires-Dist: pydantic>=1.8.0
20
+ Requires-Dist: typing-extensions>=4.0.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=7.0; extra == "dev"
23
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
24
+ Requires-Dist: black>=22.0; extra == "dev"
25
+ Requires-Dist: flake8>=5.0; extra == "dev"
26
+ Requires-Dist: mypy>=1.0; extra == "dev"
27
+
28
+ # PDFDancer Python Client
29
+
30
+ A Python client library for the PDFDancer PDF manipulation API that closely mirrors the Java client structure and functionality.
31
+
32
+ ## Features
33
+
34
+ - **100% Manual Implementation** - Pure Python, no code generation
35
+ - **Java Client Compatibility** - Same methods, validation, and patterns
36
+ - **Session-based Operations** - Automatic session management
37
+ - **Builder Pattern** - Fluent ParagraphBuilder interface
38
+ - **Strict Validation** - Matches Java client validation exactly
39
+ - **Python Enhancements** - Type hints, context managers, Pathlib support
40
+ - **Comprehensive Testing** - 77 tests covering all functionality
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ pip install pdfdancer-client-python
46
+ # Or for development:
47
+ pip install -e .
48
+ ```
49
+
50
+ ## Quick Start
51
+
52
+ ```python
53
+ from pdfdancer import ClientV1, Position, Font, Color
54
+
55
+ # Create client (mirrors Java: new Client(token, pdfFile))
56
+ client = ClientV1(token="your-jwt-token", pdf_data="document.pdf")
57
+
58
+ # Find operations (mirrors Java client methods)
59
+ paragraphs = client.find_paragraphs(None)
60
+ images = client.find_images(Position.from_page_index(0))
61
+
62
+ # Manipulation operations (mirrors Java client methods)
63
+ client.delete(paragraphs[0])
64
+ client.move(images[0], Position.on_page_coordinates(0, 100, 200))
65
+
66
+ # Builder pattern (mirrors Java ParagraphBuilder)
67
+ paragraph = (client.paragraph_builder()
68
+ .from_string("Hello World")
69
+ .with_font(Font("Arial", 12))
70
+ .with_color(Color(255, 0, 0))
71
+ .with_position(Position.from_page_index(0))
72
+ .build())
73
+
74
+ client.add_paragraph(paragraph)
75
+
76
+ # Save result (mirrors Java savePDF)
77
+ client.save_pdf("output.pdf")
78
+ ```
79
+
80
+ ## Context Manager (Python Enhancement)
81
+
82
+ ```python
83
+ from pdfdancer import ClientV1
84
+
85
+ # Automatic resource management
86
+ with ClientV1(token="jwt-token", pdf_data="input.pdf") as client:
87
+ paragraphs = client.find_paragraphs(None)
88
+ client.delete(paragraphs[0])
89
+ client.save_pdf("output.pdf")
90
+ # Session automatically cleaned up
91
+ ```
92
+
93
+ ## API Methods
94
+
95
+ ### Constructor Patterns
96
+ ```python
97
+ # File path (Java: new Client(token, new File("pdf")))
98
+ client = ClientV1(token="jwt-token", pdf_data="document.pdf")
99
+
100
+ # Bytes (Java: new Client(token, pdfBytes, httpClient))
101
+ client = ClientV1(token="jwt-token", pdf_data=pdf_bytes)
102
+
103
+ # Custom server
104
+ client = ClientV1(token="jwt-token", pdf_data=pdf_file, base_url="https://api.server")
105
+ ```
106
+
107
+ ### Find Operations
108
+ ```python
109
+ # Generic find (Java: client.find())
110
+ objects = client.find(ObjectType.PARAGRAPH, position)
111
+
112
+ # Specific finders (Java: client.findParagraphs(), etc.)
113
+ paragraphs = client.find_paragraphs(position)
114
+ images = client.find_images(position)
115
+ forms = client.find_forms(position)
116
+ paths = client.find_paths(position)
117
+ text_lines = client.find_text_lines(position)
118
+
119
+ # Page operations (Java: client.getPages(), client.getPage())
120
+ pages = client.get_pages()
121
+ page = client.get_page(1) # 1-based indexing
122
+ ```
123
+
124
+ ### Manipulation Operations
125
+ ```python
126
+ # Delete (Java: client.delete(), client.deletePage())
127
+ result = client.delete(object_ref)
128
+ result = client.delete_page(page_ref)
129
+
130
+ # Move (Java: client.move())
131
+ result = client.move(object_ref, new_position)
132
+
133
+ # Add (Java: client.addImage(), client.addParagraph())
134
+ result = client.add_image(image, position)
135
+ result = client.add_paragraph(paragraph)
136
+
137
+ # Modify (Java: client.modifyParagraph(), client.modifyTextLine())
138
+ result = client.modify_paragraph(ref, new_paragraph)
139
+ result = client.modify_text_line(ref, "new text")
140
+ ```
141
+
142
+ ### Builder Pattern
143
+ ```python
144
+ # Java: client.paragraphBuilder()
145
+ builder = client.paragraph_builder()
146
+
147
+ # Fluent interface (mirrors Java ParagraphBuilder)
148
+ paragraph = (builder
149
+ .from_string("Text content") # Java: fromString()
150
+ .with_font(Font("Arial", 12)) # Java: withFont()
151
+ .with_color(Color(255, 0, 0)) # Java: withColor()
152
+ .with_line_spacing(1.5) # Java: withLineSpacing()
153
+ .with_position(position) # Java: withPosition()
154
+ .build()) # Java: build()
155
+
156
+ # Font file registration (Java: withFont(File, double))
157
+ paragraph = (builder
158
+ .with_font_file("custom.ttf", 14.0) # Java: withFont(File, double)
159
+ .from_string("Custom font text")
160
+ .with_position(position)
161
+ .build())
162
+ ```
163
+
164
+ ### Position API
165
+
166
+ ```python
167
+ from pdfdancer import Position
168
+
169
+ # Factory methods (Java: Position.fromPageNumber(), Position.onPageCoordinates())
170
+ position = Position.from_page_index(0)
171
+ position = Position.on_page_coordinates(0, 100, 200)
172
+
173
+ # Coordinate access (Java: position.getX(), position.getY())
174
+ x = position.get_x()
175
+ y = position.get_y()
176
+
177
+ # Movement (Java: position.moveX(), position.moveY())
178
+ position.move_x(50.0)
179
+ position.move_y(-25.0)
180
+
181
+ # Copy (Java: position.copy())
182
+ position_copy = position.copy()
183
+ ```
184
+
185
+ ### Font Operations
186
+ ```python
187
+ # Find fonts (Java: client.findFonts())
188
+ fonts = client.find_fonts("Arial", 12)
189
+
190
+ # Register custom font (Java: client.registerFont())
191
+ font_name = client.register_font("custom.ttf")
192
+ font_name = client.register_font(Path("font.ttf"))
193
+ font_name = client.register_font(font_bytes)
194
+ ```
195
+
196
+ ### Document Operations
197
+ ```python
198
+ # Get PDF content (Java: client.getPDFFile())
199
+ pdf_bytes = client.get_pdf_file()
200
+
201
+ # Save PDF (Java: client.savePDF())
202
+ client.save_pdf("output.pdf")
203
+ client.save_pdf(Path("output.pdf"))
204
+ ```
205
+
206
+ ## Exception Handling
207
+
208
+ ```python
209
+ from pdfdancer import (
210
+ PdfDancerException, ValidationException,
211
+ FontNotFoundException, HttpClientException
212
+ )
213
+
214
+ try:
215
+ client = ClientV1(token="", pdf_data=b"pdf")
216
+ except ValidationException as e: # Java: IllegalArgumentException
217
+ print(f"Validation error: {e}")
218
+
219
+ try:
220
+ fonts = client.find_fonts("NonExistentFont", 12)
221
+ except FontNotFoundException as e: # Java: FontNotFoundException
222
+ print(f"Font not found: {e}")
223
+ ```
224
+
225
+ ## Data Models
226
+
227
+ ```python
228
+ from pdfdancer import ObjectRef, Position, Font, Color, ObjectType
229
+
230
+ # Object reference (Java: ObjectRef)
231
+ obj_ref = ObjectRef(internal_id="obj-123", position=position, type=ObjectType.PARAGRAPH)
232
+
233
+ # Font (Java: Font)
234
+ font = Font(name="Arial", size=12.0)
235
+
236
+ # Color (Java: Color) - RGB values 0-255
237
+ color = Color(r=255, g=128, b=0)
238
+
239
+ # Position with bounding rectangle (Java: Position, BoundingRect)
240
+ position = Position.on_page_coordinates(page=0, x=100.0, y=200.0)
241
+ ```
242
+
243
+ ## Development
244
+
245
+ ### Setup
246
+ ```bash
247
+ python -m venv venv
248
+ source venv/bin/activate # On Windows: venv\Scripts\activate
249
+ pip install -e .
250
+ pip install -r requirements-dev.txt
251
+ ```
252
+
253
+ ### Testing
254
+ ```bash
255
+ # Run all tests (77 tests)
256
+ python -m pytest tests/ -v
257
+
258
+ # Run specific test files
259
+ python -m pytest tests/test_client_v1.py -v
260
+ python -m pytest tests/test_paragraph_builder.py -v
261
+ python -m pytest tests/test_models.py -v
262
+ ```
263
+
264
+ ### Run Demo
265
+ ```bash
266
+ python demo.py
267
+ ```
268
+
269
+ ### Build Package
270
+ ```bash
271
+ python -m build
272
+ python -m twine check dist/*
273
+ ```
274
+
275
+ ## Java Client Mapping
276
+
277
+ | Java Method | Python Method | Description |
278
+ |-------------|---------------|-------------|
279
+ | `new Client(token, file)` | `ClientV1(token="", pdf_data="")` | Constructor |
280
+ | `findParagraphs(position)` | `find_paragraphs(position)` | Find paragraphs |
281
+ | `findImages(position)` | `find_images(position)` | Find images |
282
+ | `delete(objectRef)` | `delete(object_ref)` | Delete object |
283
+ | `move(objectRef, position)` | `move(object_ref, position)` | Move object |
284
+ | `addParagraph(paragraph)` | `add_paragraph(paragraph)` | Add paragraph |
285
+ | `getPDFFile()` | `get_pdf_file()` | Get PDF bytes |
286
+ | `savePDF(path)` | `save_pdf(path)` | Save to file |
287
+ | `paragraphBuilder()` | `paragraph_builder()` | Create builder |
288
+ | `findFonts(name, size)` | `find_fonts(name, size)` | Find fonts |
289
+ | `registerFont(ttfFile)` | `register_font(ttf_file)` | Register font |
290
+
291
+ ## Architecture
292
+
293
+ - **Pure Manual Implementation** - No code generation, uses `requests` for HTTP
294
+ - **Session-based** - Constructor creates session, all operations use session ID
295
+ - **Strict Validation** - Matches Java client validation exactly
296
+ - **Type Safety** - Full type hints throughout
297
+ - **Error Handling** - Complete exception hierarchy
298
+ - **Python Conventions** - snake_case methods, context managers, Pathlib support
299
+
300
+ ## Requirements
301
+
302
+ - Python 3.8+
303
+ - `requests` library for HTTP communication
304
+ - `pathlib` for file handling (built-in)
305
+
306
+ ## License
307
+
308
+ [Add your license information here]