PyPDFForm 1.5.2__tar.gz → 1.5.4__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.

Files changed (50) hide show
  1. {pypdfform-1.5.2 → pypdfform-1.5.4}/PKG-INFO +1 -1
  2. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/__init__.py +1 -1
  3. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/coordinate.py +15 -0
  4. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/filler.py +5 -2
  5. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/image.py +13 -1
  6. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/middleware/image.py +2 -0
  7. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/middleware/radio.py +1 -10
  8. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/middleware/signature.py +2 -0
  9. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/wrapper.py +6 -3
  10. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm.egg-info/PKG-INFO +1 -1
  11. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_functional_simple.py +30 -1
  12. pypdfform-1.5.4/tests/test_signature.py +180 -0
  13. pypdfform-1.5.2/tests/test_signature.py +0 -61
  14. {pypdfform-1.5.2 → pypdfform-1.5.4}/LICENSE +0 -0
  15. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/adapter.py +0 -0
  16. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/constants.py +0 -0
  17. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/font.py +0 -0
  18. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/middleware/__init__.py +0 -0
  19. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/middleware/base.py +0 -0
  20. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/middleware/checkbox.py +0 -0
  21. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/middleware/dropdown.py +0 -0
  22. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/middleware/text.py +0 -0
  23. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/patterns.py +0 -0
  24. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/template.py +0 -0
  25. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/utils.py +0 -0
  26. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/watermark.py +0 -0
  27. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/widgets/__init__.py +0 -0
  28. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/widgets/base.py +0 -0
  29. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/widgets/checkbox.py +0 -0
  30. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/widgets/dropdown.py +0 -0
  31. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm/widgets/text.py +0 -0
  32. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm.egg-info/SOURCES.txt +0 -0
  33. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm.egg-info/dependency_links.txt +0 -0
  34. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm.egg-info/requires.txt +0 -0
  35. {pypdfform-1.5.2 → pypdfform-1.5.4}/PyPDFForm.egg-info/top_level.txt +0 -0
  36. {pypdfform-1.5.2 → pypdfform-1.5.4}/README.md +0 -0
  37. {pypdfform-1.5.2 → pypdfform-1.5.4}/setup.cfg +0 -0
  38. {pypdfform-1.5.2 → pypdfform-1.5.4}/setup.py +0 -0
  39. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_adobe_mode.py +0 -0
  40. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_create_widget.py +0 -0
  41. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_dropdown.py +0 -0
  42. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_dropdown_simple.py +0 -0
  43. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_fill_max_length_text_field.py +0 -0
  44. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_fill_max_length_text_field_simple.py +0 -0
  45. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_fill_method.py +0 -0
  46. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_functional.py +0 -0
  47. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_paragraph.py +0 -0
  48. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_paragraph_simple.py +0 -0
  49. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_preview.py +0 -0
  50. {pypdfform-1.5.2 → pypdfform-1.5.4}/tests/test_use_full_widget_name.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: PyPDFForm
3
- Version: 1.5.2
3
+ Version: 1.5.4
4
4
  Summary: The Python library for PDF forms.
5
5
  Home-page: https://github.com/chinapandaman/PyPDFForm
6
6
  Author: Jinge Li
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Contains any object users might need."""
3
3
 
4
- __version__ = "1.5.2"
4
+ __version__ = "1.5.4"
5
5
 
6
6
  from .wrapper import FormWrapper, PdfWrapper
7
7
 
@@ -40,6 +40,9 @@ def get_draw_checkbox_radio_coordinates(
40
40
 
41
41
  def get_draw_image_coordinates_resolutions(
42
42
  widget: dict,
43
+ preserve_aspect_ratio: bool,
44
+ image_width: float,
45
+ image_height: float,
43
46
  ) -> Tuple[float, float, float, float]:
44
47
  """
45
48
  Returns coordinates and resolutions to draw image at given a PDF form signature/image widget.
