pdfdancer-client-python 0.1.2__tar.gz → 0.2.2__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.
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/CLAUDE.md +4 -4
- {pdfdancer_client_python-0.1.2/src/pdfdancer_client_python.egg-info → pdfdancer_client_python-0.2.2}/PKG-INFO +26 -25
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/README.md +21 -19
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/pyproject.toml +5 -6
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/release.py +9 -3
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer/__init__.py +5 -3
- pdfdancer_client_python-0.2.2/src/pdfdancer/image_builder.py +30 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer/models.py +58 -6
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer/paragraph_builder.py +15 -12
- pdfdancer_client_python-0.1.2/src/pdfdancer/client_v1.py → pdfdancer_client_python-0.2.2/src/pdfdancer/pdfdancer_v1.py +236 -55
- pdfdancer_client_python-0.2.2/src/pdfdancer/types.py +263 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2/src/pdfdancer_client_python.egg-info}/PKG-INFO +26 -25
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer_client_python.egg-info/SOURCES.txt +5 -6
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/test.py +32 -32
- pdfdancer_client_python-0.2.2/tests/e2e/test_acroform.py +83 -0
- pdfdancer_client_python-0.2.2/tests/e2e/test_form_x_objects.py +36 -0
- pdfdancer_client_python-0.2.2/tests/e2e/test_image.py +91 -0
- pdfdancer_client_python-0.2.2/tests/e2e/test_line.py +83 -0
- pdfdancer_client_python-0.2.2/tests/e2e/test_page.py +33 -0
- pdfdancer_client_python-0.2.2/tests/e2e/test_paragraph.py +169 -0
- pdfdancer_client_python-0.2.2/tests/e2e/test_path.py +69 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/test_models.py +8 -8
- pdfdancer_client_python-0.1.2/tests/e2e/test_form.py +0 -33
- pdfdancer_client_python-0.1.2/tests/e2e/test_image.py +0 -84
- pdfdancer_client_python-0.1.2/tests/e2e/test_line.py +0 -84
- pdfdancer_client_python-0.1.2/tests/e2e/test_page.py +0 -29
- pdfdancer_client_python-0.1.2/tests/e2e/test_paragraph.py +0 -165
- pdfdancer_client_python-0.1.2/tests/e2e/test_path.py +0 -56
- pdfdancer_client_python-0.1.2/tests/test_client_v1.py +0 -444
- pdfdancer_client_python-0.1.2/tests/test_error_extraction.py +0 -117
- pdfdancer_client_python-0.1.2/tests/test_exception_suppression.py +0 -53
- pdfdancer_client_python-0.1.2/tests/test_paragraph_builder.py +0 -324
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/.github/workflows/ci.yml +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/.gitignore +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/docs/openapi.yml +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/requirements-dev.txt +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/requirements.txt +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/setup.cfg +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer/exceptions.py +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer_client_python.egg-info/dependency_links.txt +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer_client_python.egg-info/requires.txt +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer_client_python.egg-info/top_level.txt +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/__init__.py +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/e2e/__init__.py +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/fixtures/DancingScript-Regular.ttf +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/fixtures/ObviouslyAwesome.pdf +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/fixtures/basic-paths.pdf +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/fixtures/form-xobject-example.pdf +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/fixtures/logo-80.png +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/fixtures/mixed-form-types.pdf +0 -0
- {pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/tests/test_openapi_compliance.py +0 -0
|
@@ -38,12 +38,12 @@ The client is a pure manual implementation that closely mirrors the Java client:
|
|
|
38
38
|
client = ClientV1(token="jwt-token", pdf_data="document.pdf")
|
|
39
39
|
|
|
40
40
|
# Find operations (mirrors Java findParagraphs, findImages, etc.)
|
|
41
|
-
paragraphs = client.
|
|
42
|
-
images = client.
|
|
41
|
+
paragraphs = client._find_paragraphs(position)
|
|
42
|
+
images = client._find_images(position)
|
|
43
43
|
|
|
44
44
|
# Manipulation operations (mirrors Java delete, move, etc.)
|
|
45
|
-
client.
|
|
46
|
-
client.
|
|
45
|
+
client._delete(paragraphs[0])
|
|
46
|
+
client._move(images[0], new_position)
|
|
47
47
|
|
|
48
48
|
# Builder pattern (mirrors Java ParagraphBuilder)
|
|
49
49
|
paragraph = (client.paragraph_builder()
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pdfdancer-client-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Python client for PDFDancer API
|
|
5
|
-
Author-email:
|
|
5
|
+
Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
|
|
6
6
|
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://
|
|
8
|
-
Project-URL: Repository, https://github.com/
|
|
7
|
+
Project-URL: Homepage, https://www.pdfdancer.com/
|
|
8
|
+
Project-URL: Repository, https://github.com/MenschMachine/pdfdancer-client-python
|
|
9
9
|
Classifier: Development Status :: 4 - Beta
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
12
|
Classifier: Programming Language :: Python :: 3.9
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
16
|
Description-Content-Type: text/markdown
|
|
18
17
|
Requires-Dist: requests>=2.25.0
|
|
19
18
|
Requires-Dist: pydantic>=1.8.0
|
|
@@ -60,8 +59,8 @@ paragraphs = client.find_paragraphs(None)
|
|
|
60
59
|
images = client.find_images(Position.at_page(0))
|
|
61
60
|
|
|
62
61
|
# Manipulation operations (mirrors Java client methods)
|
|
63
|
-
client.
|
|
64
|
-
client.
|
|
62
|
+
client._delete(paragraphs[0])
|
|
63
|
+
client._move(images[0], Position.at_page_coordinates(0, 100, 200))
|
|
65
64
|
|
|
66
65
|
# Builder pattern (mirrors Java ParagraphBuilder)
|
|
67
66
|
paragraph = (client.paragraph_builder()
|
|
@@ -71,7 +70,7 @@ paragraph = (client.paragraph_builder()
|
|
|
71
70
|
.with_position(Position.at_page(0))
|
|
72
71
|
.build())
|
|
73
72
|
|
|
74
|
-
client.
|
|
73
|
+
client._add_paragraph(paragraph)
|
|
75
74
|
|
|
76
75
|
# Save result (mirrors Java savePDF)
|
|
77
76
|
client.save_pdf("output.pdf")
|
|
@@ -85,7 +84,7 @@ from pdfdancer import ClientV1
|
|
|
85
84
|
# Automatic resource management
|
|
86
85
|
with ClientV1(token="jwt-token", pdf_data="input.pdf") as client:
|
|
87
86
|
paragraphs = client.find_paragraphs(None)
|
|
88
|
-
client.
|
|
87
|
+
client._delete(paragraphs[0])
|
|
89
88
|
client.save_pdf("output.pdf")
|
|
90
89
|
# Session automatically cleaned up
|
|
91
90
|
```
|
|
@@ -105,37 +104,39 @@ client = ClientV1(token="jwt-token", pdf_data=pdf_file, base_url="https://api.se
|
|
|
105
104
|
```
|
|
106
105
|
|
|
107
106
|
### Find Operations
|
|
107
|
+
|
|
108
108
|
```python
|
|
109
109
|
# Generic find (Java: client.find())
|
|
110
|
-
objects = client.
|
|
110
|
+
objects = client._find(ObjectType.PARAGRAPH, position)
|
|
111
111
|
|
|
112
112
|
# Specific finders (Java: client.findParagraphs(), etc.)
|
|
113
|
-
paragraphs = client.
|
|
114
|
-
images = client.
|
|
115
|
-
forms = client.
|
|
116
|
-
paths = client.
|
|
117
|
-
text_lines = client.
|
|
113
|
+
paragraphs = client._find_paragraphs(position)
|
|
114
|
+
images = client._find_images(position)
|
|
115
|
+
forms = client._find_form_x_objects(position)
|
|
116
|
+
paths = client._find_paths(position)
|
|
117
|
+
text_lines = client._find_text_lines(position)
|
|
118
118
|
|
|
119
119
|
# Page operations (Java: client.getPages(), client.getPage())
|
|
120
120
|
pages = client.get_pages()
|
|
121
|
-
page = client.
|
|
121
|
+
page = client._get_page(1) # 1-based indexing
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
### Manipulation Operations
|
|
125
|
+
|
|
125
126
|
```python
|
|
126
127
|
# Delete (Java: client.delete(), client.deletePage())
|
|
127
|
-
result = client.
|
|
128
|
-
result = client.
|
|
128
|
+
result = client._delete(object_ref)
|
|
129
|
+
result = client._delete_page(page_ref)
|
|
129
130
|
|
|
130
131
|
# Move (Java: client.move())
|
|
131
|
-
result = client.
|
|
132
|
+
result = client._move(object_ref, new_position)
|
|
132
133
|
|
|
133
134
|
# Add (Java: client.addImage(), client.addParagraph())
|
|
134
|
-
result = client.
|
|
135
|
-
result = client.
|
|
135
|
+
result = client._add_image(image, position)
|
|
136
|
+
result = client._add_paragraph(paragraph)
|
|
136
137
|
|
|
137
138
|
# Modify (Java: client.modifyParagraph(), client.modifyTextLine())
|
|
138
|
-
result = client.
|
|
139
|
+
result = client._modify_paragraph(ref, new_paragraph)
|
|
139
140
|
result = client.modify_text_line(ref, "new text")
|
|
140
141
|
```
|
|
141
142
|
|
|
@@ -171,8 +172,8 @@ position = Position.at_page(0)
|
|
|
171
172
|
position = Position.at_page_coordinates(0, 100, 200)
|
|
172
173
|
|
|
173
174
|
# Coordinate access (Java: position.getX(), position.getY())
|
|
174
|
-
x = position.
|
|
175
|
-
y = position.
|
|
175
|
+
x = position.x()
|
|
176
|
+
y = position.y()
|
|
176
177
|
|
|
177
178
|
# Movement (Java: position.moveX(), position.moveY())
|
|
178
179
|
position.move_x(50.0)
|
|
@@ -33,8 +33,8 @@ paragraphs = client.find_paragraphs(None)
|
|
|
33
33
|
images = client.find_images(Position.at_page(0))
|
|
34
34
|
|
|
35
35
|
# Manipulation operations (mirrors Java client methods)
|
|
36
|
-
client.
|
|
37
|
-
client.
|
|
36
|
+
client._delete(paragraphs[0])
|
|
37
|
+
client._move(images[0], Position.at_page_coordinates(0, 100, 200))
|
|
38
38
|
|
|
39
39
|
# Builder pattern (mirrors Java ParagraphBuilder)
|
|
40
40
|
paragraph = (client.paragraph_builder()
|
|
@@ -44,7 +44,7 @@ paragraph = (client.paragraph_builder()
|
|
|
44
44
|
.with_position(Position.at_page(0))
|
|
45
45
|
.build())
|
|
46
46
|
|
|
47
|
-
client.
|
|
47
|
+
client._add_paragraph(paragraph)
|
|
48
48
|
|
|
49
49
|
# Save result (mirrors Java savePDF)
|
|
50
50
|
client.save_pdf("output.pdf")
|
|
@@ -58,7 +58,7 @@ from pdfdancer import ClientV1
|
|
|
58
58
|
# Automatic resource management
|
|
59
59
|
with ClientV1(token="jwt-token", pdf_data="input.pdf") as client:
|
|
60
60
|
paragraphs = client.find_paragraphs(None)
|
|
61
|
-
client.
|
|
61
|
+
client._delete(paragraphs[0])
|
|
62
62
|
client.save_pdf("output.pdf")
|
|
63
63
|
# Session automatically cleaned up
|
|
64
64
|
```
|
|
@@ -78,37 +78,39 @@ client = ClientV1(token="jwt-token", pdf_data=pdf_file, base_url="https://api.se
|
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
### Find Operations
|
|
81
|
+
|
|
81
82
|
```python
|
|
82
83
|
# Generic find (Java: client.find())
|
|
83
|
-
objects = client.
|
|
84
|
+
objects = client._find(ObjectType.PARAGRAPH, position)
|
|
84
85
|
|
|
85
86
|
# Specific finders (Java: client.findParagraphs(), etc.)
|
|
86
|
-
paragraphs = client.
|
|
87
|
-
images = client.
|
|
88
|
-
forms = client.
|
|
89
|
-
paths = client.
|
|
90
|
-
text_lines = client.
|
|
87
|
+
paragraphs = client._find_paragraphs(position)
|
|
88
|
+
images = client._find_images(position)
|
|
89
|
+
forms = client._find_form_x_objects(position)
|
|
90
|
+
paths = client._find_paths(position)
|
|
91
|
+
text_lines = client._find_text_lines(position)
|
|
91
92
|
|
|
92
93
|
# Page operations (Java: client.getPages(), client.getPage())
|
|
93
94
|
pages = client.get_pages()
|
|
94
|
-
page = client.
|
|
95
|
+
page = client._get_page(1) # 1-based indexing
|
|
95
96
|
```
|
|
96
97
|
|
|
97
98
|
### Manipulation Operations
|
|
99
|
+
|
|
98
100
|
```python
|
|
99
101
|
# Delete (Java: client.delete(), client.deletePage())
|
|
100
|
-
result = client.
|
|
101
|
-
result = client.
|
|
102
|
+
result = client._delete(object_ref)
|
|
103
|
+
result = client._delete_page(page_ref)
|
|
102
104
|
|
|
103
105
|
# Move (Java: client.move())
|
|
104
|
-
result = client.
|
|
106
|
+
result = client._move(object_ref, new_position)
|
|
105
107
|
|
|
106
108
|
# Add (Java: client.addImage(), client.addParagraph())
|
|
107
|
-
result = client.
|
|
108
|
-
result = client.
|
|
109
|
+
result = client._add_image(image, position)
|
|
110
|
+
result = client._add_paragraph(paragraph)
|
|
109
111
|
|
|
110
112
|
# Modify (Java: client.modifyParagraph(), client.modifyTextLine())
|
|
111
|
-
result = client.
|
|
113
|
+
result = client._modify_paragraph(ref, new_paragraph)
|
|
112
114
|
result = client.modify_text_line(ref, "new text")
|
|
113
115
|
```
|
|
114
116
|
|
|
@@ -144,8 +146,8 @@ position = Position.at_page(0)
|
|
|
144
146
|
position = Position.at_page_coordinates(0, 100, 200)
|
|
145
147
|
|
|
146
148
|
# Coordinate access (Java: position.getX(), position.getY())
|
|
147
|
-
x = position.
|
|
148
|
-
y = position.
|
|
149
|
+
x = position.x()
|
|
150
|
+
y = position.y()
|
|
149
151
|
|
|
150
152
|
# Movement (Java: position.moveX(), position.moveY())
|
|
151
153
|
position.move_x(50.0)
|
|
@@ -4,22 +4,21 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pdfdancer-client-python"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Python client for PDFDancer API"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
11
|
-
{ name = "
|
|
11
|
+
{ name = "The Famous Cat Ltd.", email = "hi@thefamouscat.com" }
|
|
12
12
|
]
|
|
13
13
|
license = { text = "MIT" }
|
|
14
14
|
classifiers = [
|
|
15
15
|
"Development Status :: 4 - Beta",
|
|
16
16
|
"Intended Audience :: Developers",
|
|
17
17
|
"License :: OSI Approved :: MIT License",
|
|
18
|
-
"Programming Language :: Python :: 3",
|
|
19
|
-
"Programming Language :: Python :: 3.8",
|
|
20
18
|
"Programming Language :: Python :: 3.9",
|
|
21
19
|
"Programming Language :: Python :: 3.10",
|
|
22
20
|
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
23
22
|
]
|
|
24
23
|
dependencies = [
|
|
25
24
|
"requests>=2.25.0",
|
|
@@ -37,8 +36,8 @@ dev = [
|
|
|
37
36
|
]
|
|
38
37
|
|
|
39
38
|
[project.urls]
|
|
40
|
-
Homepage = "https://
|
|
41
|
-
Repository = "https://github.com/
|
|
39
|
+
Homepage = "https://www.pdfdancer.com/"
|
|
40
|
+
Repository = "https://github.com/MenschMachine/pdfdancer-client-python"
|
|
42
41
|
|
|
43
42
|
[tool.setuptools.packages.find]
|
|
44
43
|
where = ["src"]
|
|
@@ -6,11 +6,12 @@ A tool to bump version and upload to PyPI.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import argparse
|
|
9
|
+
import glob
|
|
9
10
|
import re
|
|
10
11
|
import subprocess
|
|
11
12
|
import sys
|
|
12
13
|
from pathlib import Path
|
|
13
|
-
from typing import List
|
|
14
|
+
from typing import List
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class ReleaseError(Exception):
|
|
@@ -142,7 +143,12 @@ class PyPIUploader:
|
|
|
142
143
|
if include_e2e:
|
|
143
144
|
test_path = "tests/"
|
|
144
145
|
else:
|
|
145
|
-
|
|
146
|
+
# Collect all test files except those in e2e/
|
|
147
|
+
test_files = [
|
|
148
|
+
f for f in glob.glob("tests/**/*.py", recursive=True)
|
|
149
|
+
if "e2e" not in f
|
|
150
|
+
]
|
|
151
|
+
test_path = " ".join(test_files)
|
|
146
152
|
|
|
147
153
|
self.run_command([str(self.python_exe), "-m", "pytest"] + test_path.split() + ["-v"])
|
|
148
154
|
print("All tests passed")
|
|
@@ -263,4 +269,4 @@ def main():
|
|
|
263
269
|
|
|
264
270
|
|
|
265
271
|
if __name__ == "__main__":
|
|
266
|
-
main()
|
|
272
|
+
main()
|
|
@@ -6,20 +6,19 @@ Provides a clean, Pythonic interface for PDF operations that closely
|
|
|
6
6
|
mirrors the Java client structure and functionality.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from .client_v1 import ClientV1
|
|
10
9
|
from .exceptions import (
|
|
11
10
|
PdfDancerException, FontNotFoundException, ValidationException,
|
|
12
11
|
HttpClientException, SessionException
|
|
13
12
|
)
|
|
14
13
|
from .models import (
|
|
15
|
-
ObjectRef, Position, ObjectType, Font, Color, Image, BoundingRect, Paragraph,
|
|
14
|
+
ObjectRef, Position, ObjectType, Font, Color, Image, BoundingRect, Paragraph, FormFieldRef,
|
|
16
15
|
PositionMode, ShapeType, Point
|
|
17
16
|
)
|
|
18
17
|
from .paragraph_builder import ParagraphBuilder
|
|
19
18
|
|
|
20
19
|
__version__ = "1.0.0"
|
|
21
20
|
__all__ = [
|
|
22
|
-
"
|
|
21
|
+
"PDFDancer",
|
|
23
22
|
"ParagraphBuilder",
|
|
24
23
|
"ObjectRef",
|
|
25
24
|
"Position",
|
|
@@ -29,6 +28,7 @@ __all__ = [
|
|
|
29
28
|
"Image",
|
|
30
29
|
"BoundingRect",
|
|
31
30
|
"Paragraph",
|
|
31
|
+
"FormFieldRef",
|
|
32
32
|
"PositionMode",
|
|
33
33
|
"ShapeType",
|
|
34
34
|
"Point",
|
|
@@ -38,3 +38,5 @@ __all__ = [
|
|
|
38
38
|
"HttpClientException",
|
|
39
39
|
"SessionException"
|
|
40
40
|
]
|
|
41
|
+
|
|
42
|
+
from .pdfdancer_v1 import PDFDancer
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from pdfdancer import ValidationException, Image, Position
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ImageBuilder:
|
|
7
|
+
|
|
8
|
+
def __init__(self, client: 'PDFDancer'):
|
|
9
|
+
"""
|
|
10
|
+
Initialize the image builder with a client reference.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
client: The PDFDancer instance for font registration
|
|
14
|
+
"""
|
|
15
|
+
if client is None:
|
|
16
|
+
raise ValidationException("Client cannot be null")
|
|
17
|
+
|
|
18
|
+
self._client = client
|
|
19
|
+
self._image = Image()
|
|
20
|
+
|
|
21
|
+
def from_file(self, img_path: Path) -> 'ImageBuilder':
|
|
22
|
+
self._image.data = img_path.read_bytes()
|
|
23
|
+
return self
|
|
24
|
+
|
|
25
|
+
def at(self, page, x, y) -> 'ImageBuilder':
|
|
26
|
+
self._image.position = Position.at_page_coordinates(page, x, y)
|
|
27
|
+
return self
|
|
28
|
+
|
|
29
|
+
def add(self) -> bool:
|
|
30
|
+
return self._client._add_image(self._image, self._image.position)
|
|
@@ -10,12 +10,16 @@ from typing import Optional, List, Any
|
|
|
10
10
|
|
|
11
11
|
class ObjectType(Enum):
|
|
12
12
|
"""Object type enumeration matching the Java ObjectType."""
|
|
13
|
+
FORM_FIELD = "FORM_FIELD"
|
|
13
14
|
IMAGE = "IMAGE"
|
|
14
15
|
FORM_X_OBJECT = "FORM_X_OBJECT"
|
|
15
16
|
PATH = "PATH"
|
|
16
17
|
PARAGRAPH = "PARAGRAPH"
|
|
17
18
|
TEXT_LINE = "TEXT_LINE"
|
|
18
19
|
PAGE = "PAGE"
|
|
20
|
+
TEXT_FIELD = "TEXT_FIELD"
|
|
21
|
+
CHECK_BOX = "CHECK_BOX"
|
|
22
|
+
RADIO_BUTTON = "RADIO_BUTTON"
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
class PositionMode(Enum):
|
|
@@ -74,6 +78,7 @@ class Position:
|
|
|
74
78
|
mode: Optional[PositionMode] = None
|
|
75
79
|
bounding_rect: Optional[BoundingRect] = None
|
|
76
80
|
text_starts_with: Optional[str] = None
|
|
81
|
+
name: Optional[str] = None
|
|
77
82
|
|
|
78
83
|
@staticmethod
|
|
79
84
|
def at_page(page_index: int) -> 'Position':
|
|
@@ -93,7 +98,17 @@ class Position:
|
|
|
93
98
|
position.at_coordinates(Point(x, y))
|
|
94
99
|
return position
|
|
95
100
|
|
|
96
|
-
|
|
101
|
+
@staticmethod
|
|
102
|
+
def by_name(name: str) -> 'Position':
|
|
103
|
+
"""
|
|
104
|
+
Creates a position specification for finding objects by name.
|
|
105
|
+
Equivalent to Position.byName() in Java.
|
|
106
|
+
"""
|
|
107
|
+
position = Position()
|
|
108
|
+
position.name = name
|
|
109
|
+
return position
|
|
110
|
+
|
|
111
|
+
def at_coordinates(self, point: Point) -> 'Position':
|
|
97
112
|
"""
|
|
98
113
|
Sets the position to a specific point location.
|
|
99
114
|
Equivalent to Position.set() in Java.
|
|
@@ -101,7 +116,7 @@ class Position:
|
|
|
101
116
|
self.mode = PositionMode.CONTAINS
|
|
102
117
|
self.shape = ShapeType.POINT
|
|
103
118
|
self.bounding_rect = BoundingRect(point.x, point.y, 0, 0)
|
|
104
|
-
return self
|
|
119
|
+
return self
|
|
105
120
|
|
|
106
121
|
def with_text_starts(self, text: str) -> 'Position':
|
|
107
122
|
self.text_starts_with = text
|
|
@@ -110,20 +125,20 @@ class Position:
|
|
|
110
125
|
def move_x(self, x_offset: float) -> 'Position':
|
|
111
126
|
"""Move the position horizontally by the specified offset."""
|
|
112
127
|
if self.bounding_rect:
|
|
113
|
-
self.at_coordinates(Point(self.
|
|
128
|
+
self.at_coordinates(Point(self.x() + x_offset, self.y()))
|
|
114
129
|
return self
|
|
115
130
|
|
|
116
131
|
def move_y(self, y_offset: float) -> 'Position':
|
|
117
132
|
"""Move the position vertically by the specified offset."""
|
|
118
133
|
if self.bounding_rect:
|
|
119
|
-
self.at_coordinates(Point(self.
|
|
134
|
+
self.at_coordinates(Point(self.x(), self.y() + y_offset))
|
|
120
135
|
return self
|
|
121
136
|
|
|
122
|
-
def
|
|
137
|
+
def x(self) -> Optional[float]:
|
|
123
138
|
"""Returns the X coordinate of this position."""
|
|
124
139
|
return self.bounding_rect.get_x() if self.bounding_rect else None
|
|
125
140
|
|
|
126
|
-
def
|
|
141
|
+
def y(self) -> Optional[float]:
|
|
127
142
|
"""Returns the Y coordinate of this position."""
|
|
128
143
|
return self.bounding_rect.get_y() if self.bounding_rect else None
|
|
129
144
|
|
|
@@ -269,6 +284,8 @@ class FindRequest:
|
|
|
269
284
|
"pageIndex": position.page_index,
|
|
270
285
|
"textStartsWith": position.text_starts_with
|
|
271
286
|
}
|
|
287
|
+
if position.name:
|
|
288
|
+
result["name"] = position.name
|
|
272
289
|
if position.shape:
|
|
273
290
|
result["shape"] = position.shape.value
|
|
274
291
|
if position.mode:
|
|
@@ -420,3 +437,38 @@ class ModifyTextRequest:
|
|
|
420
437
|
},
|
|
421
438
|
"newTextLine": self.new_text
|
|
422
439
|
}
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
@dataclass
|
|
443
|
+
class ChangeFormFieldRequest:
|
|
444
|
+
object_ref: ObjectRef
|
|
445
|
+
value: str
|
|
446
|
+
|
|
447
|
+
def to_dict(self) -> dict:
|
|
448
|
+
"""Convert to dictionary for JSON serialization."""
|
|
449
|
+
return {
|
|
450
|
+
"ref": {
|
|
451
|
+
"internalId": self.object_ref.internal_id,
|
|
452
|
+
"position": FindRequest._position_to_dict(self.object_ref.position),
|
|
453
|
+
"type": self.object_ref.type.value
|
|
454
|
+
},
|
|
455
|
+
"value": self.value
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
@dataclass
|
|
460
|
+
class FormFieldRef(ObjectRef):
|
|
461
|
+
"""
|
|
462
|
+
Represents a form field reference with additional form-specific properties.
|
|
463
|
+
Extends ObjectRef to include form field name and value.
|
|
464
|
+
"""
|
|
465
|
+
name: Optional[str] = None
|
|
466
|
+
value: Optional[str] = None
|
|
467
|
+
|
|
468
|
+
def get_name(self) -> Optional[str]:
|
|
469
|
+
"""Get the form field name."""
|
|
470
|
+
return self.name
|
|
471
|
+
|
|
472
|
+
def get_value(self) -> Optional[str]:
|
|
473
|
+
"""Get the form field value."""
|
|
474
|
+
return self.value
|
{pdfdancer_client_python-0.1.2 → pdfdancer_client_python-0.2.2}/src/pdfdancer/paragraph_builder.py
RENAMED
|
@@ -4,14 +4,11 @@ Closely mirrors the Java ParagraphBuilder class with Python conventions.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Optional, Union
|
|
7
|
+
from typing import Optional, Union
|
|
8
8
|
|
|
9
9
|
from .exceptions import ValidationException
|
|
10
10
|
from .models import Paragraph, Font, Color, Position
|
|
11
11
|
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from .client_v1 import ClientV1
|
|
14
|
-
|
|
15
12
|
|
|
16
13
|
class ParagraphBuilder:
|
|
17
14
|
"""
|
|
@@ -19,7 +16,7 @@ class ParagraphBuilder:
|
|
|
19
16
|
Mirrors the Java ParagraphBuilder class exactly.
|
|
20
17
|
"""
|
|
21
18
|
|
|
22
|
-
def __init__(self, client: '
|
|
19
|
+
def __init__(self, client: 'PDFDancer'):
|
|
23
20
|
"""
|
|
24
21
|
Initialize the paragraph builder with a client reference.
|
|
25
22
|
|
|
@@ -37,7 +34,7 @@ class ParagraphBuilder:
|
|
|
37
34
|
self._ttf_file: Optional[Path] = None
|
|
38
35
|
self._font: Optional[Font] = None
|
|
39
36
|
|
|
40
|
-
def
|
|
37
|
+
def text(self, text: str, color: Optional[Color] = None) -> 'ParagraphBuilder':
|
|
41
38
|
"""
|
|
42
39
|
Set the text content for the paragraph.
|
|
43
40
|
Equivalent to fromString() methods in Java ParagraphBuilder.
|
|
@@ -63,13 +60,14 @@ class ParagraphBuilder:
|
|
|
63
60
|
|
|
64
61
|
return self
|
|
65
62
|
|
|
66
|
-
def
|
|
63
|
+
def font(self, font_name: str, font_size: float) -> 'ParagraphBuilder':
|
|
67
64
|
"""
|
|
68
65
|
Set the font for the paragraph using an existing Font object.
|
|
69
66
|
Equivalent to withFont(Font) in Java ParagraphBuilder.
|
|
70
67
|
|
|
71
68
|
Args:
|
|
72
|
-
|
|
69
|
+
font_name: The Font to use
|
|
70
|
+
font_size: The font size
|
|
73
71
|
|
|
74
72
|
Returns:
|
|
75
73
|
Self for method chaining
|
|
@@ -77,6 +75,7 @@ class ParagraphBuilder:
|
|
|
77
75
|
Raises:
|
|
78
76
|
ValidationException: If font is None
|
|
79
77
|
"""
|
|
78
|
+
font = Font(font_name, font_size)
|
|
80
79
|
if font is None:
|
|
81
80
|
raise ValidationException("Font cannot be null")
|
|
82
81
|
|
|
@@ -84,7 +83,7 @@ class ParagraphBuilder:
|
|
|
84
83
|
self._ttf_file = None # Clear TTF file when using existing font
|
|
85
84
|
return self
|
|
86
85
|
|
|
87
|
-
def
|
|
86
|
+
def font_file(self, ttf_file: Union[Path, str], font_size: float) -> 'ParagraphBuilder':
|
|
88
87
|
"""
|
|
89
88
|
Set the font for the paragraph using a TTF file.
|
|
90
89
|
Equivalent to withFont(File, double) in Java ParagraphBuilder.
|
|
@@ -125,7 +124,7 @@ class ParagraphBuilder:
|
|
|
125
124
|
self._font = self._register_ttf(ttf_path, font_size)
|
|
126
125
|
return self
|
|
127
126
|
|
|
128
|
-
def
|
|
127
|
+
def line_spacing(self, spacing: float) -> 'ParagraphBuilder':
|
|
129
128
|
"""
|
|
130
129
|
Set the line spacing for the paragraph.
|
|
131
130
|
Equivalent to withLineSpacing() in Java ParagraphBuilder.
|
|
@@ -145,7 +144,7 @@ class ParagraphBuilder:
|
|
|
145
144
|
self._line_spacing = spacing
|
|
146
145
|
return self
|
|
147
146
|
|
|
148
|
-
def
|
|
147
|
+
def color(self, color: Color) -> 'ParagraphBuilder':
|
|
149
148
|
"""
|
|
150
149
|
Set the text color for the paragraph.
|
|
151
150
|
Equivalent to withColor() in Java ParagraphBuilder.
|
|
@@ -165,7 +164,7 @@ class ParagraphBuilder:
|
|
|
165
164
|
self._text_color = color
|
|
166
165
|
return self
|
|
167
166
|
|
|
168
|
-
def
|
|
167
|
+
def at(self, page_index: int, x: float, y: float) -> 'ParagraphBuilder':
|
|
169
168
|
"""
|
|
170
169
|
Set the position for the paragraph.
|
|
171
170
|
Equivalent to withPosition() in Java ParagraphBuilder.
|
|
@@ -179,6 +178,7 @@ class ParagraphBuilder:
|
|
|
179
178
|
Raises:
|
|
180
179
|
ValidationException: If position is None
|
|
181
180
|
"""
|
|
181
|
+
position = Position.at_page_coordinates(page_index, x, y)
|
|
182
182
|
if position is None:
|
|
183
183
|
raise ValidationException("Position cannot be null")
|
|
184
184
|
|
|
@@ -265,3 +265,6 @@ class ParagraphBuilder:
|
|
|
265
265
|
lines = ['']
|
|
266
266
|
|
|
267
267
|
return lines
|
|
268
|
+
|
|
269
|
+
def add(self):
|
|
270
|
+
self._client._add_paragraph(self.build())
|