PyPDFForm 5.2.2__tar.gz → 5.2.3__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.
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PKG-INFO +1 -1
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/__init__.py +1 -1
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/create.py +148 -14
- pypdfform-5.2.3/PyPDFForm/cli/inspect.py +129 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/remove.py +23 -2
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/root.py +41 -3
- pypdfform-5.2.3/PyPDFForm/cli/update.py +331 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/adapter.py +5 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/egress.py +5 -3
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/filler.py +16 -10
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/font.py +26 -18
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/hooks.py +25 -15
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/image.py +4 -3
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/middleware/base.py +14 -9
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/middleware/checkbox.py +3 -2
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/middleware/dropdown.py +12 -5
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/middleware/signature.py +6 -6
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/patterns.py +19 -9
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/raw/image.py +2 -1
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/raw/text.py +1 -1
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/template.py +39 -10
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/types.py +2 -1
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/utils.py +28 -18
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/watermark.py +33 -3
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/widgets/base.py +14 -11
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/widgets/dropdown.py +11 -4
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/widgets/image.py +6 -6
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/widgets/radio.py +6 -2
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/widgets/signature.py +11 -4
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/wrapper.py +86 -31
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm.egg-info/PKG-INFO +1 -1
- pypdfform-5.2.2/PyPDFForm/cli/inspect.py +0 -69
- pypdfform-5.2.2/PyPDFForm/cli/update.py +0 -206
- {pypdfform-5.2.2 → pypdfform-5.2.3}/LICENSE +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/__init__.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/common.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/entry.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/schemas/__init__.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/schemas/create.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/cli/schemas/update.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/__init__.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/annotations/__init__.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/annotations/base.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/annotations/link.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/annotations/stamp.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/annotations/text.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/annotations/text_markup.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/assets/__init__.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/assets/bedrock.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/assets/blank.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/constants.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/coordinate.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/deprecation.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/middleware/__init__.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/middleware/image.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/middleware/radio.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/middleware/text.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/raw/__init__.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/raw/circle.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/raw/ellipse.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/raw/line.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/raw/rect.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/widgets/__init__.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/widgets/checkbox.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm/lib/widgets/text.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm.egg-info/SOURCES.txt +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm.egg-info/dependency_links.txt +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm.egg-info/entry_points.txt +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm.egg-info/requires.txt +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/PyPDFForm.egg-info/top_level.txt +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/README.md +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/pyproject.toml +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/setup.cfg +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_bulk_create_fields.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_create_widget.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_draw_elements.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_dropdown.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_extract_middleware_attributes.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_fill_max_length_text_field.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_font_widths.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_functional.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_generate_appearance_streams.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_js.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_need_appearances.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_paragraph.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_signature.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_use_full_widget_name.py +0 -0
- {pypdfform-5.2.2 → pypdfform-5.2.3}/tests/test_widget_attr_trigger.py +0 -0
|
@@ -30,7 +30,10 @@ create_cli = typer.Typer(
|
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
@create_cli.command(
|
|
33
|
+
@create_cli.command(
|
|
34
|
+
no_args_is_help=True,
|
|
35
|
+
help="Create a new blank PDF.",
|
|
36
|
+
)
|
|
34
37
|
def blank(
|
|
35
38
|
ctx: typer.Context,
|
|
36
39
|
output: REQUIRED_OUTPUT_PDF,
|
|
@@ -60,7 +63,23 @@ def blank(
|
|
|
60
63
|
),
|
|
61
64
|
] = None,
|
|
62
65
|
) -> None:
|
|
63
|
-
"""
|
|
66
|
+
"""
|
|
67
|
+
Create a blank PDF with optional page size and page count.
|
|
68
|
+
|
|
69
|
+
The command builds a `BlankPage` using the supplied dimensions, duplicates
|
|
70
|
+
it when multiple pages are requested, wraps the result with the global CLI
|
|
71
|
+
options stored in `ctx.obj`, and writes the new PDF to the required output
|
|
72
|
+
path.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
76
|
+
options in `ctx.obj`.
|
|
77
|
+
output (Path): Output PDF path.
|
|
78
|
+
count (int, optional): Number of blank pages to create. Defaults to
|
|
79
|
+
None.
|
|
80
|
+
width (float, optional): Page width in points. Defaults to None.
|
|
81
|
+
height (float, optional): Page height in points. Defaults to None.
|
|
82
|
+
"""
|
|
64
83
|
params = {}
|
|
65
84
|
if width is not None:
|
|
66
85
|
params["width"] = width
|
|
@@ -74,7 +93,10 @@ def blank(
|
|
|
74
93
|
PdfWrapper(obj, **ctx.obj).write(output)
|
|
75
94
|
|
|
76
95
|
|
|
77
|
-
@create_cli.command(
|
|
96
|
+
@create_cli.command(
|
|
97
|
+
no_args_is_help=True,
|
|
98
|
+
help="Extract pages from an existing PDF.",
|
|
99
|
+
)
|
|
78
100
|
def extract(
|
|
79
101
|
ctx: typer.Context,
|
|
80
102
|
pdf: INPUT_PDF,
|
|
@@ -98,7 +120,28 @@ def extract(
|
|
|
98
120
|
),
|
|
99
121
|
] = None,
|
|
100
122
|
) -> None:
|
|
101
|
-
"""
|
|
123
|
+
"""
|
|
124
|
+
Extract a page range from an existing PDF.
|
|
125
|
+
|
|
126
|
+
The command validates that the requested end page does not precede the
|
|
127
|
+
start page, converts the 1-based CLI page numbers into the slice expected
|
|
128
|
+
by `PdfWrapper.pages`, and writes the extracted pages to the required
|
|
129
|
+
output path.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
133
|
+
options in `ctx.obj`.
|
|
134
|
+
pdf (Path): Input PDF path.
|
|
135
|
+
output (Path): Output PDF path.
|
|
136
|
+
start (int, optional): First page to extract, starting at 1. Defaults
|
|
137
|
+
to None.
|
|
138
|
+
end (int, optional): Last page to extract, starting at 1. Defaults to
|
|
139
|
+
None.
|
|
140
|
+
|
|
141
|
+
Raises:
|
|
142
|
+
typer.BadParameter: Raised when both page bounds are supplied and the
|
|
143
|
+
start page is after the end page.
|
|
144
|
+
"""
|
|
102
145
|
if start is not None and end is not None and start > end:
|
|
103
146
|
message = "End page must be greater than or equal to start page."
|
|
104
147
|
cli_bad_parameter(
|
|
@@ -109,7 +152,10 @@ def extract(
|
|
|
109
152
|
PdfWrapper(str(pdf), **ctx.obj).pages[slice((start or 1) - 1, end)].write(output)
|
|
110
153
|
|
|
111
154
|
|
|
112
|
-
@create_cli.command(
|
|
155
|
+
@create_cli.command(
|
|
156
|
+
no_args_is_help=True,
|
|
157
|
+
help="Merge multiple PDFs into one.",
|
|
158
|
+
)
|
|
113
159
|
def merge(
|
|
114
160
|
ctx: typer.Context,
|
|
115
161
|
pdfs: Annotated[
|
|
@@ -125,18 +171,48 @@ def merge(
|
|
|
125
171
|
],
|
|
126
172
|
output: REQUIRED_OUTPUT_PDF,
|
|
127
173
|
) -> None:
|
|
128
|
-
"""
|
|
174
|
+
"""
|
|
175
|
+
Merge input PDFs in the order provided on the command line.
|
|
176
|
+
|
|
177
|
+
Each path is loaded into a `PdfWrapper` with the global CLI options, passed
|
|
178
|
+
to `PdfArray`, merged into one document, and written to the required output
|
|
179
|
+
path.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
183
|
+
options in `ctx.obj`.
|
|
184
|
+
pdfs (list[Path]): Input PDF paths in merge order.
|
|
185
|
+
output (Path): Output PDF path.
|
|
186
|
+
"""
|
|
129
187
|
PdfArray([PdfWrapper(str(pdf), **ctx.obj) for pdf in pdfs]).merge().write(output)
|
|
130
188
|
|
|
131
189
|
|
|
132
|
-
@create_cli.command(
|
|
190
|
+
@create_cli.command(
|
|
191
|
+
no_args_is_help=True,
|
|
192
|
+
help="Add form fields to a PDF.",
|
|
193
|
+
)
|
|
133
194
|
def field(
|
|
134
195
|
ctx: typer.Context,
|
|
135
196
|
pdf: INPUT_PDF,
|
|
136
197
|
data: Annotated[Path, json_file_option("JSON file with form field definitions.")],
|
|
137
198
|
output: OPTIONAL_OUTPUT_PDF = None,
|
|
138
199
|
) -> None:
|
|
139
|
-
"""
|
|
200
|
+
"""
|
|
201
|
+
Add form fields described by grouped JSON definitions.
|
|
202
|
+
|
|
203
|
+
The command maps JSON groups such as `text`, `check`, and `signature` to
|
|
204
|
+
PyPDFForm field classes, validates the input file against the CLI field
|
|
205
|
+
schema, creates the corresponding field objects, and calls
|
|
206
|
+
`PdfWrapper.bulk_create_fields` before writing the modified PDF.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
210
|
+
options in `ctx.obj`.
|
|
211
|
+
pdf (Path): Input PDF path.
|
|
212
|
+
data (Path): JSON file containing grouped form field definitions.
|
|
213
|
+
output (Path, optional): Output PDF path. If omitted, the input PDF is
|
|
214
|
+
overwritten. Defaults to None.
|
|
215
|
+
"""
|
|
140
216
|
field_map = {
|
|
141
217
|
"text": Fields.TextField,
|
|
142
218
|
"check": Fields.CheckBoxField,
|
|
@@ -157,14 +233,32 @@ def field(
|
|
|
157
233
|
)
|
|
158
234
|
|
|
159
235
|
|
|
160
|
-
@create_cli.command(
|
|
236
|
+
@create_cli.command(
|
|
237
|
+
no_args_is_help=True,
|
|
238
|
+
help="Draw text, images, and shapes on a PDF.",
|
|
239
|
+
)
|
|
161
240
|
def raw(
|
|
162
241
|
ctx: typer.Context,
|
|
163
242
|
pdf: INPUT_PDF,
|
|
164
243
|
data: Annotated[Path, json_file_option("JSON file with raw element definitions.")],
|
|
165
244
|
output: OPTIONAL_OUTPUT_PDF = None,
|
|
166
245
|
) -> None:
|
|
167
|
-
"""
|
|
246
|
+
"""
|
|
247
|
+
Draw raw elements described by grouped JSON definitions.
|
|
248
|
+
|
|
249
|
+
The command maps JSON groups such as `text`, `image`, and `rectangle` to
|
|
250
|
+
raw element classes, validates the input file against the CLI raw element
|
|
251
|
+
schema, creates the corresponding drawable objects, and calls
|
|
252
|
+
`PdfWrapper.draw` before writing the modified PDF.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
256
|
+
options in `ctx.obj`.
|
|
257
|
+
pdf (Path): Input PDF path.
|
|
258
|
+
data (Path): JSON file containing grouped raw element definitions.
|
|
259
|
+
output (Path, optional): Output PDF path. If omitted, the input PDF is
|
|
260
|
+
overwritten. Defaults to None.
|
|
261
|
+
"""
|
|
168
262
|
raw_element_map = {
|
|
169
263
|
"text": RawElements.RawText,
|
|
170
264
|
"image": RawElements.RawImage,
|
|
@@ -185,14 +279,32 @@ def raw(
|
|
|
185
279
|
)
|
|
186
280
|
|
|
187
281
|
|
|
188
|
-
@create_cli.command(
|
|
282
|
+
@create_cli.command(
|
|
283
|
+
no_args_is_help=True,
|
|
284
|
+
help="Add annotations to a PDF.",
|
|
285
|
+
)
|
|
189
286
|
def annotation(
|
|
190
287
|
ctx: typer.Context,
|
|
191
288
|
pdf: INPUT_PDF,
|
|
192
289
|
data: Annotated[Path, json_file_option("JSON file with annotation definitions.")],
|
|
193
290
|
output: OPTIONAL_OUTPUT_PDF = None,
|
|
194
291
|
) -> None:
|
|
195
|
-
"""
|
|
292
|
+
"""
|
|
293
|
+
Add annotations described by grouped JSON definitions.
|
|
294
|
+
|
|
295
|
+
The command maps JSON groups such as `text`, `link`, and `highlight` to
|
|
296
|
+
annotation classes, validates the input file against the CLI annotation
|
|
297
|
+
schema, creates the corresponding annotation objects, and calls
|
|
298
|
+
`PdfWrapper.annotate` before writing the modified PDF.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
302
|
+
options in `ctx.obj`.
|
|
303
|
+
pdf (Path): Input PDF path.
|
|
304
|
+
data (Path): JSON file containing grouped annotation definitions.
|
|
305
|
+
output (Path, optional): Output PDF path. If omitted, the input PDF is
|
|
306
|
+
overwritten. Defaults to None.
|
|
307
|
+
"""
|
|
196
308
|
annotation_map = {
|
|
197
309
|
"text": Annotations.TextAnnotation,
|
|
198
310
|
"link": Annotations.LinkAnnotation,
|
|
@@ -214,7 +326,10 @@ def annotation(
|
|
|
214
326
|
)
|
|
215
327
|
|
|
216
328
|
|
|
217
|
-
@create_cli.command(
|
|
329
|
+
@create_cli.command(
|
|
330
|
+
no_args_is_help=True,
|
|
331
|
+
help="Add a coordinate grid to a PDF.",
|
|
332
|
+
)
|
|
218
333
|
def grid(
|
|
219
334
|
ctx: typer.Context,
|
|
220
335
|
pdf: INPUT_PDF,
|
|
@@ -259,7 +374,26 @@ def grid(
|
|
|
259
374
|
),
|
|
260
375
|
] = None,
|
|
261
376
|
) -> None:
|
|
262
|
-
"""
|
|
377
|
+
"""
|
|
378
|
+
Overlay a coordinate grid on an existing PDF.
|
|
379
|
+
|
|
380
|
+
The command collects optional RGB color components and margin values,
|
|
381
|
+
normalizes whole-number margins to integers for stable output, generates a
|
|
382
|
+
coordinate grid through `PdfWrapper.generate_coordinate_grid`, and writes
|
|
383
|
+
the result to the requested output path or back to the input file.
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
387
|
+
options in `ctx.obj`.
|
|
388
|
+
pdf (Path): Input PDF path.
|
|
389
|
+
output (Path, optional): Output PDF path. If omitted, the input PDF is
|
|
390
|
+
overwritten. Defaults to None.
|
|
391
|
+
red (float, optional): Grid red value from 0 to 1. Defaults to None.
|
|
392
|
+
green (float, optional): Grid green value from 0 to 1. Defaults to
|
|
393
|
+
None.
|
|
394
|
+
blue (float, optional): Grid blue value from 0 to 1. Defaults to None.
|
|
395
|
+
margin (float, optional): Grid margin in points. Defaults to None.
|
|
396
|
+
"""
|
|
263
397
|
params = {}
|
|
264
398
|
if any(
|
|
265
399
|
[
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
This module defines CLI commands for inspecting PDF form information.
|
|
4
|
+
|
|
5
|
+
It exposes the `inspect` command group, which prints JSON for form schemas,
|
|
6
|
+
current form values, generated sample data, and field rectangle metadata.
|
|
7
|
+
Each command wraps read-only `PdfWrapper` properties so users can inspect forms
|
|
8
|
+
from the terminal without writing Python code.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
|
|
13
|
+
import typer
|
|
14
|
+
|
|
15
|
+
from .. import PdfWrapper
|
|
16
|
+
from .common import FIELD_NAME, INPUT_PDF, get_widget
|
|
17
|
+
|
|
18
|
+
inspect_cli = typer.Typer(
|
|
19
|
+
context_settings={"help_option_names": ["--help", "-h"]}, no_args_is_help=True
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@inspect_cli.command(
|
|
24
|
+
no_args_is_help=True,
|
|
25
|
+
help="Print the form schema as JSON.",
|
|
26
|
+
)
|
|
27
|
+
def schema(
|
|
28
|
+
ctx: typer.Context,
|
|
29
|
+
pdf: INPUT_PDF,
|
|
30
|
+
) -> None:
|
|
31
|
+
"""
|
|
32
|
+
Print the JSON schema for filling an existing PDF form.
|
|
33
|
+
|
|
34
|
+
The command loads the PDF with the global CLI options stored in `ctx.obj`,
|
|
35
|
+
reads `PdfWrapper.schema`, serializes it as JSON, and writes it to standard
|
|
36
|
+
output.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
40
|
+
options in `ctx.obj`.
|
|
41
|
+
pdf (Path): Input PDF path.
|
|
42
|
+
"""
|
|
43
|
+
typer.echo(json.dumps(PdfWrapper(str(pdf), **ctx.obj).schema))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@inspect_cli.command(
|
|
47
|
+
no_args_is_help=True,
|
|
48
|
+
help="Print current form data as JSON.",
|
|
49
|
+
)
|
|
50
|
+
def data(
|
|
51
|
+
ctx: typer.Context,
|
|
52
|
+
pdf: INPUT_PDF,
|
|
53
|
+
) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Print the current field values from an existing PDF form.
|
|
56
|
+
|
|
57
|
+
The command loads the PDF with the global CLI options stored in `ctx.obj`,
|
|
58
|
+
reads `PdfWrapper.data`, serializes it as JSON, and writes it to standard
|
|
59
|
+
output.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
63
|
+
options in `ctx.obj`.
|
|
64
|
+
pdf (Path): Input PDF path.
|
|
65
|
+
"""
|
|
66
|
+
typer.echo(json.dumps(PdfWrapper(str(pdf), **ctx.obj).data))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@inspect_cli.command(
|
|
70
|
+
no_args_is_help=True,
|
|
71
|
+
help="Print sample fill data as JSON.",
|
|
72
|
+
)
|
|
73
|
+
def sample(
|
|
74
|
+
ctx: typer.Context,
|
|
75
|
+
pdf: INPUT_PDF,
|
|
76
|
+
) -> None:
|
|
77
|
+
"""
|
|
78
|
+
Print generated sample data for filling an existing PDF form.
|
|
79
|
+
|
|
80
|
+
The command loads the PDF with the global CLI options stored in `ctx.obj`,
|
|
81
|
+
reads `PdfWrapper.sample_data`, serializes it as JSON, and writes it to
|
|
82
|
+
standard output.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
86
|
+
options in `ctx.obj`.
|
|
87
|
+
pdf (Path): Input PDF path.
|
|
88
|
+
"""
|
|
89
|
+
typer.echo(json.dumps(PdfWrapper(str(pdf), **ctx.obj).sample_data))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@inspect_cli.command(
|
|
93
|
+
no_args_is_help=True,
|
|
94
|
+
help="Print a form field's location and size as JSON.",
|
|
95
|
+
)
|
|
96
|
+
def location(
|
|
97
|
+
ctx: typer.Context,
|
|
98
|
+
pdf: INPUT_PDF,
|
|
99
|
+
field: FIELD_NAME,
|
|
100
|
+
) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Print geometry metadata for a single form field.
|
|
103
|
+
|
|
104
|
+
The command loads the PDF with the global CLI options stored in `ctx.obj`,
|
|
105
|
+
resolves the requested widget name, and prints a JSON object containing the
|
|
106
|
+
page number, x-coordinate, y-coordinate, width, and height.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
110
|
+
options in `ctx.obj`.
|
|
111
|
+
pdf (Path): Input PDF path.
|
|
112
|
+
field (str): Form field name to inspect.
|
|
113
|
+
|
|
114
|
+
Raises:
|
|
115
|
+
typer.BadParameter: Raised when the requested field does not exist.
|
|
116
|
+
"""
|
|
117
|
+
f = get_widget(PdfWrapper(str(pdf), **ctx.obj), field, "--field")
|
|
118
|
+
|
|
119
|
+
typer.echo(
|
|
120
|
+
json.dumps(
|
|
121
|
+
{
|
|
122
|
+
"page_number": f.page_number,
|
|
123
|
+
"x": f.x,
|
|
124
|
+
"y": f.y,
|
|
125
|
+
"width": f.width,
|
|
126
|
+
"height": f.height,
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
)
|
|
@@ -18,14 +18,35 @@ remove_cli = typer.Typer(
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
@remove_cli.command(
|
|
21
|
+
@remove_cli.command(
|
|
22
|
+
no_args_is_help=True,
|
|
23
|
+
help="Remove form fields from a PDF.",
|
|
24
|
+
)
|
|
22
25
|
def field(
|
|
23
26
|
ctx: typer.Context,
|
|
24
27
|
pdf: INPUT_PDF,
|
|
25
28
|
fields: FIELD_NAMES,
|
|
26
29
|
output: OPTIONAL_OUTPUT_PDF = None,
|
|
27
30
|
) -> None:
|
|
28
|
-
"""
|
|
31
|
+
"""
|
|
32
|
+
Remove one or more named form fields from an existing PDF.
|
|
33
|
+
|
|
34
|
+
The command loads the PDF with the global CLI options stored in `ctx.obj`,
|
|
35
|
+
validates each requested field name before changing the document, removes
|
|
36
|
+
the fields through `PdfWrapper.remove_fields`, and writes the modified PDF
|
|
37
|
+
to the requested output path or back to the input file.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
41
|
+
options in `ctx.obj`.
|
|
42
|
+
pdf (Path): Input PDF path.
|
|
43
|
+
fields (list[str]): Form field names to remove.
|
|
44
|
+
output (Path, optional): Output PDF path. If omitted, the input PDF is
|
|
45
|
+
overwritten. Defaults to None.
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
typer.BadParameter: Raised when any requested field does not exist.
|
|
49
|
+
"""
|
|
29
50
|
obj = PdfWrapper(str(pdf), **ctx.obj)
|
|
30
51
|
for field_name in fields:
|
|
31
52
|
get_widget(obj, field_name, "--field")
|
|
@@ -117,7 +117,24 @@ def main(
|
|
|
117
117
|
),
|
|
118
118
|
] = False,
|
|
119
119
|
) -> None:
|
|
120
|
-
"""
|
|
120
|
+
"""
|
|
121
|
+
Initialize shared CLI options for the selected command.
|
|
122
|
+
|
|
123
|
+
Typer runs this callback before dispatching to a subcommand. The callback
|
|
124
|
+
stores global PDF handling options on `ctx.obj` so command groups can pass
|
|
125
|
+
a consistent set of keyword arguments to `PdfWrapper`.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
ctx (typer.Context): Typer context for the current CLI invocation.
|
|
129
|
+
version (bool): Whether to print the package version and exit.
|
|
130
|
+
need_appearances (bool): Whether to ask PDF viewers to render form
|
|
131
|
+
field appearances.
|
|
132
|
+
generate_appearance_streams (bool): Whether to generate form field
|
|
133
|
+
appearance streams while handling PDFs.
|
|
134
|
+
preserve_metadata (bool): Whether to preserve input PDF metadata.
|
|
135
|
+
use_full_widget_name (bool): Whether widget lookups should use full
|
|
136
|
+
form field names.
|
|
137
|
+
"""
|
|
121
138
|
ctx.obj = {
|
|
122
139
|
"need_appearances": need_appearances,
|
|
123
140
|
"generate_appearance_streams": generate_appearance_streams,
|
|
@@ -126,7 +143,10 @@ def main(
|
|
|
126
143
|
}
|
|
127
144
|
|
|
128
145
|
|
|
129
|
-
@cli_app.command(
|
|
146
|
+
@cli_app.command(
|
|
147
|
+
no_args_is_help=True,
|
|
148
|
+
help="Fill a PDF form with JSON data.",
|
|
149
|
+
)
|
|
130
150
|
def fill(
|
|
131
151
|
ctx: typer.Context,
|
|
132
152
|
pdf: INPUT_PDF,
|
|
@@ -137,7 +157,25 @@ def fill(
|
|
|
137
157
|
typer.Option("--flatten", help="Flatten form fields after filling."),
|
|
138
158
|
] = None,
|
|
139
159
|
) -> None:
|
|
140
|
-
"""
|
|
160
|
+
"""
|
|
161
|
+
Fill an existing PDF form from a validated JSON file.
|
|
162
|
+
|
|
163
|
+
The command loads the input PDF with the global options stored by the root
|
|
164
|
+
callback, expands the generated schema so image and signature widgets can
|
|
165
|
+
accept path objects, validates the JSON input, normalizes image and
|
|
166
|
+
signature values, and writes the filled PDF to the requested output path or
|
|
167
|
+
back to the input file.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
ctx (typer.Context): Typer context containing global `PdfWrapper`
|
|
171
|
+
options in `ctx.obj`.
|
|
172
|
+
pdf (Path): Input PDF form path.
|
|
173
|
+
data (Path): JSON file containing form field values.
|
|
174
|
+
output (Path, optional): Output PDF path. If omitted, the input PDF is
|
|
175
|
+
overwritten. Defaults to None.
|
|
176
|
+
flatten (bool, optional): Whether to flatten form fields after filling.
|
|
177
|
+
Defaults to None.
|
|
178
|
+
"""
|
|
141
179
|
obj = PdfWrapper(str(pdf), **ctx.obj)
|
|
142
180
|
|
|
143
181
|
schema = obj.schema
|