PyPDFForm 1.4.12__py3-none-any.whl → 1.4.13__py3-none-any.whl
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 PyPDFForm might be problematic. Click here for more details.
- PyPDFForm/__init__.py +2 -2
- PyPDFForm/constants.py +6 -0
- PyPDFForm/filler.py +63 -3
- PyPDFForm/wrapper.py +36 -8
- {PyPDFForm-1.4.12.dist-info → PyPDFForm-1.4.13.dist-info}/METADATA +1 -1
- {PyPDFForm-1.4.12.dist-info → PyPDFForm-1.4.13.dist-info}/RECORD +9 -9
- {PyPDFForm-1.4.12.dist-info → PyPDFForm-1.4.13.dist-info}/WHEEL +1 -1
- {PyPDFForm-1.4.12.dist-info → PyPDFForm-1.4.13.dist-info}/LICENSE +0 -0
- {PyPDFForm-1.4.12.dist-info → PyPDFForm-1.4.13.dist-info}/top_level.txt +0 -0
PyPDFForm/__init__.py
CHANGED
PyPDFForm/constants.py
CHANGED
|
@@ -26,6 +26,7 @@ WIDGET_TYPES = Union[Text, Checkbox, Radio, Dropdown, Signature]
|
|
|
26
26
|
|
|
27
27
|
DEPRECATION_NOTICE = "{} will be deprecated soon. Use {} instead."
|
|
28
28
|
|
|
29
|
+
ANNOTATION_KEY = "/Annots"
|
|
29
30
|
ANNOTATION_FIELD_KEY = "/T"
|
|
30
31
|
ANNOTATION_RECTANGLE_KEY = "/Rect"
|
|
31
32
|
SUBTYPE_KEY = "/Subtype"
|
|
@@ -34,6 +35,8 @@ WIDGET_TYPE_KEY = "/FT"
|
|
|
34
35
|
PARENT_KEY = "/Parent"
|
|
35
36
|
FIELD_FLAG_KEY = "/Ff"
|
|
36
37
|
TEXT_FIELD_IDENTIFIER = "/Tx"
|
|
38
|
+
TEXT_VALUE_IDENTIFIER = "/V"
|
|
39
|
+
TEXT_VALUE_SHOW_UP_IDENTIFIER = "/AP"
|
|
37
40
|
SIGNATURE_FIELD_IDENTIFIER = "/Sig"
|
|
38
41
|
TEXT_FIELD_APPEARANCE_IDENTIFIER = "/DA"
|
|
39
42
|
SELECTABLE_IDENTIFIER = "/Btn"
|
|
@@ -43,6 +46,7 @@ CHOICE_FIELD_IDENTIFIER = "/Ch"
|
|
|
43
46
|
CHOICES_IDENTIFIER = "/Opt"
|
|
44
47
|
BUTTON_IDENTIFIER = "/MK"
|
|
45
48
|
BUTTON_STYLE_IDENTIFIER = "/CA"
|
|
49
|
+
SELECTED_IDENTIFIER = "/AS"
|
|
46
50
|
|
|
47
51
|
# Field flag bits
|
|
48
52
|
MULTILINE = 1 << 12
|
|
@@ -65,4 +69,6 @@ BUTTON_STYLES = {
|
|
|
65
69
|
"l": "\u25CF", # circle
|
|
66
70
|
}
|
|
67
71
|
|
|
72
|
+
CHECKBOX_SELECT = "/Yes"
|
|
73
|
+
|
|
68
74
|
COORDINATE_GRID_FONT_SIZE_MARGIN_RATIO = DEFAULT_FONT_SIZE / 100
|
PyPDFForm/filler.py
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""Contains helpers for filling a PDF form."""
|
|
3
3
|
|
|
4
|
-
from
|
|
4
|
+
from io import BytesIO
|
|
5
|
+
from typing import Dict, cast
|
|
5
6
|
|
|
6
|
-
from
|
|
7
|
+
from pypdf import PdfReader, PdfWriter
|
|
8
|
+
from pypdf.generic import DictionaryObject, NameObject, TextStringObject
|
|
9
|
+
|
|
10
|
+
from .constants import (ANNOTATION_KEY, CHECKBOX_SELECT, SELECTED_IDENTIFIER,
|
|
11
|
+
TEXT_VALUE_IDENTIFIER, TEXT_VALUE_SHOW_UP_IDENTIFIER,
|
|
12
|
+
WIDGET_TYPES)
|
|
7
13
|
from .coordinate import (get_draw_checkbox_radio_coordinates,
|
|
8
14
|
get_draw_sig_coordinates_resolutions,
|
|
9
15
|
get_draw_text_coordinates,
|
|
@@ -11,10 +17,12 @@ from .coordinate import (get_draw_checkbox_radio_coordinates,
|
|
|
11
17
|
from .font import checkbox_radio_font_size
|
|
12
18
|
from .image import any_image_to_jpg
|
|
13
19
|
from .middleware.checkbox import Checkbox
|
|
20
|
+
from .middleware.dropdown import Dropdown
|
|
14
21
|
from .middleware.radio import Radio
|
|
15
22
|
from .middleware.signature import Signature
|
|
23
|
+
from .middleware.text import Text
|
|
16
24
|
from .template import get_widget_key, get_widgets_by_page
|
|
17
|
-
from .utils import checkbox_radio_to_draw
|
|
25
|
+
from .utils import checkbox_radio_to_draw, stream_to_io
|
|
18
26
|
from .watermark import create_watermarks_and_draw, merge_watermarks_with_pdf
|
|
19
27
|
|
|
20
28
|
|
|
@@ -117,3 +125,55 @@ def fill(
|
|
|
117
125
|
result = merge_watermarks_with_pdf(result, image_watermarks)
|
|
118
126
|
|
|
119
127
|
return result
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def simple_fill(
|
|
131
|
+
template: bytes,
|
|
132
|
+
widgets: Dict[str, WIDGET_TYPES],
|
|
133
|
+
) -> bytes:
|
|
134
|
+
"""Fills a PDF form in place."""
|
|
135
|
+
|
|
136
|
+
pdf = PdfReader(stream_to_io(template))
|
|
137
|
+
out = PdfWriter()
|
|
138
|
+
out.append(pdf)
|
|
139
|
+
|
|
140
|
+
radio_button_tracker = {}
|
|
141
|
+
|
|
142
|
+
for page in out.pages:
|
|
143
|
+
for annot in page.get(ANNOTATION_KEY, []): # noqa
|
|
144
|
+
annot = cast(DictionaryObject, annot.get_object())
|
|
145
|
+
key = get_widget_key(annot.get_object())
|
|
146
|
+
|
|
147
|
+
widget = widgets.get(key)
|
|
148
|
+
if widget is None:
|
|
149
|
+
continue
|
|
150
|
+
|
|
151
|
+
if isinstance(widget, Checkbox) and widget.value is True:
|
|
152
|
+
annot[NameObject(SELECTED_IDENTIFIER)] = NameObject(CHECKBOX_SELECT)
|
|
153
|
+
elif isinstance(widget, Radio):
|
|
154
|
+
if key not in radio_button_tracker:
|
|
155
|
+
radio_button_tracker[key] = 0
|
|
156
|
+
radio_button_tracker[key] += 1
|
|
157
|
+
if widget.value == radio_button_tracker[key] - 1:
|
|
158
|
+
annot[NameObject(SELECTED_IDENTIFIER)] = NameObject(
|
|
159
|
+
f"/{widget.value}"
|
|
160
|
+
)
|
|
161
|
+
elif isinstance(widget, Dropdown) and widget.value is not None:
|
|
162
|
+
annot[NameObject(TEXT_VALUE_IDENTIFIER)] = TextStringObject(
|
|
163
|
+
widget.choices[widget.value]
|
|
164
|
+
)
|
|
165
|
+
annot[NameObject(TEXT_VALUE_SHOW_UP_IDENTIFIER)] = TextStringObject(
|
|
166
|
+
widget.choices[widget.value]
|
|
167
|
+
)
|
|
168
|
+
elif isinstance(widget, Text) and widget.value:
|
|
169
|
+
annot[NameObject(TEXT_VALUE_IDENTIFIER)] = TextStringObject(
|
|
170
|
+
widget.value
|
|
171
|
+
)
|
|
172
|
+
annot[NameObject(TEXT_VALUE_SHOW_UP_IDENTIFIER)] = TextStringObject(
|
|
173
|
+
widget.value
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
with BytesIO() as f:
|
|
177
|
+
out.write(f)
|
|
178
|
+
f.seek(0)
|
|
179
|
+
return f.read()
|
PyPDFForm/wrapper.py
CHANGED
|
@@ -11,7 +11,7 @@ from .constants import (DEFAULT_FONT, DEFAULT_FONT_COLOR, DEFAULT_FONT_SIZE,
|
|
|
11
11
|
DEPRECATION_NOTICE, VERSION_IDENTIFIER_PREFIX,
|
|
12
12
|
VERSION_IDENTIFIERS)
|
|
13
13
|
from .coordinate import generate_coordinate_grid
|
|
14
|
-
from .filler import fill
|
|
14
|
+
from .filler import fill, simple_fill
|
|
15
15
|
from .font import register_font
|
|
16
16
|
from .image import any_image_to_jpg, rotate_image
|
|
17
17
|
from .middleware.dropdown import Dropdown
|
|
@@ -26,7 +26,40 @@ from .widgets.checkbox import CheckBoxWidget
|
|
|
26
26
|
from .widgets.text import TextWidget
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
class
|
|
29
|
+
class FormWrapper:
|
|
30
|
+
"""A simple base wrapper for just filling a PDF form."""
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
template: Union[bytes, str, BinaryIO] = b"",
|
|
35
|
+
) -> None:
|
|
36
|
+
"""Constructs all attributes for the object."""
|
|
37
|
+
|
|
38
|
+
self.stream = fp_or_f_obj_or_stream_to_stream(template)
|
|
39
|
+
|
|
40
|
+
def read(self) -> bytes:
|
|
41
|
+
"""Reads the file stream of a PDF form."""
|
|
42
|
+
|
|
43
|
+
return self.stream
|
|
44
|
+
|
|
45
|
+
def fill(
|
|
46
|
+
self,
|
|
47
|
+
data: Dict[str, Union[str, bool, int]],
|
|
48
|
+
) -> FormWrapper:
|
|
49
|
+
"""Fills a PDF form."""
|
|
50
|
+
|
|
51
|
+
widgets = build_widgets(self.stream) if self.stream else {}
|
|
52
|
+
|
|
53
|
+
for key, value in data.items():
|
|
54
|
+
if key in widgets:
|
|
55
|
+
widgets[key].value = value
|
|
56
|
+
|
|
57
|
+
self.stream = simple_fill(self.read(), widgets)
|
|
58
|
+
|
|
59
|
+
return self
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class PdfWrapper(FormWrapper):
|
|
30
63
|
"""A class to represent a PDF form."""
|
|
31
64
|
|
|
32
65
|
def __init__(
|
|
@@ -36,7 +69,7 @@ class PdfWrapper:
|
|
|
36
69
|
) -> None:
|
|
37
70
|
"""Constructs all attributes for the object."""
|
|
38
71
|
|
|
39
|
-
|
|
72
|
+
super().__init__(template)
|
|
40
73
|
self.widgets = build_widgets(self.stream) if self.stream else {}
|
|
41
74
|
|
|
42
75
|
self.global_font = kwargs.get("global_font")
|
|
@@ -49,11 +82,6 @@ class PdfWrapper:
|
|
|
49
82
|
each.font_size = self.global_font_size
|
|
50
83
|
each.font_color = self.global_font_color
|
|
51
84
|
|
|
52
|
-
def read(self) -> bytes:
|
|
53
|
-
"""Reads the file stream of a PDF form."""
|
|
54
|
-
|
|
55
|
-
return self.stream
|
|
56
|
-
|
|
57
85
|
@property
|
|
58
86
|
def elements(self) -> dict:
|
|
59
87
|
"""ToDo: deprecate this."""
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
PyPDFForm/__init__.py,sha256=
|
|
1
|
+
PyPDFForm/__init__.py,sha256=KAGYHIP-vZnPpNmy2UPIQSULuxgByHXmJhj303FFmCg,149
|
|
2
2
|
PyPDFForm/adapter.py,sha256=OgAIwcmukpBqHFBLymd3I7wA7wIdipRqgURZA2Y0Hgo,885
|
|
3
|
-
PyPDFForm/constants.py,sha256=
|
|
3
|
+
PyPDFForm/constants.py,sha256=qxC6FN_K5kWD5XmwypeTyGLBG778geIGf2kHnHGcXAQ,1791
|
|
4
4
|
PyPDFForm/coordinate.py,sha256=EZxqeM3mkPSvhrsdOa-R2wPylmIECvUwMIlpigWRSbI,7854
|
|
5
|
-
PyPDFForm/filler.py,sha256=
|
|
5
|
+
PyPDFForm/filler.py,sha256=aVmzJZFW_XwX19KLbRWuDCBZ8ek2s8BapLydf44ZbxY,6707
|
|
6
6
|
PyPDFForm/font.py,sha256=iXsih_EJ9qe_penqakbQWuP44yUdxhWlQzlpZlMl3uw,4347
|
|
7
7
|
PyPDFForm/image.py,sha256=0GV8PFgY5oLJFHmhPD1fG-_5SBEO7jVLLtxCc_Uodfo,1143
|
|
8
8
|
PyPDFForm/patterns.py,sha256=LQRwSk7jImTYZFfN_DC38mCWFrPrXDgkYtu-yQLI7PA,2340
|
|
9
9
|
PyPDFForm/template.py,sha256=bvjrrIz6RZZl2h7MIjpI1g1FGD0mcabCjtseTvVUQTA,13176
|
|
10
10
|
PyPDFForm/utils.py,sha256=_gskLLNmwhfGF16gfMP00twVY6iYADYYAYWHMvKCDrg,4140
|
|
11
11
|
PyPDFForm/watermark.py,sha256=clYdRqCuWEE25IL-BUHnSo4HgLkHPSOl7FUJLhbAfGg,4755
|
|
12
|
-
PyPDFForm/wrapper.py,sha256=
|
|
12
|
+
PyPDFForm/wrapper.py,sha256=pXLY84cXuL4X81hvGdmcatp_GV07XXeLfGMdjOT2sx4,10232
|
|
13
13
|
PyPDFForm/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
PyPDFForm/middleware/base.py,sha256=TmoO8XpjFa5NerAumrAGm_kUt2eFP3DyyF-Vx0uXloM,724
|
|
15
15
|
PyPDFForm/middleware/checkbox.py,sha256=Z92awlKjceMd_ryb9Fhrtyd4fLkU84Ii6fSum60rHcA,1305
|
|
@@ -21,8 +21,8 @@ PyPDFForm/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
21
21
|
PyPDFForm/widgets/base.py,sha256=Stq-oQt-cfwQ6nilQ4NqpO5udFSKDNb1mAwryrWggZA,2076
|
|
22
22
|
PyPDFForm/widgets/checkbox.py,sha256=issx3onojq9plTHbNQwEnkbnhTo5vJKA5XSAoxRzQCg,264
|
|
23
23
|
PyPDFForm/widgets/text.py,sha256=lUVlfQ-ndemSelsKNzY6nS4Kuf_H4mDPxotFMQFV-so,484
|
|
24
|
-
PyPDFForm-1.4.
|
|
25
|
-
PyPDFForm-1.4.
|
|
26
|
-
PyPDFForm-1.4.
|
|
27
|
-
PyPDFForm-1.4.
|
|
28
|
-
PyPDFForm-1.4.
|
|
24
|
+
PyPDFForm-1.4.13.dist-info/LICENSE,sha256=43awmYkI6opyTpg19me731iO1WfXZwViqb67oWtCsFY,1065
|
|
25
|
+
PyPDFForm-1.4.13.dist-info/METADATA,sha256=1RfinIDEtIhuU7zhUfbvhAzp479KlQ0MH2GrLy7QxuA,5178
|
|
26
|
+
PyPDFForm-1.4.13.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
27
|
+
PyPDFForm-1.4.13.dist-info/top_level.txt,sha256=GQQKuWqPUjT9YZqwK95NlAQzxjwoQrsxQ8ureM8lWOY,10
|
|
28
|
+
PyPDFForm-1.4.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|