@@ -50,6 +53,18 @@ def get_draw_image_coordinates_resolutions(
50
53
  width = abs(float(widget[Rect][0]) - float(widget[Rect][2]))
51
54
  height = abs(float(widget[Rect][1]) - float(widget[Rect][3]))
52
55
 
56
+ if preserve_aspect_ratio:
57
+ ratio = max(image_width / width, image_height / height)
58
+
59
+ new_width = image_width / ratio
60
+ new_height = image_height / ratio
61
+
62
+ x += abs(new_width - width) / 2
63
+ y += abs(new_height - height) / 2
64
+
65
+ width = new_width
66
+ height = new_height
67
+
53
68
  return x, y, width, height
54
69
 
55
70
 
@@ -13,7 +13,7 @@ from .coordinate import (get_draw_checkbox_radio_coordinates,
13
13
  get_draw_text_coordinates,
14
14
  get_text_line_x_coordinates)
15
15
  from .font import checkbox_radio_font_size
16
- from .image import any_image_to_jpg
16
+ from .image import any_image_to_jpg, get_image_dimensions
17
17
  from .middleware.checkbox import Checkbox
18
18
  from .middleware.dropdown import Dropdown
19
19
  from .middleware.image import Image
@@ -62,7 +62,10 @@ def signature_image_handler(
62
62
  if stream is not None:
63
63
  any_image_to_draw = True
64
64
  stream = any_image_to_jpg(stream)
65
- x, y, width, height = get_draw_image_coordinates_resolutions(widget)
65
+ image_width, image_height = get_image_dimensions(stream)
66
+ x, y, width, height = get_draw_image_coordinates_resolutions(
67
+ widget, middleware.preserve_aspect_ratio, image_width, image_height
68
+ )
66
69
  images_to_draw.append(
67
70
  [
68
71
  stream,
@@ -2,7 +2,7 @@
2
2
  """Contains helpers for image."""
3
3
 
4
4
  from io import BytesIO
5
- from typing import Union
5
+ from typing import Tuple, Union
6
6
 
7
7
  from PIL import Image
8
8
 
@@ -28,6 +28,18 @@ def rotate_image(image_stream: bytes, rotation: Union[float, int]) -> bytes:
28
28
  return result
29
29
 
30
30
 
31
+ def get_image_dimensions(image_stream: bytes) -> Tuple[float, float]:
32
+ """Gets the width and height of an image."""
33
+
34
+ buff = BytesIO()
35
+ buff.write(image_stream)
36
+ buff.seek(0)
37
+
38
+ image = Image.open(buff)
39
+
40
+ return image.size
41
+
42
+
31
43
  def any_image_to_jpg(image_stream: bytes) -> bytes:
32
44
  """Converts an image of any type to jpg."""
33
45
 
@@ -6,3 +6,5 @@ from .signature import Signature
6
6
 
7
7
  class Image(Signature):
8
8
  """A class to represent an image field widget."""
9
+
10
+ preserve_aspect_ratio = False
@@ -7,16 +7,7 @@ from .checkbox import Checkbox
7
7
  class Radio(Checkbox):
8
8
  """A class to represent a radiobutton widget."""
9
9
 
10
- def __init__(
11
- self,
12
- name: str,
13
- value: int = None,
14
- ) -> None:
15
- """Constructs all attributes for the radiobutton."""
16
-
17
- super().__init__(name, value)
18
-
19
- self.number_of_options = 0
10
+ number_of_options = 0
20
11
 
21
12
  @property
22
13
  def schema_definition(self) -> dict:
@@ -11,6 +11,8 @@ from .base import Widget
11
11
  class Signature(Widget):
12
12
  """A class to represent a signature field widget."""
13
13
 
14
+ preserve_aspect_ratio = True
15
+
14
16
  def __init__(
15
17
  self,
16
18
  name: str,
@@ -166,10 +166,13 @@ class PdfWrapper(FormWrapper):
166
166
  if not other.stream:
167
167
  return self
168
168
 
169
- new_obj = self.__class__()
170
- new_obj.stream = merge_two_pdfs(self.stream, other.stream)
169
+ for k in self.widgets:
170
+ if k in other.widgets:
171
+ other.update_widget_key(k, f"{k}-{id(other)}", defer=True)
171
172
 
172
- return new_obj
173
+ other.commit_widget_key_updates()
174
+
175
+ return self.__class__(merge_two_pdfs(self.stream, other.stream))
173
176
 
174
177
  @property
175
178
  def preview(self) -> bytes:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: PyPDFForm
3
- Version: 1.5.2
3
+ Version: 1.5.4
4
4
  Summary: The Python library for PDF forms.
5
5
  Home-page: https://github.com/chinapandaman/PyPDFForm
6
6
  Author: Jinge Li
@@ -2,7 +2,9 @@
2
2
 
3
3
  import os
4
4
 
5
- from PyPDFForm import FormWrapper
5
+ from PyPDFForm import FormWrapper, PdfWrapper
6
+ from PyPDFForm.constants import T, V
7
+ from PyPDFForm.template import get_widgets_by_page
6
8
 
7
9
 
8
10
  def test_fill(template_stream, pdf_samples, data_dict, request):
@@ -151,3 +153,30 @@ def test_undo_checkbox(pdf_samples, request):
151
153
 
152
154
  assert len(obj.stream) == len(expected)
153
155
  assert obj.stream == expected
156
+
157
+
158
+ def test_add_object_id(template_stream):
159
+ result = PdfWrapper()
160
+ ids = []
161
+
162
+ for i in range(5):
163
+ obj = PdfWrapper(
164
+ FormWrapper(template_stream).fill({"test": f"value-{i}"}).read()
165
+ )
166
+ result += obj
167
+ ids.append(id(obj))
168
+
169
+ merged = PdfWrapper(result.read())
170
+
171
+ for each in ids[1:]:
172
+ assert f"test-{each}" in merged.widgets
173
+
174
+ for page, widgets in get_widgets_by_page(result.read()).items():
175
+ for widget in widgets:
176
+ assert widget[T] in merged.widgets
177
+ if widget[T] == "test":
178
+ assert widget[V] == "value-0"
179
+ elif V in widget and "value-" in widget[V]:
180
+ assert widget[V] == f"value-{page // 3}"
181
+ assert widget[T].split("-")[0] == "test"
182
+ assert int(widget[T].split("-")[1]) in ids[1:]
@@ -0,0 +1,180 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import os
4
+
5
+ from PyPDFForm import PdfWrapper
6
+
7
+
8
+ def test_fill_signature(pdf_samples, image_samples, request):
9
+ expected_path = os.path.join(pdf_samples, "signature", "test_fill_signature.pdf")
10
+ with open(expected_path, "rb+") as f:
11
+ obj = PdfWrapper(
12
+ os.path.join(pdf_samples, "signature", "sample_template_with_signature.pdf")
13
+ ).fill({"signature": os.path.join(image_samples, "sample_signature.png")})
14
+
15
+ request.config.results["expected_path"] = expected_path
16
+ request.config.results["stream"] = obj.read()
17
+
18
+ expected = f.read()
19
+
20
+ if os.name != "nt":
21
+ assert len(obj.read()) == len(expected)
22
+ assert obj.read() == expected
23
+
24
+
25
+ def test_signature_schema(pdf_samples):
26
+ obj = PdfWrapper(
27
+ os.path.join(pdf_samples, "signature", "sample_template_with_signature.pdf")
28
+ )
29
+
30
+ assert obj.widgets["signature"].schema_definition == {"type": "string"}
31
+
32
+
33
+ def test_signature_sample_value(pdf_samples):
34
+ obj = PdfWrapper(
35
+ os.path.join(pdf_samples, "signature", "sample_template_with_signature.pdf")
36
+ )
37
+
38
+ assert obj.widgets["signature"].sample_value == os.path.expanduser(
39
+ "~/Downloads/sample_image.jpg"
40
+ )
41
+
42
+
43
+ def test_fill_signature_overlap(pdf_samples, image_samples, request):
44
+ expected_path = os.path.join(
45
+ pdf_samples, "signature", "test_fill_signature_overlap.pdf"
46
+ )
47
+ with open(expected_path, "rb+") as f:
48
+ obj = PdfWrapper(
49
+ os.path.join(
50
+ pdf_samples, "signature", "sample_template_with_signature_overlap.pdf"
51
+ )
52
+ ).fill({"signature": os.path.join(image_samples, "sample_signature.png")})
53
+
54
+ request.config.results["expected_path"] = expected_path
55
+ request.config.results["stream"] = obj.read()
56
+
57
+ expected = f.read()
58
+
59
+ if os.name != "nt":
60
+ assert len(obj.read()) == len(expected)
61
+ assert obj.read() == expected
62
+
63
+
64
+ def test_fill_signature_overlap_not_preserve_aspect_ratio(
65
+ pdf_samples, image_samples, request
66
+ ):
67
+ expected_path = os.path.join(
68
+ pdf_samples,
69
+ "signature",
70
+ "test_fill_signature_overlap_not_preserve_aspect_ratio.pdf",
71
+ )
72
+ with open(expected_path, "rb+") as f:
73
+ obj = PdfWrapper(
74
+ os.path.join(
75
+ pdf_samples, "signature", "sample_template_with_signature_overlap.pdf"
76
+ )
77
+ )
78
+ obj.widgets["signature"].preserve_aspect_ratio = False
79
+ obj.fill({"signature": os.path.join(image_samples, "sample_signature.png")})
80
+
81
+ request.config.results["expected_path"] = expected_path
82
+ request.config.results["stream"] = obj.read()
83
+
84
+ expected = f.read()
85
+
86
+ if os.name != "nt":
87
+ assert len(obj.read()) == len(expected)
88
+ assert obj.read() == expected
89
+
90
+
91
+ def test_fill_small_icon(pdf_samples, image_samples, request):
92
+ expected_path = os.path.join(pdf_samples, "signature", "test_fill_small_icon.pdf")
93
+ with open(expected_path, "rb+") as f:
94
+ obj = PdfWrapper(
95
+ os.path.join(
96
+ pdf_samples, "signature", "sample_template_with_signature_overlap.pdf"
97
+ )
98
+ )
99
+ obj.fill({"signature": os.path.join(image_samples, "small_icon.png")})
100
+
101
+ request.config.results["expected_path"] = expected_path
102
+ request.config.results["stream"] = obj.read()
103
+
104
+ expected = f.read()
105
+
106
+ if os.name != "nt":
107
+ assert len(obj.read()) == len(expected)
108
+ assert obj.read() == expected
109
+
110
+
111
+ def test_fill_small_icon_not_preserve_aspect_ratio(pdf_samples, image_samples, request):
112
+ expected_path = os.path.join(
113
+ pdf_samples, "signature", "test_fill_small_icon_not_preserve_aspect_ratio.pdf"
114
+ )
115
+ with open(expected_path, "rb+") as f:
116
+ obj = PdfWrapper(
117
+ os.path.join(
118
+ pdf_samples, "signature", "sample_template_with_signature_overlap.pdf"
119
+ )
120
+ )
121
+ obj.widgets["signature"].preserve_aspect_ratio = False
122
+ obj.fill({"signature": os.path.join(image_samples, "small_icon.png")})
123
+
124
+ request.config.results["expected_path"] = expected_path
125
+ request.config.results["stream"] = obj.read()
126
+
127
+ expected = f.read()
128
+
129
+ if os.name != "nt":
130
+ assert len(obj.read()) == len(expected)
131
+ assert obj.read() == expected
132
+
133
+
134
+ def test_fill_vertical_image(pdf_samples, image_samples, request):
135
+ expected_path = os.path.join(
136
+ pdf_samples, "signature", "test_fill_vertical_image.pdf"
137
+ )
138
+ with open(expected_path, "rb+") as f:
139
+ obj = PdfWrapper(
140
+ os.path.join(
141
+ pdf_samples, "signature", "sample_template_with_signature_overlap.pdf"
142
+ )
143
+ )
144
+ obj.fill({"signature": os.path.join(image_samples, "vertical_image.jpg")})
145
+
146
+ request.config.results["expected_path"] = expected_path
147
+ request.config.results["stream"] = obj.read()
148
+
149
+ expected = f.read()
150
+
151
+ if os.name != "nt":
152
+ assert len(obj.read()) == len(expected)
153
+ assert obj.read() == expected
154
+
155
+
156
+ def test_fill_vertical_image_not_preserve_aspect_ratio(
157
+ pdf_samples, image_samples, request
158
+ ):
159
+ expected_path = os.path.join(
160
+ pdf_samples,
161
+ "signature",
162
+ "test_fill_vertical_image_not_preserve_aspect_ratio.pdf",
163
+ )
164
+ with open(expected_path, "rb+") as f:
165
+ obj = PdfWrapper(
166
+ os.path.join(
167
+ pdf_samples, "signature", "sample_template_with_signature_overlap.pdf"
168
+ )
169
+ )
170
+ obj.widgets["signature"].preserve_aspect_ratio = False
171
+ obj.fill({"signature": os.path.join(image_samples, "vertical_image.jpg")})
172
+
173
+ request.config.results["expected_path"] = expected_path
174
+ request.config.results["stream"] = obj.read()
175
+
176
+ expected = f.read()
177
+
178
+ if os.name != "nt":
179
+ assert len(obj.read()) == len(expected)
180
+ assert obj.read() == expected
@@ -1,61 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- import os
4
-
5
- from PyPDFForm import PdfWrapper
6
-
7
-
8
- def test_fill_signature(pdf_samples, image_samples, request):
9
- expected_path = os.path.join(pdf_samples, "signature", "test_fill_signature.pdf")
10
- with open(expected_path, "rb+") as f:
11
- obj = PdfWrapper(
12
- os.path.join(pdf_samples, "signature", "sample_template_with_signature.pdf")
13
- ).fill({"signature": os.path.join(image_samples, "sample_signature.png")})
14
-
15
- request.config.results["expected_path"] = expected_path
16
- request.config.results["stream"] = obj.read()
17
-
18
- expected = f.read()
19
-
20
- if os.name != "nt":
21
- assert len(obj.read()) == len(expected)
22
- assert obj.read() == expected
23
-
24
-
25
- def test_signature_schema(pdf_samples):
26
- obj = PdfWrapper(
27
- os.path.join(pdf_samples, "signature", "sample_template_with_signature.pdf")
28
- )
29
-
30
- assert obj.widgets["signature"].schema_definition == {"type": "string"}
31
-
32
-
33
- def test_signature_sample_value(pdf_samples):
34
- obj = PdfWrapper(
35
- os.path.join(pdf_samples, "signature", "sample_template_with_signature.pdf")
36
- )
37
-
38
- assert obj.widgets["signature"].sample_value == os.path.expanduser(
39
- "~/Downloads/sample_image.jpg"
40
- )
41
-
42
-
43
- def test_fill_signature_overlap(pdf_samples, image_samples, request):
44
- expected_path = os.path.join(
45
- pdf_samples, "signature", "test_fill_signature_overlap.pdf"
46
- )
47
- with open(expected_path, "rb+") as f:
48
- obj = PdfWrapper(
49
- os.path.join(
50
- pdf_samples, "signature", "sample_template_with_signature_overlap.pdf"
51
- )
52
- ).fill({"signature": os.path.join(image_samples, "sample_signature.png")})
53
-
54
- request.config.results["expected_path"] = expected_path
55
- request.config.results["stream"] = obj.read()
56
-
57
- expected = f.read()
58
-
59
- if os.name != "nt":
60
- assert len(obj.read()) == len(expected)
61
- assert obj.read() == expected
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes