PyPDFForm 4.7.5__tar.gz → 4.7.7__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.
Files changed (74) hide show
  1. {pypdfform-4.7.5 → pypdfform-4.7.7}/PKG-INFO +1 -1
  2. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/__init__.py +1 -1
  3. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/constants.py +2 -1
  4. pypdfform-4.7.7/PyPDFForm/deprecation.py +74 -0
  5. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/wrapper.py +5 -0
  6. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm.egg-info/PKG-INFO +1 -1
  7. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_create_widget.py +216 -206
  8. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_functional.py +73 -5
  9. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_need_appearances.py +45 -53
  10. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_widget_attr_trigger.py +2 -2
  11. pypdfform-4.7.5/PyPDFForm/deprecation.py +0 -30
  12. {pypdfform-4.7.5 → pypdfform-4.7.7}/LICENSE +0 -0
  13. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/adapter.py +0 -0
  14. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/annotations/__init__.py +0 -0
  15. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/annotations/base.py +0 -0
  16. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/annotations/link.py +0 -0
  17. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/annotations/stamp.py +0 -0
  18. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/annotations/text.py +0 -0
  19. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/annotations/text_markup.py +0 -0
  20. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/assets/__init__.py +0 -0
  21. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/assets/bedrock.py +0 -0
  22. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/assets/blank.py +0 -0
  23. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/coordinate.py +0 -0
  24. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/egress.py +0 -0
  25. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/filler.py +0 -0
  26. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/font.py +0 -0
  27. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/hooks.py +0 -0
  28. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/image.py +0 -0
  29. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/middleware/__init__.py +0 -0
  30. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/middleware/base.py +0 -0
  31. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/middleware/checkbox.py +0 -0
  32. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/middleware/dropdown.py +0 -0
  33. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/middleware/image.py +0 -0
  34. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/middleware/radio.py +0 -0
  35. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/middleware/signature.py +0 -0
  36. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/middleware/text.py +0 -0
  37. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/patterns.py +0 -0
  38. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/raw/__init__.py +0 -0
  39. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/raw/circle.py +0 -0
  40. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/raw/ellipse.py +0 -0
  41. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/raw/image.py +0 -0
  42. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/raw/line.py +0 -0
  43. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/raw/rect.py +0 -0
  44. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/raw/text.py +0 -0
  45. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/template.py +0 -0
  46. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/types.py +0 -0
  47. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/utils.py +0 -0
  48. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/watermark.py +0 -0
  49. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/widgets/__init__.py +0 -0
  50. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/widgets/base.py +0 -0
  51. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/widgets/checkbox.py +0 -0
  52. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/widgets/dropdown.py +0 -0
  53. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/widgets/image.py +0 -0
  54. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/widgets/radio.py +0 -0
  55. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/widgets/signature.py +0 -0
  56. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm/widgets/text.py +0 -0
  57. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm.egg-info/SOURCES.txt +0 -0
  58. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm.egg-info/dependency_links.txt +0 -0
  59. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm.egg-info/requires.txt +0 -0
  60. {pypdfform-4.7.5 → pypdfform-4.7.7}/PyPDFForm.egg-info/top_level.txt +0 -0
  61. {pypdfform-4.7.5 → pypdfform-4.7.7}/README.md +0 -0
  62. {pypdfform-4.7.5 → pypdfform-4.7.7}/pyproject.toml +0 -0
  63. {pypdfform-4.7.5 → pypdfform-4.7.7}/setup.cfg +0 -0
  64. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_bulk_create_fields.py +0 -0
  65. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_draw_elements.py +0 -0
  66. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_dropdown.py +0 -0
  67. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_extract_middleware_attributes.py +0 -0
  68. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_fill_max_length_text_field.py +0 -0
  69. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_font_widths.py +0 -0
  70. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_generate_appearance_streams.py +0 -0
  71. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_js.py +0 -0
  72. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_paragraph.py +0 -0
  73. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_signature.py +0 -0
  74. {pypdfform-4.7.5 → pypdfform-4.7.7}/tests/test_use_full_widget_name.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPDFForm
3
- Version: 4.7.5
3
+ Version: 4.7.7
4
4
  Summary: The Python library for PDF forms.
5
5
  Author: Jinge Li
6
6
  License-Expression: MIT
@@ -22,7 +22,7 @@ PyPDFForm aims to simplify PDF form manipulation, making it accessible to develo
22
22
 
23
23
  import logging
24
24
 
25
- __version__ = "4.7.5"
25
+ __version__ = "4.7.7"
26
26
 
27
27
  from .annotations import Annotations
28
28
  from .assets.blank import BlankPage
@@ -28,7 +28,8 @@ VERSION_IDENTIFIERS = [
28
28
  ]
29
29
  VERSION_IDENTIFIER_PREFIX = "%PDF-".encode("utf-8")
30
30
 
