pdfdancer-client-python 0.2.15__tar.gz → 0.2.16__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 (51) hide show
  1. pdfdancer_client_python-0.2.16/PKG-INFO +190 -0
  2. pdfdancer_client_python-0.2.16/README.md +158 -0
  3. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/pyproject.toml +1 -1
  4. pdfdancer_client_python-0.2.16/src/pdfdancer_client_python.egg-info/PKG-INFO +190 -0
  5. pdfdancer_client_python-0.2.15/PKG-INFO +0 -200
  6. pdfdancer_client_python-0.2.15/README.md +0 -168
  7. pdfdancer_client_python-0.2.15/src/pdfdancer_client_python.egg-info/PKG-INFO +0 -200
  8. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/.claude/commands/discuss.md +0 -0
  9. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/.github/workflows/ci.yml +0 -0
  10. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/.gitignore +0 -0
  11. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/CLAUDE.md +0 -0
  12. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/docs/openapi.yml +0 -0
  13. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/release.py +0 -0
  14. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/setup.cfg +0 -0
  15. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer/__init__.py +0 -0
  16. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer/exceptions.py +0 -0
  17. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer/image_builder.py +0 -0
  18. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer/models.py +0 -0
  19. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer/paragraph_builder.py +0 -0
  20. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer/pdfdancer_v1.py +0 -0
  21. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer/types.py +0 -0
  22. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer_client_python.egg-info/SOURCES.txt +0 -0
  23. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer_client_python.egg-info/dependency_links.txt +0 -0
  24. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer_client_python.egg-info/requires.txt +0 -0
  25. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/src/pdfdancer_client_python.egg-info/top_level.txt +0 -0
  26. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/__init__.py +0 -0
  27. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/conftest.py +0 -0
  28. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/__init__.py +0 -0
  29. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/pdf_assertions.py +0 -0
  30. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_acroform.py +0 -0
  31. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_form_x_objects.py +0 -0
  32. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_image.py +0 -0
  33. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_line.py +0 -0
  34. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_new_pdf.py +0 -0
  35. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_page.py +0 -0
  36. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_paragraph.py +0 -0
  37. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_path.py +0 -0
  38. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_pdfdancer.py +0 -0
  39. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/e2e/test_positioning.py +0 -0
  40. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/fixtures/DancingScript-Regular.ttf +0 -0
  41. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/fixtures/Empty.pdf +0 -0
  42. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
  43. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/fixtures/ObviouslyAwesome.pdf +0 -0
  44. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/fixtures/basic-paths.pdf +0 -0
  45. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/fixtures/form-xobject-example.pdf +0 -0
  46. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/fixtures/logo-80.png +0 -0
  47. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/fixtures/mixed-form-types.pdf +0 -0
  48. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/test_models.py +0 -0
  49. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/test_openapi_compliance.py +0 -0
  50. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/test_pdf_object_equality.py +0 -0
  51. {pdfdancer_client_python-0.2.15 → pdfdancer_client_python-0.2.16}/tests/test_standard_fonts.py +0 -0
