PyPDFForm 5.1.1__tar.gz → 5.2.0__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.
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PKG-INFO +1 -3
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/__init__.py +1 -1
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/common.py +7 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/create.py +9 -5
- pypdfform-5.2.0/PyPDFForm/cli/remove.py +33 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/root.py +14 -8
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/update.py +10 -3
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/annotations/__init__.py +6 -2
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/annotations/base.py +7 -2
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/annotations/link.py +7 -2
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/egress.py +1 -2
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/filler.py +7 -3
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/font.py +45 -11
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/hooks.py +39 -7
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/patterns.py +39 -6
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/template.py +61 -6
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/widgets/signature.py +1 -2
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/wrapper.py +67 -15
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm.egg-info/PKG-INFO +1 -3
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm.egg-info/SOURCES.txt +1 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm.egg-info/requires.txt +0 -2
- {pypdfform-5.1.1 → pypdfform-5.2.0}/pyproject.toml +0 -2
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_font_widths.py +10 -3
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_functional.py +13 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_js.py +95 -95
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_use_full_widget_name.py +8 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/LICENSE +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/__init__.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/entry.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/inspect.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/schemas/__init__.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/schemas/create.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/cli/schemas/update.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/__init__.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/adapter.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/annotations/stamp.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/annotations/text.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/annotations/text_markup.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/assets/__init__.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/assets/bedrock.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/assets/blank.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/constants.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/coordinate.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/deprecation.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/image.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/middleware/__init__.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/middleware/base.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/middleware/checkbox.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/middleware/dropdown.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/middleware/image.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/middleware/radio.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/middleware/signature.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/middleware/text.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/raw/__init__.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/raw/circle.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/raw/ellipse.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/raw/image.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/raw/line.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/raw/rect.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/raw/text.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/types.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/utils.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/watermark.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/widgets/__init__.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/widgets/base.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/widgets/checkbox.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/widgets/dropdown.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/widgets/image.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/widgets/radio.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm/lib/widgets/text.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm.egg-info/dependency_links.txt +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm.egg-info/entry_points.txt +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/PyPDFForm.egg-info/top_level.txt +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/README.md +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/setup.cfg +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_bulk_create_fields.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_create_widget.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_draw_elements.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_dropdown.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_extract_middleware_attributes.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_fill_max_length_text_field.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_generate_appearance_streams.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_need_appearances.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_paragraph.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_signature.py +0 -0
- {pypdfform-5.1.1 → pypdfform-5.2.0}/tests/test_widget_attr_trigger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.2.0
|
|
4
4
|
Summary: The Python library & CLI for PDF forms.
|
|
5
5
|
Author: Jinge Li
|
|
6
6
|
License-Expression: MIT
|
|
@@ -34,9 +34,7 @@ Provides-Extra: cli
|
|
|
34
34
|
Requires-Dist: typer<1.0.0,>=0.26.1; extra == "cli"
|
|
35
35
|
Requires-Dist: jsonschema<5.0.0,>=4.26.0; extra == "cli"
|
|
36
36
|
Provides-Extra: dev
|
|
37
|
-
Requires-Dist: black<27.0.0,>=26.5.1; extra == "dev"
|
|
38
37
|
Requires-Dist: coverage<8.0.0,>=7.14.1; extra == "dev"
|
|
39
|
-
Requires-Dist: isort<9.0.0,>=8.0.1; extra == "dev"
|
|
40
38
|
Requires-Dist: mike<3.0.0,>=2.2.0; extra == "dev"
|
|
41
39
|
Requires-Dist: mkdocs<2.0.0,>=1.6.1; extra == "dev"
|
|
42
40
|
Requires-Dist: mkdocs-material<10.0.0,>=9.7.6; extra == "dev"
|
|
@@ -53,6 +53,13 @@ OPTIONAL_OUTPUT_PDF = Annotated[
|
|
|
53
53
|
),
|
|
54
54
|
]
|
|
55
55
|
FIELD_NAME = Annotated[str, typer.Option("--field", help="Form field name.")]
|
|
56
|
+
FIELD_NAMES = Annotated[
|
|
57
|
+
list[str],
|
|
58
|
+
typer.Option(
|
|
59
|
+
"--field",
|
|
60
|
+
help="Form field name. Repeat this option to select multiple fields.",
|
|
61
|
+
),
|
|
62
|
+
]
|
|
56
63
|
|
|
57
64
|
|
|
58
65
|
def json_file_option(help_text: str):
|
|
@@ -14,11 +14,15 @@ from typing import Annotated
|
|
|
14
14
|
|
|
15
15
|
import typer
|
|
16
16
|
|
|
17
|
-
from .. import
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
from .. import Annotations, BlankPage, Fields, PdfArray, PdfWrapper, RawElements
|
|
18
|
+
from .common import (
|
|
19
|
+
INPUT_PDF,
|
|
20
|
+
OPTIONAL_OUTPUT_PDF,
|
|
21
|
+
REQUIRED_OUTPUT_PDF,
|
|
22
|
+
cli_bad_parameter,
|
|
23
|
+
create_elements_from_file,
|
|
24
|
+
json_file_option,
|
|
25
|
+
)
|
|
22
26
|
from .schemas.create import ANNOTATION_SCHEMA, FIELD_SCHEMA, RAW_SCHEMA
|
|
23
27
|
|
|
24
28
|
create_cli = typer.Typer(
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
This module defines CLI commands for removing PDF form content.
|
|
4
|
+
|
|
5
|
+
It exposes the `remove` command group for deleting existing form fields.
|
|
6
|
+
Commands in this module load the target PDF, validate requested form field
|
|
7
|
+
names, apply the matching `PdfWrapper` operation, and write the modified PDF to
|
|
8
|
+
either the requested output path or the original file.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import typer
|
|
12
|
+
|
|
13
|
+
from .. import PdfWrapper
|
|
14
|
+
from .common import FIELD_NAMES, INPUT_PDF, OPTIONAL_OUTPUT_PDF, get_widget
|
|
15
|
+
|
|
16
|
+
remove_cli = typer.Typer(
|
|
17
|
+
context_settings={"help_option_names": ["--help", "-h"]}, no_args_is_help=True
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@remove_cli.command(no_args_is_help=True)
|
|
22
|
+
def field(
|
|
23
|
+
ctx: typer.Context,
|
|
24
|
+
pdf: INPUT_PDF,
|
|
25
|
+
fields: FIELD_NAMES,
|
|
26
|
+
output: OPTIONAL_OUTPUT_PDF = None,
|
|
27
|
+
) -> None:
|
|
28
|
+
"""Remove form fields from a PDF."""
|
|
29
|
+
obj = PdfWrapper(str(pdf), **ctx.obj)
|
|
30
|
+
for field_name in fields:
|
|
31
|
+
get_widget(obj, field_name, "--field")
|
|
32
|
+
|
|
33
|
+
obj.remove_fields(fields).write(output or pdf)
|
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
"""
|
|
3
3
|
This module defines the root command-line interface for PyPDFForm.
|
|
4
4
|
|
|
5
|
-
It creates the Typer application, attaches the `create`, `inspect`,
|
|
6
|
-
command groups, and exposes top-level options shared by those
|
|
7
|
-
callback collects global flags in the Typer context so each
|
|
8
|
-
initialize `PdfWrapper` with consistent settings.
|
|
5
|
+
It creates the Typer application, attaches the `create`, `inspect`, `update`,
|
|
6
|
+
and `remove` command groups, and exposes top-level options shared by those
|
|
7
|
+
commands. The root callback collects global flags in the Typer context so each
|
|
8
|
+
subcommand can initialize `PdfWrapper` with consistent settings.
|
|
9
9
|
|
|
10
10
|
Commands:
|
|
11
11
|
- `fill`: Fill an existing PDF form from JSON data.
|
|
12
12
|
- `create`: Create PDFs, fields, annotations, raw elements, and grid views.
|
|
13
13
|
- `inspect`: Print form metadata and field data as JSON.
|
|
14
14
|
- `update`: Modify PDF metadata, field names, properties, geometry, and scripts.
|
|
15
|
+
- `remove`: Remove PDF form fields.
|
|
15
16
|
"""
|
|
16
17
|
|
|
17
18
|
from pathlib import Path
|
|
@@ -20,10 +21,10 @@ from typing import Annotated
|
|
|
20
21
|
import typer
|
|
21
22
|
|
|
22
23
|
from .. import PdfWrapper, Widgets, __version__
|
|
23
|
-
from .common import
|
|
24
|
-
load_json_file)
|
|
24
|
+
from .common import INPUT_PDF, OPTIONAL_OUTPUT_PDF, json_file_option, load_json_file
|
|
25
25
|
from .create import create_cli
|
|
26
26
|
from .inspect import inspect_cli
|
|
27
|
+
from .remove import remove_cli
|
|
27
28
|
from .update import update_cli
|
|
28
29
|
|
|
29
30
|
cli_app = typer.Typer(
|
|
@@ -44,6 +45,11 @@ cli_app.add_typer(
|
|
|
44
45
|
name="update",
|
|
45
46
|
help="Update PDF metadata, fields, and scripts.",
|
|
46
47
|
)
|
|
48
|
+
cli_app.add_typer(
|
|
49
|
+
remove_cli,
|
|
50
|
+
name="remove",
|
|
51
|
+
help="Remove PDF form content.",
|
|
52
|
+
)
|
|
47
53
|
|
|
48
54
|
|
|
49
55
|
def version_callback(value: bool) -> None:
|
|
@@ -68,7 +74,7 @@ def version_callback(value: bool) -> None:
|
|
|
68
74
|
|
|
69
75
|
@cli_app.callback(
|
|
70
76
|
invoke_without_command=True,
|
|
71
|
-
help="
|
|
77
|
+
help="Work with PDF forms from the command line.",
|
|
72
78
|
)
|
|
73
79
|
def main(
|
|
74
80
|
ctx: typer.Context,
|
|
@@ -111,7 +117,7 @@ def main(
|
|
|
111
117
|
),
|
|
112
118
|
] = False,
|
|
113
119
|
) -> None:
|
|
114
|
-
"""
|
|
120
|
+
"""Work with PDF forms from the command line."""
|
|
115
121
|
ctx.obj = {
|
|
116
122
|
"need_appearances": need_appearances,
|
|
117
123
|
"generate_appearance_streams": generate_appearance_streams,
|
|
@@ -17,9 +17,16 @@ import typer
|
|
|
17
17
|
|
|
18
18
|
from .. import PdfWrapper
|
|
19
19
|
from ..lib.constants import PdfVersion
|
|
20
|
-
from .common import (
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
from .common import (
|
|
21
|
+
FIELD_NAME,
|
|
22
|
+
INPUT_PDF,
|
|
23
|
+
OPTIONAL_OUTPUT_PDF,
|
|
24
|
+
cli_bad_parameter,
|
|
25
|
+
get_widget,
|
|
26
|
+
handle_font_registration,
|
|
27
|
+
json_file_option,
|
|
28
|
+
load_json_file,
|
|
29
|
+
)
|
|
23
30
|
from .schemas.update import FIELD_SCHEMA, RENAME_SCHEMA
|
|
24
31
|
|
|
25
32
|
update_cli = typer.Typer(
|
|
@@ -14,8 +14,12 @@ from dataclasses import dataclass
|
|
|
14
14
|
from .link import LinkAnnotation
|
|
15
15
|
from .stamp import RubberStampAnnotation
|
|
16
16
|
from .text import TextAnnotation
|
|
17
|
-
from .text_markup import (
|
|
18
|
-
|
|
17
|
+
from .text_markup import (
|
|
18
|
+
HighlightAnnotation,
|
|
19
|
+
SquigglyAnnotation,
|
|
20
|
+
StrikeOutAnnotation,
|
|
21
|
+
UnderlineAnnotation,
|
|
22
|
+
)
|
|
19
23
|
|
|
20
24
|
AnnotationTypes = (
|
|
21
25
|
TextAnnotation
|
|
@@ -11,8 +11,13 @@ Classes:
|
|
|
11
11
|
|
|
12
12
|
from dataclasses import dataclass
|
|
13
13
|
|
|
14
|
-
from pypdf.generic import (
|
|
15
|
-
|
|
14
|
+
from pypdf.generic import (
|
|
15
|
+
ArrayObject,
|
|
16
|
+
DictionaryObject,
|
|
17
|
+
FloatObject,
|
|
18
|
+
NameObject,
|
|
19
|
+
TextStringObject,
|
|
20
|
+
)
|
|
16
21
|
|
|
17
22
|
from ..constants import Annot, Contents, Rect, Subtype, Type
|
|
18
23
|
|
|
@@ -12,8 +12,13 @@ Classes:
|
|
|
12
12
|
from dataclasses import dataclass
|
|
13
13
|
from typing import Optional
|
|
14
14
|
|
|
15
|
-
from pypdf.generic import (
|
|
16
|
-
|
|
15
|
+
from pypdf.generic import (
|
|
16
|
+
ArrayObject,
|
|
17
|
+
DictionaryObject,
|
|
18
|
+
NameObject,
|
|
19
|
+
NumberObject,
|
|
20
|
+
TextStringObject,
|
|
21
|
+
)
|
|
17
22
|
|
|
18
23
|
from ..constants import A, S
|
|
19
24
|
from .base import Annotation
|
|
@@ -17,8 +17,7 @@ from pikepdf import Pdf
|
|
|
17
17
|
from pypdf import PdfReader, PdfWriter
|
|
18
18
|
from pypdf.generic import DictionaryObject, NameObject, TextStringObject
|
|
19
19
|
|
|
20
|
-
from .constants import
|
|
21
|
-
Title)
|
|
20
|
+
from .constants import JS, XFA, AcroForm, JavaScript, OpenAction, Root, S, Title
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
@lru_cache
|
|
@@ -24,9 +24,13 @@ from .middleware.image import Image
|
|
|
24
24
|
from .middleware.radio import Radio
|
|
25
25
|
from .middleware.signature import Signature
|
|
26
26
|
from .middleware.text import Text
|
|
27
|
-
from .patterns import (
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
from .patterns import (
|
|
28
|
+
get_widget_key,
|
|
29
|
+
update_checkbox_value,
|
|
30
|
+
update_dropdown_value,
|
|
31
|
+
update_radio_value,
|
|
32
|
+
update_text_value,
|
|
33
|
+
)
|
|
30
34
|
from .watermark import create_watermarks_and_draw, merge_watermarks_with_pdf
|
|
31
35
|
|
|
32
36
|
|
|
@@ -16,20 +16,52 @@ from zlib import compress
|
|
|
16
16
|
|
|
17
17
|
from fontTools.ttLib import TTFont as FT_TTFont
|
|
18
18
|
from pypdf import PdfReader, PdfWriter
|
|
19
|
-
from pypdf.generic import (
|
|
20
|
-
|
|
19
|
+
from pypdf.generic import (
|
|
20
|
+
ArrayObject,
|
|
21
|
+
DictionaryObject,
|
|
22
|
+
FloatObject,
|
|
23
|
+
NameObject,
|
|
24
|
+
NumberObject,
|
|
25
|
+
StreamObject,
|
|
26
|
+
)
|
|
21
27
|
from reportlab.pdfbase.pdfmetrics import _fonts
|
|
22
28
|
from reportlab.pdfbase.ttfonts import TTFError, TTFont
|
|
23
29
|
|
|
24
30
|
from .assets.blank import BlankPage
|
|
25
|
-
from .constants import (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
from .constants import (
|
|
32
|
+
DEFAULT_ASSUMED_GLYPH_WIDTH,
|
|
33
|
+
DR,
|
|
34
|
+
EM_TO_PDF_FACTOR,
|
|
35
|
+
ENCODING_TABLE_SIZE,
|
|
36
|
+
FIRST_CHAR_CODE,
|
|
37
|
+
FONT_NAME_PREFIX,
|
|
38
|
+
LAST_CHAR_CODE,
|
|
39
|
+
AcroForm,
|
|
40
|
+
BaseFont,
|
|
41
|
+
Encoding,
|
|
42
|
+
Fields,
|
|
43
|
+
Filter,
|
|
44
|
+
FirstChar,
|
|
45
|
+
FlateDecode,
|
|
46
|
+
Font,
|
|
47
|
+
FontCmap,
|
|
48
|
+
FontDescriptor,
|
|
49
|
+
FontFile2,
|
|
50
|
+
FontHead,
|
|
51
|
+
FontHmtx,
|
|
52
|
+
FontName,
|
|
53
|
+
FontNotdef,
|
|
54
|
+
LastChar,
|
|
55
|
+
Length,
|
|
56
|
+
Length1,
|
|
57
|
+
MissingWidth,
|
|
58
|
+
Resources,
|
|
59
|
+
Subtype,
|
|
60
|
+
TrueType,
|
|
61
|
+
Type,
|
|
62
|
+
Widths,
|
|
63
|
+
WinAnsiEncoding,
|
|
64
|
+
)
|
|
33
65
|
from .raw.text import RawText
|
|
34
66
|
from .watermark import create_watermarks_and_draw
|
|
35
67
|
|
|
@@ -287,7 +319,9 @@ def register_font_acroform(
|
|
|
287
319
|
font_dict_ref = writer._add_object(font_dict) # type: ignore # noqa: SLF001 # # pylint: disable=W0212
|
|
288
320
|
|
|
289
321
|
if AcroForm not in writer._root_object: # type: ignore # noqa: SLF001 # # pylint: disable=W0212
|
|
290
|
-
writer._root_object[NameObject(AcroForm)] = DictionaryObject(
|
|
322
|
+
writer._root_object[NameObject(AcroForm)] = DictionaryObject( # type: ignore # noqa: SLF001 # pylint: disable=W0212
|
|
323
|
+
{NameObject(Fields): ArrayObject([])}
|
|
324
|
+
)
|
|
291
325
|
acroform = writer._root_object[AcroForm] # type: ignore # noqa: SLF001 # # pylint: disable=W0212
|
|
292
326
|
|
|
293
327
|
if DR not in acroform:
|
|
@@ -14,15 +14,47 @@ from io import BytesIO
|
|
|
14
14
|
from typing import TextIO, cast
|
|
15
15
|
|
|
16
16
|
from pypdf import PdfReader, PdfWriter
|
|
17
|
-
from pypdf.generic import (
|
|
18
|
-
|
|
17
|
+
from pypdf.generic import (
|
|
18
|
+
ArrayObject,
|
|
19
|
+
DictionaryObject,
|
|
20
|
+
FloatObject,
|
|
21
|
+
NameObject,
|
|
22
|
+
NumberObject,
|
|
23
|
+
TextStringObject,
|
|
24
|
+
)
|
|
19
25
|
|
|
20
26
|
from .adapter import fp_or_f_obj_or_f_content_to_content
|
|
21
|
-
from .constants import (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
from .constants import (
|
|
28
|
+
AA,
|
|
29
|
+
COMB,
|
|
30
|
+
DA,
|
|
31
|
+
FONT_COLOR_IDENTIFIER,
|
|
32
|
+
FONT_SIZE_IDENTIFIER,
|
|
33
|
+
HIDDEN,
|
|
34
|
+
JS,
|
|
35
|
+
MULTILINE,
|
|
36
|
+
READ_ONLY,
|
|
37
|
+
REQUIRED,
|
|
38
|
+
TU,
|
|
39
|
+
Action,
|
|
40
|
+
Annots,
|
|
41
|
+
Bl,
|
|
42
|
+
D,
|
|
43
|
+
E,
|
|
44
|
+
F,
|
|
45
|
+
Ff,
|
|
46
|
+
Fo,
|
|
47
|
+
JavaScript,
|
|
48
|
+
MaxLen,
|
|
49
|
+
Opt,
|
|
50
|
+
Parent,
|
|
51
|
+
Q,
|
|
52
|
+
Rect,
|
|
53
|
+
S,
|
|
54
|
+
Type,
|
|
55
|
+
U,
|
|
56
|
+
X,
|
|
57
|
+
)
|
|
26
58
|
from .patterns import get_widget_key
|
|
27
59
|
|
|
28
60
|
|
|
@@ -10,12 +10,45 @@ for updating these widgets.
|
|
|
10
10
|
|
|
11
11
|
from typing import Tuple
|
|
12
12
|
|
|
13
|
-
from pypdf.generic import (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
from pypdf.generic import (
|
|
14
|
+
ArrayObject,
|
|
15
|
+
DictionaryObject,
|
|
16
|
+
NameObject,
|
|
17
|
+
NumberObject,
|
|
18
|
+
TextStringObject,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
from .constants import (
|
|
22
|
+
AP,
|
|
23
|
+
AS,
|
|
24
|
+
DV,
|
|
25
|
+
FT,
|
|
26
|
+
HIDDEN,
|
|
27
|
+
IMAGE_FIELD_IDENTIFIER,
|
|
28
|
+
JS,
|
|
29
|
+
SLASH,
|
|
30
|
+
TU,
|
|
31
|
+
A,
|
|
32
|
+
Btn,
|
|
33
|
+
Ch,
|
|
34
|
+
F,
|
|
35
|
+
Ff,
|
|
36
|
+
I,
|
|
37
|
+
MaxLen,
|
|
38
|
+
N,
|
|
39
|
+
Off,
|
|
40
|
+
Opt,
|
|
41
|
+
Parent,
|
|
42
|
+
Q,
|
|
43
|
+
Rect,
|
|
44
|
+
Sig,
|
|
45
|
+
Subtype,
|
|
46
|
+
T,
|
|
47
|
+
Tx,
|
|
48
|
+
V,
|
|
49
|
+
Widget,
|
|
50
|
+
Yes,
|
|
51
|
+
)
|
|
19
52
|
from .middleware.checkbox import Checkbox
|
|
20
53
|
from .middleware.dropdown import Dropdown
|
|
21
54
|
from .middleware.image import Image
|
|
@@ -22,12 +22,22 @@ from .middleware.checkbox import Checkbox
|
|
|
22
22
|
from .middleware.dropdown import Dropdown
|
|
23
23
|
from .middleware.radio import Radio
|
|
24
24
|
from .middleware.text import Text
|
|
25
|
-
from .patterns import (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
from .patterns import (
|
|
26
|
+
WIDGET_DESCRIPTION_PATTERNS,
|
|
27
|
+
WIDGET_TYPE_PATTERNS,
|
|
28
|
+
check_field_flag,
|
|
29
|
+
get_checkbox_value,
|
|
30
|
+
get_dropdown_choices,
|
|
31
|
+
get_dropdown_value,
|
|
32
|
+
get_field_hidden,
|
|
33
|
+
get_field_rect,
|
|
34
|
+
get_radio_value,
|
|
35
|
+
get_text_field_alignment,
|
|
36
|
+
get_text_field_max_length,
|
|
37
|
+
get_text_value,
|
|
38
|
+
get_widget_key,
|
|
39
|
+
update_annotation_name,
|
|
40
|
+
)
|
|
31
41
|
from .utils import extract_widget_property, find_pattern_match
|
|
32
42
|
|
|
33
43
|
|
|
@@ -366,6 +376,51 @@ def create_annotations(
|
|
|
366
376
|
return f.read()
|
|
367
377
|
|
|
368
378
|
|
|
379
|
+
def remove_widgets_by_keys(
|
|
380
|
+
pdf: bytes, keys: List[str], use_full_widget_name: bool = False
|
|
381
|
+
) -> bytes:
|
|
382
|
+
"""
|
|
383
|
+
Removes specific widgets from a PDF by their keys.
|
|
384
|
+
|
|
385
|
+
This function removes any widget annotation whose key matches one of the
|
|
386
|
+
provided keys. If no keys are provided, the original PDF stream is returned
|
|
387
|
+
unchanged.
|
|
388
|
+
|
|
389
|
+
Args:
|
|
390
|
+
pdf (bytes): The PDF stream to remove widgets from.
|
|
391
|
+
keys (List[str]): A list of widget keys to remove.
|
|
392
|
+
use_full_widget_name (bool): Whether to match widgets by their full
|
|
393
|
+
names, including parent names.
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
bytes: The updated PDF stream with the matching widgets removed.
|
|
397
|
+
"""
|
|
398
|
+
if not keys:
|
|
399
|
+
return pdf
|
|
400
|
+
|
|
401
|
+
writer = PdfWriter(BytesIO(pdf))
|
|
402
|
+
|
|
403
|
+
for page in writer.pages:
|
|
404
|
+
needs_update = False
|
|
405
|
+
page_annots = ArrayObject([])
|
|
406
|
+
|
|
407
|
+
for annot in page.get(Annots, []):
|
|
408
|
+
annot = cast(DictionaryObject, annot.get_object())
|
|
409
|
+
key = get_widget_key(annot.get_object(), use_full_widget_name)
|
|
410
|
+
if key not in keys:
|
|
411
|
+
page_annots.append(annot)
|
|
412
|
+
else:
|
|
413
|
+
needs_update = True
|
|
414
|
+
|
|
415
|
+
if needs_update:
|
|
416
|
+
page[NameObject(Annots)] = page_annots
|
|
417
|
+
|
|
418
|
+
with BytesIO() as f:
|
|
419
|
+
writer.write(f)
|
|
420
|
+
f.seek(0)
|
|
421
|
+
return f.read()
|
|
422
|
+
|
|
423
|
+
|
|
369
424
|
def update_widget_keys(
|
|
370
425
|
template: bytes,
|
|
371
426
|
widgets: Dict[str, WIDGET_TYPES],
|
|
@@ -19,8 +19,7 @@ from io import BytesIO
|
|
|
19
19
|
from typing import List, Optional, Type
|
|
20
20
|
|
|
21
21
|
from pypdf import PdfReader, PdfWriter
|
|
22
|
-
from pypdf.generic import
|
|
23
|
-
TextStringObject)
|
|
22
|
+
from pypdf.generic import ArrayObject, FloatObject, NameObject, TextStringObject
|
|
24
23
|
from reportlab.pdfgen.canvas import Canvas
|
|
25
24
|
|
|
26
25
|
from ..assets.bedrock import BEDROCK_PDF
|
|
@@ -22,30 +22,61 @@ from collections import defaultdict
|
|
|
22
22
|
from dataclasses import asdict
|
|
23
23
|
from functools import cached_property
|
|
24
24
|
from os import PathLike
|
|
25
|
-
from typing import (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
from typing import (
|
|
26
|
+
TYPE_CHECKING,
|
|
27
|
+
BinaryIO,
|
|
28
|
+
Dict,
|
|
29
|
+
List,
|
|
30
|
+
Optional,
|
|
31
|
+
Sequence,
|
|
32
|
+
TextIO,
|
|
33
|
+
Tuple,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
from .adapter import (
|
|
37
|
+
fp_or_f_obj_or_f_content_to_content,
|
|
38
|
+
fp_or_f_obj_or_stream_to_stream,
|
|
39
|
+
)
|
|
30
40
|
from .constants import VERSION_IDENTIFIER_PREFIX, VERSION_IDENTIFIERS
|
|
31
41
|
from .coordinate import generate_coordinate_grid
|
|
32
42
|
from .egress import appearance_streams_handler, preserve_pdf_properties
|
|
33
43
|
from .filler import fill
|
|
34
|
-
from .font import (
|
|
35
|
-
|
|
44
|
+
from .font import (
|
|
45
|
+
get_all_available_fonts,
|
|
46
|
+
register_font_acroform,
|
|
47
|
+
temporary_font_registration,
|
|
48
|
+
validate_font,
|
|
49
|
+
)
|
|
36
50
|
from .hooks import trigger_widget_hooks
|
|
37
51
|
from .middleware.dropdown import Dropdown
|
|
38
52
|
from .middleware.signature import Signature
|
|
39
53
|
from .middleware.text import Text
|
|
40
|
-
from .template import (
|
|
41
|
-
|
|
54
|
+
from .template import (
|
|
55
|
+
build_widgets,
|
|
56
|
+
create_annotations,
|
|
57
|
+
get_metadata,
|
|
58
|
+
remove_widgets_by_keys,
|
|
59
|
+
update_widget_keys,
|
|
60
|
+
)
|
|
42
61
|
from .types import PdfArray
|
|
43
|
-
from .utils import (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
from .utils import (
|
|
63
|
+
generate_unique_suffix,
|
|
64
|
+
get_page_streams,
|
|
65
|
+
merge_pdfs,
|
|
66
|
+
remove_all_widgets,
|
|
67
|
+
)
|
|
68
|
+
from .watermark import (
|
|
69
|
+
copy_watermark_widgets,
|
|
70
|
+
create_watermarks_and_draw,
|
|
71
|
+
merge_watermarks_with_pdf,
|
|
72
|
+
)
|
|
73
|
+
from .widgets import (
|
|
74
|
+
CheckBoxField,
|
|
75
|
+
DropdownField,
|
|
76
|
+
ImageField,
|
|
77
|
+
RadioGroup,
|
|
78
|
+
SignatureField,
|
|
79
|
+
)
|
|
49
80
|
|
|
50
81
|
if TYPE_CHECKING:
|
|
51
82
|
from .annotations import AnnotationTypes
|
|
@@ -665,6 +696,27 @@ class PdfWrapper:
|
|
|
665
696
|
|
|
666
697
|
return self
|
|
667
698
|
|
|
699
|
+
def remove_fields(self, keys: List[str]) -> PdfWrapper:
|
|
700
|
+
"""
|
|
701
|
+
Removes form fields from the PDF by their keys.
|
|
702
|
+
|
|
703
|
+
This method removes any fields whose keys are included in `keys` and
|
|
704
|
+
refreshes the wrapper's widget metadata after the PDF stream is updated.
|
|
705
|
+
|
|
706
|
+
Args:
|
|
707
|
+
keys (List[str]): A list of form field keys to remove.
|
|
708
|
+
|
|
709
|
+
Returns:
|
|
710
|
+
PdfWrapper: The `PdfWrapper` object, allowing for method chaining.
|
|
711
|
+
"""
|
|
712
|
+
|
|
713
|
+
self._stream = remove_widgets_by_keys(
|
|
714
|
+
self._read(), keys, getattr(self, "use_full_widget_name")
|
|
715
|
+
)
|
|
716
|
+
self._init_helper()
|
|
717
|
+
|
|
718
|
+
return self
|
|
719
|
+
|
|
668
720
|
def update_widget_key(
|
|
669
721
|
self, old_key: str, new_key: str, index: int = 0
|
|
670
722
|
) -> PdfWrapper:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.2.0
|
|
4
4
|
Summary: The Python library & CLI for PDF forms.
|
|
5
5
|
Author: Jinge Li
|
|
6
6
|
License-Expression: MIT
|
|
@@ -34,9 +34,7 @@ Provides-Extra: cli
|
|
|
34
34
|
Requires-Dist: typer<1.0.0,>=0.26.1; extra == "cli"
|
|
35
35
|
Requires-Dist: jsonschema<5.0.0,>=4.26.0; extra == "cli"
|
|
36
36
|
Provides-Extra: dev
|
|
37
|
-
Requires-Dist: black<27.0.0,>=26.5.1; extra == "dev"
|
|
38
37
|
Requires-Dist: coverage<8.0.0,>=7.14.1; extra == "dev"
|
|
39
|
-
Requires-Dist: isort<9.0.0,>=8.0.1; extra == "dev"
|
|
40
38
|
Requires-Dist: mike<3.0.0,>=2.2.0; extra == "dev"
|
|
41
39
|
Requires-Dist: mkdocs<2.0.0,>=1.6.1; extra == "dev"
|
|
42
40
|
Requires-Dist: mkdocs-material<10.0.0,>=9.7.6; extra == "dev"
|
|
@@ -45,9 +45,7 @@ Documentation = "https://chinapandaman.github.io/PyPDFForm/"
|
|
|
45
45
|
# update `CLI_DEPENDENCIES` in `PyPDFForm/cli/entry.py` when changing cli dependencies
|
|
46
46
|
cli = ["typer>=0.26.1,<1.0.0", "jsonschema>=4.26.0,<5.0.0"]
|
|
47
47
|
dev = [
|
|
48
|
-
"black>=26.5.1,<27.0.0",
|
|
49
48
|
"coverage>=7.14.1,<8.0.0",
|
|
50
|
-
"isort>=8.0.1,<9.0.0",
|
|
51
49
|
"mike>=2.2.0,<3.0.0",
|
|
52
50
|
"mkdocs>=1.6.1,<2.0.0",
|
|
53
51
|
"mkdocs-material>=9.7.6,<10.0.0",
|
|
@@ -13,9 +13,16 @@ from fontTools.ttLib import TTLibError
|
|
|
13
13
|
from pypdf import PdfWriter
|
|
14
14
|
|
|
15
15
|
from PyPDFForm import PdfWrapper
|
|
16
|
-
from PyPDFForm.lib.constants import (
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
from PyPDFForm.lib.constants import (
|
|
17
|
+
DEFAULT_ASSUMED_GLYPH_WIDTH,
|
|
18
|
+
DR,
|
|
19
|
+
ENCODING_TABLE_SIZE,
|
|
20
|
+
AcroForm,
|
|
21
|
+
Font,
|
|
22
|
+
FontDescriptor,
|
|
23
|
+
MissingWidth,
|
|
24
|
+
Widths,
|
|
25
|
+
)
|
|
19
26
|
from PyPDFForm.lib.font import compute_font_glyph_widths
|
|
20
27
|
|
|
21
28
|
|
|
@@ -834,6 +834,19 @@ def test_hidden_sejda(sejda_template, pdf_samples, request):
|
|
|
834
834
|
assert obj.read() == expected
|
|
835
835
|
|
|
836
836
|
|
|
837
|
+
def test_remove_fields_update_widgets(template_stream):
|
|
838
|
+
obj = PdfWrapper(template_stream)
|
|
839
|
+
obj.remove_fields(["test", "test_2", "check_2"])
|
|
840
|
+
|
|
841
|
+
assert "test" not in obj.widgets
|
|
842
|
+
assert "test_2" not in obj.widgets
|
|
843
|
+
assert "check_2" not in obj.widgets
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
def test_remove_fields_no_keys_specified(template_stream):
|
|
847
|
+
assert PdfWrapper(template_stream).remove_fields([]).read() == template_stream
|
|
848
|
+
|
|
849
|
+
|
|
837
850
|
def test_merge(template_stream):
|
|
838
851
|
pdf_list = PdfArray()
|
|
839
852
|
for i in range(20):
|
|
@@ -44,25 +44,25 @@ def test_text_field_scripts(template_stream, pdf_samples, request):
|
|
|
44
44
|
expected_path = os.path.join(pdf_samples, "js", "test_text_field_scripts.pdf")
|
|
45
45
|
with open(expected_path, "rb+") as f:
|
|
46
46
|
pdf = PdfWrapper(template_stream)
|
|
47
|
-
pdf.widgets[
|
|
48
|
-
|
|
49
|
-
)
|
|
50
|
-
pdf.widgets[
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
pdf.widgets[
|
|
54
|
-
|
|
55
|
-
)
|
|
56
|
-
pdf.widgets[
|
|
57
|
-
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
pdf.widgets[
|
|
61
|
-
|
|
62
|
-
)
|
|
63
|
-
pdf.widgets[
|
|
64
|
-
|
|
65
|
-
)
|
|
47
|
+
pdf.widgets[
|
|
48
|
+
"test"
|
|
49
|
+
].on_hovered_over_javascript = 'this.getField("test").value = "hoverover";'
|
|
50
|
+
pdf.widgets[
|
|
51
|
+
"test"
|
|
52
|
+
].on_hovered_off_javascript = 'this.getField("test").value = "hoveroff";'
|
|
53
|
+
pdf.widgets[
|
|
54
|
+
"test"
|
|
55
|
+
].on_mouse_pressed_javascript = 'this.getField("test").value = "pressed";'
|
|
56
|
+
pdf.widgets[
|
|
57
|
+
"test"
|
|
58
|
+
].on_mouse_released_javascript = 'this.getField("test").value = "released";'
|
|
59
|
+
|
|
60
|
+
pdf.widgets[
|
|
61
|
+
"test_2"
|
|
62
|
+
].on_focused_javascript = 'this.getField("test_2").value = "focused";'
|
|
63
|
+
pdf.widgets[
|
|
64
|
+
"test_2"
|
|
65
|
+
].on_blurred_javascript = 'this.getField("test_2").value = "defocused";'
|
|
66
66
|
|
|
67
67
|
request.config.results["expected_path"] = expected_path
|
|
68
68
|
request.config.results["stream"] = pdf.read()
|
|
@@ -77,25 +77,25 @@ def test_checkbox_scripts(template_stream, pdf_samples, request):
|
|
|
77
77
|
expected_path = os.path.join(pdf_samples, "js", "test_checkbox_scripts.pdf")
|
|
78
78
|
with open(expected_path, "rb+") as f:
|
|
79
79
|
pdf = PdfWrapper(template_stream)
|
|
80
|
-
pdf.widgets[
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
pdf.widgets[
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
pdf.widgets[
|
|
87
|
-
|
|
88
|
-
)
|
|
89
|
-
pdf.widgets[
|
|
90
|
-
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
pdf.widgets[
|
|
94
|
-
|
|
95
|
-
)
|
|
96
|
-
pdf.widgets[
|
|
97
|
-
|
|
98
|
-
)
|
|
80
|
+
pdf.widgets[
|
|
81
|
+
"check"
|
|
82
|
+
].on_hovered_over_javascript = 'this.getField("test").value = "hoverover";'
|
|
83
|
+
pdf.widgets[
|
|
84
|
+
"check"
|
|
85
|
+
].on_hovered_off_javascript = 'this.getField("test").value = "hoveroff";'
|
|
86
|
+
pdf.widgets[
|
|
87
|
+
"check"
|
|
88
|
+
].on_mouse_pressed_javascript = 'this.getField("test").value = "pressed";'
|
|
89
|
+
pdf.widgets[
|
|
90
|
+
"check"
|
|
91
|
+
].on_mouse_released_javascript = 'this.getField("test").value = "released";'
|
|
92
|
+
|
|
93
|
+
pdf.widgets[
|
|
94
|
+
"check_2"
|
|
95
|
+
].on_focused_javascript = 'this.getField("test_2").value = "focused";'
|
|
96
|
+
pdf.widgets[
|
|
97
|
+
"check_2"
|
|
98
|
+
].on_blurred_javascript = 'this.getField("test_2").value = "defocused";'
|
|
99
99
|
|
|
100
100
|
request.config.results["expected_path"] = expected_path
|
|
101
101
|
request.config.results["stream"] = pdf.read()
|
|
@@ -110,25 +110,25 @@ def test_radio_scripts(template_with_radiobutton_stream, pdf_samples, request):
|
|
|
110
110
|
expected_path = os.path.join(pdf_samples, "js", "test_radio_scripts.pdf")
|
|
111
111
|
with open(expected_path, "rb+") as f:
|
|
112
112
|
pdf = PdfWrapper(template_with_radiobutton_stream)
|
|
113
|
-
pdf.widgets[
|
|
114
|
-
|
|
115
|
-
)
|
|
116
|
-
pdf.widgets[
|
|
117
|
-
|
|
118
|
-
)
|
|
119
|
-
pdf.widgets[
|
|
120
|
-
|
|
121
|
-
)
|
|
122
|
-
pdf.widgets[
|
|
123
|
-
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
pdf.widgets[
|
|
127
|
-
|
|
128
|
-
)
|
|
129
|
-
pdf.widgets[
|
|
130
|
-
|
|
131
|
-
)
|
|
113
|
+
pdf.widgets[
|
|
114
|
+
"radio_1"
|
|
115
|
+
].on_hovered_over_javascript = 'this.getField("test").value = "hoverover";'
|
|
116
|
+
pdf.widgets[
|
|
117
|
+
"radio_1"
|
|
118
|
+
].on_hovered_off_javascript = 'this.getField("test").value = "hoveroff";'
|
|
119
|
+
pdf.widgets[
|
|
120
|
+
"radio_1"
|
|
121
|
+
].on_mouse_pressed_javascript = 'this.getField("test").value = "pressed";'
|
|
122
|
+
pdf.widgets[
|
|
123
|
+
"radio_1"
|
|
124
|
+
].on_mouse_released_javascript = 'this.getField("test").value = "released";'
|
|
125
|
+
|
|
126
|
+
pdf.widgets[
|
|
127
|
+
"radio_2"
|
|
128
|
+
].on_focused_javascript = 'this.getField("test_2").value = "focused";'
|
|
129
|
+
pdf.widgets[
|
|
130
|
+
"radio_2"
|
|
131
|
+
].on_blurred_javascript = 'this.getField("test_2").value = "defocused";'
|
|
132
132
|
|
|
133
133
|
request.config.results["expected_path"] = expected_path
|
|
134
134
|
request.config.results["stream"] = pdf.read()
|
|
@@ -143,25 +143,25 @@ def test_dropdown_scripts(sample_template_with_dropdown, pdf_samples, request):
|
|
|
143
143
|
expected_path = os.path.join(pdf_samples, "js", "test_dropdown_scripts.pdf")
|
|
144
144
|
with open(expected_path, "rb+") as f:
|
|
145
145
|
pdf = PdfWrapper(sample_template_with_dropdown)
|
|
146
|
-
pdf.widgets[
|
|
147
|
-
|
|
148
|
-
)
|
|
149
|
-
pdf.widgets[
|
|
150
|
-
|
|
151
|
-
)
|
|
152
|
-
pdf.widgets[
|
|
153
|
-
|
|
154
|
-
)
|
|
155
|
-
pdf.widgets[
|
|
156
|
-
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
pdf.widgets[
|
|
160
|
-
|
|
161
|
-
)
|
|
162
|
-
pdf.widgets[
|
|
163
|
-
|
|
164
|
-
)
|
|
146
|
+
pdf.widgets[
|
|
147
|
+
"dropdown_1"
|
|
148
|
+
].on_hovered_over_javascript = 'this.getField("test_1").value = "hoverover";'
|
|
149
|
+
pdf.widgets[
|
|
150
|
+
"dropdown_1"
|
|
151
|
+
].on_hovered_off_javascript = 'this.getField("test_1").value = "hoveroff";'
|
|
152
|
+
pdf.widgets[
|
|
153
|
+
"dropdown_1"
|
|
154
|
+
].on_mouse_pressed_javascript = 'this.getField("test_1").value = "pressed";'
|
|
155
|
+
pdf.widgets[
|
|
156
|
+
"dropdown_1"
|
|
157
|
+
].on_mouse_released_javascript = 'this.getField("test_1").value = "released";'
|
|
158
|
+
|
|
159
|
+
pdf.widgets[
|
|
160
|
+
"dropdown_1"
|
|
161
|
+
].on_focused_javascript = 'this.getField("test_2").value = "focused";'
|
|
162
|
+
pdf.widgets[
|
|
163
|
+
"dropdown_1"
|
|
164
|
+
].on_blurred_javascript = 'this.getField("test_2").value = "defocused";'
|
|
165
165
|
|
|
166
166
|
request.config.results["expected_path"] = expected_path
|
|
167
167
|
request.config.results["stream"] = pdf.read()
|
|
@@ -176,25 +176,25 @@ def test_image_scripts(sample_template_with_image_field, pdf_samples, request):
|
|
|
176
176
|
expected_path = os.path.join(pdf_samples, "js", "test_image_scripts.pdf")
|
|
177
177
|
with open(expected_path, "rb+") as f:
|
|
178
178
|
pdf = PdfWrapper(sample_template_with_image_field)
|
|
179
|
-
pdf.widgets[
|
|
180
|
-
|
|
181
|
-
)
|
|
182
|
-
pdf.widgets[
|
|
183
|
-
|
|
184
|
-
)
|
|
185
|
-
pdf.widgets[
|
|
186
|
-
|
|
187
|
-
)
|
|
188
|
-
pdf.widgets[
|
|
189
|
-
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
pdf.widgets[
|
|
193
|
-
|
|
194
|
-
)
|
|
195
|
-
pdf.widgets[
|
|
196
|
-
|
|
197
|
-
)
|
|
179
|
+
pdf.widgets[
|
|
180
|
+
"image_1"
|
|
181
|
+
].on_hovered_over_javascript = 'this.getField("test").value = "hoverover";'
|
|
182
|
+
pdf.widgets[
|
|
183
|
+
"image_1"
|
|
184
|
+
].on_hovered_off_javascript = 'this.getField("test").value = "hoveroff";'
|
|
185
|
+
pdf.widgets[
|
|
186
|
+
"image_1"
|
|
187
|
+
].on_mouse_pressed_javascript = 'this.getField("test").value = "pressed";'
|
|
188
|
+
pdf.widgets[
|
|
189
|
+
"image_1"
|
|
190
|
+
].on_mouse_released_javascript = 'this.getField("test").value = "released";'
|
|
191
|
+
|
|
192
|
+
pdf.widgets[
|
|
193
|
+
"image_1"
|
|
194
|
+
].on_focused_javascript = 'this.getField("test_2").value = "focused";'
|
|
195
|
+
pdf.widgets[
|
|
196
|
+
"image_1"
|
|
197
|
+
].on_blurred_javascript = 'this.getField("test_2").value = "defocused";'
|
|
198
198
|
|
|
199
199
|
request.config.results["expected_path"] = expected_path
|
|
200
200
|
request.config.results["stream"] = pdf.read()
|
|
@@ -45,3 +45,11 @@ def test_schema(sample_template_with_full_key):
|
|
|
45
45
|
obj = PdfWrapper(sample_template_with_full_key, use_full_widget_name=True)
|
|
46
46
|
assert "Gain de 2 classes.0" in obj.schema["properties"]
|
|
47
47
|
assert "0" not in obj.schema
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_remove_fields(sample_template_with_full_key):
|
|
51
|
+
obj = PdfWrapper(sample_template_with_full_key, use_full_widget_name=True)
|
|
52
|
+
obj.remove_fields(["Gain de 2 classes.0"])
|
|
53
|
+
|
|
54
|
+
assert "Gain de 2 classes.0" not in obj.widgets
|
|
55
|
+
assert "0" not in obj.widgets
|
|
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
|
|
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
|