31
- DEPRECATION_NOTICE = "{} will be deprecated soon. Use {} instead."
31
+ DEPRECATION_NOTICE = "{} will be deprecated soon."
32
+ DEPRECATION_REPLACE_NOTICE = "Use {} instead."
32
33
 
33
34
  Title = "/Title"
34
35
  Annots = "/Annots"
@@ -0,0 +1,74 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ A module for handling deprecation notices within the PyPDFForm library.
4
+
5
+ This module provides utility functions to issue standard DeprecationWarning
6
+ messages, ensuring consistency across the library when notifying users of
7
+ deprecated features.
8
+ """
9
+
10
+ from functools import wraps
11
+ from warnings import warn
12
+
13
+ from .constants import DEPRECATION_NOTICE, DEPRECATION_REPLACE_NOTICE
14
+
15
+
16
+ def deprecation_notice(to_replace: str, param: str = "") -> callable:
17
+ """
18
+ Issues a DeprecationWarning when a deprecated method is called. Can also be called
19
+ directly within a method to emit deprecation warnings conditionally.
20
+
21
+ Args:
22
+ to_replace (str): The name of the method to use instead.
23
+ param (str): Optional parameter name to include in the deprecation notice.
24
+
25
+ Returns:
26
+ callable: A decorator function. The decorator has an `emit_notice` method
27
+ that can be called directly within a method body for conditional emission.
28
+
29
+ Examples:
30
+ As a decorator (emits on every call)::
31
+
32
+ @deprecation_notice(to_replace="new_method")
33
+ def old_method(self):
34
+ pass
35
+
36
+ As a decorator with a parameter (emits on every call)::
37
+
38
+ @deprecation_notice(to_replace="old_method.new_param.", param="old_param")
39
+ def old_method(self, old_param=None):
40
+ pass
41
+
42
+ Conditionally within a method body::
43
+
44
+ def my_method(self, use_legacy=False):
45
+ if use_legacy:
46
+ deprecation_notice(to_replace="", param="use_legacy").emit_notice(self, "my_method")
47
+ # legacy logic here
48
+ """
49
+
50
+ def _emit(class_name: str, method_name: str, stacklevel: int):
51
+ to_deprecate = (
52
+ f"{class_name}.{method_name}.{param}"
53
+ if param
54
+ else f"{class_name}.{method_name}"
55
+ )
56
+ notice = DEPRECATION_NOTICE.format(to_deprecate)
57
+ if to_replace:
58
+ replacement = f"{class_name}.{to_replace}"
59
+ notice = f"{notice} {DEPRECATION_REPLACE_NOTICE.format(replacement)}"
60
+ warn(notice, DeprecationWarning, stacklevel=stacklevel)
61
+
62
+ def decorator(func: callable) -> callable:
63
+ @wraps(func)
64
+ def wrapper(*args, **kwargs):
65
+ _emit(args[0].__class__.__name__, func.__name__, stacklevel=3)
66
+ return func(*args, **kwargs)
67
+
68
+ return wrapper
69
+
70
+ def emit_notice(obj, method_name: str):
71
+ _emit(obj.__class__.__name__, method_name, stacklevel=4)
72
+
73
+ decorator.emit_notice = emit_notice
74
+ return decorator
@@ -29,6 +29,7 @@ from .adapter import (fp_or_f_obj_or_f_content_to_content,
29
29
  fp_or_f_obj_or_stream_to_stream)
30
30
  from .constants import VERSION_IDENTIFIER_PREFIX, VERSION_IDENTIFIERS
31
31
  from .coordinate import generate_coordinate_grid
32
+ from .deprecation import deprecation_notice
32
33
  from .egress import appearance_streams_handler, preserve_pdf_properties
33
34
  from .filler import fill
34
35
  from .font import (get_all_available_fonts, register_font_acroform,
@@ -664,6 +665,7 @@ class PdfWrapper:
664
665
 
665
666
  return self
666
667
 
668
+ @deprecation_notice(to_replace="bulk_create_fields")
667
669
  def create_field(
668
670
  self,
669
671
  field: FieldTypes,
@@ -710,6 +712,9 @@ class PdfWrapper:
710
712
  raise NotImplementedError
711
713
 
712
714
  if defer:
715
+ deprecation_notice(to_replace="", param="defer").emit_notice(
716
+ self, "update_widget_key"
717
+ )
713
718
  self._keys_to_update.append((old_key, new_key, index))
714
719
  return self
715
720
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPDFForm
3
- Version: 4.7.5
3
+ Version: 4.7.7
4
4
  Summary: The Python library for PDF forms.
5
5
  Author: Jinge Li
6
6
  License-Expression: MIT
@@ -7,25 +7,42 @@ import pytest
7
7
  from PyPDFForm import Fields, PdfWrapper
8
8
 
9
9
 
10
+ def test_create_field_deprecated(template_stream):
11
+ with pytest.warns(
12
+ DeprecationWarning,
13
+ match="PdfWrapper.create_field will be deprecated soon. Use PdfWrapper.bulk_create_fields instead.",
14
+ ):
15
+ assert (
16
+ PdfWrapper(template_stream)
17
+ .create_field(Fields.TextField("foo", 1, 100, 100))
18
+ .read()
19
+ == PdfWrapper(template_stream)
20
+ .bulk_create_fields([Fields.TextField("foo", 1, 100, 100)])
21
+ .read()
22
+ )
23
+
24
+
10
25
  @pytest.mark.posix_only
11
26
  def test_create_checkbox_complex_fill(template_stream, pdf_samples, request):
12
27
  expected_path = os.path.join(
13
28
  pdf_samples, "widget", "test_create_checkbox_complex_fill.pdf"
14
29
  )
15
30
  with open(expected_path, "rb+") as f:
16
- obj = PdfWrapper(template_stream).create_field(
17
- Fields.CheckBoxField(
18
- name="foo",
19
- page_number=1,
20
- x=100,
21
- y=100,
22
- size=100,
23
- button_style="check",
24
- tick_color=(0, 1, 0),
25
- bg_color=(0, 0, 1),
26
- border_color=(1, 0, 0),
27
- border_width=5,
28
- )
31
+ obj = PdfWrapper(template_stream).bulk_create_fields(
32
+ [
33
+ Fields.CheckBoxField(
34
+ name="foo",
35
+ page_number=1,
36
+ x=100,
37
+ y=100,
38
+ size=100,
39
+ button_style="check",
40
+ tick_color=(0, 1, 0),
41
+ bg_color=(0, 0, 1),
42
+ border_color=(1, 0, 0),
43
+ border_width=5,
44
+ )
45
+ ]
29
46
  )
30
47
  obj.fill(obj.sample_data)
31
48
 
@@ -46,14 +63,16 @@ def test_create_checkbox_check_fill(template_stream, pdf_samples, request):
46
63
  pdf_samples, "widget", "test_create_checkbox_check_fill.pdf"
47
64
  )
48
65
  with open(expected_path, "rb+") as f:
49
- obj = PdfWrapper(template_stream).create_field(
50
- Fields.CheckBoxField(
51
- name="foo",
52
- page_number=1,
53
- x=100,
54
- y=100,
55
- button_style="check",
56
- )
66
+ obj = PdfWrapper(template_stream).bulk_create_fields(
67
+ [
68
+ Fields.CheckBoxField(
69
+ name="foo",
70
+ page_number=1,
71
+ x=100,
72
+ y=100,
73
+ button_style="check",
74
+ )
75
+ ]
57
76
  )
58
77
  obj.fill(obj.sample_data)
59
78
 
@@ -72,14 +91,16 @@ def test_create_checkbox_circle_fill(template_stream, pdf_samples, request):
72
91
  pdf_samples, "widget", "test_create_checkbox_circle_fill.pdf"
73
92
  )
74
93
  with open(expected_path, "rb+") as f:
75
- obj = PdfWrapper(template_stream).create_field(
76
- Fields.CheckBoxField(
77
- name="foo",
78
- page_number=1,
79
- x=100,
80
- y=100,
81
- button_style="circle",
82
- )
94
+ obj = PdfWrapper(template_stream).bulk_create_fields(
95
+ [
96
+ Fields.CheckBoxField(
97
+ name="foo",
98
+ page_number=1,
99
+ x=100,
100
+ y=100,
101
+ button_style="circle",
102
+ )
103
+ ]
83
104
  )
84
105
  obj.fill(obj.sample_data)
85
106
 
@@ -98,14 +119,16 @@ def test_create_checkbox_cross_fill(template_stream, pdf_samples, request):
98
119
  pdf_samples, "widget", "test_create_checkbox_cross_fill.pdf"
99
120
  )
100
121
  with open(expected_path, "rb+") as f:
101
- obj = PdfWrapper(template_stream).create_field(
102
- Fields.CheckBoxField(
103
- name="foo",
104
- page_number=1,
105
- x=100,
106
- y=100,
107
- button_style="cross",
108
- )
122
+ obj = PdfWrapper(template_stream).bulk_create_fields(
123
+ [
124
+ Fields.CheckBoxField(
125
+ name="foo",
126
+ page_number=1,
127
+ x=100,
128
+ y=100,
129
+ button_style="cross",
130
+ )
131
+ ]
109
132
  )
110
133
  obj.fill(obj.sample_data)
111
134
 
@@ -124,14 +147,16 @@ def test_create_text_alpha_bg_color(template_stream, pdf_samples, request):
124
147
  pdf_samples, "widget", "test_create_text_alpha_bg_color.pdf"
125
148
  )
126
149
  with open(expected_path, "rb+") as f:
127
- obj = PdfWrapper(template_stream).create_field(
128
- Fields.TextField(
129
- name="foo",
130
- page_number=1,
131
- x=100,
132
- y=100,
133
- bg_color=(0, 0, 1, 0),
134
- )
150
+ obj = PdfWrapper(template_stream).bulk_create_fields(
151
+ [
152
+ Fields.TextField(
153
+ name="foo",
154
+ page_number=1,
155
+ x=100,
156
+ y=100,
157
+ bg_color=(0, 0, 1, 0),
158
+ )
159
+ ]
135
160
  )
136
161
  assert obj.schema["properties"]["foo"]["type"] == "string"
137
162
 
@@ -150,14 +175,16 @@ def test_create_text_align_center(template_stream, pdf_samples, request):
150
175
  pdf_samples, "widget", "test_create_text_align_center.pdf"
151
176
  )
152
177
  with open(expected_path, "rb+") as f:
153
- obj = PdfWrapper(template_stream).create_field(
154
- Fields.TextField(
155
- name="foo",
156
- page_number=1,
157
- x=100,
158
- y=100,
159
- alignment=1,
160
- )
178
+ obj = PdfWrapper(template_stream).bulk_create_fields(
179
+ [
180
+ Fields.TextField(
181
+ name="foo",
182
+ page_number=1,
183
+ x=100,
184
+ y=100,
185
+ alignment=1,
186
+ )
187
+ ]
161
188
  )
162
189
  assert obj.schema["properties"]["foo"]["type"] == "string"
163
190
 
@@ -176,14 +203,16 @@ def test_create_text_multiline(template_stream, pdf_samples, request):
176
203
  pdf_samples, "widget", "test_create_text_align_multiline.pdf"
177
204
  )
178
205
  with open(expected_path, "rb+") as f:
179
- obj = PdfWrapper(template_stream).create_field(
180
- Fields.TextField(
181
- name="foo",
182
- page_number=1,
183
- x=100,
184
- y=100,
185
- multiline=True,
186
- )
206
+ obj = PdfWrapper(template_stream).bulk_create_fields(
207
+ [
208
+ Fields.TextField(
209
+ name="foo",
210
+ page_number=1,
211
+ x=100,
212
+ y=100,
213
+ multiline=True,
214
+ )
215
+ ]
187
216
  )
188
217
  assert obj.schema["properties"]["foo"]["type"] == "string"
189
218
 
@@ -207,22 +236,24 @@ def test_create_text_complex_filled(
207
236
  obj = (
208
237
  PdfWrapper(template_stream)
209
238
  .register_font("new_font", sample_font_stream)
210
- .create_field(
211
- Fields.TextField(
212
- name="foo",
213
- page_number=1,
214
- x=100,
215
- y=100,
216
- width=400,
217
- height=400,
218
- max_length=2,
219
- font="new_font",
220
- font_size=50,
221
- font_color=(1, 0.5, 1),
222
- bg_color=(0, 0, 1),
223
- border_color=(1, 0, 0),
224
- border_width=5,
225
- )
239
+ .bulk_create_fields(
240
+ [
241
+ Fields.TextField(
242
+ name="foo",
243
+ page_number=1,
244
+ x=100,
245
+ y=100,
246
+ width=400,
247
+ height=400,
248
+ max_length=2,
249
+ font="new_font",
250
+ font_size=50,
251
+ font_color=(1, 0.5, 1),
252
+ bg_color=(0, 0, 1),
253
+ border_color=(1, 0, 0),
254
+ border_width=5,
255
+ )
256
+ ]
226
257
  )
227
258
  )
228
259
  obj.fill(obj.sample_data)
@@ -240,15 +271,17 @@ def test_create_text_complex_filled(
240
271
  def test_create_text_comb(template_stream, pdf_samples, request):
241
272
  expected_path = os.path.join(pdf_samples, "widget", "test_create_text_comb.pdf")
242
273
  with open(expected_path, "rb+") as f:
243
- obj = PdfWrapper(template_stream).create_field(
244
- Fields.TextField(
245
- "foo",
246
- page_number=1,
247
- x=100,
248
- y=100,
249
- max_length=3,
250
- comb=True,
251
- )
274
+ obj = PdfWrapper(template_stream).bulk_create_fields(
275
+ [
276
+ Fields.TextField(
277
+ "foo",
278
+ page_number=1,
279
+ x=100,
280
+ y=100,
281
+ max_length=3,
282
+ comb=True,
283
+ )
284
+ ]
252
285
  )
253
286
 
254
287
  request.config.results["expected_path"] = expected_path
@@ -271,13 +304,15 @@ def test_create_checkbox_persist_old_widgets_fill(
271
304
  obj = PdfWrapper(template_stream)
272
305
  obj.widgets["test"].font_size = 30
273
306
  obj.widgets["test"].font_color = (0, 1, 0)
274
- obj.create_field(
275
- Fields.CheckBoxField(
276
- name="foo",
277
- page_number=1,
278
- x=100,
279
- y=100,
280
- )
307
+ obj.bulk_create_fields(
308
+ [
309
+ Fields.CheckBoxField(
310
+ name="foo",
311
+ page_number=1,
312
+ x=100,
313
+ y=100,
314
+ )
315
+ ]
281
316
  ).fill(obj.sample_data)
282
317
  assert obj.schema["properties"]["foo"]["type"] == "boolean"
283
318
 
@@ -297,19 +332,21 @@ def test_create_widget_sejda_fill_flatten_before(sejda_template, pdf_samples, re
297
332
  )
298
333
  with open(expected_path, "rb+") as f:
299
334
  obj = PdfWrapper(sejda_template)
300
- obj.fill(obj.sample_data, flatten=True).create_field(
301
- Fields.TextField(
302
- name="new_text_field_widget",
303
- page_number=1,
304
- x=72,
305
- y=730,
306
- width=120,
307
- height=40,
308
- max_length=6,
309
- font="Helvetica",
310
- font_size=20,
311
- font_color=(0, 0, 1),
312
- )
335
+ obj.fill(obj.sample_data, flatten=True).bulk_create_fields(
336
+ [
337
+ Fields.TextField(
338
+ name="new_text_field_widget",
339
+ page_number=1,
340
+ x=72,
341
+ y=730,
342
+ width=120,
343
+ height=40,
344
+ max_length=6,
345
+ font="Helvetica",
346
+ font_size=20,
347
+ font_color=(0, 0, 1),
348
+ )
349
+ ]
313
350
  ).fill(obj.sample_data)
314
351
  assert obj.schema["properties"]["new_text_field_widget"]["type"] == "string"
315
352
 
@@ -329,19 +366,21 @@ def test_create_widget_sejda_fill_flatten_after(sejda_template, pdf_samples, req
329
366
  )
330
367
  with open(expected_path, "rb+") as f:
331
368
  obj = PdfWrapper(sejda_template)
332
- obj.fill(obj.sample_data).create_field(
333
- Fields.TextField(
334
- name="new_text_field_widget",
335
- page_number=1,
336
- x=72,
337
- y=730,
338
- width=120,
339
- height=40,
340
- max_length=6,
341
- font="Helvetica",
342
- font_size=20,
343
- font_color=(0, 0, 1),
344
- )
369
+ obj.fill(obj.sample_data).bulk_create_fields(
370
+ [
371
+ Fields.TextField(
372
+ name="new_text_field_widget",
373
+ page_number=1,
374
+ x=72,
375
+ y=730,
376
+ width=120,
377
+ height=40,
378
+ max_length=6,
379
+ font="Helvetica",
380
+ font_size=20,
381
+ font_color=(0, 0, 1),
382
+ )
383
+ ]
345
384
  ).fill(obj.sample_data, flatten=True)
346
385
  assert obj.schema["properties"]["new_text_field_widget"]["type"] == "string"
347
386
 
@@ -359,19 +398,21 @@ def test_create_widget_sejda_schema(sejda_template):
359
398
  old_schema = obj.schema
360
399
  schema = (
361
400
  PdfWrapper(sejda_template)
362
- .create_field(
363
- Fields.TextField(
364
- name="new_text_field_widget",
365
- page_number=1,
366
- x=72,
367
- y=730,
368
- width=120,
369
- height=40,
370
- max_length=6,
371
- font="Times-Roman",
372
- font_size=20,
373
- font_color=(0, 0, 1),
374
- )
401
+ .bulk_create_fields(
402
+ [
403
+ Fields.TextField(
404
+ name="new_text_field_widget",
405
+ page_number=1,
406
+ x=72,
407
+ y=730,
408
+ width=120,
409
+ height=40,
410
+ max_length=6,
411
+ font="Times-Roman",
412
+ font_size=20,
413
+ font_color=(0, 0, 1),
414
+ )
415
+ ]
375
416
  )
376
417
  .schema
377
418
  )
@@ -400,20 +441,22 @@ def test_fill_cmyk_color(pdf_samples, request):
400
441
  def test_create_radio_complex(template_stream, pdf_samples, request):
401
442
  expected_path = os.path.join(pdf_samples, "widget", "test_create_radio_complex.pdf")
402
443
  with open(expected_path, "rb+") as f:
403
- obj = PdfWrapper(template_stream).create_field(
404
- Fields.RadioGroup(
405
- name="radio",
406
- page_number=2,
407
- x=[50, 100, 150],
408
- y=[50, 100, 150],
409
- size=50,
410
- button_style="check",
411
- shape="circle",
412
- tick_color=(0, 1, 0),
413
- bg_color=(0, 0, 1, 1),
414
- border_color=(1, 0, 0),
415
- border_width=5,
416
- )
444
+ obj = PdfWrapper(template_stream).bulk_create_fields(
445
+ [
446
+ Fields.RadioGroup(
447
+ name="radio",
448
+ page_number=2,
449
+ x=[50, 100, 150],
450
+ y=[50, 100, 150],
451
+ size=50,
452
+ button_style="check",
453
+ shape="circle",
454
+ tick_color=(0, 1, 0),
455
+ bg_color=(0, 0, 1, 1),
456
+ border_color=(1, 0, 0),
457
+ border_width=5,
458
+ )
459
+ ]
417
460
  )
418
461
  assert obj.schema["properties"]["radio"]["type"] == "integer"
419
462
 
@@ -432,28 +475,21 @@ def test_create_required_fields(pdf_samples, request):
432
475
  pdf_samples, "widget", "test_create_required_fields.pdf"
433
476
  )
434
477
  with open(expected_path, "rb+") as f:
435
- obj = (
436
- PdfWrapper(os.path.join(pdf_samples, "dummy.pdf"))
437
- .create_field(
478
+ obj = PdfWrapper(os.path.join(pdf_samples, "dummy.pdf")).bulk_create_fields(
479
+ [
438
480
  Fields.TextField(
439
481
  name="new_text", page_number=1, x=100, y=100, required=True
440
- )
441
- )
442
- .create_field(
482
+ ),
443
483
  Fields.CheckBoxField(
444
484
  name="new_check", page_number=1, x=100, y=200, required=True
445
- )
446
- )
447
- .create_field(
485
+ ),
448
486
  Fields.RadioGroup(
449
487
  name="new_radio_group",
450
488
  page_number=1,
451
489
  x=[300, 350, 400],
452
490
  y=[100, 150, 200],
453
491
  required=True,
454
- )
455
- )
456
- .create_field(
492
+ ),
457
493
  Fields.DropdownField(
458
494
  name="new_dropdown",
459
495
  page_number=1,
@@ -461,22 +497,18 @@ def test_create_required_fields(pdf_samples, request):
461
497
  y=400,
462
498
  required=True,
463
499
  options=["apple", "banana", "cherry"],
464
- )
465
- )
466
- .create_field(
500
+ ),
467
501
  Fields.ImageField(
468
502
  name="new_image",
469
503
  page_number=1,
470
504
  x=300,
471
505
  y=600,
472
506
  required=True,
473
- )
474
- )
475
- .create_field(
507
+ ),
476
508
  Fields.SignatureField(
477
509
  name="new_signature", page_number=1, x=100, y=600, required=True
478
- )
479
- )
510
+ ),
511
+ ]
480
512
  )
481
513
 
482
514
  request.config.results["expected_path"] = expected_path
@@ -494,28 +526,21 @@ def test_create_not_required_fields(pdf_samples, request):
494
526
  pdf_samples, "widget", "test_create_not_required_fields.pdf"
495
527
  )
496
528
  with open(expected_path, "rb+") as f:
497
- obj = (
498
- PdfWrapper(os.path.join(pdf_samples, "dummy.pdf"))
499
- .create_field(
529
+ obj = PdfWrapper(os.path.join(pdf_samples, "dummy.pdf")).bulk_create_fields(
530
+ [
500
531
  Fields.TextField(
501
532
  name="new_text", page_number=1, x=100, y=100, required=False
502
- )
503
- )
504
- .create_field(
533
+ ),
505
534
  Fields.CheckBoxField(
506
535
  name="new_check", page_number=1, x=100, y=200, required=False
507
- )
508
- )
509
- .create_field(
536
+ ),
510
537
  Fields.RadioGroup(
511
538
  name="new_radio_group",
512
539
  page_number=1,
513
540
  x=[300, 350, 400],
514
541
  y=[100, 150, 200],
515
542
  required=False,
516
- )
517
- )
518
- .create_field(
543
+ ),
519
544
  Fields.DropdownField(
520
545
  name="new_dropdown",
521
546
  page_number=1,
@@ -523,22 +548,18 @@ def test_create_not_required_fields(pdf_samples, request):
523
548
  y=400,
524
549
  required=False,
525
550
  options=["apple", "banana", "cherry"],
526
- )
527
- )
528
- .create_field(
551
+ ),
529
552
  Fields.ImageField(
530
553
  name="new_image",
531
554
  page_number=1,
532
555
  x=300,
533
556
  y=600,
534
557
  required=False,
535
- )
536
- )
537
- .create_field(
558
+ ),
538
559
  Fields.SignatureField(
539
560
  name="new_signature", page_number=1, x=100, y=600, required=False
540
- )
541
- )
561
+ ),
562
+ ]
542
563
  )
543
564
 
544
565
  request.config.results["expected_path"] = expected_path
@@ -556,32 +577,25 @@ def test_create_fields_with_tooltips(pdf_samples, request):
556
577
  pdf_samples, "widget", "test_create_fields_with_tooltips.pdf"
557
578
  )
558
579
  with open(expected_path, "rb+") as f:
559
- obj = (
560
- PdfWrapper(os.path.join(pdf_samples, "dummy.pdf"))
561
- .create_field(
580
+ obj = PdfWrapper(os.path.join(pdf_samples, "dummy.pdf")).bulk_create_fields(
581
+ [
562
582
  Fields.TextField(
563
583
  name="new_text", page_number=1, x=100, y=100, tooltip="new_text"
564
- )
565
- )
566
- .create_field(
584
+ ),
567
585
  Fields.CheckBoxField(
568
586
  name="new_check",
569
587
  page_number=1,
570
588
  x=100,
571
589
  y=200,
572
590
  tooltip="new_checkbox",
573
- )
574
- )
575
- .create_field(
591
+ ),
576
592
  Fields.RadioGroup(
577
593
  name="new_radio_group",
578
594
  page_number=1,
579
595
  x=[300, 350, 400],
580
596
  y=[100, 150, 200],
581
597
  tooltip="new_radio_group",
582
- )
583
- )
584
- .create_field(
598
+ ),
585
599
  Fields.DropdownField(
586
600
  name="new_dropdown",
587
601
  page_number=1,
@@ -589,26 +603,22 @@ def test_create_fields_with_tooltips(pdf_samples, request):
589
603
  y=400,
590
604
  options=["apple", "banana", "cherry"],
591
605
  tooltip="new_dropdown",
592
- )
593
- )
594
- .create_field(
606
+ ),
595
607
  Fields.ImageField(
596
608
  name="new_image",
597
609
  page_number=1,
598
610
  x=300,
599
611
  y=600,
600
612
  tooltip="new_image",
601
- )
602
- )
603
- .create_field(
613
+ ),
604
614
  Fields.SignatureField(
605
615
  name="new_signature",
606
616
  page_number=1,
607
617
  x=100,
608
618
  y=600,
609
619
  tooltip="new_signature",
610
- )
611
- )
620
+ ),
621
+ ]
612
622
  )
613
623
 
614
624
  request.config.results["expected_path"] = expected_path
@@ -14,13 +14,81 @@ from PyPDFForm.template import get_widgets_by_page
14
14
 
15
15
 
16
16
  def test_deprecation_warning():
17
+ class MockClass:
18
+ @deprecation_notice(to_replace="new_method")
19
+ def old_method(self):
20
+ return "result"
21
+
22
+ obj = MockClass()
17
23
  with pytest.warns(
18
- DeprecationWarning, match="foo will be deprecated soon. Use bar instead."
24
+ DeprecationWarning,
25
+ match="MockClass.old_method will be deprecated soon. Use MockClass.new_method instead.",
19
26
  ):
20
- deprecation_notice(
21
- "foo",
22
- "bar",
23
- )
27
+ assert obj.old_method() == "result"
28
+
29
+
30
+ def test_deprecation_warning_with_param():
31
+ class MockClass:
32
+ @deprecation_notice(to_replace="old_method.new_param", param="old_param")
33
+ def old_method(self):
34
+ return "result"
35
+
36
+ obj = MockClass()
37
+ with pytest.warns(
38
+ DeprecationWarning,
39
+ match="MockClass.old_method.old_param will be deprecated soon. Use MockClass.old_method.new_param instead.",
40
+ ):
41
+ assert obj.old_method() == "result"
42
+
43
+
44
+ def test_deprecation_warning_empty_replace():
45
+ class MockClass:
46
+ @deprecation_notice(to_replace="")
47
+ def old_method(self):
48
+ return "result"
49
+
50
+ obj = MockClass()
51
+ with pytest.warns(
52
+ DeprecationWarning,
53
+ match="MockClass.old_method will be deprecated soon.",
54
+ ) as record:
55
+ assert obj.old_method() == "result"
56
+ assert "Use" not in str(record[0].message)
57
+
58
+
59
+ def test_deprecation_warning_direct_call():
60
+ class MockClass:
61
+ def my_method(self, use_legacy=False):
62
+ if use_legacy:
63
+ deprecation_notice(to_replace="", param="use_legacy").emit_notice(
64
+ self, "my_method"
65
+ )
66
+ return "result"
67
+
68
+ obj = MockClass()
69
+ assert obj.my_method(use_legacy=False) == "result"
70
+ with pytest.warns(
71
+ DeprecationWarning,
72
+ match="MockClass.my_method.use_legacy will be deprecated soon.",
73
+ ):
74
+ assert obj.my_method(use_legacy=True) == "result"
75
+
76
+
77
+ def test_deprecation_warning_direct_call_with_replace():
78
+ class MockClass:
79
+ def my_method(self, use_legacy=False):
80
+ if use_legacy:
81
+ deprecation_notice(
82
+ to_replace="my_method.new_param", param="use_legacy"
83
+ ).emit_notice(self, "my_method")
84
+ return "result"
85
+
86
+ obj = MockClass()
87
+ with pytest.warns(
88
+ DeprecationWarning,
89
+ match="MockClass.my_method.use_legacy will be deprecated soon. Use MockClass.my_method.new_param instead.",
90
+ ):
91
+ assert obj.my_method(use_legacy=True) == "result"
24
92
 
25
93
 
26
94
  def test_base_schema_definition():
@@ -32,59 +32,51 @@ def run_sample_template_library_test(
32
32
  need_appearances=need_appearances,
33
33
  )
34
34
  .register_font("new_font", sample_font_stream)
35
- .create_field(
36
- Fields.TextField(
37
- name="new_text_field_widget",
38
- page_number=1,
39
- x=60,
40
- y=710,
41
- )
42
- )
43
- .create_field(
44
- Fields.CheckBoxField(
45
- name="new_checkbox_widget",
46
- page_number=1,
47
- x=100,
48
- y=600,
49
- )
50
- )
51
- .create_field(
52
- Fields.RadioGroup(
53
- name="new_radio_group",
54
- page_number=1,
55
- x=[50, 100, 150],
56
- y=[50, 100, 150],
57
- )
58
- )
59
- .create_field(
60
- Fields.DropdownField(
61
- name="new_dropdown_widget",
62
- page_number=1,
63
- x=300,
64
- y=710,
65
- options=[
66
- "foo",
67
- "bar",
68
- "foobar",
69
- ],
70
- font="new_font",
71
- )
72
- )
73
- .create_field(
74
- Fields.ImageField(
75
- name="new_image_widget",
76
- page_number=1,
77
- x=300,
78
- y=200,
79
- )
80
- )
81
- .create_field(
82
- Fields.SignatureField(
83
- name="new_signature_wiget",
84
- page_number=1,
85
- x=300,
86
- y=400,
87
- )
35
+ .bulk_create_fields(
36
+ [
37
+ Fields.TextField(
38
+ name="new_text_field_widget",
39
+ page_number=1,
40
+ x=60,
41
+ y=710,
42
+ ),
43
+ Fields.CheckBoxField(
44
+ name="new_checkbox_widget",
45
+ page_number=1,
46
+ x=100,
47
+ y=600,
48
+ ),
49
+ Fields.RadioGroup(
50
+ name="new_radio_group",
51
+ page_number=1,
52
+ x=[50, 100, 150],
53
+ y=[50, 100, 150],
54
+ ),
55
+ Fields.DropdownField(
56
+ name="new_dropdown_widget",
57
+ page_number=1,
58
+ x=300,
59
+ y=710,
60
+ options=[
61
+ "foo",
62
+ "bar",
63
+ "foobar",
64
+ ],
65
+ font="new_font",
66
+ ),
67
+ Fields.ImageField(
68
+ name="new_image_widget",
69
+ page_number=1,
70
+ x=300,
71
+ y=200,
72
+ ),
73
+ Fields.SignatureField(
74
+ name="new_signature_wiget",
75
+ page_number=1,
76
+ x=300,
77
+ y=400,
78
+ ),
79
+ ]
88
80
  )
89
81
  .fill(
90
82
  {
@@ -14,8 +14,8 @@ def test_register_font_no_form_fields(pdf_samples, sample_font_stream, request):
14
14
  )
15
15
  with open(expected_path, "rb+") as f:
16
16
  obj = PdfWrapper(os.path.join(pdf_samples, "dummy.pdf"))
17
- obj.register_font("new_font", sample_font_stream).create_field(
18
- Fields.TextField(name="foo", page_number=1, x=100, y=100, font="new_font")
17
+ obj.register_font("new_font", sample_font_stream).bulk_create_fields(
18
+ [Fields.TextField(name="foo", page_number=1, x=100, y=100, font="new_font")]
19
19
  )
20
20
  obj.draw([RawElements.RawText("foo", 1, 200, 200, font="new_font")])
21
21
 
@@ -1,30 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- A module for handling deprecation notices within the PyPDFForm library.
4
-
5
- This module provides utility functions to issue standard DeprecationWarning
6
- messages, ensuring consistency across the library when notifying users of
7
- deprecated features.
8
- """
9
-
10
- from warnings import warn
11
-
12
- from .constants import DEPRECATION_NOTICE
13
-
14
-
15
- def deprecation_notice(to_deprecate: str, to_replace: str) -> None:
16
- """
17
- Issues a DeprecationWarning for a feature that is being deprecated.
18
-
19
- Args:
20
- to_deprecate (str): The name of the feature or function being deprecated.
21
- to_replace (str): The name of the feature or function that should be used instead.
22
- """
23
- warn(
24
- DEPRECATION_NOTICE.format(
25
- to_deprecate,
26
- to_replace,
27
- ),
28
- DeprecationWarning, # noqa: PT030
29
- stacklevel=3,
30
- )
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