PyPDFForm 2.2.3__tar.gz → 2.2.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.
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PKG-INFO +1 -1
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/__init__.py +1 -1
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/watermark.py +20 -9
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/wrapper.py +6 -5
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm.egg-info/PKG-INFO +1 -1
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_functional.py +50 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/LICENSE +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/adapter.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/constants.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/coordinate.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/filler.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/font.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/image.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/middleware/__init__.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/middleware/base.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/middleware/checkbox.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/middleware/dropdown.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/middleware/image.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/middleware/radio.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/middleware/signature.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/middleware/text.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/patterns.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/template.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/utils.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/__init__.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/base.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/bedrock.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/checkbox.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/dropdown.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/image.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/radio.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/signature.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm/widgets/text.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm.egg-info/SOURCES.txt +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm.egg-info/dependency_links.txt +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm.egg-info/requires.txt +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/PyPDFForm.egg-info/top_level.txt +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/README.md +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/pyproject.toml +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/setup.cfg +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_adobe_mode.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_create_widget.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_dropdown.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_dropdown_simple.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_fill_max_length_text_field.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_fill_max_length_text_field_simple.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_fill_method.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_functional_simple.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_paragraph.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_paragraph_simple.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_preview.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_signature.py +0 -0
- {pypdfform-2.2.3 → pypdfform-2.2.4}/tests/test_use_full_widget_name.py +0 -0
|
@@ -335,22 +335,28 @@ def merge_watermarks_with_pdf(
|
|
|
335
335
|
|
|
336
336
|
|
|
337
337
|
def copy_watermark_widgets(
|
|
338
|
-
pdf: bytes,
|
|
338
|
+
pdf: bytes,
|
|
339
|
+
watermarks: Union[List[bytes], bytes],
|
|
340
|
+
keys: Union[List[str], None],
|
|
341
|
+
page_num: Union[int, None],
|
|
339
342
|
) -> bytes:
|
|
340
|
-
"""
|
|
341
|
-
Copies annotation widgets (form fields) from watermark PDFs onto the corresponding pages of a base PDF,
|
|
342
|
-
including only those widgets whose key matches an entry in the provided keys list.
|
|
343
|
+
"""Copies annotation widgets (form fields) from watermark PDFs onto the corresponding pages of a base PDF.
|
|
343
344
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
This function selectively copies annotation widgets (form fields) from watermark PDFs to a base PDF.
|
|
346
|
+
It allows specifying which widgets to copy based on their keys, and optionally restricts the operation
|
|
347
|
+
to a specific page number.
|
|
348
|
+
|
|
349
|
+
The function can handle either a list of watermarks (one per page) or a single watermark PDF applied to all pages.
|
|
350
|
+
Widgets are only copied if their key is present in the provided keys list.
|
|
347
351
|
|
|
348
352
|
Args:
|
|
349
353
|
pdf: The original PDF document as bytes.
|
|
350
|
-
watermarks: Either a list of watermark PDF data (as bytes, one per page) or a single watermark PDF.
|
|
354
|
+
watermarks: Either a list of watermark PDF data (as bytes, one per page) or a single watermark PDF as bytes.
|
|
351
355
|
Empty or None entries are skipped.
|
|
352
356
|
keys: List of widget keys (str). Only widgets whose key is in this list will be copied.
|
|
353
357
|
If None, all widgets will be copied.
|
|
358
|
+
page_num: Optional page number (0-based) to restrict widget copying to. If None, widgets are copied
|
|
359
|
+
across all pages.
|
|
354
360
|
|
|
355
361
|
Returns:
|
|
356
362
|
bytes: The resulting PDF document with selected annotation widgets from watermarks copied onto their respective pages.
|
|
@@ -368,6 +374,9 @@ def copy_watermark_widgets(
|
|
|
368
374
|
watermarks = [watermarks]
|
|
369
375
|
widgets_to_copy = widgets_to_copy_pdf
|
|
370
376
|
|
|
377
|
+
if page_num is not None:
|
|
378
|
+
widgets_to_copy = widgets_to_copy_watermarks
|
|
379
|
+
|
|
371
380
|
for i, watermark in enumerate(watermarks):
|
|
372
381
|
if not watermark:
|
|
373
382
|
continue
|
|
@@ -380,7 +389,9 @@ def copy_watermark_widgets(
|
|
|
380
389
|
key = extract_widget_property(
|
|
381
390
|
annot.get_object(), WIDGET_KEY_PATTERNS, None, str
|
|
382
391
|
)
|
|
383
|
-
if keys is None or key in keys
|
|
392
|
+
if (keys is None or key in keys) and (
|
|
393
|
+
page_num is None or page_num == j
|
|
394
|
+
):
|
|
384
395
|
widgets_to_copy_watermarks[i].append(annot.clone(out))
|
|
385
396
|
widgets_to_copy_pdf[j].append(annot.clone(out))
|
|
386
397
|
|
|
@@ -288,9 +288,10 @@ class PdfWrapper(FormWrapper):
|
|
|
288
288
|
|
|
289
289
|
return [
|
|
290
290
|
self.__class__(
|
|
291
|
-
each,
|
|
291
|
+
copy_watermark_widgets(each, self.stream, None, i),
|
|
292
|
+
**{param: getattr(self, param) for param, _ in self.USER_PARAMS},
|
|
292
293
|
)
|
|
293
|
-
for each in get_page_streams(self.
|
|
294
|
+
for i, each in enumerate(get_page_streams(remove_all_widgets(self.read())))
|
|
294
295
|
]
|
|
295
296
|
|
|
296
297
|
def change_version(self, version: str) -> PdfWrapper:
|
|
@@ -497,7 +498,7 @@ class PdfWrapper(FormWrapper):
|
|
|
497
498
|
obj = _class(name=name, page_number=page_number, x=x, y=y, **kwargs)
|
|
498
499
|
watermarks = obj.watermarks(self.read())
|
|
499
500
|
|
|
500
|
-
self.stream = copy_watermark_widgets(self.read(), watermarks, [name])
|
|
501
|
+
self.stream = copy_watermark_widgets(self.read(), watermarks, [name], None)
|
|
501
502
|
if obj.non_acro_form_params:
|
|
502
503
|
self.stream = handle_non_acro_form_params(
|
|
503
504
|
self.stream, name, obj.non_acro_form_params
|
|
@@ -630,7 +631,7 @@ class PdfWrapper(FormWrapper):
|
|
|
630
631
|
stream_with_widgets = self.read()
|
|
631
632
|
self.stream = merge_watermarks_with_pdf(self.stream, watermarks)
|
|
632
633
|
self.stream = copy_watermark_widgets(
|
|
633
|
-
remove_all_widgets(self.stream), stream_with_widgets, None
|
|
634
|
+
remove_all_widgets(self.stream), stream_with_widgets, None, None
|
|
634
635
|
)
|
|
635
636
|
|
|
636
637
|
return self
|
|
@@ -672,7 +673,7 @@ class PdfWrapper(FormWrapper):
|
|
|
672
673
|
stream_with_widgets = self.read()
|
|
673
674
|
self.stream = merge_watermarks_with_pdf(self.stream, watermarks)
|
|
674
675
|
self.stream = copy_watermark_widgets(
|
|
675
|
-
remove_all_widgets(self.stream), stream_with_widgets, None
|
|
676
|
+
remove_all_widgets(self.stream), stream_with_widgets, None, None
|
|
676
677
|
)
|
|
677
678
|
|
|
678
679
|
return self
|
|
@@ -629,6 +629,56 @@ def test_pages(template_stream, pdf_samples, request):
|
|
|
629
629
|
assert obj.pages[0].read() == f.read()
|
|
630
630
|
|
|
631
631
|
|
|
632
|
+
def test_sejda_pages_1(sejda_template, pdf_samples, request):
|
|
633
|
+
expected_path = os.path.join(pdf_samples, "pages", "test_sejda_pages_1.pdf")
|
|
634
|
+
obj = PdfWrapper(sejda_template)
|
|
635
|
+
|
|
636
|
+
with open(expected_path, "rb+") as f:
|
|
637
|
+
request.config.results["expected_path"] = expected_path
|
|
638
|
+
request.config.results["stream"] = obj.pages[0].read()
|
|
639
|
+
assert obj.pages[0].read() == f.read()
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
def test_sejda_pages_2(sejda_template, pdf_samples, request):
|
|
643
|
+
expected_path = os.path.join(pdf_samples, "pages", "test_sejda_pages_2.pdf")
|
|
644
|
+
obj = PdfWrapper(sejda_template)
|
|
645
|
+
|
|
646
|
+
with open(expected_path, "rb+") as f:
|
|
647
|
+
request.config.results["expected_path"] = expected_path
|
|
648
|
+
request.config.results["stream"] = obj.pages[1].read()
|
|
649
|
+
assert obj.pages[1].read() == f.read()
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
def test_radio_pages_1(template_with_radiobutton_stream, pdf_samples, request):
|
|
653
|
+
expected_path = os.path.join(pdf_samples, "pages", "test_radio_pages_1.pdf")
|
|
654
|
+
obj = PdfWrapper(template_with_radiobutton_stream)
|
|
655
|
+
|
|
656
|
+
with open(expected_path, "rb+") as f:
|
|
657
|
+
request.config.results["expected_path"] = expected_path
|
|
658
|
+
request.config.results["stream"] = obj.pages[0].read()
|
|
659
|
+
assert obj.pages[0].read() == f.read()
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
def test_radio_pages_2(template_with_radiobutton_stream, pdf_samples, request):
|
|
663
|
+
expected_path = os.path.join(pdf_samples, "pages", "test_radio_pages_2.pdf")
|
|
664
|
+
obj = PdfWrapper(template_with_radiobutton_stream)
|
|
665
|
+
|
|
666
|
+
with open(expected_path, "rb+") as f:
|
|
667
|
+
request.config.results["expected_path"] = expected_path
|
|
668
|
+
request.config.results["stream"] = obj.pages[1].read()
|
|
669
|
+
assert obj.pages[1].read() == f.read()
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
def test_radio_pages_3(template_with_radiobutton_stream, pdf_samples, request):
|
|
673
|
+
expected_path = os.path.join(pdf_samples, "pages", "test_radio_pages_3.pdf")
|
|
674
|
+
obj = PdfWrapper(template_with_radiobutton_stream)
|
|
675
|
+
|
|
676
|
+
with open(expected_path, "rb+") as f:
|
|
677
|
+
request.config.results["expected_path"] = expected_path
|
|
678
|
+
request.config.results["stream"] = obj.pages[2].read()
|
|
679
|
+
assert obj.pages[2].read() == f.read()
|
|
680
|
+
|
|
681
|
+
|
|
632
682
|
def test_pages_inherit_attributes(template_stream):
|
|
633
683
|
obj = PdfWrapper(
|
|
634
684
|
template_stream,
|
|
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
|
|
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
|