PyPDFForm 5.0.0__tar.gz → 5.1.0__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.0.0 → pypdfform-5.1.0}/PKG-INFO +32 -21
- pypdfform-5.1.0/PyPDFForm/__init__.py +46 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/common.py +26 -18
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/entry.py +4 -2
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/inspect.py +2 -5
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/schemas/create.py +1 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/schemas/update.py +1 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/update.py +5 -7
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/raw/image.py +1 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/raw/rect.py +1 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/widgets/dropdown.py +1 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/widgets/signature.py +1 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm.egg-info/PKG-INFO +32 -21
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm.egg-info/SOURCES.txt +0 -8
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm.egg-info/requires.txt +5 -8
- {pypdfform-5.0.0 → pypdfform-5.1.0}/README.md +20 -11
- {pypdfform-5.0.0 → pypdfform-5.1.0}/pyproject.toml +13 -11
- pypdfform-5.0.0/PyPDFForm/__init__.py +0 -50
- pypdfform-5.0.0/PyPDFForm/api/__init__.py +0 -28
- pypdfform-5.0.0/PyPDFForm/api/common.py +0 -101
- pypdfform-5.0.0/PyPDFForm/api/create.py +0 -75
- pypdfform-5.0.0/PyPDFForm/api/inspect.py +0 -127
- pypdfform-5.0.0/PyPDFForm/api/root.py +0 -20
- pypdfform-5.0.0/PyPDFForm/api/update.py +0 -56
- pypdfform-5.0.0/PyPDFForm/shared/__init__.py +0 -0
- pypdfform-5.0.0/PyPDFForm/shared/utils.py +0 -42
- {pypdfform-5.0.0 → pypdfform-5.1.0}/LICENSE +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/__init__.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/create.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/root.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/cli/schemas/__init__.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/__init__.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/adapter.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/annotations/__init__.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/annotations/base.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/annotations/link.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/annotations/stamp.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/annotations/text.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/annotations/text_markup.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/assets/__init__.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/assets/bedrock.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/assets/blank.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/constants.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/coordinate.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/deprecation.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/egress.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/filler.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/font.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/hooks.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/image.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/middleware/__init__.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/middleware/base.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/middleware/checkbox.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/middleware/dropdown.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/middleware/image.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/middleware/radio.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/middleware/signature.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/middleware/text.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/patterns.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/raw/__init__.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/raw/circle.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/raw/ellipse.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/raw/line.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/raw/text.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/template.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/types.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/utils.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/watermark.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/widgets/__init__.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/widgets/base.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/widgets/checkbox.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/widgets/image.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/widgets/radio.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/widgets/text.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm/lib/wrapper.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm.egg-info/dependency_links.txt +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm.egg-info/entry_points.txt +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/PyPDFForm.egg-info/top_level.txt +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/setup.cfg +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_bulk_create_fields.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_create_widget.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_draw_elements.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_dropdown.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_extract_middleware_attributes.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_fill_max_length_text_field.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_font_widths.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_functional.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_generate_appearance_streams.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_js.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_need_appearances.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_paragraph.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_signature.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_use_full_widget_name.py +0 -0
- {pypdfform-5.0.0 → pypdfform-5.1.0}/tests/test_widget_attr_trigger.py +0 -0
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 5.
|
|
4
|
-
Summary: The Python library for PDF forms.
|
|
3
|
+
Version: 5.1.0
|
|
4
|
+
Summary: The Python library & CLI for PDF forms.
|
|
5
5
|
Author: Jinge Li
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/chinapandaman/PyPDFForm
|
|
8
8
|
Project-URL: Documentation, https://chinapandaman.github.io/PyPDFForm/
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Environment :: Console
|
|
10
11
|
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
11
13
|
Classifier: Programming Language :: Python :: 3
|
|
12
14
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -15,24 +17,24 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
15
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
19
|
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
-
Classifier:
|
|
20
|
+
Classifier: Topic :: File Formats
|
|
19
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Text Processing
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
20
24
|
Requires-Python: >=3.10
|
|
21
25
|
Description-Content-Type: text/markdown
|
|
22
26
|
License-File: LICENSE
|
|
23
27
|
Requires-Dist: cryptography<49.0.0,>=48.0.0
|
|
24
|
-
Requires-Dist: fonttools<5.0.0,>=4.
|
|
28
|
+
Requires-Dist: fonttools<5.0.0,>=4.63.0
|
|
25
29
|
Requires-Dist: pikepdf<11.0.0,>=10.5.1
|
|
26
30
|
Requires-Dist: pillow<13.0.0,>=12.2.0
|
|
27
31
|
Requires-Dist: pypdf<7.0.0,>=6.11.0
|
|
28
|
-
Requires-Dist: reportlab<5.0.0,>=4.5.
|
|
32
|
+
Requires-Dist: reportlab<5.0.0,>=4.5.1
|
|
29
33
|
Provides-Extra: cli
|
|
30
34
|
Requires-Dist: typer<1.0.0,>=0.25.1; extra == "cli"
|
|
31
35
|
Requires-Dist: jsonschema<5.0.0,>=4.26.0; extra == "cli"
|
|
32
|
-
Provides-Extra: web-api
|
|
33
|
-
Requires-Dist: fastapi[standard]<1.0.0,>=0.136.1; extra == "web-api"
|
|
34
36
|
Provides-Extra: dev
|
|
35
|
-
Requires-Dist: black<27.0.0,>=26.
|
|
37
|
+
Requires-Dist: black<27.0.0,>=26.5.1; extra == "dev"
|
|
36
38
|
Requires-Dist: coverage<8.0.0,>=7.14.0; extra == "dev"
|
|
37
39
|
Requires-Dist: isort<9.0.0,>=8.0.1; extra == "dev"
|
|
38
40
|
Requires-Dist: mike<3.0.0,>=2.2.0; extra == "dev"
|
|
@@ -42,13 +44,13 @@ Requires-Dist: pudb<2026.0.0,>=2025.1.5; extra == "dev"
|
|
|
42
44
|
Requires-Dist: pylint<5.0.0,>=4.0.5; extra == "dev"
|
|
43
45
|
Requires-Dist: pyright<2.0.0,>=1.1.409; extra == "dev"
|
|
44
46
|
Requires-Dist: pytest<10.0.0,>=9.0.3; extra == "dev"
|
|
45
|
-
Requires-Dist: requests<3.0.0,>=2.34.
|
|
46
|
-
Requires-Dist: ruff<1.0.0,>=0.15.
|
|
47
|
+
Requires-Dist: requests<3.0.0,>=2.34.2; extra == "dev"
|
|
48
|
+
Requires-Dist: ruff<1.0.0,>=0.15.13; extra == "dev"
|
|
47
49
|
Dynamic: license-file
|
|
48
50
|
|
|
49
51
|
<p align="center"><img src="https://github.com/chinapandaman/PyPDFForm/raw/master/docs/img/logo.png"></p>
|
|
50
52
|
<p align="center">
|
|
51
|
-
<em>PDF Form Automation Simplified
|
|
53
|
+
<em>PDF Form Automation Simplified - Create, Inspect, Style, and Fill Forms in Python or from the Command Line.</em>
|
|
52
54
|
</p>
|
|
53
55
|
<p align="center">
|
|
54
56
|
<a href="https://pypi.org/project/PyPDFForm/"><img src="https://img.shields.io/pypi/v/pypdfform?label=version&color=magenta"></a>
|
|
@@ -61,26 +63,36 @@ Dynamic: license-file
|
|
|
61
63
|
|
|
62
64
|
## Introduction
|
|
63
65
|
|
|
64
|
-
PyPDFForm is a Python library for PDF
|
|
66
|
+
PyPDFForm is a Python library and command line tool for working with PDF forms. It provides Python APIs and CLI commands for creating, inspecting, updating, and filling forms, plus common PDF utilities.
|
|
67
|
+
|
|
68
|
+
With PyPDFForm, you can:
|
|
65
69
|
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
70
|
+
* Create PDF forms, form fields, and raw elements.
|
|
71
|
+
* Inspect form fields, metadata, and values.
|
|
72
|
+
* Update field styling, behavior, and scripts.
|
|
73
|
+
* Fill PDF forms.
|
|
74
|
+
* Extract pages and merge PDFs.
|
|
69
75
|
|
|
70
|
-
|
|
76
|
+
The goal is to make PDF form work straightforward, whether you are handling one document or building a larger workflow.
|
|
71
77
|
|
|
72
78
|
## Installing
|
|
73
79
|
|
|
74
|
-
|
|
80
|
+
To use PyPDFForm as a Python library, install the base package with [pip](https://pypi.org/project/PyPDFForm/):
|
|
75
81
|
|
|
76
|
-
```shell
|
|
82
|
+
```shell
|
|
77
83
|
pip install PyPDFForm
|
|
78
84
|
```
|
|
79
85
|
|
|
86
|
+
To use the CLI, install PyPDFForm with the `cli` extra using [pipx](https://pipx.pypa.io/stable/):
|
|
87
|
+
|
|
88
|
+
```shell
|
|
89
|
+
pipx install "PyPDFForm[cli]"
|
|
90
|
+
```
|
|
91
|
+
|
|
80
92
|
## Quick Example
|
|
81
93
|

|
|
82
94
|
|
|
83
|
-
|
|
95
|
+
The GIF above shows the CLI filling a PDF form. To try the same workflow with the Python library, download the [sample PDF form](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_template.pdf) and run:
|
|
84
96
|
|
|
85
97
|
```python
|
|
86
98
|
from PyPDFForm import PdfWrapper
|
|
@@ -99,8 +111,7 @@ filled = PdfWrapper("sample_template.pdf", need_appearances=True).fill(
|
|
|
99
111
|
filled.write("output.pdf")
|
|
100
112
|
```
|
|
101
113
|
|
|
102
|
-
After running
|
|
103
|
-
and it should look like [this](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_filled.pdf).
|
|
114
|
+
After running this snippet, `output.pdf` will be written to the location you specified and should look like [this](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_filled.pdf).
|
|
104
115
|
|
|
105
116
|
## Documentation
|
|
106
117
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
PyPDFForm provides Python APIs and CLI commands for working with PDF forms.
|
|
4
|
+
|
|
5
|
+
It helps users create, inspect, update, and fill PDF forms, plus handle common
|
|
6
|
+
PDF utilities such as extracting pages and merging documents.
|
|
7
|
+
|
|
8
|
+
The project supports PDF form features including:
|
|
9
|
+
|
|
10
|
+
- Text, checkbox, radio, dropdown, signature, and image fields.
|
|
11
|
+
- Field styling, sizing, positioning, visibility, and editability.
|
|
12
|
+
- Form data inspection and JSON schema generation.
|
|
13
|
+
- PDF annotations, raw drawing elements, metadata, scripts, and versions.
|
|
14
|
+
|
|
15
|
+
PyPDFForm aims to make PDF form automation straightforward whether it is used
|
|
16
|
+
from Python code or from the command line.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import logging
|
|
20
|
+
|
|
21
|
+
__version__ = "5.1.0"
|
|
22
|
+
|
|
23
|
+
from .lib.annotations import Annotations
|
|
24
|
+
from .lib.assets.blank import BlankPage
|
|
25
|
+
from .lib.middleware import Widgets
|
|
26
|
+
from .lib.raw import RawElements
|
|
27
|
+
from .lib.types import PdfArray
|
|
28
|
+
from .lib.widgets import Fields
|
|
29
|
+
from .lib.wrapper import PdfWrapper
|
|
30
|
+
|
|
31
|
+
# TODO: figure out why `Annotation sizes differ:`
|
|
32
|
+
for logger in [
|
|
33
|
+
logging.getLogger(name) for name in getattr(logging.root.manager, "loggerDict")
|
|
34
|
+
]:
|
|
35
|
+
if "pypdf" in logger.name:
|
|
36
|
+
logger.setLevel(logging.ERROR)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"PdfWrapper",
|
|
40
|
+
"PdfArray",
|
|
41
|
+
"Annotations",
|
|
42
|
+
"Fields",
|
|
43
|
+
"BlankPage",
|
|
44
|
+
"RawElements",
|
|
45
|
+
"Widgets",
|
|
46
|
+
]
|
|
@@ -15,7 +15,7 @@ import typer
|
|
|
15
15
|
from jsonschema import ValidationError, validate
|
|
16
16
|
|
|
17
17
|
from .. import PdfWrapper
|
|
18
|
-
from ..
|
|
18
|
+
from ..lib.middleware.base import Widget
|
|
19
19
|
|
|
20
20
|
INPUT_PDF = Annotated[
|
|
21
21
|
Path,
|
|
@@ -100,23 +100,6 @@ def cli_bad_parameter(
|
|
|
100
100
|
raise typer.BadParameter(message, param_hint=param_hint) from cause
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
def cli_widget_key_error(param_hint: str) -> WidgetKeyErrorHandler:
|
|
104
|
-
"""
|
|
105
|
-
Build a CLI error handler for missing form fields.
|
|
106
|
-
|
|
107
|
-
Args:
|
|
108
|
-
param_hint (str): CLI parameter associated with the field name.
|
|
109
|
-
|
|
110
|
-
Returns:
|
|
111
|
-
WidgetKeyErrorHandler: Handler that raises a Typer input error.
|
|
112
|
-
"""
|
|
113
|
-
|
|
114
|
-
def _raise_cli_bad_parameter(message: str, cause: KeyError) -> NoReturn:
|
|
115
|
-
cli_bad_parameter(message, param_hint=param_hint, cause=cause)
|
|
116
|
-
|
|
117
|
-
return _raise_cli_bad_parameter
|
|
118
|
-
|
|
119
|
-
|
|
120
103
|
def _validation_error_path(exc: ValidationError) -> str:
|
|
121
104
|
"""
|
|
122
105
|
Builds a dotted JSON path for a validation error.
|
|
@@ -170,6 +153,31 @@ def load_json_file(data: Path, schema: dict, param_hint: str) -> Any:
|
|
|
170
153
|
return input_data
|
|
171
154
|
|
|
172
155
|
|
|
156
|
+
def get_widget(wrapper: PdfWrapper, field: str, param_hint: str) -> Widget:
|
|
157
|
+
"""
|
|
158
|
+
Look up a widget and report missing names as CLI input errors.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
wrapper (PdfWrapper): PDF wrapper containing form widgets.
|
|
162
|
+
field (str): Form field name to look up.
|
|
163
|
+
param_hint (str): CLI parameter associated with the field name.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Widget: The matching widget.
|
|
167
|
+
|
|
168
|
+
Raises:
|
|
169
|
+
typer.BadParameter: Raised when the widget name is not present.
|
|
170
|
+
"""
|
|
171
|
+
try:
|
|
172
|
+
return wrapper.widgets[field]
|
|
173
|
+
except KeyError as exc:
|
|
174
|
+
cli_bad_parameter(
|
|
175
|
+
f"Form field '{field}' does not exist.",
|
|
176
|
+
param_hint=param_hint,
|
|
177
|
+
cause=exc,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
173
181
|
def handle_font_registration(
|
|
174
182
|
obj: PdfWrapper, params: dict, registered_font: dict
|
|
175
183
|
) -> None:
|
|
@@ -11,7 +11,8 @@ import importlib
|
|
|
11
11
|
import sys
|
|
12
12
|
|
|
13
13
|
CLI_DEPENDENCIES = {"jsonschema", "typer"}
|
|
14
|
-
CLI_INSTALL_HINT =
|
|
14
|
+
CLI_INSTALL_HINT = 'pipx install "PyPDFForm[cli]"'
|
|
15
|
+
CLI_ENV_INSTALL_HINT = "pip install 'PyPDFForm[cli]'"
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
def main() -> None:
|
|
@@ -28,7 +29,8 @@ def main() -> None:
|
|
|
28
29
|
if exc.name in CLI_DEPENDENCIES:
|
|
29
30
|
print(
|
|
30
31
|
"PyPDFForm CLI dependencies are not installed. "
|
|
31
|
-
f"Install them with: {CLI_INSTALL_HINT}"
|
|
32
|
+
f"Install them with: {CLI_INSTALL_HINT}. "
|
|
33
|
+
f"Inside an existing environment, use: {CLI_ENV_INSTALL_HINT}",
|
|
32
34
|
file=sys.stderr,
|
|
33
35
|
)
|
|
34
36
|
raise SystemExit(1) from None
|
|
@@ -13,8 +13,7 @@ import json
|
|
|
13
13
|
import typer
|
|
14
14
|
|
|
15
15
|
from .. import PdfWrapper
|
|
16
|
-
from
|
|
17
|
-
from .common import FIELD_NAME, INPUT_PDF, cli_widget_key_error
|
|
16
|
+
from .common import FIELD_NAME, INPUT_PDF, get_widget
|
|
18
17
|
|
|
19
18
|
inspect_cli = typer.Typer(
|
|
20
19
|
context_settings={"help_option_names": ["--help", "-h"]}, no_args_is_help=True
|
|
@@ -55,9 +54,7 @@ def location(
|
|
|
55
54
|
field: FIELD_NAME,
|
|
56
55
|
) -> None:
|
|
57
56
|
"""Print a form field's location and size as JSON."""
|
|
58
|
-
f = get_widget(
|
|
59
|
-
PdfWrapper(str(pdf), **ctx.obj), field, cli_widget_key_error("--field")
|
|
60
|
-
)
|
|
57
|
+
f = get_widget(PdfWrapper(str(pdf), **ctx.obj), field, "--field")
|
|
61
58
|
|
|
62
59
|
typer.echo(
|
|
63
60
|
json.dumps(
|
|
@@ -17,11 +17,9 @@ import typer
|
|
|
17
17
|
|
|
18
18
|
from .. import PdfWrapper
|
|
19
19
|
from ..lib.constants import PdfVersion
|
|
20
|
-
from ..shared.utils import get_widget
|
|
21
20
|
from .common import (FIELD_NAME, INPUT_PDF, OPTIONAL_OUTPUT_PDF,
|
|
22
|
-
cli_bad_parameter,
|
|
23
|
-
|
|
24
|
-
load_json_file)
|
|
21
|
+
cli_bad_parameter, get_widget, handle_font_registration,
|
|
22
|
+
json_file_option, load_json_file)
|
|
25
23
|
from .schemas.update import FIELD_SCHEMA, RENAME_SCHEMA
|
|
26
24
|
|
|
27
25
|
update_cli = typer.Typer(
|
|
@@ -109,7 +107,7 @@ def bounds(
|
|
|
109
107
|
) -> None:
|
|
110
108
|
"""Update a form field's position and size."""
|
|
111
109
|
obj = PdfWrapper(str(pdf), **ctx.obj)
|
|
112
|
-
f = get_widget(obj, widget,
|
|
110
|
+
f = get_widget(obj, widget, "--field")
|
|
113
111
|
|
|
114
112
|
f.x = x if x is not None else f.x
|
|
115
113
|
f.y = y if y is not None else f.y
|
|
@@ -139,7 +137,7 @@ def rename(
|
|
|
139
137
|
obj = PdfWrapper(str(pdf), **ctx.obj)
|
|
140
138
|
for item in input_data:
|
|
141
139
|
for k, v in item.items():
|
|
142
|
-
widget = get_widget(obj, k,
|
|
140
|
+
widget = get_widget(obj, k, "--file")
|
|
143
141
|
obj.update_widget_key(widget.name, v["new_key"], index=v.get("index", 0))
|
|
144
142
|
|
|
145
143
|
obj.commit_widget_key_updates().write(output or pdf)
|
|
@@ -160,7 +158,7 @@ def field(
|
|
|
160
158
|
obj = PdfWrapper(str(pdf), **ctx.obj)
|
|
161
159
|
registered_font = {}
|
|
162
160
|
for k, each in input_data.items():
|
|
163
|
-
widget = get_widget(obj, k,
|
|
161
|
+
widget = get_widget(obj, k, "--file")
|
|
164
162
|
handle_font_registration(obj, each, registered_font)
|
|
165
163
|
for param, v in each.items():
|
|
166
164
|
setattr(widget, param, v)
|
|
@@ -89,6 +89,7 @@ class DropdownField(Field):
|
|
|
89
89
|
options: Optional[List[str | Tuple[str, str]]] = None
|
|
90
90
|
width: Optional[float] = None
|
|
91
91
|
height: Optional[float] = None
|
|
92
|
+
# pylint: disable=R0801
|
|
92
93
|
font: Optional[str] = None
|
|
93
94
|
font_size: Optional[float] = None
|
|
94
95
|
font_color: Optional[Tuple[float, ...]] = None
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 5.
|
|
4
|
-
Summary: The Python library for PDF forms.
|
|
3
|
+
Version: 5.1.0
|
|
4
|
+
Summary: The Python library & CLI for PDF forms.
|
|
5
5
|
Author: Jinge Li
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/chinapandaman/PyPDFForm
|
|
8
8
|
Project-URL: Documentation, https://chinapandaman.github.io/PyPDFForm/
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Environment :: Console
|
|
10
11
|
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
11
13
|
Classifier: Programming Language :: Python :: 3
|
|
12
14
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -15,24 +17,24 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
15
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
19
|
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
-
Classifier:
|
|
20
|
+
Classifier: Topic :: File Formats
|
|
19
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Text Processing
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
20
24
|
Requires-Python: >=3.10
|
|
21
25
|
Description-Content-Type: text/markdown
|
|
22
26
|
License-File: LICENSE
|
|
23
27
|
Requires-Dist: cryptography<49.0.0,>=48.0.0
|
|
24
|
-
Requires-Dist: fonttools<5.0.0,>=4.
|
|
28
|
+
Requires-Dist: fonttools<5.0.0,>=4.63.0
|
|
25
29
|
Requires-Dist: pikepdf<11.0.0,>=10.5.1
|
|
26
30
|
Requires-Dist: pillow<13.0.0,>=12.2.0
|
|
27
31
|
Requires-Dist: pypdf<7.0.0,>=6.11.0
|
|
28
|
-
Requires-Dist: reportlab<5.0.0,>=4.5.
|
|
32
|
+
Requires-Dist: reportlab<5.0.0,>=4.5.1
|
|
29
33
|
Provides-Extra: cli
|
|
30
34
|
Requires-Dist: typer<1.0.0,>=0.25.1; extra == "cli"
|
|
31
35
|
Requires-Dist: jsonschema<5.0.0,>=4.26.0; extra == "cli"
|
|
32
|
-
Provides-Extra: web-api
|
|
33
|
-
Requires-Dist: fastapi[standard]<1.0.0,>=0.136.1; extra == "web-api"
|
|
34
36
|
Provides-Extra: dev
|
|
35
|
-
Requires-Dist: black<27.0.0,>=26.
|
|
37
|
+
Requires-Dist: black<27.0.0,>=26.5.1; extra == "dev"
|
|
36
38
|
Requires-Dist: coverage<8.0.0,>=7.14.0; extra == "dev"
|
|
37
39
|
Requires-Dist: isort<9.0.0,>=8.0.1; extra == "dev"
|
|
38
40
|
Requires-Dist: mike<3.0.0,>=2.2.0; extra == "dev"
|
|
@@ -42,13 +44,13 @@ Requires-Dist: pudb<2026.0.0,>=2025.1.5; extra == "dev"
|
|
|
42
44
|
Requires-Dist: pylint<5.0.0,>=4.0.5; extra == "dev"
|
|
43
45
|
Requires-Dist: pyright<2.0.0,>=1.1.409; extra == "dev"
|
|
44
46
|
Requires-Dist: pytest<10.0.0,>=9.0.3; extra == "dev"
|
|
45
|
-
Requires-Dist: requests<3.0.0,>=2.34.
|
|
46
|
-
Requires-Dist: ruff<1.0.0,>=0.15.
|
|
47
|
+
Requires-Dist: requests<3.0.0,>=2.34.2; extra == "dev"
|
|
48
|
+
Requires-Dist: ruff<1.0.0,>=0.15.13; extra == "dev"
|
|
47
49
|
Dynamic: license-file
|
|
48
50
|
|
|
49
51
|
<p align="center"><img src="https://github.com/chinapandaman/PyPDFForm/raw/master/docs/img/logo.png"></p>
|
|
50
52
|
<p align="center">
|
|
51
|
-
<em>PDF Form Automation Simplified
|
|
53
|
+
<em>PDF Form Automation Simplified - Create, Inspect, Style, and Fill Forms in Python or from the Command Line.</em>
|
|
52
54
|
</p>
|
|
53
55
|
<p align="center">
|
|
54
56
|
<a href="https://pypi.org/project/PyPDFForm/"><img src="https://img.shields.io/pypi/v/pypdfform?label=version&color=magenta"></a>
|
|
@@ -61,26 +63,36 @@ Dynamic: license-file
|
|
|
61
63
|
|
|
62
64
|
## Introduction
|
|
63
65
|
|
|
64
|
-
PyPDFForm is a Python library for PDF
|
|
66
|
+
PyPDFForm is a Python library and command line tool for working with PDF forms. It provides Python APIs and CLI commands for creating, inspecting, updating, and filling forms, plus common PDF utilities.
|
|
67
|
+
|
|
68
|
+
With PyPDFForm, you can:
|
|
65
69
|
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
70
|
+
* Create PDF forms, form fields, and raw elements.
|
|
71
|
+
* Inspect form fields, metadata, and values.
|
|
72
|
+
* Update field styling, behavior, and scripts.
|
|
73
|
+
* Fill PDF forms.
|
|
74
|
+
* Extract pages and merge PDFs.
|
|
69
75
|
|
|
70
|
-
|
|
76
|
+
The goal is to make PDF form work straightforward, whether you are handling one document or building a larger workflow.
|
|
71
77
|
|
|
72
78
|
## Installing
|
|
73
79
|
|
|
74
|
-
|
|
80
|
+
To use PyPDFForm as a Python library, install the base package with [pip](https://pypi.org/project/PyPDFForm/):
|
|
75
81
|
|
|
76
|
-
```shell
|
|
82
|
+
```shell
|
|
77
83
|
pip install PyPDFForm
|
|
78
84
|
```
|
|
79
85
|
|
|
86
|
+
To use the CLI, install PyPDFForm with the `cli` extra using [pipx](https://pipx.pypa.io/stable/):
|
|
87
|
+
|
|
88
|
+
```shell
|
|
89
|
+
pipx install "PyPDFForm[cli]"
|
|
90
|
+
```
|
|
91
|
+
|
|
80
92
|
## Quick Example
|
|
81
93
|

|
|
82
94
|
|
|
83
|
-
|
|
95
|
+
The GIF above shows the CLI filling a PDF form. To try the same workflow with the Python library, download the [sample PDF form](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_template.pdf) and run:
|
|
84
96
|
|
|
85
97
|
```python
|
|
86
98
|
from PyPDFForm import PdfWrapper
|
|
@@ -99,8 +111,7 @@ filled = PdfWrapper("sample_template.pdf", need_appearances=True).fill(
|
|
|
99
111
|
filled.write("output.pdf")
|
|
100
112
|
```
|
|
101
113
|
|
|
102
|
-
After running
|
|
103
|
-
and it should look like [this](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_filled.pdf).
|
|
114
|
+
After running this snippet, `output.pdf` will be written to the location you specified and should look like [this](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_filled.pdf).
|
|
104
115
|
|
|
105
116
|
## Documentation
|
|
106
117
|
|
|
@@ -8,12 +8,6 @@ PyPDFForm.egg-info/dependency_links.txt
|
|
|
8
8
|
PyPDFForm.egg-info/entry_points.txt
|
|
9
9
|
PyPDFForm.egg-info/requires.txt
|
|
10
10
|
PyPDFForm.egg-info/top_level.txt
|
|
11
|
-
PyPDFForm/api/__init__.py
|
|
12
|
-
PyPDFForm/api/common.py
|
|
13
|
-
PyPDFForm/api/create.py
|
|
14
|
-
PyPDFForm/api/inspect.py
|
|
15
|
-
PyPDFForm/api/root.py
|
|
16
|
-
PyPDFForm/api/update.py
|
|
17
11
|
PyPDFForm/cli/__init__.py
|
|
18
12
|
PyPDFForm/cli/common.py
|
|
19
13
|
PyPDFForm/cli/create.py
|
|
@@ -72,8 +66,6 @@ PyPDFForm/lib/widgets/image.py
|
|
|
72
66
|
PyPDFForm/lib/widgets/radio.py
|
|
73
67
|
PyPDFForm/lib/widgets/signature.py
|
|
74
68
|
PyPDFForm/lib/widgets/text.py
|
|
75
|
-
PyPDFForm/shared/__init__.py
|
|
76
|
-
PyPDFForm/shared/utils.py
|
|
77
69
|
tests/test_bulk_create_fields.py
|
|
78
70
|
tests/test_create_widget.py
|
|
79
71
|
tests/test_draw_elements.py
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
cryptography<49.0.0,>=48.0.0
|
|
2
|
-
fonttools<5.0.0,>=4.
|
|
2
|
+
fonttools<5.0.0,>=4.63.0
|
|
3
3
|
pikepdf<11.0.0,>=10.5.1
|
|
4
4
|
pillow<13.0.0,>=12.2.0
|
|
5
5
|
pypdf<7.0.0,>=6.11.0
|
|
6
|
-
reportlab<5.0.0,>=4.5.
|
|
6
|
+
reportlab<5.0.0,>=4.5.1
|
|
7
7
|
|
|
8
8
|
[cli]
|
|
9
9
|
typer<1.0.0,>=0.25.1
|
|
10
10
|
jsonschema<5.0.0,>=4.26.0
|
|
11
11
|
|
|
12
12
|
[dev]
|
|
13
|
-
black<27.0.0,>=26.
|
|
13
|
+
black<27.0.0,>=26.5.1
|
|
14
14
|
coverage<8.0.0,>=7.14.0
|
|
15
15
|
isort<9.0.0,>=8.0.1
|
|
16
16
|
mike<3.0.0,>=2.2.0
|
|
@@ -20,8 +20,5 @@ pudb<2026.0.0,>=2025.1.5
|
|
|
20
20
|
pylint<5.0.0,>=4.0.5
|
|
21
21
|
pyright<2.0.0,>=1.1.409
|
|
22
22
|
pytest<10.0.0,>=9.0.3
|
|
23
|
-
requests<3.0.0,>=2.34.
|
|
24
|
-
ruff<1.0.0,>=0.15.
|
|
25
|
-
|
|
26
|
-
[web_api]
|
|
27
|
-
fastapi[standard]<1.0.0,>=0.136.1
|
|
23
|
+
requests<3.0.0,>=2.34.2
|
|
24
|
+
ruff<1.0.0,>=0.15.13
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<p align="center"><img src="https://github.com/chinapandaman/PyPDFForm/raw/master/docs/img/logo.png"></p>
|
|
2
2
|
<p align="center">
|
|
3
|
-
<em>PDF Form Automation Simplified
|
|
3
|
+
<em>PDF Form Automation Simplified - Create, Inspect, Style, and Fill Forms in Python or from the Command Line.</em>
|
|
4
4
|
</p>
|
|
5
5
|
<p align="center">
|
|
6
6
|
<a href="https://pypi.org/project/PyPDFForm/"><img src="https://img.shields.io/pypi/v/pypdfform?label=version&color=magenta"></a>
|
|
@@ -13,26 +13,36 @@
|
|
|
13
13
|
|
|
14
14
|
## Introduction
|
|
15
15
|
|
|
16
|
-
PyPDFForm is a Python library for PDF
|
|
16
|
+
PyPDFForm is a Python library and command line tool for working with PDF forms. It provides Python APIs and CLI commands for creating, inspecting, updating, and filling forms, plus common PDF utilities.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
* Fill a PDF form by simply creating a Python dictionary.
|
|
20
|
-
* Create form fields on a PDF.
|
|
18
|
+
With PyPDFForm, you can:
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
* Create PDF forms, form fields, and raw elements.
|
|
21
|
+
* Inspect form fields, metadata, and values.
|
|
22
|
+
* Update field styling, behavior, and scripts.
|
|
23
|
+
* Fill PDF forms.
|
|
24
|
+
* Extract pages and merge PDFs.
|
|
25
|
+
|
|
26
|
+
The goal is to make PDF form work straightforward, whether you are handling one document or building a larger workflow.
|
|
23
27
|
|
|
24
28
|
## Installing
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
To use PyPDFForm as a Python library, install the base package with [pip](https://pypi.org/project/PyPDFForm/):
|
|
27
31
|
|
|
28
|
-
```shell
|
|
32
|
+
```shell
|
|
29
33
|
pip install PyPDFForm
|
|
30
34
|
```
|
|
31
35
|
|
|
36
|
+
To use the CLI, install PyPDFForm with the `cli` extra using [pipx](https://pipx.pypa.io/stable/):
|
|
37
|
+
|
|
38
|
+
```shell
|
|
39
|
+
pipx install "PyPDFForm[cli]"
|
|
40
|
+
```
|
|
41
|
+
|
|
32
42
|
## Quick Example
|
|
33
43
|

|
|
34
44
|
|
|
35
|
-
|
|
45
|
+
The GIF above shows the CLI filling a PDF form. To try the same workflow with the Python library, download the [sample PDF form](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_template.pdf) and run:
|
|
36
46
|
|
|
37
47
|
```python
|
|
38
48
|
from PyPDFForm import PdfWrapper
|
|
@@ -51,8 +61,7 @@ filled = PdfWrapper("sample_template.pdf", need_appearances=True).fill(
|
|
|
51
61
|
filled.write("output.pdf")
|
|
52
62
|
```
|
|
53
63
|
|
|
54
|
-
After running
|
|
55
|
-
and it should look like [this](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_filled.pdf).
|
|
64
|
+
After running this snippet, `output.pdf` will be written to the location you specified and should look like [this](https://chinapandaman.github.io/PyPDFForm/latest/pdfs/sample_filled.pdf).
|
|
56
65
|
|
|
57
66
|
## Documentation
|
|
58
67
|
|