PyPDFForm 3.5.4__py3-none-any.whl → 3.6.0__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 +1 -1
- PyPDFForm/widgets/__init__.py +6 -0
- PyPDFForm/widgets/base.py +93 -29
- PyPDFForm/widgets/checkbox.py +32 -30
- PyPDFForm/widgets/dropdown.py +41 -39
- PyPDFForm/widgets/image.py +16 -16
- PyPDFForm/widgets/radio.py +29 -26
- PyPDFForm/widgets/signature.py +20 -20
- PyPDFForm/widgets/text.py +40 -38
- PyPDFForm/wrapper.py +89 -1
- {pypdfform-3.5.4.dist-info → pypdfform-3.6.0.dist-info}/METADATA +1 -1
- {pypdfform-3.5.4.dist-info → pypdfform-3.6.0.dist-info}/RECORD +15 -15
- {pypdfform-3.5.4.dist-info → pypdfform-3.6.0.dist-info}/WHEEL +0 -0
- {pypdfform-3.5.4.dist-info → pypdfform-3.6.0.dist-info}/licenses/LICENSE +0 -0
- {pypdfform-3.5.4.dist-info → pypdfform-3.6.0.dist-info}/top_level.txt +0 -0
PyPDFForm/__init__.py
CHANGED
|
@@ -20,7 +20,7 @@ The library supports various PDF form features, including:
|
|
|
20
20
|
PyPDFForm aims to simplify PDF form manipulation, making it accessible to developers of all skill levels.
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
__version__ = "3.
|
|
23
|
+
__version__ = "3.6.0"
|
|
24
24
|
|
|
25
25
|
from .middleware.text import Text # exposing for setting global font attrs
|
|
26
26
|
from .widgets import Fields
|
PyPDFForm/widgets/__init__.py
CHANGED
|
@@ -21,6 +21,12 @@ from .text import TextField
|
|
|
21
21
|
FieldTypes = Union[
|
|
22
22
|
TextField, CheckBoxField, RadioGroup, DropdownField, SignatureField, ImageField
|
|
23
23
|
]
|
|
24
|
+
BulkFieldTypes = Union[
|
|
25
|
+
TextField,
|
|
26
|
+
CheckBoxField,
|
|
27
|
+
RadioGroup,
|
|
28
|
+
DropdownField,
|
|
29
|
+
]
|
|
24
30
|
|
|
25
31
|
|
|
26
32
|
@dataclass
|
PyPDFForm/widgets/base.py
CHANGED
|
@@ -12,6 +12,8 @@ Classes:
|
|
|
12
12
|
functionality for rendering and manipulation.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from dataclasses import dataclass
|
|
16
18
|
from inspect import signature
|
|
17
19
|
from io import BytesIO
|
|
@@ -25,35 +27,6 @@ from ..constants import fieldFlags, required
|
|
|
25
27
|
from ..utils import stream_to_io
|
|
26
28
|
|
|
27
29
|
|
|
28
|
-
@dataclass
|
|
29
|
-
class Field:
|
|
30
|
-
"""
|
|
31
|
-
Base dataclass for all PDF form fields.
|
|
32
|
-
|
|
33
|
-
This class defines the common properties that all types of form fields
|
|
34
|
-
(e.g., text fields, checkboxes, radio buttons) share. Specific field types
|
|
35
|
-
will extend this class to add their unique attributes.
|
|
36
|
-
|
|
37
|
-
Attributes:
|
|
38
|
-
name (str): The name of the form field. This is used to identify the
|
|
39
|
-
field within the PDF document.
|
|
40
|
-
page_number (int): The 1-based page number on which the field is located.
|
|
41
|
-
x (float): The x-coordinate of the field's position on the page.
|
|
42
|
-
y (float): The y-coordinate of the field's position on the page.
|
|
43
|
-
required (Optional[bool]): Indicates whether the field is required to be
|
|
44
|
-
filled by the user. Defaults to None, meaning not explicitly set.
|
|
45
|
-
tooltip (Optional[str]): A tooltip message that appears when the user
|
|
46
|
-
hovers over the field. Defaults to None.
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
name: str
|
|
50
|
-
page_number: int
|
|
51
|
-
x: float
|
|
52
|
-
y: float
|
|
53
|
-
required: Optional[bool] = None
|
|
54
|
-
tooltip: Optional[str] = None
|
|
55
|
-
|
|
56
|
-
|
|
57
30
|
class Widget:
|
|
58
31
|
"""
|
|
59
32
|
Base class for all widgets in PyPDFForm.
|
|
@@ -219,3 +192,94 @@ class Widget:
|
|
|
219
192
|
watermark.read() if i == self.page_number - 1 else b""
|
|
220
193
|
for i in range(page_count)
|
|
221
194
|
]
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def bulk_watermarks(widgets: List[Widget], stream: bytes) -> List[bytes]:
|
|
198
|
+
"""
|
|
199
|
+
Generates watermarks for multiple widgets in bulk.
|
|
200
|
+
|
|
201
|
+
This static method processes a list of widgets and a PDF stream to create
|
|
202
|
+
a list of watermark streams, one for each page of the PDF. Widgets are
|
|
203
|
+
grouped by their page number, and all widgets for a given page are drawn
|
|
204
|
+
onto a single ReportLab canvas, which is then returned as the watermark
|
|
205
|
+
stream for that page. This is more efficient than generating watermarks
|
|
206
|
+
for each widget individually.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
widgets (List[Widget]): A list of Widget objects to be watermarked.
|
|
210
|
+
stream (bytes): The PDF stream to be watermarked.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
List[bytes]: A list of watermark streams (bytes), where the index
|
|
214
|
+
corresponds to the 0-based page index of the original PDF.
|
|
215
|
+
Each element is a byte stream representing the combined
|
|
216
|
+
watermark for that page. Pages without any widgets will
|
|
217
|
+
have an empty byte string (b"").
|
|
218
|
+
"""
|
|
219
|
+
result = []
|
|
220
|
+
|
|
221
|
+
pdf = PdfReader(stream_to_io(stream))
|
|
222
|
+
watermark = BytesIO()
|
|
223
|
+
|
|
224
|
+
widgets_by_page = {}
|
|
225
|
+
for widget in widgets:
|
|
226
|
+
if widget.page_number not in widgets_by_page:
|
|
227
|
+
widgets_by_page[widget.page_number] = []
|
|
228
|
+
widgets_by_page[widget.page_number].append(widget)
|
|
229
|
+
|
|
230
|
+
for i, page in enumerate(pdf.pages):
|
|
231
|
+
page_num = i + 1
|
|
232
|
+
if page_num not in widgets_by_page:
|
|
233
|
+
result.append(b"")
|
|
234
|
+
continue
|
|
235
|
+
|
|
236
|
+
watermark.seek(0)
|
|
237
|
+
watermark.flush()
|
|
238
|
+
|
|
239
|
+
canvas = Canvas(
|
|
240
|
+
watermark,
|
|
241
|
+
pagesize=(
|
|
242
|
+
float(page.mediabox[2]),
|
|
243
|
+
float(page.mediabox[3]),
|
|
244
|
+
),
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
for widget in widgets_by_page[page_num]:
|
|
248
|
+
getattr(widget, "_required_handler")(canvas)
|
|
249
|
+
widget.canvas_operations(canvas)
|
|
250
|
+
|
|
251
|
+
canvas.showPage()
|
|
252
|
+
canvas.save()
|
|
253
|
+
watermark.seek(0)
|
|
254
|
+
result.append(watermark.read())
|
|
255
|
+
|
|
256
|
+
return result
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@dataclass
|
|
260
|
+
class Field:
|
|
261
|
+
"""
|
|
262
|
+
Base dataclass for all PDF form fields.
|
|
263
|
+
|
|
264
|
+
This class defines the common properties that all types of form fields
|
|
265
|
+
(e.g., text fields, checkboxes, radio buttons) share. Specific field types
|
|
266
|
+
will extend this class to add their unique attributes.
|
|
267
|
+
|
|
268
|
+
Attributes:
|
|
269
|
+
name (str): The name of the form field. This is used to identify the
|
|
270
|
+
field within the PDF document.
|
|
271
|
+
page_number (int): The 1-based page number on which the field is located.
|
|
272
|
+
x (float): The x-coordinate of the field's position on the page.
|
|
273
|
+
y (float): The y-coordinate of the field's position on the page.
|
|
274
|
+
required (Optional[bool]): Indicates whether the field is required to be
|
|
275
|
+
filled by the user. Defaults to None, meaning not explicitly set.
|
|
276
|
+
tooltip (Optional[str]): A tooltip message that appears when the user
|
|
277
|
+
hovers over the field. Defaults to None.
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
name: str
|
|
281
|
+
page_number: int
|
|
282
|
+
x: float
|
|
283
|
+
y: float
|
|
284
|
+
required: Optional[bool] = None
|
|
285
|
+
tooltip: Optional[str] = None
|
PyPDFForm/widgets/checkbox.py
CHANGED
|
@@ -11,40 +11,11 @@ functionality for interacting with checkbox form fields in PDFs.
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from dataclasses import dataclass
|
|
14
|
-
from typing import Optional, Tuple
|
|
14
|
+
from typing import Optional, Tuple, Type
|
|
15
15
|
|
|
16
16
|
from .base import Field, Widget
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
@dataclass
|
|
20
|
-
class CheckBoxField(Field):
|
|
21
|
-
"""
|
|
22
|
-
Represents a checkbox field in a PDF document.
|
|
23
|
-
|
|
24
|
-
This dataclass extends the `Field` base class and defines the specific
|
|
25
|
-
attributes that can be configured for a checkbox field.
|
|
26
|
-
|
|
27
|
-
Attributes:
|
|
28
|
-
_field_type (str): The type of the field, fixed as "checkbox".
|
|
29
|
-
size (Optional[float]): The size of the checkbox.
|
|
30
|
-
button_style (Optional[str]): The visual style of the checkbox button
|
|
31
|
-
(e.g., "check", "circle", "cross").
|
|
32
|
-
tick_color (Optional[Tuple[float, ...]]): The color of the checkmark or tick.
|
|
33
|
-
bg_color (Optional[Tuple[float, ...]]): The background color of the checkbox.
|
|
34
|
-
border_color (Optional[Tuple[float, ...]]): The color of the checkbox's border.
|
|
35
|
-
border_width (Optional[float]): The width of the checkbox's border.
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
_field_type: str = "checkbox"
|
|
39
|
-
|
|
40
|
-
size: Optional[float] = None
|
|
41
|
-
button_style: Optional[str] = None
|
|
42
|
-
tick_color: Optional[Tuple[float, ...]] = None
|
|
43
|
-
bg_color: Optional[Tuple[float, ...]] = None
|
|
44
|
-
border_color: Optional[Tuple[float, ...]] = None
|
|
45
|
-
border_width: Optional[float] = None
|
|
46
|
-
|
|
47
|
-
|
|
48
19
|
class CheckBoxWidget(Widget):
|
|
49
20
|
"""
|
|
50
21
|
Represents a checkbox widget in a PDF form.
|
|
@@ -74,3 +45,34 @@ class CheckBoxWidget(Widget):
|
|
|
74
45
|
COLOR_PARAMS = ["tick_color", "bg_color", "border_color"]
|
|
75
46
|
ALLOWED_HOOK_PARAMS = ["size"]
|
|
76
47
|
ACRO_FORM_FUNC = "checkbox"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class CheckBoxField(Field):
|
|
52
|
+
"""
|
|
53
|
+
Represents a checkbox field in a PDF document.
|
|
54
|
+
|
|
55
|
+
This dataclass extends the `Field` base class and defines the specific
|
|
56
|
+
attributes that can be configured for a checkbox field.
|
|
57
|
+
|
|
58
|
+
Attributes:
|
|
59
|
+
_field_type (str): The type of the field, fixed as "checkbox".
|
|
60
|
+
_widget_class (Type[Widget]): The widget class associated with this field type.
|
|
61
|
+
size (Optional[float]): The size of the checkbox.
|
|
62
|
+
button_style (Optional[str]): The visual style of the checkbox button
|
|
63
|
+
(e.g., "check", "circle", "cross").
|
|
64
|
+
tick_color (Optional[Tuple[float, ...]]): The color of the checkmark or tick.
|
|
65
|
+
bg_color (Optional[Tuple[float, ...]]): The background color of the checkbox.
|
|
66
|
+
border_color (Optional[Tuple[float, ...]]): The color of the checkbox's border.
|
|
67
|
+
border_width (Optional[float]): The width of the checkbox's border.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
_field_type: str = "checkbox"
|
|
71
|
+
_widget_class: Type[Widget] = CheckBoxWidget
|
|
72
|
+
|
|
73
|
+
size: Optional[float] = None
|
|
74
|
+
button_style: Optional[str] = None
|
|
75
|
+
tick_color: Optional[Tuple[float, ...]] = None
|
|
76
|
+
bg_color: Optional[Tuple[float, ...]] = None
|
|
77
|
+
border_color: Optional[Tuple[float, ...]] = None
|
|
78
|
+
border_width: Optional[float] = None
|
PyPDFForm/widgets/dropdown.py
CHANGED
|
@@ -11,49 +11,12 @@ specific functionality for interacting with dropdown form fields in PDFs.
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from dataclasses import dataclass
|
|
14
|
-
from typing import List, Optional, Tuple, Union
|
|
14
|
+
from typing import List, Optional, Tuple, Type, Union
|
|
15
15
|
|
|
16
|
-
from .base import Field
|
|
16
|
+
from .base import Field, Widget
|
|
17
17
|
from .text import TextWidget
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
@dataclass
|
|
21
|
-
class DropdownField(Field):
|
|
22
|
-
"""
|
|
23
|
-
Represents a dropdown field in a PDF document.
|
|
24
|
-
|
|
25
|
-
This dataclass extends the `Field` base class and defines the specific
|
|
26
|
-
attributes that can be configured for a dropdown selection field.
|
|
27
|
-
|
|
28
|
-
Attributes:
|
|
29
|
-
_field_type (str): The type of the field, fixed as "dropdown".
|
|
30
|
-
options (Optional[List[Union[str, Tuple[str, str]]]]): A list of options
|
|
31
|
-
available in the dropdown. Each option can be a string (display value)
|
|
32
|
-
or a tuple of strings (display value, export value).
|
|
33
|
-
width (Optional[float]): The width of the dropdown field.
|
|
34
|
-
height (Optional[float]): The height of the dropdown field.
|
|
35
|
-
font (Optional[str]): The font to use for the dropdown text.
|
|
36
|
-
font_size (Optional[float]): The font size for the dropdown text.
|
|
37
|
-
font_color (Optional[Tuple[float, ...]]): The color of the font as an RGB or RGBA tuple.
|
|
38
|
-
bg_color (Optional[Tuple[float, ...]]): The background color of the dropdown field.
|
|
39
|
-
border_color (Optional[Tuple[float, ...]]): The color of the dropdown's border.
|
|
40
|
-
border_width (Optional[float]): The width of the dropdown's border.
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
_field_type: str = "dropdown"
|
|
44
|
-
|
|
45
|
-
options: Optional[List[Union[str, Tuple[str, str]]]] = None
|
|
46
|
-
width: Optional[float] = None
|
|
47
|
-
height: Optional[float] = None
|
|
48
|
-
# pylint: disable=R0801
|
|
49
|
-
font: Optional[str] = None
|
|
50
|
-
font_size: Optional[float] = None
|
|
51
|
-
font_color: Optional[Tuple[float, ...]] = None
|
|
52
|
-
bg_color: Optional[Tuple[float, ...]] = None
|
|
53
|
-
border_color: Optional[Tuple[float, ...]] = None
|
|
54
|
-
border_width: Optional[float] = None
|
|
55
|
-
|
|
56
|
-
|
|
57
20
|
class DropdownWidget(TextWidget):
|
|
58
21
|
"""
|
|
59
22
|
Represents a dropdown widget in a PDF form.
|
|
@@ -94,3 +57,42 @@ class DropdownWidget(TextWidget):
|
|
|
94
57
|
super().__init__(name, page_number, x, y, **kwargs)
|
|
95
58
|
self.acro_form_params["wkind"] = "choice"
|
|
96
59
|
self.acro_form_params["value"] = self.acro_form_params["options"][0]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class DropdownField(Field):
|
|
64
|
+
"""
|
|
65
|
+
Represents a dropdown field in a PDF document.
|
|
66
|
+
|
|
67
|
+
This dataclass extends the `Field` base class and defines the specific
|
|
68
|
+
attributes that can be configured for a dropdown selection field.
|
|
69
|
+
|
|
70
|
+
Attributes:
|
|
71
|
+
_field_type (str): The type of the field, fixed as "dropdown".
|
|
72
|
+
_widget_class (Type[Widget]): The widget class associated with this field type.
|
|
73
|
+
options (Optional[List[Union[str, Tuple[str, str]]]]): A list of options
|
|
74
|
+
available in the dropdown. Each option can be a string (display value)
|
|
75
|
+
or a tuple of strings (display value, export value).
|
|
76
|
+
width (Optional[float]): The width of the dropdown field.
|
|
77
|
+
height (Optional[float]): The height of the dropdown field.
|
|
78
|
+
font (Optional[str]): The font to use for the dropdown text.
|
|
79
|
+
font_size (Optional[float]): The font size for the dropdown text.
|
|
80
|
+
font_color (Optional[Tuple[float, ...]]): The color of the font as an RGB or RGBA tuple.
|
|
81
|
+
bg_color (Optional[Tuple[float, ...]]): The background color of the dropdown field.
|
|
82
|
+
border_color (Optional[Tuple[float, ...]]): The color of the dropdown's border.
|
|
83
|
+
border_width (Optional[float]): The width of the dropdown's border.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
_field_type: str = "dropdown"
|
|
87
|
+
_widget_class: Type[Widget] = DropdownWidget
|
|
88
|
+
|
|
89
|
+
options: Optional[List[Union[str, Tuple[str, str]]]] = None
|
|
90
|
+
width: Optional[float] = None
|
|
91
|
+
height: Optional[float] = None
|
|
92
|
+
# pylint: disable=R0801
|
|
93
|
+
font: Optional[str] = None
|
|
94
|
+
font_size: Optional[float] = None
|
|
95
|
+
font_color: Optional[Tuple[float, ...]] = None
|
|
96
|
+
bg_color: Optional[Tuple[float, ...]] = None
|
|
97
|
+
border_color: Optional[Tuple[float, ...]] = None
|
|
98
|
+
border_width: Optional[float] = None
|
PyPDFForm/widgets/image.py
CHANGED
|
@@ -16,22 +16,6 @@ from dataclasses import dataclass
|
|
|
16
16
|
from .signature import SignatureField, SignatureWidget
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
@dataclass
|
|
20
|
-
class ImageField(SignatureField):
|
|
21
|
-
"""
|
|
22
|
-
Represents an image field in a PDF document.
|
|
23
|
-
|
|
24
|
-
This dataclass extends the `SignatureField` base class and defines the
|
|
25
|
-
specific attributes for an image input field. It inherits `width` and
|
|
26
|
-
`height` from `SignatureField` as images also have dimensions.
|
|
27
|
-
|
|
28
|
-
Attributes:
|
|
29
|
-
_field_type (str): The type of the field, fixed as "image".
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
|
-
_field_type: str = "image"
|
|
33
|
-
|
|
34
|
-
|
|
35
19
|
class ImageWidget(SignatureWidget):
|
|
36
20
|
"""
|
|
37
21
|
Represents an image widget in a PDF form.
|
|
@@ -47,3 +31,19 @@ class ImageWidget(SignatureWidget):
|
|
|
47
31
|
"""
|
|
48
32
|
|
|
49
33
|
BEDROCK_WIDGET_TO_COPY = "image"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class ImageField(SignatureField):
|
|
38
|
+
"""
|
|
39
|
+
Represents an image field in a PDF document.
|
|
40
|
+
|
|
41
|
+
This dataclass extends the `SignatureField` base class and defines the
|
|
42
|
+
specific attributes for an image input field. It inherits `width` and
|
|
43
|
+
`height` from `SignatureField` as images also have dimensions.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
_field_type (str): The type of the field, fixed as "image".
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
_field_type: str = "image"
|
PyPDFForm/widgets/radio.py
CHANGED
|
@@ -11,38 +11,14 @@ specific functionality for interacting with radio button form fields in PDFs.
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from dataclasses import dataclass
|
|
14
|
-
from typing import List, Optional
|
|
14
|
+
from typing import List, Optional, Type
|
|
15
15
|
|
|
16
16
|
from reportlab.pdfgen.canvas import Canvas
|
|
17
17
|
|
|
18
|
+
from .base import Widget
|
|
18
19
|
from .checkbox import CheckBoxField, CheckBoxWidget
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
@dataclass
|
|
22
|
-
class RadioGroup(CheckBoxField):
|
|
23
|
-
"""
|
|
24
|
-
Represents a group of radio buttons in a PDF document.
|
|
25
|
-
|
|
26
|
-
This dataclass extends the `CheckBoxField` base class and defines the specific
|
|
27
|
-
attributes that can be configured for a radio button group. Unlike a single
|
|
28
|
-
checkbox, a radio group allows for multiple positions (x, y coordinates)
|
|
29
|
-
where individual radio buttons can be placed, but only one can be selected.
|
|
30
|
-
|
|
31
|
-
Attributes:
|
|
32
|
-
_field_type (str): The type of the field, fixed as "radio".
|
|
33
|
-
x (List[float]): A list of x-coordinates for each radio button in the group.
|
|
34
|
-
y (List[float]): A list of y-coordinates for each radio button in the group.
|
|
35
|
-
shape (Optional[str]): The shape of the radio button. Valid values are
|
|
36
|
-
"circle" or "square". Defaults to None, which typically means a default circle shape.
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
_field_type: str = "radio"
|
|
40
|
-
|
|
41
|
-
x: List[float]
|
|
42
|
-
y: List[float]
|
|
43
|
-
shape: Optional[str] = None
|
|
44
|
-
|
|
45
|
-
|
|
46
22
|
class RadioWidget(CheckBoxWidget):
|
|
47
23
|
"""
|
|
48
24
|
Represents a radio button widget in a PDF form.
|
|
@@ -97,3 +73,30 @@ class RadioWidget(CheckBoxWidget):
|
|
|
97
73
|
new_acro_form_params["y"] = y
|
|
98
74
|
new_acro_form_params["value"] = str(i)
|
|
99
75
|
getattr(canvas.acroForm, self.ACRO_FORM_FUNC)(**new_acro_form_params)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass
|
|
79
|
+
class RadioGroup(CheckBoxField):
|
|
80
|
+
"""
|
|
81
|
+
Represents a group of radio buttons in a PDF document.
|
|
82
|
+
|
|
83
|
+
This dataclass extends the `CheckBoxField` base class and defines the specific
|
|
84
|
+
attributes that can be configured for a radio button group. Unlike a single
|
|
85
|
+
checkbox, a radio group allows for multiple positions (x, y coordinates)
|
|
86
|
+
where individual radio buttons can be placed, but only one can be selected.
|
|
87
|
+
|
|
88
|
+
Attributes:
|
|
89
|
+
_field_type (str): The type of the field, fixed as "radio".
|
|
90
|
+
_widget_class (Type[Widget]): The widget class associated with this field type.
|
|
91
|
+
x (List[float]): A list of x-coordinates for each radio button in the group.
|
|
92
|
+
y (List[float]): A list of y-coordinates for each radio button in the group.
|
|
93
|
+
shape (Optional[str]): The shape of the radio button. Valid values are
|
|
94
|
+
"circle" or "square". Defaults to None, which typically means a default circle shape.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
_field_type: str = "radio"
|
|
98
|
+
_widget_class: Type[Widget] = RadioWidget
|
|
99
|
+
|
|
100
|
+
x: List[float]
|
|
101
|
+
y: List[float]
|
|
102
|
+
shape: Optional[str] = None
|
PyPDFForm/widgets/signature.py
CHANGED
|
@@ -26,26 +26,6 @@ from .base import Field
|
|
|
26
26
|
from .bedrock import BEDROCK_PDF
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
@dataclass
|
|
30
|
-
class SignatureField(Field):
|
|
31
|
-
"""
|
|
32
|
-
Represents a signature field in a PDF document.
|
|
33
|
-
|
|
34
|
-
This dataclass extends the `Field` base class and defines the specific
|
|
35
|
-
attributes that can be configured for a signature input field.
|
|
36
|
-
|
|
37
|
-
Attributes:
|
|
38
|
-
_field_type (str): The type of the field, fixed as "signature".
|
|
39
|
-
width (Optional[float]): The width of the signature field.
|
|
40
|
-
height (Optional[float]): The height of the signature field.
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
_field_type: str = "signature"
|
|
44
|
-
|
|
45
|
-
width: Optional[float] = None
|
|
46
|
-
height: Optional[float] = None
|
|
47
|
-
|
|
48
|
-
|
|
49
29
|
class SignatureWidget:
|
|
50
30
|
"""
|
|
51
31
|
Represents a signature widget in a PDF form.
|
|
@@ -151,3 +131,23 @@ class SignatureWidget:
|
|
|
151
131
|
f.read() if i == self.page_number - 1 else b""
|
|
152
132
|
for i in range(page_count)
|
|
153
133
|
]
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@dataclass
|
|
137
|
+
class SignatureField(Field):
|
|
138
|
+
"""
|
|
139
|
+
Represents a signature field in a PDF document.
|
|
140
|
+
|
|
141
|
+
This dataclass extends the `Field` base class and defines the specific
|
|
142
|
+
attributes that can be configured for a signature input field.
|
|
143
|
+
|
|
144
|
+
Attributes:
|
|
145
|
+
_field_type (str): The type of the field, fixed as "signature".
|
|
146
|
+
width (Optional[float]): The width of the signature field.
|
|
147
|
+
height (Optional[float]): The height of the signature field.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
_field_type: str = "signature"
|
|
151
|
+
|
|
152
|
+
width: Optional[float] = None
|
|
153
|
+
height: Optional[float] = None
|
PyPDFForm/widgets/text.py
CHANGED
|
@@ -11,11 +11,48 @@ functionality for interacting with text form fields in PDFs.
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from dataclasses import dataclass
|
|
14
|
-
from typing import Optional, Tuple
|
|
14
|
+
from typing import Optional, Tuple, Type
|
|
15
15
|
|
|
16
16
|
from .base import Field, Widget
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
class TextWidget(Widget):
|
|
20
|
+
"""
|
|
21
|
+
Represents a text widget in a PDF form.
|
|
22
|
+
|
|
23
|
+
This class inherits from the base Widget class and provides specific
|
|
24
|
+
parameters for text field styling, such as width, height, font size,
|
|
25
|
+
font color, background color, border color, border width, and maximum
|
|
26
|
+
length.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
USER_PARAMS (list): A list of tuples, where each tuple contains the
|
|
30
|
+
user-facing parameter name and the corresponding AcroForm parameter name.
|
|
31
|
+
COLOR_PARAMS (list): A list of user-facing parameter names that represent colors.
|
|
32
|
+
ALLOWED_HOOK_PARAMS (list): A list of allowed hook parameters.
|
|
33
|
+
NONE_DEFAULTS (list): A list of parameters that default to None.
|
|
34
|
+
ACRO_FORM_FUNC (str): The name of the AcroForm function to use for
|
|
35
|
+
creating the text field.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
USER_PARAMS = [
|
|
39
|
+
("required", "required"),
|
|
40
|
+
("tooltip", "tooltip"),
|
|
41
|
+
("width", "width"),
|
|
42
|
+
("height", "height"),
|
|
43
|
+
("font_size", "fontSize"),
|
|
44
|
+
("font_color", "textColor"),
|
|
45
|
+
("bg_color", "fillColor"),
|
|
46
|
+
("border_color", "borderColor"),
|
|
47
|
+
("border_width", "borderWidth"),
|
|
48
|
+
("max_length", "maxlen"),
|
|
49
|
+
]
|
|
50
|
+
COLOR_PARAMS = ["font_color", "bg_color", "border_color"]
|
|
51
|
+
ALLOWED_HOOK_PARAMS = ["alignment", "multiline", "comb", "font"]
|
|
52
|
+
NONE_DEFAULTS = ["max_length"]
|
|
53
|
+
ACRO_FORM_FUNC = "textfield"
|
|
54
|
+
|
|
55
|
+
|
|
19
56
|
@dataclass
|
|
20
57
|
class TextField(Field):
|
|
21
58
|
"""
|
|
@@ -26,6 +63,7 @@ class TextField(Field):
|
|
|
26
63
|
|
|
27
64
|
Attributes:
|
|
28
65
|
_field_type (str): The type of the field, fixed as "text".
|
|
66
|
+
_widget_class (Type[Widget]): The widget class associated with this field type.
|
|
29
67
|
width (Optional[float]): The width of the text field.
|
|
30
68
|
height (Optional[float]): The height of the text field.
|
|
31
69
|
max_length (Optional[int]): The maximum number of characters allowed in the text field.
|
|
@@ -42,6 +80,7 @@ class TextField(Field):
|
|
|
42
80
|
"""
|
|
43
81
|
|
|
44
82
|
_field_type: str = "text"
|
|
83
|
+
_widget_class: Type[Widget] = TextWidget
|
|
45
84
|
|
|
46
85
|
width: Optional[float] = None
|
|
47
86
|
height: Optional[float] = None
|
|
@@ -55,40 +94,3 @@ class TextField(Field):
|
|
|
55
94
|
border_width: Optional[float] = None
|
|
56
95
|
alignment: Optional[int] = None
|
|
57
96
|
multiline: Optional[bool] = None
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
class TextWidget(Widget):
|
|
61
|
-
"""
|
|
62
|
-
Represents a text widget in a PDF form.
|
|
63
|
-
|
|
64
|
-
This class inherits from the base Widget class and provides specific
|
|
65
|
-
parameters for text field styling, such as width, height, font size,
|
|
66
|
-
font color, background color, border color, border width, and maximum
|
|
67
|
-
length.
|
|
68
|
-
|
|
69
|
-
Attributes:
|
|
70
|
-
USER_PARAMS (list): A list of tuples, where each tuple contains the
|
|
71
|
-
user-facing parameter name and the corresponding AcroForm parameter name.
|
|
72
|
-
COLOR_PARAMS (list): A list of user-facing parameter names that represent colors.
|
|
73
|
-
ALLOWED_HOOK_PARAMS (list): A list of allowed hook parameters.
|
|
74
|
-
NONE_DEFAULTS (list): A list of parameters that default to None.
|
|
75
|
-
ACRO_FORM_FUNC (str): The name of the AcroForm function to use for
|
|
76
|
-
creating the text field.
|
|
77
|
-
"""
|
|
78
|
-
|
|
79
|
-
USER_PARAMS = [
|
|
80
|
-
("required", "required"),
|
|
81
|
-
("tooltip", "tooltip"),
|
|
82
|
-
("width", "width"),
|
|
83
|
-
("height", "height"),
|
|
84
|
-
("font_size", "fontSize"),
|
|
85
|
-
("font_color", "textColor"),
|
|
86
|
-
("bg_color", "fillColor"),
|
|
87
|
-
("border_color", "borderColor"),
|
|
88
|
-
("border_width", "borderWidth"),
|
|
89
|
-
("max_length", "maxlen"),
|
|
90
|
-
]
|
|
91
|
-
COLOR_PARAMS = ["font_color", "bg_color", "border_color"]
|
|
92
|
-
ALLOWED_HOOK_PARAMS = ["alignment", "multiline", "comb", "font"]
|
|
93
|
-
NONE_DEFAULTS = ["max_length"]
|
|
94
|
-
ACRO_FORM_FUNC = "textfield"
|
PyPDFForm/wrapper.py
CHANGED
|
@@ -18,6 +18,7 @@ underlying PDF manipulation.
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
+
from collections import defaultdict
|
|
21
22
|
from dataclasses import asdict
|
|
22
23
|
from functools import cached_property
|
|
23
24
|
from typing import TYPE_CHECKING, BinaryIO, Dict, List, Sequence, Tuple, Union
|
|
@@ -41,6 +42,8 @@ from .utils import (enable_adobe_mode, generate_unique_suffix,
|
|
|
41
42
|
get_page_streams, merge_two_pdfs, remove_all_widgets)
|
|
42
43
|
from .watermark import (copy_watermark_widgets, create_watermarks_and_draw,
|
|
43
44
|
merge_watermarks_with_pdf)
|
|
45
|
+
from .widgets import CheckBoxField
|
|
46
|
+
from .widgets.base import Widget
|
|
44
47
|
from .widgets.checkbox import CheckBoxWidget
|
|
45
48
|
from .widgets.dropdown import DropdownWidget
|
|
46
49
|
from .widgets.image import ImageWidget
|
|
@@ -49,7 +52,7 @@ from .widgets.signature import SignatureWidget
|
|
|
49
52
|
from .widgets.text import TextWidget
|
|
50
53
|
|
|
51
54
|
if TYPE_CHECKING:
|
|
52
|
-
from .widgets import FieldTypes
|
|
55
|
+
from .widgets import BulkFieldTypes, FieldTypes
|
|
53
56
|
|
|
54
57
|
|
|
55
58
|
class PdfWrapper:
|
|
@@ -451,6 +454,91 @@ class PdfWrapper:
|
|
|
451
454
|
|
|
452
455
|
return self
|
|
453
456
|
|
|
457
|
+
def bulk_create_fields(self, fields: List[BulkFieldTypes]) -> PdfWrapper:
|
|
458
|
+
"""
|
|
459
|
+
Creates multiple new form fields (widgets) on the PDF in a single operation.
|
|
460
|
+
|
|
461
|
+
This method takes a list of field definition objects (`BulkFieldTypes`),
|
|
462
|
+
groups them by type (if necessary for specific widget handling, like CheckBoxField),
|
|
463
|
+
and then delegates the creation to the internal `_bulk_create_fields` method.
|
|
464
|
+
This is the preferred method for creating multiple fields as it minimizes
|
|
465
|
+
PDF manipulation overhead.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
fields (List[BulkFieldTypes]): A list of field definition objects
|
|
469
|
+
(e.g., `TextField`, `CheckBoxField`, etc.) to be created.
|
|
470
|
+
|
|
471
|
+
Returns:
|
|
472
|
+
PdfWrapper: The `PdfWrapper` object, allowing for method chaining.
|
|
473
|
+
"""
|
|
474
|
+
|
|
475
|
+
needs_separate_creation = [CheckBoxField]
|
|
476
|
+
needs_separate_creation_dict = defaultdict(list)
|
|
477
|
+
general_creation = []
|
|
478
|
+
|
|
479
|
+
for each in fields:
|
|
480
|
+
if type(each) in needs_separate_creation:
|
|
481
|
+
needs_separate_creation_dict[type(each)].append(each)
|
|
482
|
+
else:
|
|
483
|
+
general_creation.append(each)
|
|
484
|
+
|
|
485
|
+
for each in needs_separate_creation_dict.values():
|
|
486
|
+
self._bulk_create_fields(each)
|
|
487
|
+
self._bulk_create_fields(general_creation)
|
|
488
|
+
|
|
489
|
+
return self
|
|
490
|
+
|
|
491
|
+
def _bulk_create_fields(self, fields: List[BulkFieldTypes]) -> PdfWrapper:
|
|
492
|
+
"""
|
|
493
|
+
Internal method to create multiple new form fields (widgets) on the PDF in a single operation.
|
|
494
|
+
|
|
495
|
+
This method takes a list of field definition objects (`BulkFieldTypes`),
|
|
496
|
+
converts them into `Widget` objects, and efficiently draws them onto the
|
|
497
|
+
PDF using bulk watermarking. It is designed to be called by the public
|
|
498
|
+
`bulk_create_fields` method after fields have been grouped for creation.
|
|
499
|
+
|
|
500
|
+
Args:
|
|
501
|
+
fields (List[BulkFieldTypes]): A list of field definition objects
|
|
502
|
+
(e.g., `TextField`, `CheckBoxField`, etc.) to be created.
|
|
503
|
+
|
|
504
|
+
Returns:
|
|
505
|
+
PdfWrapper: The `PdfWrapper` object, allowing for method chaining.
|
|
506
|
+
"""
|
|
507
|
+
|
|
508
|
+
widgets = []
|
|
509
|
+
for field in fields:
|
|
510
|
+
field_dict = asdict(field)
|
|
511
|
+
widget_class = getattr(field, "_widget_class")
|
|
512
|
+
name = field_dict.pop("name")
|
|
513
|
+
page_number = field_dict.pop("page_number")
|
|
514
|
+
x = field_dict.pop("x")
|
|
515
|
+
y = field_dict.pop("y")
|
|
516
|
+
widgets.append(
|
|
517
|
+
widget_class(
|
|
518
|
+
name=name,
|
|
519
|
+
page_number=page_number,
|
|
520
|
+
x=x,
|
|
521
|
+
y=y,
|
|
522
|
+
**{k: v for k, v in field_dict.items() if v is not None},
|
|
523
|
+
)
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
watermarks = Widget.bulk_watermarks(widgets, self.read())
|
|
527
|
+
self._stream = copy_watermark_widgets(
|
|
528
|
+
self.read(),
|
|
529
|
+
watermarks,
|
|
530
|
+
[widget.acro_form_params["name"] for widget in widgets],
|
|
531
|
+
None,
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
self._init_helper()
|
|
535
|
+
|
|
536
|
+
for widget in widgets:
|
|
537
|
+
for k, v in widget.hook_params:
|
|
538
|
+
self.widgets[widget.acro_form_params["name"]].__setattr__(k, v)
|
|
539
|
+
|
|
540
|
+
return self
|
|
541
|
+
|
|
454
542
|
def create_field(
|
|
455
543
|
self,
|
|
456
544
|
field: FieldTypes,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
PyPDFForm/__init__.py,sha256=
|
|
1
|
+
PyPDFForm/__init__.py,sha256=CC5j1ui603ZNCwB7vhfBoSkfUothfptPDO9jrhWLbMs,963
|
|
2
2
|
PyPDFForm/adapter.py,sha256=0OTZBzGYzOerfXzUPvNq2HNVcMmkRnxNHQ1-Ys2VjYA,2427
|
|
3
3
|
PyPDFForm/constants.py,sha256=tFtomm4bSsghxRqKaMP6Tln7ug9W_72e-AAU3sEU_no,2917
|
|
4
4
|
PyPDFForm/coordinate.py,sha256=VMVkqa-VAGJSGVvetZwOxeMzIgQtQdvtn_DI_qSecCE,3876
|
|
@@ -10,7 +10,7 @@ PyPDFForm/patterns.py,sha256=Xhdsef7pPEIVEYhQRyOzonld3z1wk6WZ3TTjnj-RvpU,9573
|
|
|
10
10
|
PyPDFForm/template.py,sha256=GSNMH5meKk5B62sj_UXxiJgs4SOVDcQCNISvARmXJZ0,10004
|
|
11
11
|
PyPDFForm/utils.py,sha256=hLSVUG6qnE0iTMB-yPNQQIhmm3R69X7fcnbCTDvSUQs,11001
|
|
12
12
|
PyPDFForm/watermark.py,sha256=9p1tjaIqicXngTNai_iOEkCoXRYnR66azB4s7wNsZUw,9349
|
|
13
|
-
PyPDFForm/wrapper.py,sha256=
|
|
13
|
+
PyPDFForm/wrapper.py,sha256=8kYjgd18F_27QJXRJnxcZQ6RLyRmpXJHb0BAdtwUviw,30951
|
|
14
14
|
PyPDFForm/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
PyPDFForm/middleware/base.py,sha256=YQNVhjoDV2E3WYSQrahHkD6_Zdfxpcnr9ONKeB7hcgM,3223
|
|
16
16
|
PyPDFForm/middleware/checkbox.py,sha256=OCSZEFD8wQG_Y9qO7Os6VXTaxJCpkRYTxI4wDgG0GZc,1870
|
|
@@ -19,17 +19,17 @@ PyPDFForm/middleware/image.py,sha256=eKM7anU56jbaECnK6rq0jGsBRY3HW_fM86fgA3hq7xA
|
|
|
19
19
|
PyPDFForm/middleware/radio.py,sha256=PuGDJ8RN1C-MkL9Jf14ABWYV67cN18R66dI4nR-03DU,2211
|
|
20
20
|
PyPDFForm/middleware/signature.py,sha256=a2IfD36zpEWXWNNWRvtJ6nG6TszkF6Wil82Szsbjfns,2149
|
|
21
21
|
PyPDFForm/middleware/text.py,sha256=WLK6Ae9zT3uUu1AzcWUhR-hs5rm0z9Ydz-fL8Qu-44o,3997
|
|
22
|
-
PyPDFForm/widgets/__init__.py,sha256=
|
|
23
|
-
PyPDFForm/widgets/base.py,sha256=
|
|
22
|
+
PyPDFForm/widgets/__init__.py,sha256=gVJzqdpj6NRltqXrvCeHJO28snlIwHydbftWCnLZnvI,1399
|
|
23
|
+
PyPDFForm/widgets/base.py,sha256=FCFMJPMeqE1z0zNe_IK6kEu8M_sYFy7Tu8SyAMDJ14M,10195
|
|
24
24
|
PyPDFForm/widgets/bedrock.py,sha256=j6beU04kaQzpAIFZHI5VJLaDT5RVAAa6LzkU1luJpN8,137660
|
|
25
|
-
PyPDFForm/widgets/checkbox.py,sha256=
|
|
26
|
-
PyPDFForm/widgets/dropdown.py,sha256=
|
|
27
|
-
PyPDFForm/widgets/image.py,sha256=
|
|
28
|
-
PyPDFForm/widgets/radio.py,sha256=
|
|
29
|
-
PyPDFForm/widgets/signature.py,sha256
|
|
30
|
-
PyPDFForm/widgets/text.py,sha256=
|
|
31
|
-
pypdfform-3.
|
|
32
|
-
pypdfform-3.
|
|
33
|
-
pypdfform-3.
|
|
34
|
-
pypdfform-3.
|
|
35
|
-
pypdfform-3.
|
|
25
|
+
PyPDFForm/widgets/checkbox.py,sha256=QQH9MURhyASDss83uWRvD8R7uyZ1D9fxtLnpNCVFc10,3013
|
|
26
|
+
PyPDFForm/widgets/dropdown.py,sha256=jIRefrCqUZy9MJxeMlAnreclnSeai6YflsNDuRzim-o,3679
|
|
27
|
+
PyPDFForm/widgets/image.py,sha256=t-nHD38hF_wgHCAeBliqedbHX94k331L4HtKYhxkOaY,1628
|
|
28
|
+
PyPDFForm/widgets/radio.py,sha256=ip1imdGQhbQ6GO57Z8HNrzQkQH7SEq6K-azS949lMkU,3746
|
|
29
|
+
PyPDFForm/widgets/signature.py,sha256=-hc3bvU0zLPnla0CLzrnMAkJkPo_Nce_VO8UdeDUH90,5247
|
|
30
|
+
PyPDFForm/widgets/text.py,sha256=RJXPLCopmuayKJSvVeDVaiMRvqOjFoFwqiEzgyydIhg,3975
|
|
31
|
+
pypdfform-3.6.0.dist-info/licenses/LICENSE,sha256=43awmYkI6opyTpg19me731iO1WfXZwViqb67oWtCsFY,1065
|
|
32
|
+
pypdfform-3.6.0.dist-info/METADATA,sha256=3w5_arGBmdkCiaWFjWYwLlDv-E3D8XFY5N2sh2_KtM4,4269
|
|
33
|
+
pypdfform-3.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
34
|
+
pypdfform-3.6.0.dist-info/top_level.txt,sha256=GQQKuWqPUjT9YZqwK95NlAQzxjwoQrsxQ8ureM8lWOY,10
|
|
35
|
+
pypdfform-3.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|