PyPDFForm 1.4.26__tar.gz → 1.4.27__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.27}/PKG-INFO +1 -1
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/__init__.py +1 -1
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/constants.py +5 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/filler.py +14 -2
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/font.py +38 -2
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/template.py +3 -33
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/wrapper.py +4 -1
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm.egg-info/PKG-INFO +1 -1
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm.egg-info/SOURCES.txt +1 -0
- pypdfform-1.4.27/tests/test_adobe_mode.py +45 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/LICENSE +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/adapter.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/coordinate.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/image.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/middleware/__init__.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/middleware/base.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/middleware/checkbox.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/middleware/dropdown.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/middleware/image.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/middleware/radio.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/middleware/signature.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/middleware/text.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/patterns.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/utils.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/watermark.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/widgets/__init__.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/widgets/base.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/widgets/checkbox.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/widgets/dropdown.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm/widgets/text.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm.egg-info/dependency_links.txt +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm.egg-info/requires.txt +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/PyPDFForm.egg-info/top_level.txt +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/README.md +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/setup.cfg +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/setup.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_create_widget.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_dropdown.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_dropdown_simple.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_fill_max_length_text_field.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_fill_max_length_text_field_simple.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_functional.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_functional_simple.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_paragraph.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_paragraph_simple.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_preview.py +0 -0
- {pypdfform-1.4.26 → pypdfform-1.4.27}/tests/test_signature.py +0 -0
|
@@ -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,26 @@ 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
|
|
|
180
|
+
# pylint: disable=too-many-branches
|
|
170
181
|
pdf = PdfReader(stream_to_io(template))
|
|
182
|
+
enable_adobe_mode(pdf, adobe_mode)
|
|
171
183
|
out = PdfWriter()
|
|
172
184
|
out.append(pdf)
|
|
173
185
|
|
|
@@ -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
|
|
@@ -58,7 +58,10 @@ class FormWrapper:
|
|
|
58
58
|
widgets[key].value = value
|
|
59
59
|
|
|
60
60
|
self.stream = simple_fill(
|
|
61
|
-
self.read(),
|
|
61
|
+
self.read(),
|
|
62
|
+
widgets,
|
|
63
|
+
flatten=kwargs.get("flatten", False),
|
|
64
|
+
adobe_mode=kwargs.get("adobe_mode", False),
|
|
62
65
|
)
|
|
63
66
|
|
|
64
67
|
return self
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from PyPDFForm import FormWrapper
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_fill_sejda_complex(sejda_template_complex, pdf_samples, request):
|
|
9
|
+
expected_path = os.path.join(
|
|
10
|
+
pdf_samples, "adobe_mode", "paragraph", "sample_filled_sejda_complex.pdf"
|
|
11
|
+
)
|
|
12
|
+
with open(expected_path, "rb+") as f:
|
|
13
|
+
obj = FormWrapper(sejda_template_complex).fill(
|
|
14
|
+
{
|
|
15
|
+
"checkbox": True,
|
|
16
|
+
"radio": 0,
|
|
17
|
+
"dropdown_font_auto_left": 0,
|
|
18
|
+
"dropdown_font_auto_center": 1,
|
|
19
|
+
"dropdown_font_auto_right": 2,
|
|
20
|
+
"dropdown_font_ten_left": 0,
|
|
21
|
+
"dropdown_font_ten_center": 1,
|
|
22
|
+
"dropdown_font_ten_right": 2,
|
|
23
|
+
"paragraph_font_auto_left": "paragraph_font_auto_left",
|
|
24
|
+
"paragraph_font_auto_center": "paragraph_font_auto_center",
|
|
25
|
+
"paragraph_font_auto_right": "paragraph_font_auto_right",
|
|
26
|
+
"paragraph_font_ten_left": "paragraph_font_ten_left",
|
|
27
|
+
"paragraph_font_ten_center": "paragraph_font_ten_center",
|
|
28
|
+
"paragraph_font_ten_right": "paragraph_font_ten_right",
|
|
29
|
+
"text__font_auto_left": "test text",
|
|
30
|
+
"text_font_auto_center": "test text",
|
|
31
|
+
"text_font_auto_right": "test text",
|
|
32
|
+
"text_font_ten_left": "text_font_ten_left",
|
|
33
|
+
"text_font_ten_center": "text_font_ten_center",
|
|
34
|
+
"text_font_ten_right": "text_font_ten_right",
|
|
35
|
+
},
|
|
36
|
+
adobe_mode=True,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
request.config.results["expected_path"] = expected_path
|
|
40
|
+
request.config.results["stream"] = obj.read()
|
|
41
|
+
|
|
42
|
+
expected = f.read()
|
|
43
|
+
|
|
44
|
+
assert len(obj.read()) == len(expected)
|
|
45
|
+
assert obj.stream == expected
|
|
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
|
|
File without changes
|
|
File without changes
|