@@ -0,0 +1,190 @@
1
+ Metadata-Version: 2.4
2
+ Name: pdfdancer-client-python
3
+ Version: 0.2.16
4
+ Summary: Python client for PDFDancer API
5
+ Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://www.pdfdancer.com/
8
+ Project-URL: Repository, https://github.com/MenschMachine/pdfdancer-client-python
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Python: >=3.10
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
+ Requires-Dist: python-dotenv>=0.19.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0; extra == "dev"
24
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
25
+ Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
26
+ Requires-Dist: black>=22.0; extra == "dev"
27
+ Requires-Dist: flake8>=5.0; extra == "dev"
28
+ Requires-Dist: mypy>=1.0; extra == "dev"
29
+ Requires-Dist: isort>=5.10.0; extra == "dev"
30
+ Requires-Dist: build>=0.8.0; extra == "dev"
31
+ Requires-Dist: twine>=4.0.0; extra == "dev"
32
+
33
+ # PDFDancer Python Client
34
+
35
+ **Getting Started with PDFDancer**
36
+
37
+ PDFDancer gives you pixel-perfect programmatic control over any PDF document from Python. Locate existing elements by
38
+ coordinates or text, adjust them precisely, add brand-new content, and ship the modified PDF in memory or on disk. The
39
+ same API is also available for TypeScript and Java, so teams can orchestrate identical PDF workflows across stacks.
40
+
41
+ > Need the raw API schema? The latest OpenAPI description lives in `docs/openapi.yml` and is published at
42
+ > https://bucket.pdfdancer.com/api-doc/development-0.0.yml.
43
+
44
+ ## Highlights
45
+
46
+ - Locate paragraphs, text lines, images, vector paths, form fields, and pages by index, coordinates, or text prefixes.
47
+ - Edit existing content in place with fluent editors and context managers that apply changes safely.
48
+ - Programmatically control third-party PDFs—modify invoices, contracts, and reports you did not author.
49
+ - Add content with precise XY positioning using paragraph and image builders, custom fonts, and color helpers.
50
+ - Export results as bytes for downstream processing or save directly to disk with one call.
51
+
52
+ ## What Makes PDFDancer Different
53
+
54
+ - **Edit any PDF**: Work with documents from customers, governments, or vendors—not just ones you generated.
55
+ - **Pixel-perfect positioning**: Move or add elements at exact coordinates and keep the original layout intact.
56
+ - **Surgical text replacement**: Swap or rewrite paragraphs without reflowing the rest of the page.
57
+ - **Form manipulation**: Inspect, fill, and update AcroForm fields programmatically.
58
+ - **Coordinate-based selection**: Select objects by position, bounding box, or text patterns.
59
+ - **Real PDF editing**: Modify the underlying PDF structure instead of merely stamping overlays.
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install pdfdancer-client-python
65
+
66
+ # Editable install for local development
67
+ pip install -e .
68
+ ```
69
+
70
+ Requires Python 3.10+ and a PDFDancer API token.
71
+
72
+ ## Quick Start — Edit an Existing PDF
73
+
74
+ ```python
75
+ from pathlib import Path
76
+ from pdfdancer import Color, PDFDancer, StandardFonts
77
+
78
+ with PDFDancer.open(
79
+ pdf_data=Path("input.pdf"),
80
+ token="your-api-token", # optional when PDFDANCER_TOKEN is set
81
+ base_url="https://api.pdfdancer.com",
82
+ ) as pdf:
83
+ # Locate and update an existing paragraph
84
+ heading = pdf.page(0).select_paragraphs_starting_with("Executive Summary")[0]
85
+ heading.move_to(72, 680)
86
+ with heading.edit() as editor:
87
+ editor.replace("Overview")
88
+
89
+ # Add a new paragraph with precise placement
90
+ pdf.new_paragraph() \
91
+ .text("Generated with PDFDancer") \
92
+ .font(StandardFonts.HELVETICA, 12) \
93
+ .color(Color(70, 70, 70)) \
94
+ .line_spacing(1.4) \
95
+ .at(page_index=0, x=72, y=520) \
96
+ .add()
97
+
98
+ # Persist the modified document
99
+ pdf.save("output.pdf")
100
+ # or keep it in memory
101
+ pdf_bytes = pdf.get_bytes()
102
+ ```
103
+
104
+ ## Create a Blank PDF
105
+
106
+ ```python
107
+ from pathlib import Path
108
+ from pdfdancer import Color, PDFDancer, StandardFonts
109
+
110
+ with PDFDancer.new(token="your-api-token") as pdf:
111
+ pdf.new_paragraph() \
112
+ .text("Quarterly Summary") \
113
+ .font(StandardFonts.TIMES_BOLD, 18) \
114
+ .color(Color(10, 10, 80)) \
115
+ .line_spacing(1.2) \
116
+ .at(page_index=0, x=72, y=730) \
117
+ .add()
118
+
119
+ pdf.new_image() \
120
+ .from_file(Path("logo.png")) \
121
+ .at(page=0, x=420, y=710) \
122
+ .add()
123
+
124
+ pdf.save("summary.pdf")
125
+ ```
126
+
127
+ ## Work with Forms and Layout
128
+
129
+ ```python
130
+ from pdfdancer import PDFDancer
131
+
132
+ with PDFDancer.open("contract.pdf") as pdf:
133
+ # Inspect global document structure
134
+ pages = pdf.pages()
135
+ print("Total pages:", len(pages))
136
+
137
+ # Update form fields
138
+ signature = pdf.select_form_fields_by_name("signature")[0]
139
+ signature.edit().value("Signed by Jane Doe").apply()
140
+
141
+ # Trim or move content at specific coordinates
142
+ images = pdf.page(1).select_images()
143
+ for image in images:
144
+ x = image.position.x()
145
+ if x is not None and x < 100:
146
+ image.delete()
147
+ ```
148
+
149
+ Selectors return typed objects (`ParagraphObject`, `TextLineObject`, `ImageObject`, `FormFieldObject`, `PageClient`, …)
150
+ with helpers such as `delete()`, `move_to(x, y)`, or `edit()` depending on the object type.
151
+
152
+ ## Configuration
153
+
154
+ - Set `PDFDANCER_TOKEN` for authentication (preferred for local development and CI).
155
+ - Override the API host with `PDFDANCER_BASE_URL` (e.g., sandbox environments).
156
+ - Tune HTTP read timeouts via the `timeout` argument on `PDFDancer.open()` and `PDFDancer.new()`.
157
+
158
+ ## Error Handling
159
+
160
+ Operations raise subclasses of `PdfDancerException`:
161
+
162
+ - `ValidationException`: input validation problems (missing token, invalid coordinates, etc.).
163
+ - `FontNotFoundException`: requested font unavailable on the service.
164
+ - `HttpClientException`: transport or server errors with detailed context.
165
+ - `SessionException`: session creation and lifecycle failures.
166
+
167
+ Wrap automated workflows in `try/except` blocks to surface actionable errors to your users.
168
+
169
+ ## Development
170
+
171
+ ```bash
172
+ python -m venv venv
173
+ source venv/bin/activate # Windows: venv\Scripts\activate
174
+ pip install -e ".[dev]"
175
+
176
+ pytest -q # unit suite
177
+ pytest tests/e2e # integration tests (requires live API + fixtures)
178
+ python -m build # produce distribution artifacts
179
+ ```
180
+
181
+ Releases are published with `python release.py`. Contributions are welcome via pull request.
182
+
183
+ ## Related SDKs
184
+
185
+ - TypeScript client: https://github.com/MenschMachine/pdfdancer-client-js
186
+ - Java client: https://github.com/MenschMachine/pdfdancer-client-java
187
+
188
+ ## License
189
+
190
+ MIT © The Famous Cat Ltd.
@@ -0,0 +1,158 @@
1
+ # PDFDancer Python Client
2
+
3
+ **Getting Started with PDFDancer**
4
+
5
+ PDFDancer gives you pixel-perfect programmatic control over any PDF document from Python. Locate existing elements by
6
+ coordinates or text, adjust them precisely, add brand-new content, and ship the modified PDF in memory or on disk. The
7
+ same API is also available for TypeScript and Java, so teams can orchestrate identical PDF workflows across stacks.
8
+
9
+ > Need the raw API schema? The latest OpenAPI description lives in `docs/openapi.yml` and is published at
10
+ > https://bucket.pdfdancer.com/api-doc/development-0.0.yml.
11
+
12
+ ## Highlights
13
+
14
+ - Locate paragraphs, text lines, images, vector paths, form fields, and pages by index, coordinates, or text prefixes.
15
+ - Edit existing content in place with fluent editors and context managers that apply changes safely.
16
+ - Programmatically control third-party PDFs—modify invoices, contracts, and reports you did not author.
17
+ - Add content with precise XY positioning using paragraph and image builders, custom fonts, and color helpers.
18
+ - Export results as bytes for downstream processing or save directly to disk with one call.
19
+
20
+ ## What Makes PDFDancer Different
21
+
22
+ - **Edit any PDF**: Work with documents from customers, governments, or vendors—not just ones you generated.
23
+ - **Pixel-perfect positioning**: Move or add elements at exact coordinates and keep the original layout intact.
24
+ - **Surgical text replacement**: Swap or rewrite paragraphs without reflowing the rest of the page.
25
+ - **Form manipulation**: Inspect, fill, and update AcroForm fields programmatically.
26
+ - **Coordinate-based selection**: Select objects by position, bounding box, or text patterns.
27
+ - **Real PDF editing**: Modify the underlying PDF structure instead of merely stamping overlays.
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ pip install pdfdancer-client-python
33
+
34
+ # Editable install for local development
35
+ pip install -e .
36
+ ```
37
+
38
+ Requires Python 3.10+ and a PDFDancer API token.
39
+
40
+ ## Quick Start — Edit an Existing PDF
41
+
42
+ ```python
43
+ from pathlib import Path
44
+ from pdfdancer import Color, PDFDancer, StandardFonts
45
+
46
+ with PDFDancer.open(
47
+ pdf_data=Path("input.pdf"),
48
+ token="your-api-token", # optional when PDFDANCER_TOKEN is set
49
+ base_url="https://api.pdfdancer.com",
50
+ ) as pdf:
51
+ # Locate and update an existing paragraph
52
+ heading = pdf.page(0).select_paragraphs_starting_with("Executive Summary")[0]
53
+ heading.move_to(72, 680)
54
+ with heading.edit() as editor:
55
+ editor.replace("Overview")
56
+
57
+ # Add a new paragraph with precise placement
58
+ pdf.new_paragraph() \
59
+ .text("Generated with PDFDancer") \
60
+ .font(StandardFonts.HELVETICA, 12) \
61
+ .color(Color(70, 70, 70)) \
62
+ .line_spacing(1.4) \
63
+ .at(page_index=0, x=72, y=520) \
64
+ .add()
65
+
66
+ # Persist the modified document
67
+ pdf.save("output.pdf")
68
+ # or keep it in memory
69
+ pdf_bytes = pdf.get_bytes()
70
+ ```
71
+
72
+ ## Create a Blank PDF
73
+
74
+ ```python
75
+ from pathlib import Path
76
+ from pdfdancer import Color, PDFDancer, StandardFonts
77
+
78
+ with PDFDancer.new(token="your-api-token") as pdf:
79
+ pdf.new_paragraph() \
80
+ .text("Quarterly Summary") \
81
+ .font(StandardFonts.TIMES_BOLD, 18) \
82
+ .color(Color(10, 10, 80)) \
83
+ .line_spacing(1.2) \
84
+ .at(page_index=0, x=72, y=730) \
85
+ .add()
86
+
87
+ pdf.new_image() \
88
+ .from_file(Path("logo.png")) \
89
+ .at(page=0, x=420, y=710) \
90
+ .add()
91
+
92
+ pdf.save("summary.pdf")
93
+ ```
94
+
95
+ ## Work with Forms and Layout
96
+
97
+ ```python
98
+ from pdfdancer import PDFDancer
99
+
100
+ with PDFDancer.open("contract.pdf") as pdf:
101
+ # Inspect global document structure
102
+ pages = pdf.pages()
103
+ print("Total pages:", len(pages))
104
+
105
+ # Update form fields
106
+ signature = pdf.select_form_fields_by_name("signature")[0]
107
+ signature.edit().value("Signed by Jane Doe").apply()
108
+
109
+ # Trim or move content at specific coordinates
110
+ images = pdf.page(1).select_images()
111
+ for image in images:
112
+ x = image.position.x()
113
+ if x is not None and x < 100:
114
+ image.delete()
115
+ ```
116
+
117
+ Selectors return typed objects (`ParagraphObject`, `TextLineObject`, `ImageObject`, `FormFieldObject`, `PageClient`, …)
118
+ with helpers such as `delete()`, `move_to(x, y)`, or `edit()` depending on the object type.
119
+
120
+ ## Configuration
121
+
122
+ - Set `PDFDANCER_TOKEN` for authentication (preferred for local development and CI).
123
+ - Override the API host with `PDFDANCER_BASE_URL` (e.g., sandbox environments).
124
+ - Tune HTTP read timeouts via the `timeout` argument on `PDFDancer.open()` and `PDFDancer.new()`.
125
+
126
+ ## Error Handling
127
+
128
+ Operations raise subclasses of `PdfDancerException`:
129
+
130
+ - `ValidationException`: input validation problems (missing token, invalid coordinates, etc.).
131
+ - `FontNotFoundException`: requested font unavailable on the service.
132
+ - `HttpClientException`: transport or server errors with detailed context.
133
+ - `SessionException`: session creation and lifecycle failures.
134
+
135
+ Wrap automated workflows in `try/except` blocks to surface actionable errors to your users.
136
+
137
+ ## Development
138
+
139
+ ```bash
140
+ python -m venv venv
141
+ source venv/bin/activate # Windows: venv\Scripts\activate
142
+ pip install -e ".[dev]"
143
+
144
+ pytest -q # unit suite
145
+ pytest tests/e2e # integration tests (requires live API + fixtures)
146
+ python -m build # produce distribution artifacts
147
+ ```
148
+
149
+ Releases are published with `python release.py`. Contributions are welcome via pull request.
150
+
151
+ ## Related SDKs
152
+
153
+ - TypeScript client: https://github.com/MenschMachine/pdfdancer-client-js
154
+ - Java client: https://github.com/MenschMachine/pdfdancer-client-java
155
+
156
+ ## License
157
+
158
+ MIT © The Famous Cat Ltd.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pdfdancer-client-python"
7
- version = "0.2.15"
7
+ version = "0.2.16"
8
8
  description = "Python client for PDFDancer API"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -0,0 +1,190 @@
