PyPDFForm 1.4.26__tar.gz → 1.4.28__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.
Potentially problematic release.
This version of PyPDFForm might be problematic. Click here for more details.
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PKG-INFO +1 -17
- pypdfform-1.4.28/PyPDFForm/__init__.py +6 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/constants.py +5 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/filler.py +13 -2
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/font.py +38 -2
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/template.py +3 -33
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/wrapper.py +5 -52
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm.egg-info/PKG-INFO +1 -17
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm.egg-info/SOURCES.txt +1 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/README.md +0 -16
- pypdfform-1.4.28/tests/test_adobe_mode.py +97 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_functional.py +1 -26
- pypdfform-1.4.26/PyPDFForm/__init__.py +0 -6
- {pypdfform-1.4.26 → pypdfform-1.4.28}/LICENSE +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/adapter.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/coordinate.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/image.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/middleware/__init__.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/middleware/base.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/middleware/checkbox.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/middleware/dropdown.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/middleware/image.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/middleware/radio.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/middleware/signature.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/middleware/text.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/patterns.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/utils.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/watermark.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/widgets/__init__.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/widgets/base.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/widgets/checkbox.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/widgets/dropdown.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm/widgets/text.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm.egg-info/dependency_links.txt +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm.egg-info/requires.txt +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/PyPDFForm.egg-info/top_level.txt +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/setup.cfg +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/setup.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_create_widget.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_dropdown.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_dropdown_simple.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_fill_max_length_text_field.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_fill_max_length_text_field_simple.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_functional_simple.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_paragraph.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_paragraph_simple.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_preview.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.28}/tests/test_signature.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.28
|
|
4
4
|
Summary: The Python library for PDF forms.
|
|
5
5
|
Home-page: https://github.com/chinapandaman/PyPDFForm
|
|
6
6
|
Author: Jinge Li
|
|
@@ -34,22 +34,6 @@ Requires-Dist: reportlab
|
|
|
34
34
|
<a href="https://pypistats.org/packages/pypdfform"><img src="https://img.shields.io/pypi/dm/pypdfform?logo=pypi&logoColor=white&label=downloads&labelColor=black&color=blue&style=for-the-badge"></a>
|
|
35
35
|
</p>
|
|
36
36
|
|
|
37
|
-
## Important API Changes
|
|
38
|
-
|
|
39
|
-
Happy new year fellow developers! We start the year 2024 with a new release of v1.4.0 and
|
|
40
|
-
there are some important changes I'm making to the APIs of the library.
|
|
41
|
-
|
|
42
|
-
* The PDF object that gets instantiated is now `PyPDFForm.PdfWrapper`, changed from `PyPDFForm.PyPDFForm`.
|
|
43
|
-
* Form widgets are now accessed via the `PdfWrapper.widgets` attribute, changed from `PdfWrapper.elements`.
|
|
44
|
-
* The JSON schema of the form data is now accessed via a new attribute called `PdfWrapper.schema`,
|
|
45
|
-
changed from the old method of `PdfWrapper.generate_schema()`.
|
|
46
|
-
|
|
47
|
-
All the old APIs will be persisted for half a year and then fully deprecated. Each of them
|
|
48
|
-
will emit a `DeprecationWarning` when invoked, so it is advised that you make the switch before they are
|
|
49
|
-
removed and start breaking your code.
|
|
50
|
-
|
|
51
|
-
Happy hacking!
|
|
52
|
-
|
|
53
37
|
## Introduction
|
|
54
38
|
|
|
55
39
|
PyPDFForm is a free and open source pure-Python 3 library for PDF form processing. It contains the essential
|
|
@@ -5,9 +5,9 @@ from io import BytesIO
|
|
|
5
5
|
from typing import Dict, Tuple, Union, cast
|
|
6
6
|
|
|
7
7
|
from pypdf import PdfReader, PdfWriter
|
|
8
|
-
from pypdf.generic import DictionaryObject
|
|
8
|
+
from pypdf.generic import BooleanObject, DictionaryObject, NameObject
|
|
9
9
|
|
|
10
|
-
from .constants import WIDGET_TYPES, Annots
|
|
10
|
+
from .constants import WIDGET_TYPES, AcroForm, Annots, NeedAppearances, Root
|
|
11
11
|
from .coordinate import (get_draw_checkbox_radio_coordinates,
|
|
12
12
|
get_draw_image_coordinates_resolutions,
|
|
13
13
|
get_draw_text_coordinates,
|
|
@@ -160,14 +160,25 @@ def fill(
|
|
|
160
160
|
return result
|
|
161
161
|
|
|
162
162
|
|
|
163
|
+
def enable_adobe_mode(pdf: PdfReader, adobe_mode: bool) -> None:
|
|
164
|
+
"""Enables Adobe mode so that texts filled can show up in Acrobat."""
|
|
165
|
+
|
|
166
|
+
if adobe_mode and AcroForm in pdf.trailer[Root]:
|
|
167
|
+
pdf.trailer[Root][AcroForm].update(
|
|
168
|
+
{NameObject(NeedAppearances): BooleanObject(True)}
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
163
172
|
def simple_fill(
|
|
164
173
|
template: bytes,
|
|
165
174
|
widgets: Dict[str, WIDGET_TYPES],
|
|
166
175
|
flatten: bool = False,
|
|
176
|
+
adobe_mode: bool = False,
|
|
167
177
|
) -> bytes:
|
|
168
178
|
"""Fills a PDF form in place."""
|
|
169
179
|
|
|
170
180
|
pdf = PdfReader(stream_to_io(template))
|
|
181
|
+
enable_adobe_mode(pdf, adobe_mode)
|
|
171
182
|
out = PdfWriter()
|
|
172
183
|
out.append(pdf)
|
|
173
184
|
|
|
@@ -7,11 +7,14 @@ from re import findall
|
|
|
7
7
|
from typing import Tuple, Union
|
|
8
8
|
|
|
9
9
|
from reportlab.pdfbase.acroform import AcroForm
|
|
10
|
-
from reportlab.pdfbase.pdfmetrics import registerFont, standardFonts
|
|
10
|
+
from reportlab.pdfbase.pdfmetrics import (registerFont, standardFonts,
|
|
11
|
+
stringWidth)
|
|
11
12
|
from reportlab.pdfbase.ttfonts import TTFError, TTFont
|
|
12
13
|
|
|
13
14
|
from .constants import (DEFAULT_FONT, FONT_COLOR_IDENTIFIER,
|
|
14
|
-
FONT_SIZE_IDENTIFIER,
|
|
15
|
+
FONT_SIZE_IDENTIFIER, FONT_SIZE_REDUCE_STEP,
|
|
16
|
+
MARGIN_BETWEEN_LINES, Rect)
|
|
17
|
+
from .middleware.text import Text
|
|
15
18
|
from .patterns import TEXT_FIELD_APPEARANCE_PATTERNS
|
|
16
19
|
from .utils import traverse_pattern
|
|
17
20
|
|
|
@@ -146,3 +149,36 @@ def get_text_field_font_color(
|
|
|
146
149
|
break
|
|
147
150
|
|
|
148
151
|
return result
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def adjust_paragraph_font_size(widget: dict, widget_middleware: Text) -> None:
|
|
155
|
+
"""Reduces the font size of a paragraph field until texts fits."""
|
|
156
|
+
|
|
157
|
+
# pylint: disable=C0415, R0401
|
|
158
|
+
from .template import get_paragraph_lines
|
|
159
|
+
|
|
160
|
+
height = abs(float(widget[Rect][1]) - float(widget[Rect][3]))
|
|
161
|
+
|
|
162
|
+
while (
|
|
163
|
+
widget_middleware.font_size > FONT_SIZE_REDUCE_STEP
|
|
164
|
+
and len(widget_middleware.text_lines)
|
|
165
|
+
* (widget_middleware.font_size + MARGIN_BETWEEN_LINES)
|
|
166
|
+
> height
|
|
167
|
+
):
|
|
168
|
+
widget_middleware.font_size -= FONT_SIZE_REDUCE_STEP
|
|
169
|
+
widget_middleware.text_lines = get_paragraph_lines(widget, widget_middleware)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def adjust_text_field_font_size(widget: dict, widget_middleware: Text) -> None:
|
|
173
|
+
"""Reduces the font size of a text field until texts fits."""
|
|
174
|
+
|
|
175
|
+
width = abs(float(widget[Rect][0]) - float(widget[Rect][2]))
|
|
176
|
+
|
|
177
|
+
while (
|
|
178
|
+
widget_middleware.font_size > FONT_SIZE_REDUCE_STEP
|
|
179
|
+
and stringWidth(
|
|
180
|
+
widget_middleware.value, widget_middleware.font, widget_middleware.font_size
|
|
181
|
+
)
|
|
182
|
+
> width
|
|
183
|
+
):
|
|
184
|
+
widget_middleware.font_size -= FONT_SIZE_REDUCE_STEP
|
|
@@ -8,10 +8,10 @@ from typing import Dict, List, Tuple, Union
|
|
|
8
8
|
from pypdf import PdfReader
|
|
9
9
|
from reportlab.pdfbase.pdfmetrics import stringWidth
|
|
10
10
|
|
|
11
|
-
from .constants import (COMB, DEFAULT_FONT_SIZE,
|
|
12
|
-
MARGIN_BETWEEN_LINES, MULTILINE, NEW_LINE_SYMBOL,
|
|
11
|
+
from .constants import (COMB, DEFAULT_FONT_SIZE, MULTILINE, NEW_LINE_SYMBOL,
|
|
13
12
|
WIDGET_TYPES, MaxLen, Rect)
|
|
14
|
-
from .font import (
|
|
13
|
+
from .font import (adjust_paragraph_font_size, adjust_text_field_font_size,
|
|
14
|
+
auto_detect_font, get_text_field_font_color,
|
|
15
15
|
get_text_field_font_size, text_field_font_size)
|
|
16
16
|
from .middleware.checkbox import Checkbox
|
|
17
17
|
from .middleware.dropdown import Dropdown
|
|
@@ -403,33 +403,3 @@ def get_paragraph_auto_wrap_length(widget_middleware: Text) -> int:
|
|
|
403
403
|
result = min(result, len(line))
|
|
404
404
|
|
|
405
405
|
return result
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
def adjust_paragraph_font_size(widget: dict, widget_middleware: Text) -> None:
|
|
409
|
-
"""Reduces the font size of a paragraph field until texts fits."""
|
|
410
|
-
|
|
411
|
-
height = abs(float(widget[Rect][1]) - float(widget[Rect][3]))
|
|
412
|
-
|
|
413
|
-
while (
|
|
414
|
-
widget_middleware.font_size > FONT_SIZE_REDUCE_STEP
|
|
415
|
-
and len(widget_middleware.text_lines)
|
|
416
|
-
* (widget_middleware.font_size + MARGIN_BETWEEN_LINES)
|
|
417
|
-
> height
|
|
418
|
-
):
|
|
419
|
-
widget_middleware.font_size -= FONT_SIZE_REDUCE_STEP
|
|
420
|
-
widget_middleware.text_lines = get_paragraph_lines(widget, widget_middleware)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
def adjust_text_field_font_size(widget: dict, widget_middleware: Text) -> None:
|
|
424
|
-
"""Reduces the font size of a text field until texts fits."""
|
|
425
|
-
|
|
426
|
-
width = abs(float(widget[Rect][0]) - float(widget[Rect][2]))
|
|
427
|
-
|
|
428
|
-
while (
|
|
429
|
-
widget_middleware.font_size > FONT_SIZE_REDUCE_STEP
|
|
430
|
-
and stringWidth(
|
|
431
|
-
widget_middleware.value, widget_middleware.font, widget_middleware.font_size
|
|
432
|
-
)
|
|
433
|
-
> width
|
|
434
|
-
):
|
|
435
|
-
widget_middleware.font_size -= FONT_SIZE_REDUCE_STEP
|
|
@@ -5,12 +5,10 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
from functools import cached_property
|
|
7
7
|
from typing import BinaryIO, Dict, List, Tuple, Union
|
|
8
|
-
from warnings import warn
|
|
9
8
|
|
|
10
9
|
from .adapter import fp_or_f_obj_or_stream_to_stream
|
|
11
10
|
from .constants import (DEFAULT_FONT, DEFAULT_FONT_COLOR, DEFAULT_FONT_SIZE,
|
|
12
|
-
|
|
13
|
-
VERSION_IDENTIFIERS)
|
|
11
|
+
VERSION_IDENTIFIER_PREFIX, VERSION_IDENTIFIERS)
|
|
14
12
|
from .coordinate import generate_coordinate_grid
|
|
15
13
|
from .filler import fill, simple_fill
|
|
16
14
|
from .font import register_font
|
|
@@ -58,7 +56,10 @@ class FormWrapper:
|
|
|
58
56
|
widgets[key].value = value
|
|
59
57
|
|
|
60
58
|
self.stream = simple_fill(
|
|
61
|
-
self.read(),
|
|
59
|
+
self.read(),
|
|
60
|
+
widgets,
|
|
61
|
+
flatten=kwargs.get("flatten", False),
|
|
62
|
+
adobe_mode=kwargs.get("adobe_mode", False),
|
|
62
63
|
)
|
|
63
64
|
|
|
64
65
|
return self
|
|
@@ -87,21 +88,6 @@ class PdfWrapper(FormWrapper):
|
|
|
87
88
|
each.font_size = self.global_font_size
|
|
88
89
|
each.font_color = self.global_font_color
|
|
89
90
|
|
|
90
|
-
@property
|
|
91
|
-
def elements(self) -> dict:
|
|
92
|
-
"""ToDo: deprecate this."""
|
|
93
|
-
|
|
94
|
-
warn(
|
|
95
|
-
DEPRECATION_NOTICE.format(
|
|
96
|
-
f"{self.__class__.__name__}.elements",
|
|
97
|
-
f"{self.__class__.__name__}.widgets",
|
|
98
|
-
),
|
|
99
|
-
DeprecationWarning,
|
|
100
|
-
stacklevel=2,
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
return self.widgets
|
|
104
|
-
|
|
105
91
|
@property
|
|
106
92
|
def sample_data(self) -> dict:
|
|
107
93
|
"""Returns a valid sample data that can be filled into the PDF form."""
|
|
@@ -311,20 +297,6 @@ class PdfWrapper(FormWrapper):
|
|
|
311
297
|
|
|
312
298
|
return result
|
|
313
299
|
|
|
314
|
-
def generate_schema(self) -> dict:
|
|
315
|
-
"""ToDo: deprecate this."""
|
|
316
|
-
|
|
317
|
-
warn(
|
|
318
|
-
DEPRECATION_NOTICE.format(
|
|
319
|
-
f"{self.__class__.__name__}.generate_schema()",
|
|
320
|
-
f"{self.__class__.__name__}.schema",
|
|
321
|
-
),
|
|
322
|
-
DeprecationWarning,
|
|
323
|
-
stacklevel=2,
|
|
324
|
-
)
|
|
325
|
-
|
|
326
|
-
return self.schema
|
|
327
|
-
|
|
328
300
|
@classmethod
|
|
329
301
|
def register_font(
|
|
330
302
|
cls, font_name: str, ttf_file: Union[bytes, str, BinaryIO]
|
|
@@ -334,22 +306,3 @@ class PdfWrapper(FormWrapper):
|
|
|
334
306
|
ttf_file = fp_or_f_obj_or_stream_to_stream(ttf_file)
|
|
335
307
|
|
|
336
308
|
return register_font(font_name, ttf_file) if ttf_file is not None else False
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
class PyPDFForm(PdfWrapper):
|
|
340
|
-
"""ToDo: deprecate this."""
|
|
341
|
-
|
|
342
|
-
def __init__(
|
|
343
|
-
self,
|
|
344
|
-
template: Union[bytes, str, BinaryIO] = b"",
|
|
345
|
-
**kwargs,
|
|
346
|
-
):
|
|
347
|
-
"""Only extra thing is the deprecation notice."""
|
|
348
|
-
|
|
349
|
-
warn(
|
|
350
|
-
DEPRECATION_NOTICE.format("PyPDFForm.PyPDFForm", "PyPDFForm.PdfWrapper"),
|
|
351
|
-
DeprecationWarning,
|
|
352
|
-
stacklevel=2,
|
|
353
|
-
)
|
|
354
|
-
|
|
355
|
-
super().__init__(template, **kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.28
|
|
4
4
|
Summary: The Python library for PDF forms.
|
|
5
5
|
Home-page: https://github.com/chinapandaman/PyPDFForm
|
|
6
6
|
Author: Jinge Li
|
|
@@ -34,22 +34,6 @@ Requires-Dist: reportlab
|
|
|
34
34
|
<a href="https://pypistats.org/packages/pypdfform"><img src="https://img.shields.io/pypi/dm/pypdfform?logo=pypi&logoColor=white&label=downloads&labelColor=black&color=blue&style=for-the-badge"></a>
|
|
35
35
|
</p>
|
|
36
36
|
|
|
37
|
-
## Important API Changes
|
|
38
|
-
|
|
39
|
-
Happy new year fellow developers! We start the year 2024 with a new release of v1.4.0 and
|
|
40
|
-
there are some important changes I'm making to the APIs of the library.
|
|
41
|
-
|
|
42
|
-
* The PDF object that gets instantiated is now `PyPDFForm.PdfWrapper`, changed from `PyPDFForm.PyPDFForm`.
|
|
43
|
-
* Form widgets are now accessed via the `PdfWrapper.widgets` attribute, changed from `PdfWrapper.elements`.
|
|
44
|
-
* The JSON schema of the form data is now accessed via a new attribute called `PdfWrapper.schema`,
|
|
45
|
-
changed from the old method of `PdfWrapper.generate_schema()`.
|
|
46
|
-
|
|
47
|
-
All the old APIs will be persisted for half a year and then fully deprecated. Each of them
|
|
48
|
-
will emit a `DeprecationWarning` when invoked, so it is advised that you make the switch before they are
|
|
49
|
-
removed and start breaking your code.
|
|
50
|
-
|
|
51
|
-
Happy hacking!
|
|
52
|
-
|
|
53
37
|
## Introduction
|
|
54
38
|
|
|
55
39
|
PyPDFForm is a free and open source pure-Python 3 library for PDF form processing. It contains the essential
|
|
@@ -8,22 +8,6 @@
|
|
|
8
8
|
<a href="https://pypistats.org/packages/pypdfform"><img src="https://img.shields.io/pypi/dm/pypdfform?logo=pypi&logoColor=white&label=downloads&labelColor=black&color=blue&style=for-the-badge"></a>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
## Important API Changes
|
|
12
|
-
|
|
13
|
-
Happy new year fellow developers! We start the year 2024 with a new release of v1.4.0 and
|
|
14
|
-
there are some important changes I'm making to the APIs of the library.
|
|
15
|
-
|
|
16
|
-
* The PDF object that gets instantiated is now `PyPDFForm.PdfWrapper`, changed from `PyPDFForm.PyPDFForm`.
|
|
17
|
-
* Form widgets are now accessed via the `PdfWrapper.widgets` attribute, changed from `PdfWrapper.elements`.
|
|
18
|
-
* The JSON schema of the form data is now accessed via a new attribute called `PdfWrapper.schema`,
|
|
19
|
-
changed from the old method of `PdfWrapper.generate_schema()`.
|
|
20
|
-
|
|
21
|
-
All the old APIs will be persisted for half a year and then fully deprecated. Each of them
|
|
22
|
-
will emit a `DeprecationWarning` when invoked, so it is advised that you make the switch before they are
|
|
23
|
-
removed and start breaking your code.
|
|
24
|
-
|
|
25
|
-
Happy hacking!
|
|
26
|
-
|
|
27
11
|
## Introduction
|
|
28
12
|
|
|
29
13
|
PyPDFForm is a free and open source pure-Python 3 library for PDF form processing. It contains the essential
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from PyPDFForm import FormWrapper
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_dropdown_one(sample_template_with_dropdown, pdf_samples, request):
|
|
9
|
+
expected_path = os.path.join(
|
|
10
|
+
pdf_samples, "adobe_mode", "dropdown", "dropdown_one.pdf"
|
|
11
|
+
)
|
|
12
|
+
with open(expected_path, "rb+") as f:
|
|
13
|
+
obj = FormWrapper(sample_template_with_dropdown).fill(
|
|
14
|
+
{
|
|
15
|
+
"test_1": "test_1",
|
|
16
|
+
"test_2": "test_2",
|
|
17
|
+
"test_3": "test_3",
|
|
18
|
+
"check_1": True,
|
|
19
|
+
"check_2": True,
|
|
20
|
+
"check_3": True,
|
|
21
|
+
"radio_1": 1,
|
|
22
|
+
"dropdown_1": 0,
|
|
23
|
+
},
|
|
24
|
+
adobe_mode=True,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
request.config.results["expected_path"] = expected_path
|
|
28
|
+
request.config.results["stream"] = obj.read()
|
|
29
|
+
|
|
30
|
+
expected = f.read()
|
|
31
|
+
|
|
32
|
+
assert len(obj.read()) == len(expected)
|
|
33
|
+
assert obj.stream == expected
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_fill_sejda_complex(sejda_template_complex, pdf_samples, request):
|
|
37
|
+
expected_path = os.path.join(
|
|
38
|
+
pdf_samples, "adobe_mode", "paragraph", "sample_filled_sejda_complex.pdf"
|
|
39
|
+
)
|
|
40
|
+
with open(expected_path, "rb+") as f:
|
|
41
|
+
obj = FormWrapper(sejda_template_complex).fill(
|
|
42
|
+
{
|
|
43
|
+
"checkbox": True,
|
|
44
|
+
"radio": 0,
|
|
45
|
+
"dropdown_font_auto_left": 0,
|
|
46
|
+
"dropdown_font_auto_center": 1,
|
|
47
|
+
"dropdown_font_auto_right": 2,
|
|
48
|
+
"dropdown_font_ten_left": 0,
|
|
49
|
+
"dropdown_font_ten_center": 1,
|
|
50
|
+
"dropdown_font_ten_right": 2,
|
|
51
|
+
"paragraph_font_auto_left": "paragraph_font_auto_left",
|
|
52
|
+
"paragraph_font_auto_center": "paragraph_font_auto_center",
|
|
53
|
+
"paragraph_font_auto_right": "paragraph_font_auto_right",
|
|
54
|
+
"paragraph_font_ten_left": "paragraph_font_ten_left",
|
|
55
|
+
"paragraph_font_ten_center": "paragraph_font_ten_center",
|
|
56
|
+
"paragraph_font_ten_right": "paragraph_font_ten_right",
|
|
57
|
+
"text__font_auto_left": "test text",
|
|
58
|
+
"text_font_auto_center": "test text",
|
|
59
|
+
"text_font_auto_right": "test text",
|
|
60
|
+
"text_font_ten_left": "text_font_ten_left",
|
|
61
|
+
"text_font_ten_center": "text_font_ten_center",
|
|
62
|
+
"text_font_ten_right": "text_font_ten_right",
|
|
63
|
+
},
|
|
64
|
+
adobe_mode=True,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
request.config.results["expected_path"] = expected_path
|
|
68
|
+
request.config.results["stream"] = obj.read()
|
|
69
|
+
|
|
70
|
+
expected = f.read()
|
|
71
|
+
|
|
72
|
+
assert len(obj.read()) == len(expected)
|
|
73
|
+
assert obj.stream == expected
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_issue_613(pdf_samples, request):
|
|
77
|
+
expected_path = os.path.join(
|
|
78
|
+
pdf_samples, "adobe_mode", "issues", "613_expected.pdf"
|
|
79
|
+
)
|
|
80
|
+
with open(expected_path, "rb+") as f:
|
|
81
|
+
obj = FormWrapper(
|
|
82
|
+
os.path.join(pdf_samples, "scenario", "issues", "613.pdf")
|
|
83
|
+
).fill(
|
|
84
|
+
{
|
|
85
|
+
"301 Full name": "John Smith",
|
|
86
|
+
"301 Address Street": "1234 road number 6",
|
|
87
|
+
},
|
|
88
|
+
adobe_mode=True,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
request.config.results["expected_path"] = expected_path
|
|
92
|
+
request.config.results["stream"] = obj.read()
|
|
93
|
+
|
|
94
|
+
expected = f.read()
|
|
95
|
+
|
|
96
|
+
assert len(obj.read()) == len(expected)
|
|
97
|
+
assert obj.stream == expected
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
|
-
import pytest
|
|
6
5
|
from jsonschema import ValidationError, validate
|
|
7
6
|
|
|
8
|
-
from PyPDFForm import PdfWrapper,
|
|
7
|
+
from PyPDFForm import PdfWrapper, constants, template
|
|
9
8
|
from PyPDFForm.middleware.base import Widget
|
|
10
9
|
from PyPDFForm.middleware.text import Text
|
|
11
10
|
|
|
@@ -18,30 +17,6 @@ def test_base_schema_definition():
|
|
|
18
17
|
pass
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
def test_elements_deprecation_notice(template_stream):
|
|
22
|
-
with pytest.warns(DeprecationWarning) as r:
|
|
23
|
-
obj = PdfWrapper(template_stream)
|
|
24
|
-
assert not r
|
|
25
|
-
assert obj.elements is obj.widgets
|
|
26
|
-
obj.elements["test"].font_size = 20
|
|
27
|
-
assert obj.widgets["test"].font_size == 20
|
|
28
|
-
assert r
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def test_generate_schema_deprecation_notice(template_stream):
|
|
32
|
-
with pytest.warns(DeprecationWarning) as r:
|
|
33
|
-
obj = PdfWrapper(template_stream)
|
|
34
|
-
assert not r
|
|
35
|
-
assert obj.generate_schema() == obj.schema
|
|
36
|
-
assert r
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def test_pypdfform_deprecation_notice(template_stream):
|
|
40
|
-
with pytest.warns(DeprecationWarning) as r:
|
|
41
|
-
assert PyPDFForm(template_stream)
|
|
42
|
-
assert r
|
|
43
|
-
|
|
44
|
-
|
|
45
20
|
def test_fill(template_stream, pdf_samples, data_dict, request):
|
|
46
21
|
expected_path = os.path.join(pdf_samples, "sample_filled.pdf")
|
|
47
22
|
with open(expected_path, "rb+") as f:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|