PyPDFForm 1.3.4__py3-none-any.whl → 1.4.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 +3 -5
- PyPDFForm/core/constants.py +1 -1
- PyPDFForm/core/coordinate.py +65 -65
- PyPDFForm/core/filler.py +17 -17
- PyPDFForm/core/font.py +38 -42
- PyPDFForm/core/patterns.py +15 -14
- PyPDFForm/core/template.py +95 -72
- PyPDFForm/core/utils.py +53 -36
- PyPDFForm/core/watermark.py +30 -32
- PyPDFForm/middleware/checkbox.py +6 -6
- PyPDFForm/middleware/constants.py +3 -1
- PyPDFForm/middleware/dropdown.py +6 -6
- PyPDFForm/middleware/radio.py +6 -6
- PyPDFForm/middleware/template.py +30 -32
- PyPDFForm/middleware/text.py +6 -6
- PyPDFForm/middleware/{element.py → widget.py} +10 -10
- PyPDFForm/wrapper.py +88 -34
- {PyPDFForm-1.3.4.dist-info → PyPDFForm-1.4.0.dist-info}/METADATA +24 -4
- PyPDFForm-1.4.0.dist-info/RECORD +26 -0
- PyPDFForm-1.3.4.dist-info/RECORD +0 -26
- {PyPDFForm-1.3.4.dist-info → PyPDFForm-1.4.0.dist-info}/LICENSE +0 -0
- {PyPDFForm-1.3.4.dist-info → PyPDFForm-1.4.0.dist-info}/WHEEL +0 -0
- {PyPDFForm-1.3.4.dist-info → PyPDFForm-1.4.0.dist-info}/top_level.txt +0 -0
PyPDFForm/middleware/radio.py
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""Contains radio middleware."""
|
|
3
3
|
|
|
4
|
-
from .
|
|
4
|
+
from .widget import Widget
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class Radio(
|
|
8
|
-
"""A class to represent a radiobutton
|
|
7
|
+
class Radio(Widget):
|
|
8
|
+
"""A class to represent a radiobutton widget."""
|
|
9
9
|
|
|
10
10
|
def __init__(
|
|
11
11
|
self,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
name: str,
|
|
13
|
+
value: int = None,
|
|
14
14
|
) -> None:
|
|
15
15
|
"""Constructs all attributes for the radiobutton."""
|
|
16
16
|
|
|
17
|
-
super().__init__(
|
|
17
|
+
super().__init__(name, value)
|
|
18
18
|
|
|
19
19
|
self.number_of_options = 0
|
|
20
20
|
|
PyPDFForm/middleware/template.py
CHANGED
|
@@ -3,68 +3,66 @@
|
|
|
3
3
|
|
|
4
4
|
from typing import Dict
|
|
5
5
|
|
|
6
|
-
from ..core.template import (
|
|
7
|
-
get_dropdown_choices,
|
|
8
|
-
|
|
6
|
+
from ..core.template import (construct_widget, get_character_x_paddings,
|
|
7
|
+
get_dropdown_choices, get_text_field_max_length,
|
|
8
|
+
get_widget_key, get_widgets_by_page,
|
|
9
9
|
is_text_field_comb)
|
|
10
|
-
from .constants import
|
|
10
|
+
from .constants import WIDGET_TYPES
|
|
11
11
|
from .dropdown import Dropdown
|
|
12
12
|
from .radio import Radio
|
|
13
13
|
from .text import Text
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def set_character_x_paddings(
|
|
17
|
-
pdf_stream: bytes,
|
|
18
|
-
) -> Dict[str,
|
|
17
|
+
pdf_stream: bytes, widgets: Dict[str, WIDGET_TYPES]
|
|
18
|
+
) -> Dict[str, WIDGET_TYPES]:
|
|
19
19
|
"""Sets paddings between characters for combed text fields."""
|
|
20
20
|
|
|
21
|
-
for
|
|
22
|
-
for
|
|
23
|
-
key =
|
|
24
|
-
|
|
21
|
+
for _widgets in get_widgets_by_page(pdf_stream).values():
|
|
22
|
+
for widget in _widgets:
|
|
23
|
+
key = get_widget_key(widget)
|
|
24
|
+
_widget = widgets[key]
|
|
25
25
|
|
|
26
|
-
if isinstance(
|
|
27
|
-
|
|
28
|
-
element, _element
|
|
29
|
-
)
|
|
26
|
+
if isinstance(_widget, Text) and _widget.comb is True:
|
|
27
|
+
_widget.character_paddings = get_character_x_paddings(widget, _widget)
|
|
30
28
|
|
|
31
|
-
return
|
|
29
|
+
return widgets
|
|
32
30
|
|
|
33
31
|
|
|
34
|
-
def
|
|
35
|
-
"""Builds
|
|
32
|
+
def build_widgets(pdf_stream: bytes) -> Dict[str, WIDGET_TYPES]:
|
|
33
|
+
"""Builds a widget dict given a PDF form stream."""
|
|
36
34
|
|
|
37
35
|
results = {}
|
|
38
36
|
|
|
39
|
-
for
|
|
40
|
-
for
|
|
41
|
-
key =
|
|
37
|
+
for widgets in get_widgets_by_page(pdf_stream).values():
|
|
38
|
+
for widget in widgets:
|
|
39
|
+
key = get_widget_key(widget)
|
|
42
40
|
|
|
43
|
-
|
|
41
|
+
_widget = construct_widget(widget, key)
|
|
44
42
|
|
|
45
|
-
if
|
|
46
|
-
if isinstance(
|
|
47
|
-
|
|
48
|
-
if
|
|
49
|
-
|
|
43
|
+
if _widget is not None:
|
|
44
|
+
if isinstance(_widget, Text):
|
|
45
|
+
_widget.max_length = get_text_field_max_length(widget)
|
|
46
|
+
if _widget.max_length is not None and is_text_field_comb(widget):
|
|
47
|
+
_widget.comb = True
|
|
50
48
|
|
|
51
|
-
if isinstance(
|
|
52
|
-
|
|
49
|
+
if isinstance(_widget, Dropdown):
|
|
50
|
+
_widget.choices = get_dropdown_choices(widget)
|
|
53
51
|
|
|
54
|
-
if isinstance(
|
|
52
|
+
if isinstance(_widget, Radio):
|
|
55
53
|
if key not in results:
|
|
56
|
-
results[key] =
|
|
54
|
+
results[key] = _widget
|
|
57
55
|
|
|
58
56
|
results[key].number_of_options += 1
|
|
59
57
|
continue
|
|
60
58
|
|
|
61
|
-
results[key] =
|
|
59
|
+
results[key] = _widget
|
|
62
60
|
|
|
63
61
|
return results
|
|
64
62
|
|
|
65
63
|
|
|
66
64
|
def dropdown_to_text(dropdown: Dropdown) -> Text:
|
|
67
|
-
"""Converts a dropdown
|
|
65
|
+
"""Converts a dropdown widget to a text widget."""
|
|
68
66
|
|
|
69
67
|
result = Text(dropdown.name)
|
|
70
68
|
|
PyPDFForm/middleware/text.py
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""Contains text middleware."""
|
|
3
3
|
|
|
4
|
-
from .
|
|
4
|
+
from .widget import Widget
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class Text(
|
|
8
|
-
"""A class to represent a text field
|
|
7
|
+
class Text(Widget):
|
|
8
|
+
"""A class to represent a text field widget."""
|
|
9
9
|
|
|
10
10
|
def __init__(
|
|
11
11
|
self,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
name: str,
|
|
13
|
+
value: str = None,
|
|
14
14
|
) -> None:
|
|
15
15
|
"""Constructs all attributes for the text field."""
|
|
16
16
|
|
|
17
|
-
super().__init__(
|
|
17
|
+
super().__init__(name, value)
|
|
18
18
|
|
|
19
19
|
self.font = None
|
|
20
20
|
self.font_size = None
|
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
"""Contains
|
|
2
|
+
"""Contains widget middleware."""
|
|
3
3
|
|
|
4
4
|
from typing import Any, Union
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class
|
|
8
|
-
"""Base class for all PDF form
|
|
7
|
+
class Widget:
|
|
8
|
+
"""Base class for all PDF form widgets."""
|
|
9
9
|
|
|
10
10
|
def __init__(
|
|
11
11
|
self,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
name: str,
|
|
13
|
+
value: Union[str, bool, int] = None,
|
|
14
14
|
) -> None:
|
|
15
15
|
"""Constructs basic attributes for the object."""
|
|
16
16
|
|
|
17
|
-
self._name =
|
|
18
|
-
self.value =
|
|
17
|
+
self._name = name
|
|
18
|
+
self.value = value
|
|
19
19
|
|
|
20
20
|
@property
|
|
21
21
|
def name(self) -> str:
|
|
22
|
-
"""Name of the
|
|
22
|
+
"""Name of the widget."""
|
|
23
23
|
|
|
24
24
|
return self._name
|
|
25
25
|
|
|
26
26
|
@property
|
|
27
27
|
def schema_definition(self) -> dict:
|
|
28
|
-
"""Json schema definition of the
|
|
28
|
+
"""Json schema definition of the widget."""
|
|
29
29
|
|
|
30
30
|
raise NotImplementedError
|
|
31
31
|
|
|
32
32
|
@property
|
|
33
33
|
def sample_value(self) -> Any:
|
|
34
|
-
"""Sample value of the
|
|
34
|
+
"""Sample value of the widget."""
|
|
35
35
|
|
|
36
36
|
raise NotImplementedError
|
PyPDFForm/wrapper.py
CHANGED
|
@@ -3,26 +3,28 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
-
from typing import BinaryIO, Dict, Union
|
|
6
|
+
from typing import BinaryIO, Dict, List, Union
|
|
7
|
+
from warnings import warn
|
|
7
8
|
|
|
8
9
|
from .core.constants import DEFAULT_FONT, DEFAULT_FONT_COLOR, DEFAULT_FONT_SIZE
|
|
9
10
|
from .core.filler import fill
|
|
10
11
|
from .core.font import register_font, update_text_field_attributes
|
|
11
12
|
from .core.image import any_image_to_jpg, rotate_image
|
|
12
|
-
from .core.utils import (
|
|
13
|
-
|
|
13
|
+
from .core.utils import (get_page_streams, merge_two_pdfs,
|
|
14
|
+
preview_widget_to_draw, remove_all_widgets)
|
|
14
15
|
from .core.watermark import (create_watermarks_and_draw,
|
|
15
16
|
merge_watermarks_with_pdf)
|
|
16
17
|
from .middleware.adapter import fp_or_f_obj_or_stream_to_stream
|
|
17
|
-
from .middleware.constants import (
|
|
18
|
+
from .middleware.constants import (DEPRECATION_NOTICE,
|
|
19
|
+
VERSION_IDENTIFIER_PREFIX,
|
|
18
20
|
VERSION_IDENTIFIERS)
|
|
19
21
|
from .middleware.dropdown import Dropdown
|
|
20
|
-
from .middleware.template import (
|
|
22
|
+
from .middleware.template import (build_widgets, dropdown_to_text,
|
|
21
23
|
set_character_x_paddings)
|
|
22
24
|
from .middleware.text import Text
|
|
23
25
|
|
|
24
26
|
|
|
25
|
-
class
|
|
27
|
+
class PdfWrapper:
|
|
26
28
|
"""A class to represent a PDF form."""
|
|
27
29
|
|
|
28
30
|
def __init__(
|
|
@@ -33,9 +35,9 @@ class Wrapper:
|
|
|
33
35
|
"""Constructs all attributes for the object."""
|
|
34
36
|
|
|
35
37
|
self.stream = fp_or_f_obj_or_stream_to_stream(template)
|
|
36
|
-
self.
|
|
38
|
+
self.widgets = build_widgets(self.stream) if self.stream else {}
|
|
37
39
|
|
|
38
|
-
for each in self.
|
|
40
|
+
for each in self.widgets.values():
|
|
39
41
|
if isinstance(each, Text):
|
|
40
42
|
each.font = kwargs.get("global_font")
|
|
41
43
|
each.font_size = kwargs.get("global_font_size")
|
|
@@ -46,11 +48,26 @@ class Wrapper:
|
|
|
46
48
|
|
|
47
49
|
return self.stream
|
|
48
50
|
|
|
51
|
+
@property
|
|
52
|
+
def elements(self) -> dict:
|
|
53
|
+
"""ToDo: deprecate this."""
|
|
54
|
+
|
|
55
|
+
warn(
|
|
56
|
+
DEPRECATION_NOTICE.format(
|
|
57
|
+
f"{self.__class__.__name__}.elements",
|
|
58
|
+
f"{self.__class__.__name__}.widgets",
|
|
59
|
+
),
|
|
60
|
+
DeprecationWarning,
|
|
61
|
+
stacklevel=2,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return self.widgets
|
|
65
|
+
|
|
49
66
|
@property
|
|
50
67
|
def sample_data(self) -> dict:
|
|
51
68
|
"""Returns a valid sample data that can be filled into the PDF form."""
|
|
52
69
|
|
|
53
|
-
return {key: value.sample_value for key, value in self.
|
|
70
|
+
return {key: value.sample_value for key, value in self.widgets.items()}
|
|
54
71
|
|
|
55
72
|
@property
|
|
56
73
|
def version(self) -> Union[str, None]:
|
|
@@ -62,7 +79,13 @@ class Wrapper:
|
|
|
62
79
|
|
|
63
80
|
return None
|
|
64
81
|
|
|
65
|
-
|
|
82
|
+
@property
|
|
83
|
+
def pages(self) -> List[PdfWrapper]:
|
|
84
|
+
"""Returns a list of pdf wrapper objects where each is a page of the PDF form."""
|
|
85
|
+
|
|
86
|
+
return [self.__class__(each) for each in get_page_streams(self.stream)]
|
|
87
|
+
|
|
88
|
+
def change_version(self, version: str) -> PdfWrapper:
|
|
66
89
|
"""Changes the version of the PDF."""
|
|
67
90
|
|
|
68
91
|
self.stream = self.stream.replace(
|
|
@@ -73,7 +96,7 @@ class Wrapper:
|
|
|
73
96
|
|
|
74
97
|
return self
|
|
75
98
|
|
|
76
|
-
def __add__(self, other:
|
|
99
|
+
def __add__(self, other: PdfWrapper) -> PdfWrapper:
|
|
77
100
|
"""Overloaded addition operator to perform merging PDFs."""
|
|
78
101
|
|
|
79
102
|
if not self.stream:
|
|
@@ -89,35 +112,32 @@ class Wrapper:
|
|
|
89
112
|
|
|
90
113
|
@property
|
|
91
114
|
def preview(self) -> bytes:
|
|
92
|
-
"""Inspects all supported
|
|
115
|
+
"""Inspects all supported widgets' names for the PDF form."""
|
|
93
116
|
|
|
94
117
|
return fill(
|
|
95
118
|
self.stream,
|
|
96
|
-
{
|
|
97
|
-
key: preview_element_to_draw(value)
|
|
98
|
-
for key, value in self.elements.items()
|
|
99
|
-
},
|
|
119
|
+
{key: preview_widget_to_draw(value) for key, value in self.widgets.items()},
|
|
100
120
|
)
|
|
101
121
|
|
|
102
122
|
def fill(
|
|
103
123
|
self,
|
|
104
124
|
data: Dict[str, Union[str, bool, int]],
|
|
105
|
-
) ->
|
|
125
|
+
) -> PdfWrapper:
|
|
106
126
|
"""Fills a PDF form."""
|
|
107
127
|
|
|
108
128
|
for key, value in data.items():
|
|
109
|
-
if key in self.
|
|
110
|
-
self.
|
|
129
|
+
if key in self.widgets:
|
|
130
|
+
self.widgets[key].value = value
|
|
111
131
|
|
|
112
|
-
for key, value in self.
|
|
132
|
+
for key, value in self.widgets.items():
|
|
113
133
|
if isinstance(value, Dropdown):
|
|
114
|
-
self.
|
|
134
|
+
self.widgets[key] = dropdown_to_text(value)
|
|
115
135
|
|
|
116
|
-
update_text_field_attributes(self.stream, self.
|
|
136
|
+
update_text_field_attributes(self.stream, self.widgets)
|
|
117
137
|
if self.read():
|
|
118
|
-
self.
|
|
138
|
+
self.widgets = set_character_x_paddings(self.stream, self.widgets)
|
|
119
139
|
|
|
120
|
-
self.stream =
|
|
140
|
+
self.stream = remove_all_widgets(fill(self.stream, self.widgets))
|
|
121
141
|
|
|
122
142
|
return self
|
|
123
143
|
|
|
@@ -128,14 +148,14 @@ class Wrapper:
|
|
|
128
148
|
x: Union[float, int],
|
|
129
149
|
y: Union[float, int],
|
|
130
150
|
**kwargs,
|
|
131
|
-
) ->
|
|
151
|
+
) -> PdfWrapper:
|
|
132
152
|
"""Draws a text on a PDF form."""
|
|
133
153
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
154
|
+
new_widget = Text("new")
|
|
155
|
+
new_widget.value = text
|
|
156
|
+
new_widget.font = kwargs.get("font", DEFAULT_FONT)
|
|
157
|
+
new_widget.font_size = kwargs.get("font_size", DEFAULT_FONT_SIZE)
|
|
158
|
+
new_widget.font_color = kwargs.get("font_color", DEFAULT_FONT_COLOR)
|
|
139
159
|
|
|
140
160
|
watermarks = create_watermarks_and_draw(
|
|
141
161
|
self.stream,
|
|
@@ -143,7 +163,7 @@ class Wrapper:
|
|
|
143
163
|
"text",
|
|
144
164
|
[
|
|
145
165
|
[
|
|
146
|
-
|
|
166
|
+
new_widget,
|
|
147
167
|
x,
|
|
148
168
|
y,
|
|
149
169
|
]
|
|
@@ -163,7 +183,7 @@ class Wrapper:
|
|
|
163
183
|
width: Union[float, int],
|
|
164
184
|
height: Union[float, int],
|
|
165
185
|
rotation: Union[float, int] = 0,
|
|
166
|
-
) ->
|
|
186
|
+
) -> PdfWrapper:
|
|
167
187
|
"""Draws an image on a PDF form."""
|
|
168
188
|
|
|
169
189
|
image = fp_or_f_obj_or_stream_to_stream(image)
|
|
@@ -177,18 +197,33 @@ class Wrapper:
|
|
|
177
197
|
|
|
178
198
|
return self
|
|
179
199
|
|
|
180
|
-
|
|
200
|
+
@property
|
|
201
|
+
def schema(self) -> dict:
|
|
181
202
|
"""Generates a json schema for the PDF form template."""
|
|
182
203
|
|
|
183
204
|
result = {
|
|
184
205
|
"type": "object",
|
|
185
206
|
"properties": {
|
|
186
|
-
key: value.schema_definition for key, value in self.
|
|
207
|
+
key: value.schema_definition for key, value in self.widgets.items()
|
|
187
208
|
},
|
|
188
209
|
}
|
|
189
210
|
|
|
190
211
|
return result
|
|
191
212
|
|
|
213
|
+
def generate_schema(self) -> dict:
|
|
214
|
+
"""ToDo: deprecate this."""
|
|
215
|
+
|
|
216
|
+
warn(
|
|
217
|
+
DEPRECATION_NOTICE.format(
|
|
218
|
+
f"{self.__class__.__name__}.generate_schema()",
|
|
219
|
+
f"{self.__class__.__name__}.schema",
|
|
220
|
+
),
|
|
221
|
+
DeprecationWarning,
|
|
222
|
+
stacklevel=2,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
return self.schema
|
|
226
|
+
|
|
192
227
|
@classmethod
|
|
193
228
|
def register_font(
|
|
194
229
|
cls, font_name: str, ttf_file: Union[bytes, str, BinaryIO]
|
|
@@ -198,3 +233,22 @@ class Wrapper:
|
|
|
198
233
|
ttf_file = fp_or_f_obj_or_stream_to_stream(ttf_file)
|
|
199
234
|
|
|
200
235
|
return register_font(font_name, ttf_file) if ttf_file is not None else False
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class PyPDFForm(PdfWrapper):
|
|
239
|
+
"""ToDo: deprecate this."""
|
|
240
|
+
|
|
241
|
+
def __init__(
|
|
242
|
+
self,
|
|
243
|
+
template: Union[bytes, str, BinaryIO] = b"",
|
|
244
|
+
**kwargs,
|
|
245
|
+
):
|
|
246
|
+
"""Only extra thing is the deprecation notice."""
|
|
247
|
+
|
|
248
|
+
warn(
|
|
249
|
+
DEPRECATION_NOTICE.format("PyPDFForm.PyPDFForm", "PyPDFForm.PdfWrapper"),
|
|
250
|
+
DeprecationWarning,
|
|
251
|
+
stacklevel=2,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
super().__init__(template, **kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: The Python library for PDF forms.
|
|
5
5
|
Home-page: https://github.com/chinapandaman/PyPDFForm
|
|
6
6
|
Author: Jinge Li
|
|
@@ -24,12 +24,28 @@ Requires-Dist: reportlab
|
|
|
24
24
|
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-orange.svg"></a>
|
|
25
25
|
</p>
|
|
26
26
|
|
|
27
|
+
## Important API Changes
|
|
28
|
+
|
|
29
|
+
Happy new year fellow developers! We start the year 2024 with a new release of v1.4.0 and
|
|
30
|
+
there are some important changes I'm making to the APIs of the library.
|
|
31
|
+
|
|
32
|
+
* The PDF object that gets instantiated is now `PyPDFForm.PdfWrapper`, changed from `PyPDFForm.PyPDFForm`.
|
|
33
|
+
* Form widgets are now accessed via the `PdfWrapper.widgets` attribute, changed from `PdfWrapper.elements`.
|
|
34
|
+
* The JSON schema of the form data is now accessed via a new attribute called `PdfWrapper.schema`,
|
|
35
|
+
changed from the old method of `PdfWrapper.generate_schema()`.
|
|
36
|
+
|
|
37
|
+
All the old APIs will be persisted for half a year and then fully deprecated. Each of them
|
|
38
|
+
will emit a `DeprecationWarning` when invoked, so it is advised that you make the switch before they are
|
|
39
|
+
removed and start breaking your code.
|
|
40
|
+
|
|
41
|
+
Happy hacking!
|
|
42
|
+
|
|
27
43
|
## Introduction
|
|
28
44
|
|
|
29
45
|
PyPDFForm is a pure Python library for PDF form processing.
|
|
30
46
|
It allows filling a PDF form programmatically by creating
|
|
31
47
|
a Python dictionary with keys matching its annotated names
|
|
32
|
-
for
|
|
48
|
+
for widgets like text fields and checkboxes. It also supports other functionalities such as
|
|
33
49
|
drawing image and merging multiple PDFs together.
|
|
34
50
|
|
|
35
51
|
## Installing
|
|
@@ -48,7 +64,7 @@ A sample PDF form can be found [here](https://github.com/chinapandaman/PyPDFForm
|
|
|
48
64
|
```python
|
|
49
65
|
import os
|
|
50
66
|
|
|
51
|
-
from PyPDFForm import
|
|
67
|
+
from PyPDFForm import PdfWrapper
|
|
52
68
|
|
|
53
69
|
PATH_TO_DOWNLOADED_SAMPLE_PDF_FORM = os.path.join(
|
|
54
70
|
os.path.expanduser("~/Downloads"), "sample_template.pdf"
|
|
@@ -60,7 +76,7 @@ PATH_TO_FILLED_PDF_FORM = os.path.join(
|
|
|
60
76
|
|
|
61
77
|
with open(PATH_TO_FILLED_PDF_FORM, "wb+") as output:
|
|
62
78
|
output.write(
|
|
63
|
-
|
|
79
|
+
PdfWrapper(PATH_TO_DOWNLOADED_SAMPLE_PDF_FORM)
|
|
64
80
|
.fill(
|
|
65
81
|
{
|
|
66
82
|
"test": "test_1",
|
|
@@ -82,6 +98,10 @@ and it should look like [this](https://github.com/chinapandaman/PyPDFForm/raw/ma
|
|
|
82
98
|
|
|
83
99
|
[Examples](https://github.com/chinapandaman/PyPDFForm/blob/master/docs/examples.md)
|
|
84
100
|
|
|
101
|
+
## Public Speak
|
|
102
|
+
|
|
103
|
+
[Chicago Python User Group - Dec 14, 2023](https://youtu.be/8t1RdAKwr9w?si=TLgumBNXv9H8szSn)
|
|
104
|
+
|
|
85
105
|
## How to Contribute
|
|
86
106
|
|
|
87
107
|
It is difficult to make sure that the library supports all the PDF form creating tools out
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
PyPDFForm/__init__.py,sha256=rhfuv6pEoYKPZZjU_oHscNXkBManw1LvL-7SoJP7nUE,135
|
|
2
|
+
PyPDFForm/wrapper.py,sha256=o9m4Kr5FcKk4ca9DPGHtfix-gSh7gn380xtioQ2SEkI,7568
|
|
3
|
+
PyPDFForm/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
PyPDFForm/core/constants.py,sha256=0zd1tW4YBEv-SAJRwWUCOJWOolrxIWc_aTJ-ljHw_wo,774
|
|
5
|
+
PyPDFForm/core/coordinate.py,sha256=hBAqC-U-Uzp2YsKS6Nc9bxOifU2uCFxp7BUGchGsAKs,5092
|
|
6
|
+
PyPDFForm/core/filler.py,sha256=rNhVcBcAu1xsAlq_AuomlT_6B27KxCrzXqNBSr94kk8,2802
|
|
7
|
+
PyPDFForm/core/font.py,sha256=W5LPZX5bqN19gaBRv_uvDcudb3cUMfOA1SFNc5CgmdQ,5848
|
|
8
|
+
PyPDFForm/core/image.py,sha256=Fqh4GZKHRZEKZos_Dnp_oyeOXXbbJQ3MUOE7qQxp5Hg,1067
|
|
9
|
+
PyPDFForm/core/patterns.py,sha256=oj6eQ13H353oUJt8H1TD7iQ_bz102wdj7i4NQUAiwzQ,2027
|
|
10
|
+
PyPDFForm/core/template.py,sha256=XdOCEWcv3ZwGIllUEoCMtmFJ68edGtqSfgwAUTVd1t8,8778
|
|
11
|
+
PyPDFForm/core/utils.py,sha256=bXUYCkZpn8HOlT5-H0fYKB_AUVSMtVg5KUvkOSe46Ro,3903
|
|
12
|
+
PyPDFForm/core/watermark.py,sha256=rqg5UAvIUthjytqF9lwiZHdt9Z8elUUGsA65yRz8gXU,4245
|
|
13
|
+
PyPDFForm/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
PyPDFForm/middleware/adapter.py,sha256=OgAIwcmukpBqHFBLymd3I7wA7wIdipRqgURZA2Y0Hgo,885
|
|
15
|
+
PyPDFForm/middleware/checkbox.py,sha256=xnV5VUDwPHQAk6pYU_Pmm5LKsvHEqJ37nbHIyfAEPn0,618
|
|
16
|
+
PyPDFForm/middleware/constants.py,sha256=Gk3z3yvKrqyncT3KkHkJ67z-n_DuLlzIXtUm75ZsKCE,548
|
|
17
|
+
PyPDFForm/middleware/dropdown.py,sha256=wwZKzNnPDN9S4Hr2MeKBxAp84TvYxymdcqvATIYiayM,676
|
|
18
|
+
PyPDFForm/middleware/radio.py,sha256=6T4XkOgHTduulytR9NHR2rQ8fvIC0oOZ8NfcswLcQ14,694
|
|
19
|
+
PyPDFForm/middleware/template.py,sha256=T6EJWRhRfcsAA0xVdB_gs2oOW7bCXLkzv4s14d2LCYo,2378
|
|
20
|
+
PyPDFForm/middleware/text.py,sha256=RqXo-C2zCZqufW-Uer90aUFvDLcPKLkKa1LRzRogv4o,1059
|
|
21
|
+
PyPDFForm/middleware/widget.py,sha256=90DKZYoA1lTZ2Jk4rWjT2oH59PvAI2_-Xwr7qWodtj0,749
|
|
22
|
+
PyPDFForm-1.4.0.dist-info/LICENSE,sha256=43awmYkI6opyTpg19me731iO1WfXZwViqb67oWtCsFY,1065
|
|
23
|
+
PyPDFForm-1.4.0.dist-info/METADATA,sha256=9yPCr-yEwbZnqQsgD-fhkBzpSGpFcta0sORXBCrsY5Q,4919
|
|
24
|
+
PyPDFForm-1.4.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
25
|
+
PyPDFForm-1.4.0.dist-info/top_level.txt,sha256=GQQKuWqPUjT9YZqwK95NlAQzxjwoQrsxQ8ureM8lWOY,10
|
|
26
|
+
PyPDFForm-1.4.0.dist-info/RECORD,,
|
PyPDFForm-1.3.4.dist-info/RECORD
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
PyPDFForm/__init__.py,sha256=xwD6TyBoidD0ms_rq1M_4LVpaD5x1VXLTSH5_OgfrBE,122
|
|
2
|
-
PyPDFForm/wrapper.py,sha256=RwQx2oZSKJPW0bHsF5kAXTT2uiklT0nvDEzjMQR5xJE,6119
|
|
3
|
-
PyPDFForm/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
PyPDFForm/core/constants.py,sha256=5ekojW6YlD72tbZG7-0vj0cNP0iIw2-dsOT2YJ2BABM,775
|
|
5
|
-
PyPDFForm/core/coordinate.py,sha256=wEN--iRpEwirOikfOELAxlsInXfYmd41VuRUBP_HAO8,5175
|
|
6
|
-
PyPDFForm/core/filler.py,sha256=Zi_adOTjKD6xbgy3ZOCjAoR0r3-R373pQN8uKuDa0fA,2827
|
|
7
|
-
PyPDFForm/core/font.py,sha256=3bzuhWCAPpaDepXNFhpIyqWHSOP24oOe8rA2R26tuIs,5968
|
|
8
|
-
PyPDFForm/core/image.py,sha256=Fqh4GZKHRZEKZos_Dnp_oyeOXXbbJQ3MUOE7qQxp5Hg,1067
|
|
9
|
-
PyPDFForm/core/patterns.py,sha256=Uyio6jahksPsYar8MnVukiRIhL1K5hlO9TEGHrx3SxU,2015
|
|
10
|
-
PyPDFForm/core/template.py,sha256=PjsaczdpNqUm7tGJSZrirmrZDFJhdrWRsypjdTNNUU4,8207
|
|
11
|
-
PyPDFForm/core/utils.py,sha256=wmqY_c2SOZjEyN9jcmnKQHuSF31F1wCua_qJGH_EmA0,3574
|
|
12
|
-
PyPDFForm/core/watermark.py,sha256=vt6EFDAlOZ7g1nrZLfR_nMozDFSHxzw3cUyEzdgzFOo,4270
|
|
13
|
-
PyPDFForm/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
PyPDFForm/middleware/adapter.py,sha256=OgAIwcmukpBqHFBLymd3I7wA7wIdipRqgURZA2Y0Hgo,885
|
|
15
|
-
PyPDFForm/middleware/checkbox.py,sha256=fU_VV6B6m7aYe3i6HzXBUu9U9yH5gP0WXz1J9q4c0Fs,654
|
|
16
|
-
PyPDFForm/middleware/constants.py,sha256=r56j2oURQei7KX0gWPqb10bQXRVdyVd0T8BapSlDlYM,481
|
|
17
|
-
PyPDFForm/middleware/dropdown.py,sha256=OJQI_XffMPf4yxUCk5WOaLIqZpRd97gNV-YG-llFaa8,712
|
|
18
|
-
PyPDFForm/middleware/element.py,sha256=Xo_lFRCTkEorfYOSU7RcP7tmvCrkKEpiZAzKIPHRwVs,787
|
|
19
|
-
PyPDFForm/middleware/radio.py,sha256=gwNTE__eiaSqxY8_ov__tI8byz-cKOfTp9nWJ5DkFzQ,730
|
|
20
|
-
PyPDFForm/middleware/template.py,sha256=U2Agl5Vs_fllaeyL1xBq1sP8PFUU33G_BRgjxQLS9LQ,2451
|
|
21
|
-
PyPDFForm/middleware/text.py,sha256=rrTfXcxaXZlLsjuJ1C4KaHt_reZk2c9MQ-z0ec3OD9g,1095
|
|
22
|
-
PyPDFForm-1.3.4.dist-info/LICENSE,sha256=43awmYkI6opyTpg19me731iO1WfXZwViqb67oWtCsFY,1065
|
|
23
|
-
PyPDFForm-1.3.4.dist-info/METADATA,sha256=auVwgQRFHc_VhlenjBEZIbRDbdMyTYzntns41n7EqOs,3985
|
|
24
|
-
PyPDFForm-1.3.4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
25
|
-
PyPDFForm-1.3.4.dist-info/top_level.txt,sha256=GQQKuWqPUjT9YZqwK95NlAQzxjwoQrsxQ8ureM8lWOY,10
|
|
26
|
-
PyPDFForm-1.3.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|