1
+ Metadata-Version: 2.4
2
+ Name: pdfdancer-client-python
3
+ Version: 0.2.16
4
+ Summary: Python client for PDFDancer API
5
+ Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://www.pdfdancer.com/
8
+ Project-URL: Repository, https://github.com/MenschMachine/pdfdancer-client-python
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Python: >=3.10
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
+ Requires-Dist: python-dotenv>=0.19.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0; extra == "dev"
24
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
25
+ Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
26
+ Requires-Dist: black>=22.0; extra == "dev"
27
+ Requires-Dist: flake8>=5.0; extra == "dev"
28
+ Requires-Dist: mypy>=1.0; extra == "dev"
29
+ Requires-Dist: isort>=5.10.0; extra == "dev"
30
+ Requires-Dist: build>=0.8.0; extra == "dev"
31
+ Requires-Dist: twine>=4.0.0; extra == "dev"
32
+
33
+ # PDFDancer Python Client
34
+
35
+ **Getting Started with PDFDancer**
36
+
37
+ PDFDancer gives you pixel-perfect programmatic control over any PDF document from Python. Locate existing elements by
38
+ coordinates or text, adjust them precisely, add brand-new content, and ship the modified PDF in memory or on disk. The
39
+ same API is also available for TypeScript and Java, so teams can orchestrate identical PDF workflows across stacks.
40
+
41
+ > Need the raw API schema? The latest OpenAPI description lives in `docs/openapi.yml` and is published at
42
+ > https://bucket.pdfdancer.com/api-doc/development-0.0.yml.
43
+
44
+ ## Highlights
45
+
46
+ - Locate paragraphs, text lines, images, vector paths, form fields, and pages by index, coordinates, or text prefixes.
47
+ - Edit existing content in place with fluent editors and context managers that apply changes safely.
48
+ - Programmatically control third-party PDFs—modify invoices, contracts, and reports you did not author.
49
+ - Add content with precise XY positioning using paragraph and image builders, custom fonts, and color helpers.
50
+ - Export results as bytes for downstream processing or save directly to disk with one call.
51
+
52
+ ## What Makes PDFDancer Different
53
+
54
+ - **Edit any PDF**: Work with documents from customers, governments, or vendors—not just ones you generated.
55
+ - **Pixel-perfect positioning**: Move or add elements at exact coordinates and keep the original layout intact.
56
+ - **Surgical text replacement**: Swap or rewrite paragraphs without reflowing the rest of the page.
57
+ - **Form manipulation**: Inspect, fill, and update AcroForm fields programmatically.
58
+ - **Coordinate-based selection**: Select objects by position, bounding box, or text patterns.
59
+ - **Real PDF editing**: Modify the underlying PDF structure instead of merely stamping overlays.
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install pdfdancer-client-python
65
+
66
+ # Editable install for local development
67
+ pip install -e .
68
+ ```
69
+
70
+ Requires Python 3.10+ and a PDFDancer API token.
71
+
72
+ ## Quick Start — Edit an Existing PDF
73
+
74
+ ```python
75
+ from pathlib import Path
76
+ from pdfdancer import Color, PDFDancer, StandardFonts
77
+
78
+ with PDFDancer.open(
79
+ pdf_data=Path("input.pdf"),
80
+ token="your-api-token", # optional when PDFDANCER_TOKEN is set
81
+ base_url="https://api.pdfdancer.com",
82
+ ) as pdf:
83
+ # Locate and update an existing paragraph
84
+ heading = pdf.page(0).select_paragraphs_starting_with("Executive Summary")[0]
85
+ heading.move_to(72, 680)
86
+ with heading.edit() as editor:
87
+ editor.replace("Overview")
88
+
89
+ # Add a new paragraph with precise placement
90
+ pdf.new_paragraph() \
91
+ .text("Generated with PDFDancer") \
92
+ .font(StandardFonts.HELVETICA, 12) \
93
+ .color(Color(70, 70, 70)) \
94
+ .line_spacing(1.4) \
95
+ .at(page_index=0, x=72, y=520) \
96
+ .add()
97
+
98
+ # Persist the modified document
99
+ pdf.save("output.pdf")
100
+ # or keep it in memory
101
+ pdf_bytes = pdf.get_bytes()
102
+ ```
103
+
104
+ ## Create a Blank PDF
105
+
106
+ ```python
107
+ from pathlib import Path
108
+ from pdfdancer import Color, PDFDancer, StandardFonts
109
+
110
+ with PDFDancer.new(token="your-api-token") as pdf:
111
+ pdf.new_paragraph() \
112
+ .text("Quarterly Summary") \
113
+ .font(StandardFonts.TIMES_BOLD, 18) \
114
+ .color(Color(10, 10, 80)) \
115
+ .line_spacing(1.2) \
116
+ .at(page_index=0, x=72, y=730) \
117
+ .add()
118
+
119
+ pdf.new_image() \
120
+ .from_file(Path("logo.png")) \
121
+ .at(page=0, x=420, y=710) \
122
+ .add()
123
+
124
+ pdf.save("summary.pdf")
125
+ ```
126
+
127
+ ## Work with Forms and Layout
128
+
129
+ ```python
130
+ from pdfdancer import PDFDancer
131
+
132
+ with PDFDancer.open("contract.pdf") as pdf:
133
+ # Inspect global document structure
134
+ pages = pdf.pages()
135
+ print("Total pages:", len(pages))
136
+
137
+ # Update form fields
138
+ signature = pdf.select_form_fields_by_name("signature")[0]
139
+ signature.edit().value("Signed by Jane Doe").apply()
140
+
141
+ # Trim or move content at specific coordinates
142
+ images = pdf.page(1).select_images()
143
+ for image in images:
144
+ x = image.position.x()
145
+ if x is not None and x < 100:
146
+ image.delete()
147
+ ```
148
+
149
+ Selectors return typed objects (`ParagraphObject`, `TextLineObject`, `ImageObject`, `FormFieldObject`, `PageClient`, …)
150
+ with helpers such as `delete()`, `move_to(x, y)`, or `edit()` depending on the object type.
151
+
152
+ ## Configuration
153
+
154
+ - Set `PDFDANCER_TOKEN` for authentication (preferred for local development and CI).
155
+ - Override the API host with `PDFDANCER_BASE_URL` (e.g., sandbox environments).
156
+ - Tune HTTP read timeouts via the `timeout` argument on `PDFDancer.open()` and `PDFDancer.new()`.
157
+
158
+ ## Error Handling
159
+
160
+ Operations raise subclasses of `PdfDancerException`:
161
+
162
+ - `ValidationException`: input validation problems (missing token, invalid coordinates, etc.).
163
+ - `FontNotFoundException`: requested font unavailable on the service.
164
+ - `HttpClientException`: transport or server errors with detailed context.
165
+ - `SessionException`: session creation and lifecycle failures.
166
+
167
+ Wrap automated workflows in `try/except` blocks to surface actionable errors to your users.
168
+
169
+ ## Development
170
+
171
+ ```bash
172
+ python -m venv venv
173
+ source venv/bin/activate # Windows: venv\Scripts\activate
174
+ pip install -e ".[dev]"
175
+
176
+ pytest -q # unit suite
177
+ pytest tests/e2e # integration tests (requires live API + fixtures)
178
+ python -m build # produce distribution artifacts
179
+ ```
180
+
181
+ Releases are published with `python release.py`. Contributions are welcome via pull request.
182
+
183
+ ## Related SDKs
184
+
185
+ - TypeScript client: https://github.com/MenschMachine/pdfdancer-client-js
186
+ - Java client: https://github.com/MenschMachine/pdfdancer-client-java
187
+
188
+ ## License
189
+
190
+ MIT © The Famous Cat Ltd.
@@ -1,200 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: pdfdancer-client-python
3
- Version: 0.2.15
4
- Summary: Python client for PDFDancer API
5
- Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
- License: MIT
7
- Project-URL: Homepage, https://www.pdfdancer.com/
8
- Project-URL: Repository, https://github.com/MenschMachine/pdfdancer-client-python
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.13
16
- Requires-Python: >=3.10
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
- Requires-Dist: python-dotenv>=0.19.0
22
- Provides-Extra: dev
23
- Requires-Dist: pytest>=7.0; extra == "dev"
24
- Requires-Dist: pytest-cov>=4.0; extra == "dev"
25
- Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
26
- Requires-Dist: black>=22.0; extra == "dev"
27
- Requires-Dist: flake8>=5.0; extra == "dev"
28
- Requires-Dist: mypy>=1.0; extra == "dev"
29
- Requires-Dist: isort>=5.10.0; extra == "dev"
30
- Requires-Dist: build>=0.8.0; extra == "dev"
31
- Requires-Dist: twine>=4.0.0; extra == "dev"
32
-
33
- # PDFDancer Python Client
34
-
35
- Automate PDF clean-up, redaction, form filling, and content injection against the PDFDancer API from Python. The client
36
- gives you page-scoped selectors, fluent editors, and builders so you can read, modify, and export PDFs programmatically
37
- in just a few lines.
38
-
39
- Latest schema version available at https://bucket.pdfdancer.com/api-doc/development-0.0.yml.
40
-
41
- ## Highlights
42
-
43
- - Locate anything inside a PDF—paragraphs, text lines, images, vector paths, pages, AcroForm fields—by page,
44
- coordinates, or text prefixes
45
- - Edit or delete existing content with fluent paragraph/text editors and safe apply-on-exit context managers
46
- - Fill or update form fields and propagate the changes back to the document instantly
47
- - Add brand-new content with paragraph/image builders, custom fonts, and precise page positioning
48
- - Download results as bytes for downstream processing or save directly to disk with one method call
49
-
50
- ## Core Capabilities
51
-
52
- - Clean up layout by moving or deleting paragraphs, text lines, or shapes on specific pages
53
- - Search and filter content (e.g., paragraphs starting with "Invoice") to drive custom workflows
54
- - Redact or replace text in bulk with chained editor operations
55
- - Populate AcroForms for contract generation or onboarding flows
56
- - Insert logos, signatures, and generated paragraphs at deterministic coordinates
57
- - Export modified PDFs as bytes for APIs, S3 uploads, or direct file saves
58
-
59
- ## Requirements
60
-
61
- - Python 3.10 or newer
62
- - A PDFDancer API token (set `PDFDANCER_TOKEN` or pass `token=...`)
63
- - Network access to a PDFDancer service (defaults to `https://api.pdfdancer.com`; override with `PDFDANCER_BASE_URL`)
64
-
65
- ## Installation
66
-
67
- ```bash
68
- pip install pdfdancer-client-python
69
-
70
- # Editable install for local development
71
- pip install -e .
72
- ```
73
-
74
- ## Getting Started
75
-
76
- ```python
77
- from pathlib import Path
78
- from pdfdancer import Color, PDFDancer
79
-
80
- with PDFDancer.open(
81
- pdf_data=Path("input.pdf"),
82
- token="your-api-token", # optional when PDFDANCER_TOKEN is set
83
- base_url="https://api.pdfdancer.com",
84
- ) as pdf:
85
- # Locate existing content
86
- heading = pdf.page(0).select_paragraphs_starting_with("Executive Summary")[0]
87
- heading.edit().replace("Overview").apply()
88
-
89
- # Add a new paragraph using the fluent builder
90
- pdf.new_paragraph()
91
- .text("Generated with PDFDancer")
92
- .font("Helvetica", 12)
93
- .color(Color(70, 70, 70))
94
- .line_spacing(1.4)
95
- .at(page_index=0, x=72, y=520)
96
- .add()
97
-
98
- # Persist the modified document
99
- pdf.save("output.pdf")
100
- ```
101
-
102
- ### Authentication Tips
103
-
104
- - Prefer setting `PDFDANCER_TOKEN` in your environment for local development.
105
- - Override the API host by setting `PDFDANCER_BASE_URL` or passing `base_url="https://sandbox.pdfdancer.com"`.
106
- - Use the `timeout` parameter on `PDFDancer.open()` to adjust HTTP read timeouts.
107
-
108
- ## Selecting PDF Content
109
-
110
- ```python
111
- with PDFDancer.open("report.pdf") as pdf: # environment variables provide token/URL
112
- all_paragraphs = pdf.select_paragraphs()
113
- page_zero_images = pdf.page(0).select_images()
114
- form_fields = pdf.page(2).select_form_fields()
115
- paths_at_cursor = pdf.page(3).select_paths_at(x=150, y=320)
116
-
117
- page = pdf.page(0).get()
118
- print(page.internal_id, page.position.bounding_rect)
119
- ```
120
-
121
- Selectors return rich objects (`ParagraphObject`, `TextLineObject`, `ImageObject`, `FormFieldObject`, etc.) with helpers
122
- such as `delete()`, `move_to(x, y)`, or `edit()` depending on the object type.
123
-
124
- ## Editing Text and Forms
125
-
126
- ```python
127
- with PDFDancer.open("report.pdf") as pdf:
128
- paragraph = pdf.page(0).select_paragraphs_starting_with("Disclaimer")[0]
129
-
130
- # Chain updates explicitly…
131
- paragraph.edit()
132
- .replace("Updated disclaimer text")
133
- .font("Roboto-Regular", 11)
134
- .line_spacing(1.1)
135
- .move_to(72, 140)
136
- .apply()
137
-
138
- # …or use the context manager to auto-apply on success
139
- with paragraph.edit() as edit:
140
- edit.replace("Context-managed update").color(Color(120, 0, 0))
141
-
142
- # Update an AcroForm field
143
- field = pdf.page(1).select_form_fields_by_name("signature")[0]
144
- field.edit().value("Signed by Jane Doe").apply()
145
- ```
146
-
147
- ## Adding New Content
148
-
149
- ```python
150
- with PDFDancer.open("report.pdf") as pdf:
151
- # Register fonts from the service
152
- fonts = pdf.find_fonts("Roboto", 12)
153
- pdf.register_font("/path/to/custom.ttf")
154
-
155
- # Paragraphs
156
- pdf.new_paragraph()
157
- .text("Greetings from PDFDancer!")
158
- .font(fonts[0].name, fonts[0].size)
159
- .at(page_index=0, x=220, y=480)
160
- .add()
161
-
162
- # Raster images
163
- pdf.new_image()
164
- .from_file(Path("logo.png"))
165
- .at(page=0, x=48, y=700)
166
- .add()
167
- ```
168
-
169
- ## Downloading Results
170
-
171
- - `pdf.get_pdf_file()` returns the modified PDF as `bytes` (ideal for storage services or HTTP responses).
172
- - `pdf.save("output.pdf")` writes directly to disk, creating directories when needed.
173
-
174
- ## Error Handling
175
-
176
- Most operations raise subclasses of `PdfDancerException`:
177
-
178
- - `ValidationException` for client-side validation issues (missing token, invalid coordinates, etc.).
179
- - `FontNotFoundException` when the service cannot locate a requested font.
180
- - `HttpClientException` for transport or server errors with detailed messages.
181
- - `SessionException` when session creation fails.
182
-
183
- Wrap complex workflows in `try/except` blocks to surface actionable errors to your users.
184
-
185
- ## Local Development
186
-
187
- ```bash
188
- python -m venv venv
189
- source venv/bin/activate # Windows: venv\Scripts\activate
190
- pip install -e ".[dev]"
191
-
192
- pytest -q # run the fast unit suite
193
- pytest tests/e2e # integration tests (requires live API + fixtures)
194
- ```
195
-
196
- Package builds are handled by `python -m build`, and release artifacts are published via `python release.py`.
197
-
198
- ## License
199
-
200
- MIT © The Famous Cat Ltd.
@@ -1,168 +0,0 @@
1
- # PDFDancer Python Client
2
-
3
- Automate PDF clean-up, redaction, form filling, and content injection against the PDFDancer API from Python. The client
4
- gives you page-scoped selectors, fluent editors, and builders so you can read, modify, and export PDFs programmatically
5
- in just a few lines.
6
-
7
- Latest schema version available at https://bucket.pdfdancer.com/api-doc/development-0.0.yml.
8
-
9
- ## Highlights
10
-
11
- - Locate anything inside a PDF—paragraphs, text lines, images, vector paths, pages, AcroForm fields—by page,
12
- coordinates, or text prefixes
13
- - Edit or delete existing content with fluent paragraph/text editors and safe apply-on-exit context managers
14
- - Fill or update form fields and propagate the changes back to the document instantly
15
- - Add brand-new content with paragraph/image builders, custom fonts, and precise page positioning
16
- - Download results as bytes for downstream processing or save directly to disk with one method call
17
-
18
- ## Core Capabilities
19
-
20
- - Clean up layout by moving or deleting paragraphs, text lines, or shapes on specific pages
21
- - Search and filter content (e.g., paragraphs starting with "Invoice") to drive custom workflows
22
- - Redact or replace text in bulk with chained editor operations
23
- - Populate AcroForms for contract generation or onboarding flows
24
- - Insert logos, signatures, and generated paragraphs at deterministic coordinates
25
- - Export modified PDFs as bytes for APIs, S3 uploads, or direct file saves
26
-
27
- ## Requirements
28
-
29
- - Python 3.10 or newer
30
- - A PDFDancer API token (set `PDFDANCER_TOKEN` or pass `token=...`)
31
- - Network access to a PDFDancer service (defaults to `https://api.pdfdancer.com`; override with `PDFDANCER_BASE_URL`)
32
-
33
- ## Installation
34
-
35
- ```bash
36
- pip install pdfdancer-client-python
37
-
38
- # Editable install for local development
39
- pip install -e .
40
- ```
41
-
42
- ## Getting Started
43
-
44
- ```python
45
- from pathlib import Path
46
- from pdfdancer import Color, PDFDancer
47
-
48
- with PDFDancer.open(
49
- pdf_data=Path("input.pdf"),
50
- token="your-api-token", # optional when PDFDANCER_TOKEN is set
51
- base_url="https://api.pdfdancer.com",
52
- ) as pdf:
53
- # Locate existing content
54
- heading = pdf.page(0).select_paragraphs_starting_with("Executive Summary")[0]
55
- heading.edit().replace("Overview").apply()
56
-
57
- # Add a new paragraph using the fluent builder
58
- pdf.new_paragraph()
59
- .text("Generated with PDFDancer")
60
- .font("Helvetica", 12)
61
- .color(Color(70, 70, 70))
62
- .line_spacing(1.4)
63
- .at(page_index=0, x=72, y=520)
64
- .add()
65
-
66
- # Persist the modified document
67
- pdf.save("output.pdf")
68
- ```
69
-
70
- ### Authentication Tips
71
-
72
- - Prefer setting `PDFDANCER_TOKEN` in your environment for local development.
73
- - Override the API host by setting `PDFDANCER_BASE_URL` or passing `base_url="https://sandbox.pdfdancer.com"`.
74
- - Use the `timeout` parameter on `PDFDancer.open()` to adjust HTTP read timeouts.
75
-
76
- ## Selecting PDF Content
77
-
78
- ```python
79
- with PDFDancer.open("report.pdf") as pdf: # environment variables provide token/URL
80
- all_paragraphs = pdf.select_paragraphs()
81
- page_zero_images = pdf.page(0).select_images()
82
- form_fields = pdf.page(2).select_form_fields()
83
- paths_at_cursor = pdf.page(3).select_paths_at(x=150, y=320)
84
-
85
- page = pdf.page(0).get()
86
- print(page.internal_id, page.position.bounding_rect)
87
- ```
88
-
89
- Selectors return rich objects (`ParagraphObject`, `TextLineObject`, `ImageObject`, `FormFieldObject`, etc.) with helpers
90
- such as `delete()`, `move_to(x, y)`, or `edit()` depending on the object type.
91
-
92
- ## Editing Text and Forms
93
-
94
- ```python
95
- with PDFDancer.open("report.pdf") as pdf:
96
- paragraph = pdf.page(0).select_paragraphs_starting_with("Disclaimer")[0]
97
-
98
- # Chain updates explicitly…
99
- paragraph.edit()
100
- .replace("Updated disclaimer text")
101
- .font("Roboto-Regular", 11)
102
- .line_spacing(1.1)
103
- .move_to(72, 140)
104
- .apply()
105
-
106
- # …or use the context manager to auto-apply on success
107
- with paragraph.edit() as edit:
108
- edit.replace("Context-managed update").color(Color(120, 0, 0))
109
-
110
- # Update an AcroForm field
111
- field = pdf.page(1).select_form_fields_by_name("signature")[0]
112
- field.edit().value("Signed by Jane Doe").apply()
113
- ```
114
-
115
- ## Adding New Content
116
-
117
- ```python
118
- with PDFDancer.open("report.pdf") as pdf:
119
- # Register fonts from the service
120
- fonts = pdf.find_fonts("Roboto", 12)
121
- pdf.register_font("/path/to/custom.ttf")
122
-
123
- # Paragraphs
124
- pdf.new_paragraph()
125
- .text("Greetings from PDFDancer!")
126
- .font(fonts[0].name, fonts[0].size)
127
- .at(page_index=0, x=220, y=480)
128
- .add()
129
-
130
- # Raster images
131
- pdf.new_image()
132
- .from_file(Path("logo.png"))
133
- .at(page=0, x=48, y=700)
134
- .add()
135
- ```
136
-
137
- ## Downloading Results
138
-
139
- - `pdf.get_pdf_file()` returns the modified PDF as `bytes` (ideal for storage services or HTTP responses).
140
- - `pdf.save("output.pdf")` writes directly to disk, creating directories when needed.
141
-
142
- ## Error Handling
143
-
144
- Most operations raise subclasses of `PdfDancerException`:
145
-
146
- - `ValidationException` for client-side validation issues (missing token, invalid coordinates, etc.).
147
- - `FontNotFoundException` when the service cannot locate a requested font.
148
- - `HttpClientException` for transport or server errors with detailed messages.
149
- - `SessionException` when session creation fails.
150
-
151
- Wrap complex workflows in `try/except` blocks to surface actionable errors to your users.
152
-
153
- ## Local Development
154
-
155
- ```bash
156
- python -m venv venv
157
- source venv/bin/activate # Windows: venv\Scripts\activate
158
- pip install -e ".[dev]"
159
-
160
- pytest -q # run the fast unit suite
161
- pytest tests/e2e # integration tests (requires live API + fixtures)
162
- ```
163
-
164
- Package builds are handled by `python -m build`, and release artifacts are published via `python release.py`.
165
-
166
- ## License
167
-
168
- MIT © The Famous Cat Ltd.
@@ -1,200 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: pdfdancer-client-python
3
- Version: 0.2.15
4
- Summary: Python client for PDFDancer API
5
- Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
- License: MIT
7
- Project-URL: Homepage, https://www.pdfdancer.com/
8
- Project-URL: Repository, https://github.com/MenschMachine/pdfdancer-client-python
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.13
16
- Requires-Python: >=3.10
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
- Requires-Dist: python-dotenv>=0.19.0
22
- Provides-Extra: dev
23
- Requires-Dist: pytest>=7.0; extra == "dev"
24
- Requires-Dist: pytest-cov>=4.0; extra == "dev"
25
- Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
26
- Requires-Dist: black>=22.0; extra == "dev"
27
- Requires-Dist: flake8>=5.0; extra == "dev"
28
- Requires-Dist: mypy>=1.0; extra == "dev"
29
- Requires-Dist: isort>=5.10.0; extra == "dev"
30
- Requires-Dist: build>=0.8.0; extra == "dev"
31
- Requires-Dist: twine>=4.0.0; extra == "dev"
32
-
33
- # PDFDancer Python Client
34
-
35
- Automate PDF clean-up, redaction, form filling, and content injection against the PDFDancer API from Python. The client
36
- gives you page-scoped selectors, fluent editors, and builders so you can read, modify, and export PDFs programmatically
37
- in just a few lines.
38
-
39
- Latest schema version available at https://bucket.pdfdancer.com/api-doc/development-0.0.yml.
40
-
41
- ## Highlights
42
-
43
- - Locate anything inside a PDF—paragraphs, text lines, images, vector paths, pages, AcroForm fields—by page,
44
- coordinates, or text prefixes
45
- - Edit or delete existing content with fluent paragraph/text editors and safe apply-on-exit context managers
46
- - Fill or update form fields and propagate the changes back to the document instantly
47
- - Add brand-new content with paragraph/image builders, custom fonts, and precise page positioning
48
- - Download results as bytes for downstream processing or save directly to disk with one method call
49
-
50
- ## Core Capabilities
51
-
52
- - Clean up layout by moving or deleting paragraphs, text lines, or shapes on specific pages
53
- - Search and filter content (e.g., paragraphs starting with "Invoice") to drive custom workflows
54
- - Redact or replace text in bulk with chained editor operations
55
- - Populate AcroForms for contract generation or onboarding flows
56
- - Insert logos, signatures, and generated paragraphs at deterministic coordinates
57
- - Export modified PDFs as bytes for APIs, S3 uploads, or direct file saves
58
-
59
- ## Requirements
60
-
61
- - Python 3.10 or newer
62
- - A PDFDancer API token (set `PDFDANCER_TOKEN` or pass `token=...`)
63
- - Network access to a PDFDancer service (defaults to `https://api.pdfdancer.com`; override with `PDFDANCER_BASE_URL`)
64
-
65
- ## Installation
66
-
67
- ```bash
68
- pip install pdfdancer-client-python
69
-
70
- # Editable install for local development
71
- pip install -e .
72
- ```
73
-
74
- ## Getting Started
75
-
76
- ```python
77
- from pathlib import Path
78
- from pdfdancer import Color, PDFDancer
79
-
80
- with PDFDancer.open(
81
- pdf_data=Path("input.pdf"),
82
- token="your-api-token", # optional when PDFDANCER_TOKEN is set
83
- base_url="https://api.pdfdancer.com",
84
- ) as pdf:
85
- # Locate existing content
86
- heading = pdf.page(0).select_paragraphs_starting_with("Executive Summary")[0]
87
- heading.edit().replace("Overview").apply()
88
-
89
- # Add a new paragraph using the fluent builder
90
- pdf.new_paragraph()
91
- .text("Generated with PDFDancer")
92
- .font("Helvetica", 12)
93
- .color(Color(70, 70, 70))
94
- .line_spacing(1.4)
95
- .at(page_index=0, x=72, y=520)
96
- .add()
97
-
98
- # Persist the modified document
99
- pdf.save("output.pdf")
100
- ```
101
-
102
- ### Authentication Tips
103
-
104
- - Prefer setting `PDFDANCER_TOKEN` in your environment for local development.
105
- - Override the API host by setting `PDFDANCER_BASE_URL` or passing `base_url="https://sandbox.pdfdancer.com"`.
106
- - Use the `timeout` parameter on `PDFDancer.open()` to adjust HTTP read timeouts.
107
-
108
- ## Selecting PDF Content
109
-
110
- ```python
111
- with PDFDancer.open("report.pdf") as pdf: # environment variables provide token/URL
112
- all_paragraphs = pdf.select_paragraphs()
113
- page_zero_images = pdf.page(0).select_images()
114
- form_fields = pdf.page(2).select_form_fields()
115
- paths_at_cursor = pdf.page(3).select_paths_at(x=150, y=320)
116
-
117
- page = pdf.page(0).get()
118
- print(page.internal_id, page.position.bounding_rect)
119
- ```
120
-
121
- Selectors return rich objects (`ParagraphObject`, `TextLineObject`, `ImageObject`, `FormFieldObject`, etc.) with helpers
122
- such as `delete()`, `move_to(x, y)`, or `edit()` depending on the object type.
123
-
124
- ## Editing Text and Forms
125
-
126
- ```python
127
- with PDFDancer.open("report.pdf") as pdf:
128
- paragraph = pdf.page(0).select_paragraphs_starting_with("Disclaimer")[0]
129
-
130
- # Chain updates explicitly…
131
- paragraph.edit()
132
- .replace("Updated disclaimer text")
133
- .font("Roboto-Regular", 11)
134
- .line_spacing(1.1)
135
- .move_to(72, 140)
136
- .apply()
137
-
138
- # …or use the context manager to auto-apply on success
139
- with paragraph.edit() as edit:
140
- edit.replace("Context-managed update").color(Color(120, 0, 0))
141
-
142
- # Update an AcroForm field
143
- field = pdf.page(1).select_form_fields_by_name("signature")[0]
144
- field.edit().value("Signed by Jane Doe").apply()
145
- ```
146
-
147
- ## Adding New Content
148
-
149
- ```python
150
- with PDFDancer.open("report.pdf") as pdf:
151
- # Register fonts from the service
152
- fonts = pdf.find_fonts("Roboto", 12)
153
- pdf.register_font("/path/to/custom.ttf")
154
-
155
- # Paragraphs
156
- pdf.new_paragraph()
157
- .text("Greetings from PDFDancer!")
158
- .font(fonts[0].name, fonts[0].size)
159
- .at(page_index=0, x=220, y=480)
160
- .add()
161
-
162
- # Raster images
163
- pdf.new_image()
164
- .from_file(Path("logo.png"))
165
- .at(page=0, x=48, y=700)
166
- .add()
167
- ```
168
-
169
- ## Downloading Results
170
-
171
- - `pdf.get_pdf_file()` returns the modified PDF as `bytes` (ideal for storage services or HTTP responses).
172
- - `pdf.save("output.pdf")` writes directly to disk, creating directories when needed.
173
-
174
- ## Error Handling
175
-
176
- Most operations raise subclasses of `PdfDancerException`:
177
-
178
- - `ValidationException` for client-side validation issues (missing token, invalid coordinates, etc.).
179
- - `FontNotFoundException` when the service cannot locate a requested font.
180
- - `HttpClientException` for transport or server errors with detailed messages.
181
- - `SessionException` when session creation fails.
182
-
183
- Wrap complex workflows in `try/except` blocks to surface actionable errors to your users.
184
-
185
- ## Local Development
186
-
187
- ```bash
188
- python -m venv venv
189
- source venv/bin/activate # Windows: venv\Scripts\activate
190
- pip install -e ".[dev]"
191
-
192
- pytest -q # run the fast unit suite
193
- pytest tests/e2e # integration tests (requires live API + fixtures)
194
- ```
195
-
196
- Package builds are handled by `python -m build`, and release artifacts are published via `python release.py`.
197
-
198
- ## License
199
-
200
- MIT © The Famous Cat Ltd.