PyPDFForm 4.7.7__tar.gz → 4.7.9__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-4.7.7 → pypdfform-4.7.9}/PKG-INFO +3 -1
- {pypdfform-4.7.7 → pypdfform-4.7.9}/PyPDFForm/__init__.py +9 -9
- pypdfform-4.7.9/PyPDFForm/cli/__init__.py +166 -0
- pypdfform-4.7.9/PyPDFForm/cli/update.py +46 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/annotations/__init__.py +1 -1
- pypdfform-4.7.9/PyPDFForm/lib/assets/__init__.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/middleware/__init__.py +1 -1
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/raw/__init__.py +1 -1
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/template.py +1 -1
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/watermark.py +1 -3
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/widgets/__init__.py +1 -1
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/widgets/base.py +3 -3
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/widgets/signature.py +1 -4
- {pypdfform-4.7.7 → pypdfform-4.7.9}/PyPDFForm.egg-info/PKG-INFO +3 -1
- pypdfform-4.7.9/PyPDFForm.egg-info/SOURCES.txt +76 -0
- pypdfform-4.7.9/PyPDFForm.egg-info/entry_points.txt +2 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/PyPDFForm.egg-info/requires.txt +3 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/pyproject.toml +6 -4
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_bulk_create_fields.py +52 -1
- pypdfform-4.7.9/tests/test_cli.py +35 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_font_widths.py +5 -5
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_functional.py +4 -4
- pypdfform-4.7.7/PyPDFForm.egg-info/SOURCES.txt +0 -71
- {pypdfform-4.7.7 → pypdfform-4.7.9}/LICENSE +0 -0
- {pypdfform-4.7.7/PyPDFForm/assets → pypdfform-4.7.9/PyPDFForm/lib}/__init__.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/adapter.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/annotations/base.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/annotations/link.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/annotations/stamp.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/annotations/text.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/annotations/text_markup.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/assets/bedrock.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/assets/blank.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/constants.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/coordinate.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/deprecation.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/egress.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/filler.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/font.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/hooks.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/image.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/middleware/base.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/middleware/checkbox.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/middleware/dropdown.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/middleware/image.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/middleware/radio.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/middleware/signature.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/middleware/text.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/patterns.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/raw/circle.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/raw/ellipse.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/raw/image.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/raw/line.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/raw/rect.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/raw/text.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/types.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/utils.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/widgets/checkbox.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/widgets/dropdown.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/widgets/image.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/widgets/radio.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/widgets/text.py +0 -0
- {pypdfform-4.7.7/PyPDFForm → pypdfform-4.7.9/PyPDFForm/lib}/wrapper.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/PyPDFForm.egg-info/dependency_links.txt +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/PyPDFForm.egg-info/top_level.txt +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/README.md +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/setup.cfg +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_create_widget.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_draw_elements.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_dropdown.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_extract_middleware_attributes.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_fill_max_length_text_field.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_generate_appearance_streams.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_js.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_need_appearances.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_paragraph.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_signature.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_use_full_widget_name.py +0 -0
- {pypdfform-4.7.7 → pypdfform-4.7.9}/tests/test_widget_attr_trigger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 4.7.
|
|
3
|
+
Version: 4.7.9
|
|
4
4
|
Summary: The Python library for PDF forms.
|
|
5
5
|
Author: Jinge Li
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,6 +26,8 @@ Requires-Dist: pikepdf<11.0.0,>=10.5.0
|
|
|
26
26
|
Requires-Dist: pillow<13.0.0,>=12.0.0
|
|
27
27
|
Requires-Dist: pypdf<7.0.0,>=6.9.0
|
|
28
28
|
Requires-Dist: reportlab<5.0.0,>=4.4.6
|
|
29
|
+
Provides-Extra: cli
|
|
30
|
+
Requires-Dist: typer<1.0.0,>=0.24.1; extra == "cli"
|
|
29
31
|
Provides-Extra: dev
|
|
30
32
|
Requires-Dist: black<27.0.0,>=25.11.0; extra == "dev"
|
|
31
33
|
Requires-Dist: coverage<8.0.0,>=7.12.0; extra == "dev"
|
|
@@ -22,15 +22,15 @@ PyPDFForm aims to simplify PDF form manipulation, making it accessible to develo
|
|
|
22
22
|
|
|
23
23
|
import logging
|
|
24
24
|
|
|
25
|
-
__version__ = "4.7.
|
|
26
|
-
|
|
27
|
-
from .annotations import Annotations
|
|
28
|
-
from .assets.blank import BlankPage
|
|
29
|
-
from .middleware import Widgets
|
|
30
|
-
from .raw import RawElements
|
|
31
|
-
from .types import PdfArray
|
|
32
|
-
from .widgets import Fields
|
|
33
|
-
from .wrapper import PdfWrapper
|
|
25
|
+
__version__ = "4.7.9"
|
|
26
|
+
|
|
27
|
+
from .lib.annotations import Annotations
|
|
28
|
+
from .lib.assets.blank import BlankPage
|
|
29
|
+
from .lib.middleware import Widgets
|
|
30
|
+
from .lib.raw import RawElements
|
|
31
|
+
from .lib.types import PdfArray
|
|
32
|
+
from .lib.widgets import Fields
|
|
33
|
+
from .lib.wrapper import PdfWrapper
|
|
34
34
|
|
|
35
35
|
# TODO: figure out why `Annotation sizes differ:`
|
|
36
36
|
for logger in [
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
This module provides the command-line interface for PyPDFForm.
|
|
4
|
+
|
|
5
|
+
It defines the CLI application using Typer, providing commands for
|
|
6
|
+
interacting with PyPDFForm functionality from the terminal.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Annotated
|
|
10
|
+
|
|
11
|
+
import typer
|
|
12
|
+
|
|
13
|
+
from .. import __version__
|
|
14
|
+
from .update import update_cli
|
|
15
|
+
|
|
16
|
+
cli_app = typer.Typer(
|
|
17
|
+
context_settings={"help_option_names": ["--help", "-h"]}, no_args_is_help=True
|
|
18
|
+
)
|
|
19
|
+
cli_app.add_typer(
|
|
20
|
+
update_cli,
|
|
21
|
+
name="update",
|
|
22
|
+
help="Subcommands for updating PDF files and their elements.",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def version_callback(value: bool) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Callback function to handle the version option.
|
|
29
|
+
|
|
30
|
+
This is triggered when the --version or -v flag is passed to the CLI.
|
|
31
|
+
It prints the current version of PyPDFForm and exits the application.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
value (bool): The value passed to the version option. If True,
|
|
35
|
+
the version information is displayed and the application exits.
|
|
36
|
+
"""
|
|
37
|
+
if value:
|
|
38
|
+
print(f"v{__version__}")
|
|
39
|
+
raise typer.Exit
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def need_appearances_callback(ctx: typer.Context, value: bool) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Callback function to handle the need_appearances option.
|
|
45
|
+
|
|
46
|
+
This is triggered when the --need-appearances flag is passed to the CLI.
|
|
47
|
+
It stores the value in the context object for use by subcommands.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
ctx (typer.Context): The Typer context object used to pass data
|
|
51
|
+
between callbacks and commands.
|
|
52
|
+
value (bool): The value passed to the need_appearances option.
|
|
53
|
+
If True, PDF viewers will be instructed to generate appearance
|
|
54
|
+
streams for the output.
|
|
55
|
+
"""
|
|
56
|
+
if not ctx.obj:
|
|
57
|
+
ctx.obj = {}
|
|
58
|
+
ctx.obj["need_appearances"] = value
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def generate_appearance_streams_callback(ctx: typer.Context, value: bool) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Callback function to handle the generate_appearance_streams option.
|
|
64
|
+
|
|
65
|
+
This is triggered when the --generate-appearance-streams flag is passed
|
|
66
|
+
to the CLI. It stores the value in the context object for use by subcommands.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
ctx (typer.Context): The Typer context object used to pass data
|
|
70
|
+
between callbacks and commands.
|
|
71
|
+
value (bool): The value passed to the generate_appearance_streams
|
|
72
|
+
option. If True, appearance streams will be explicitly generated
|
|
73
|
+
for all form fields in output PDFs using pikepdf.
|
|
74
|
+
"""
|
|
75
|
+
if not ctx.obj:
|
|
76
|
+
ctx.obj = {}
|
|
77
|
+
ctx.obj["generate_appearance_streams"] = value
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def preserve_metadata_callback(ctx: typer.Context, value: bool) -> None:
|
|
81
|
+
"""
|
|
82
|
+
Callback function to handle the preserve_metadata option.
|
|
83
|
+
|
|
84
|
+
This is triggered when the --preserve-metadata flag is passed to the CLI.
|
|
85
|
+
It stores the value in the context object for use by subcommands.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
ctx (typer.Context): The Typer context object used to pass data
|
|
89
|
+
between callbacks and commands.
|
|
90
|
+
value (bool): The value passed to the preserve_metadata option.
|
|
91
|
+
If True, metadata will be preserved in output PDFs.
|
|
92
|
+
"""
|
|
93
|
+
if not ctx.obj:
|
|
94
|
+
ctx.obj = {}
|
|
95
|
+
ctx.obj["preserve_metadata"] = value
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def use_full_widget_name_callback(ctx: typer.Context, value: bool) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Callback function to handle the use_full_widget_name option.
|
|
101
|
+
|
|
102
|
+
This is triggered when the --use-full-widget-name flag is passed to the CLI.
|
|
103
|
+
It stores the value in the context object for use by subcommands.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
ctx (typer.Context): The Typer context object used to pass data
|
|
107
|
+
between callbacks and commands.
|
|
108
|
+
value (bool): The value passed to the use_full_widget_name option.
|
|
109
|
+
If True, fully qualified names (including parent field names)
|
|
110
|
+
will be used when looking up form fields.
|
|
111
|
+
"""
|
|
112
|
+
if not ctx.obj:
|
|
113
|
+
ctx.obj = {}
|
|
114
|
+
ctx.obj["use_full_widget_name"] = value
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@cli_app.callback(invoke_without_command=True, help="Welcome to the PyPDFForm CLI!")
|
|
118
|
+
def main(
|
|
119
|
+
version: Annotated[ # pylint: disable=W0613
|
|
120
|
+
bool,
|
|
121
|
+
typer.Option(
|
|
122
|
+
"--version",
|
|
123
|
+
"-v",
|
|
124
|
+
callback=version_callback,
|
|
125
|
+
is_eager=True,
|
|
126
|
+
help="Show current version of the CLI and exit.",
|
|
127
|
+
),
|
|
128
|
+
] = False,
|
|
129
|
+
need_appearances: Annotated[ # pylint: disable=W0613
|
|
130
|
+
bool,
|
|
131
|
+
typer.Option(
|
|
132
|
+
"--need-appearances",
|
|
133
|
+
callback=need_appearances_callback,
|
|
134
|
+
help="Instruct PDF viewers to generate appearance streams for any output PDF.",
|
|
135
|
+
),
|
|
136
|
+
] = False,
|
|
137
|
+
generate_appearance_streams: Annotated[ # pylint: disable=W0613
|
|
138
|
+
bool,
|
|
139
|
+
typer.Option(
|
|
140
|
+
"--generate-appearance-streams",
|
|
141
|
+
callback=generate_appearance_streams_callback,
|
|
142
|
+
help="Generate appearance streams for any output PDF.",
|
|
143
|
+
),
|
|
144
|
+
] = False,
|
|
145
|
+
preserve_metadata: Annotated[ # pylint: disable=W0613
|
|
146
|
+
bool,
|
|
147
|
+
typer.Option(
|
|
148
|
+
"--preserve-metadata",
|
|
149
|
+
callback=preserve_metadata_callback,
|
|
150
|
+
help="Preserve PDF metadata in output.",
|
|
151
|
+
),
|
|
152
|
+
] = False,
|
|
153
|
+
use_full_widget_name: Annotated[ # pylint: disable=W0613
|
|
154
|
+
bool,
|
|
155
|
+
typer.Option(
|
|
156
|
+
"--use-full-widget-name",
|
|
157
|
+
callback=use_full_widget_name_callback,
|
|
158
|
+
help="Use fully qualified names when accessing form fields.",
|
|
159
|
+
),
|
|
160
|
+
] = False,
|
|
161
|
+
) -> None:
|
|
162
|
+
# pylint: disable=C0116
|
|
163
|
+
...
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
__all__ = ["cli_app"]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# TODO: fix this docstring
|
|
3
|
+
"""
|
|
4
|
+
CLI commands for updating PDF metadata.
|
|
5
|
+
|
|
6
|
+
This module provides command-line interface commands for modifying
|
|
7
|
+
PDF file metadata such as title, author, subject, and other properties.
|
|
8
|
+
These commands allow users to update PDF documents directly from
|
|
9
|
+
the terminal without needing to use Python code.
|
|
10
|
+
|
|
11
|
+
The commands in this module wrap the functionality provided by
|
|
12
|
+
the PdfWrapper class, exposing it through a Typer-based CLI for
|
|
13
|
+
ease of use.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from typing import Annotated
|
|
17
|
+
|
|
18
|
+
import typer
|
|
19
|
+
|
|
20
|
+
from .. import PdfWrapper
|
|
21
|
+
|
|
22
|
+
update_cli = typer.Typer(
|
|
23
|
+
context_settings={"help_option_names": ["--help", "-h"]}, no_args_is_help=True
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@update_cli.command(no_args_is_help=True)
|
|
28
|
+
def title(
|
|
29
|
+
ctx: typer.Context,
|
|
30
|
+
pdf: Annotated[str, typer.Argument(help="The local path to a PDF.")],
|
|
31
|
+
new_title: Annotated[
|
|
32
|
+
str, typer.Option("--title", "-t", help="The new title for the PDF.")
|
|
33
|
+
],
|
|
34
|
+
output: Annotated[
|
|
35
|
+
str,
|
|
36
|
+
typer.Option(
|
|
37
|
+
"--output",
|
|
38
|
+
"-o",
|
|
39
|
+
help="The location to save the PDF to. Defaults to the original path if unspecified.",
|
|
40
|
+
),
|
|
41
|
+
] = None,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Update the title of a PDF.
|
|
45
|
+
"""
|
|
46
|
+
PdfWrapper(pdf, title=new_title, **ctx.obj).write(output or pdf)
|
|
@@ -34,7 +34,7 @@ class Annotations:
|
|
|
34
34
|
A container class that provides convenient access to all available PDF annotation types.
|
|
35
35
|
|
|
36
36
|
This class acts as a namespace for the various `Annotation` classes defined in the
|
|
37
|
-
`PyPDFForm.annotations` package, making it easier to reference them (e.g., `Annotations.TextAnnotation`).
|
|
37
|
+
`PyPDFForm.lib.annotations` package, making it easier to reference them (e.g., `Annotations.TextAnnotation`).
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
TextAnnotation = TextAnnotation
|
|
File without changes
|
|
@@ -26,7 +26,7 @@ class Widgets:
|
|
|
26
26
|
A container class that provides convenient access to all available middleware widget classes.
|
|
27
27
|
|
|
28
28
|
This class acts as a namespace for the various middleware classes defined in the
|
|
29
|
-
`PyPDFForm.middleware` package, making it easier to reference them (e.g., `Widgets.Text`).
|
|
29
|
+
`PyPDFForm.lib.middleware` package, making it easier to reference them (e.g., `Widgets.Text`).
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
32
|
Text = Text
|
|
@@ -25,7 +25,7 @@ class RawElements:
|
|
|
25
25
|
A container class that provides convenient access to all available raw drawable elements.
|
|
26
26
|
|
|
27
27
|
This class acts as a namespace for the various `Raw` classes defined in the
|
|
28
|
-
`PyPDFForm.raw` package, making it easier to reference them (e.g., `RawElements.RawText`).
|
|
28
|
+
`PyPDFForm.lib.raw` package, making it easier to reference them (e.g., `RawElements.RawText`).
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
31
|
RawText = RawText
|
|
@@ -325,7 +325,7 @@ def create_annotations(
|
|
|
325
325
|
|
|
326
326
|
This function takes a PDF template and a list of annotation objects, and
|
|
327
327
|
renders each annotation onto its specified page in the PDF. It supports
|
|
328
|
-
various annotation types defined in the `PyPDFForm.annotations` package.
|
|
328
|
+
various annotation types defined in the `PyPDFForm.lib.annotations` package.
|
|
329
329
|
|
|
330
330
|
Args:
|
|
331
331
|
template (bytes): The PDF template to add annotations to.
|
|
@@ -260,7 +260,6 @@ def create_watermarks_and_draw(
|
|
|
260
260
|
page_to_to_draw[each["page_number"]].append(each)
|
|
261
261
|
|
|
262
262
|
pdf_file = PdfReader(BytesIO(pdf))
|
|
263
|
-
buff = BytesIO()
|
|
264
263
|
|
|
265
264
|
for i, page in enumerate(pdf_file.pages):
|
|
266
265
|
elements = page_to_to_draw[i + 1]
|
|
@@ -268,8 +267,7 @@ def create_watermarks_and_draw(
|
|
|
268
267
|
result.append(b"")
|
|
269
268
|
continue
|
|
270
269
|
|
|
271
|
-
buff
|
|
272
|
-
buff.flush()
|
|
270
|
+
buff = BytesIO()
|
|
273
271
|
|
|
274
272
|
canvas = Canvas(
|
|
275
273
|
buff,
|
|
@@ -29,7 +29,7 @@ class Fields:
|
|
|
29
29
|
A container class that provides convenient access to all available PDF form field types.
|
|
30
30
|
|
|
31
31
|
This class acts as a namespace for the various `Field` classes defined in the
|
|
32
|
-
`PyPDFForm.widgets` package, making it easier to reference them (e.g., `Fields.TextField`).
|
|
32
|
+
`PyPDFForm.lib.widgets` package, making it easier to reference them (e.g., `Fields.TextField`).
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
35
|
TextField = TextField
|
|
@@ -177,7 +177,6 @@ class Widget:
|
|
|
177
177
|
result = []
|
|
178
178
|
|
|
179
179
|
pdf = PdfReader(BytesIO(stream))
|
|
180
|
-
watermark = BytesIO()
|
|
181
180
|
|
|
182
181
|
widgets_by_page = {}
|
|
183
182
|
for widget in widgets:
|
|
@@ -191,8 +190,9 @@ class Widget:
|
|
|
191
190
|
result.append(b"")
|
|
192
191
|
continue
|
|
193
192
|
|
|
194
|
-
|
|
195
|
-
watermark.
|
|
193
|
+
# Use a fresh buffer per page to avoid stale trailing bytes
|
|
194
|
+
# when the current page watermark is smaller than a previous page.
|
|
195
|
+
watermark = BytesIO()
|
|
196
196
|
|
|
197
197
|
canvas = Canvas(
|
|
198
198
|
watermark,
|
|
@@ -120,12 +120,9 @@ class SignatureWidget:
|
|
|
120
120
|
key = get_widget_key(annot.get_object(), False)
|
|
121
121
|
annot_type_to_annot[key] = annot.get_object()
|
|
122
122
|
|
|
123
|
-
watermark = BytesIO()
|
|
124
|
-
|
|
125
123
|
for i, p in enumerate(input_pdf.pages):
|
|
126
124
|
# pylint: disable=R0801
|
|
127
|
-
watermark
|
|
128
|
-
watermark.flush()
|
|
125
|
+
watermark = BytesIO()
|
|
129
126
|
canvas = Canvas(
|
|
130
127
|
watermark,
|
|
131
128
|
pagesize=(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 4.7.
|
|
3
|
+
Version: 4.7.9
|
|
4
4
|
Summary: The Python library for PDF forms.
|
|
5
5
|
Author: Jinge Li
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,6 +26,8 @@ Requires-Dist: pikepdf<11.0.0,>=10.5.0
|
|
|
26
26
|
Requires-Dist: pillow<13.0.0,>=12.0.0
|
|
27
27
|
Requires-Dist: pypdf<7.0.0,>=6.9.0
|
|
28
28
|
Requires-Dist: reportlab<5.0.0,>=4.4.6
|
|
29
|
+
Provides-Extra: cli
|
|
30
|
+
Requires-Dist: typer<1.0.0,>=0.24.1; extra == "cli"
|
|
29
31
|
Provides-Extra: dev
|
|
30
32
|
Requires-Dist: black<27.0.0,>=25.11.0; extra == "dev"
|
|
31
33
|
Requires-Dist: coverage<8.0.0,>=7.12.0; extra == "dev"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
PyPDFForm/__init__.py
|
|
5
|
+
PyPDFForm.egg-info/PKG-INFO
|
|
6
|
+
PyPDFForm.egg-info/SOURCES.txt
|
|
7
|
+
PyPDFForm.egg-info/dependency_links.txt
|
|
8
|
+
PyPDFForm.egg-info/entry_points.txt
|
|
9
|
+
PyPDFForm.egg-info/requires.txt
|
|
10
|
+
PyPDFForm.egg-info/top_level.txt
|
|
11
|
+
PyPDFForm/cli/__init__.py
|
|
12
|
+
PyPDFForm/cli/update.py
|
|
13
|
+
PyPDFForm/lib/__init__.py
|
|
14
|
+
PyPDFForm/lib/adapter.py
|
|
15
|
+
PyPDFForm/lib/constants.py
|
|
16
|
+
PyPDFForm/lib/coordinate.py
|
|
17
|
+
PyPDFForm/lib/deprecation.py
|
|
18
|
+
PyPDFForm/lib/egress.py
|
|
19
|
+
PyPDFForm/lib/filler.py
|
|
20
|
+
PyPDFForm/lib/font.py
|
|
21
|
+
PyPDFForm/lib/hooks.py
|
|
22
|
+
PyPDFForm/lib/image.py
|
|
23
|
+
PyPDFForm/lib/patterns.py
|
|
24
|
+
PyPDFForm/lib/template.py
|
|
25
|
+
PyPDFForm/lib/types.py
|
|
26
|
+
PyPDFForm/lib/utils.py
|
|
27
|
+
PyPDFForm/lib/watermark.py
|
|
28
|
+
PyPDFForm/lib/wrapper.py
|
|
29
|
+
PyPDFForm/lib/annotations/__init__.py
|
|
30
|
+
PyPDFForm/lib/annotations/base.py
|
|
31
|
+
PyPDFForm/lib/annotations/link.py
|
|
32
|
+
PyPDFForm/lib/annotations/stamp.py
|
|
33
|
+
PyPDFForm/lib/annotations/text.py
|
|
34
|
+
PyPDFForm/lib/annotations/text_markup.py
|
|
35
|
+
PyPDFForm/lib/assets/__init__.py
|
|
36
|
+
PyPDFForm/lib/assets/bedrock.py
|
|
37
|
+
PyPDFForm/lib/assets/blank.py
|
|
38
|
+
PyPDFForm/lib/middleware/__init__.py
|
|
39
|
+
PyPDFForm/lib/middleware/base.py
|
|
40
|
+
PyPDFForm/lib/middleware/checkbox.py
|
|
41
|
+
PyPDFForm/lib/middleware/dropdown.py
|
|
42
|
+
PyPDFForm/lib/middleware/image.py
|
|
43
|
+
PyPDFForm/lib/middleware/radio.py
|
|
44
|
+
PyPDFForm/lib/middleware/signature.py
|
|
45
|
+
PyPDFForm/lib/middleware/text.py
|
|
46
|
+
PyPDFForm/lib/raw/__init__.py
|
|
47
|
+
PyPDFForm/lib/raw/circle.py
|
|
48
|
+
PyPDFForm/lib/raw/ellipse.py
|
|
49
|
+
PyPDFForm/lib/raw/image.py
|
|
50
|
+
PyPDFForm/lib/raw/line.py
|
|
51
|
+
PyPDFForm/lib/raw/rect.py
|
|
52
|
+
PyPDFForm/lib/raw/text.py
|
|
53
|
+
PyPDFForm/lib/widgets/__init__.py
|
|
54
|
+
PyPDFForm/lib/widgets/base.py
|
|
55
|
+
PyPDFForm/lib/widgets/checkbox.py
|
|
56
|
+
PyPDFForm/lib/widgets/dropdown.py
|
|
57
|
+
PyPDFForm/lib/widgets/image.py
|
|
58
|
+
PyPDFForm/lib/widgets/radio.py
|
|
59
|
+
PyPDFForm/lib/widgets/signature.py
|
|
60
|
+
PyPDFForm/lib/widgets/text.py
|
|
61
|
+
tests/test_bulk_create_fields.py
|
|
62
|
+
tests/test_cli.py
|
|
63
|
+
tests/test_create_widget.py
|
|
64
|
+
tests/test_draw_elements.py
|
|
65
|
+
tests/test_dropdown.py
|
|
66
|
+
tests/test_extract_middleware_attributes.py
|
|
67
|
+
tests/test_fill_max_length_text_field.py
|
|
68
|
+
tests/test_font_widths.py
|
|
69
|
+
tests/test_functional.py
|
|
70
|
+
tests/test_generate_appearance_streams.py
|
|
71
|
+
tests/test_js.py
|
|
72
|
+
tests/test_need_appearances.py
|
|
73
|
+
tests/test_paragraph.py
|
|
74
|
+
tests/test_signature.py
|
|
75
|
+
tests/test_use_full_widget_name.py
|
|
76
|
+
tests/test_widget_attr_trigger.py
|
|
@@ -7,9 +7,7 @@ name = "PyPDFForm"
|
|
|
7
7
|
dynamic = ["version"]
|
|
8
8
|
description = "The Python library for PDF forms."
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
authors = [
|
|
11
|
-
{name = "Jinge Li"}
|
|
12
|
-
]
|
|
10
|
+
authors = [{ name = "Jinge Li" }]
|
|
13
11
|
license = "MIT"
|
|
14
12
|
license-files = ["LICENSE"]
|
|
15
13
|
classifiers = [
|
|
@@ -40,6 +38,7 @@ Homepage = "https://github.com/chinapandaman/PyPDFForm"
|
|
|
40
38
|
Documentation = "https://chinapandaman.github.io/PyPDFForm/"
|
|
41
39
|
|
|
42
40
|
[project.optional-dependencies]
|
|
41
|
+
cli = ["typer>=0.24.1,<1.0.0"]
|
|
43
42
|
dev = [
|
|
44
43
|
"black>=25.11.0,<27.0.0",
|
|
45
44
|
"coverage>=7.12.0,<8.0.0",
|
|
@@ -56,6 +55,9 @@ dev = [
|
|
|
56
55
|
"ruff>=0.14.6,<1.0.0",
|
|
57
56
|
]
|
|
58
57
|
|
|
58
|
+
[project.scripts]
|
|
59
|
+
pypdfform = "PyPDFForm.cli:cli_app"
|
|
60
|
+
|
|
59
61
|
[tool.coverage.run]
|
|
60
62
|
include = ["PyPDFForm/*"]
|
|
61
63
|
|
|
@@ -129,7 +131,7 @@ reportAssignmentType = "error"
|
|
|
129
131
|
reportOptionalSubscript = "error"
|
|
130
132
|
|
|
131
133
|
[tool.setuptools.dynamic]
|
|
132
|
-
version = {attr = "PyPDFForm.__version__"}
|
|
134
|
+
version = { attr = "PyPDFForm.__version__" }
|
|
133
135
|
|
|
134
136
|
[tool.setuptools.packages.find]
|
|
135
137
|
include = ["PyPDFForm*"]
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
from io import BytesIO
|
|
4
5
|
|
|
5
6
|
import pytest
|
|
7
|
+
from pypdf import PdfReader
|
|
6
8
|
|
|
7
|
-
from PyPDFForm import Fields, PdfWrapper
|
|
9
|
+
from PyPDFForm import BlankPage, Fields, PdfWrapper
|
|
10
|
+
from PyPDFForm.lib.constants import Annots, Subtype, Widget
|
|
8
11
|
|
|
9
12
|
|
|
10
13
|
@pytest.mark.posix_only
|
|
@@ -144,3 +147,51 @@ def test_bulk_create_fields_stress_max_mixed(pdf_samples, request):
|
|
|
144
147
|
|
|
145
148
|
assert len(obj.read()) == len(expected)
|
|
146
149
|
assert obj.read() == expected
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_bulk_create_fields_does_not_duplicate_widgets():
|
|
153
|
+
wrapper = PdfWrapper(BlankPage() * 2)
|
|
154
|
+
|
|
155
|
+
fields = []
|
|
156
|
+
y = 760.0
|
|
157
|
+
for i in range(35):
|
|
158
|
+
fields.append(
|
|
159
|
+
Fields.TextField(
|
|
160
|
+
f"p1_field_{i}",
|
|
161
|
+
1,
|
|
162
|
+
50.0,
|
|
163
|
+
y,
|
|
164
|
+
width=220.0,
|
|
165
|
+
height=16.0,
|
|
166
|
+
font_size=9.0,
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
y -= 20.0
|
|
170
|
+
|
|
171
|
+
y = 760.0
|
|
172
|
+
for i in range(4):
|
|
173
|
+
fields.append(
|
|
174
|
+
Fields.TextField(
|
|
175
|
+
f"p2_field_{i}",
|
|
176
|
+
2,
|
|
177
|
+
50.0,
|
|
178
|
+
y,
|
|
179
|
+
width=220.0,
|
|
180
|
+
height=16.0,
|
|
181
|
+
font_size=9.0,
|
|
182
|
+
)
|
|
183
|
+
)
|
|
184
|
+
y -= 24.0
|
|
185
|
+
|
|
186
|
+
output = wrapper.bulk_create_fields(fields).read()
|
|
187
|
+
reader = PdfReader(BytesIO(output))
|
|
188
|
+
|
|
189
|
+
widget_count = 0
|
|
190
|
+
for page in reader.pages:
|
|
191
|
+
annots = page.get(Annots) or []
|
|
192
|
+
for annot_ref in annots:
|
|
193
|
+
annot = annot_ref.get_object()
|
|
194
|
+
if str(annot.get(Subtype)) == Widget:
|
|
195
|
+
widget_count += 1
|
|
196
|
+
|
|
197
|
+
assert widget_count == len(fields)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from typer.testing import CliRunner
|
|
4
|
+
|
|
5
|
+
from PyPDFForm import __version__
|
|
6
|
+
from PyPDFForm.cli import cli_app
|
|
7
|
+
|
|
8
|
+
runner = CliRunner()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_root_command():
|
|
12
|
+
result = runner.invoke(cli_app)
|
|
13
|
+
assert result.exit_code == 2
|
|
14
|
+
|
|
15
|
+
assert "Welcome to the PyPDFForm CLI!" in result.output
|
|
16
|
+
assert "Usage:" in result.output
|
|
17
|
+
assert "main" not in result.output
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_root_command_with_version():
|
|
21
|
+
long = runner.invoke(cli_app, ["--version"])
|
|
22
|
+
short = runner.invoke(cli_app, ["-v"])
|
|
23
|
+
|
|
24
|
+
assert long.exit_code == 0
|
|
25
|
+
assert short.exit_code == 0
|
|
26
|
+
|
|
27
|
+
assert long.output == f"v{__version__}\n"
|
|
28
|
+
assert long.output == short.output
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_update_command():
|
|
32
|
+
result = runner.invoke(cli_app, ["update"])
|
|
33
|
+
assert result.exit_code == 2
|
|
34
|
+
|
|
35
|
+
assert "Usage:" in result.output
|
|
@@ -13,10 +13,10 @@ from fontTools.ttLib import TTLibError
|
|
|
13
13
|
from pypdf import PdfWriter
|
|
14
14
|
|
|
15
15
|
from PyPDFForm import PdfWrapper
|
|
16
|
-
from PyPDFForm.constants import (DEFAULT_ASSUMED_GLYPH_WIDTH, DR,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
from PyPDFForm.font import compute_font_glyph_widths
|
|
16
|
+
from PyPDFForm.lib.constants import (DEFAULT_ASSUMED_GLYPH_WIDTH, DR,
|
|
17
|
+
ENCODING_TABLE_SIZE, AcroForm, Font,
|
|
18
|
+
FontDescriptor, MissingWidth, Widths)
|
|
19
|
+
from PyPDFForm.lib.font import compute_font_glyph_widths
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@pytest.fixture
|
|
@@ -72,7 +72,7 @@ def test_compute_font_widths_raises_for_invalid_ttf():
|
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def test_compute_font_glyph_widths_with_missing_tables():
|
|
75
|
-
with patch("PyPDFForm.font.FT_TTFont") as mock_ttfont:
|
|
75
|
+
with patch("PyPDFForm.lib.font.FT_TTFont") as mock_ttfont:
|
|
76
76
|
mock_font = MagicMock()
|
|
77
77
|
mock_font.get.side_effect = lambda table: None
|
|
78
78
|
mock_ttfont.return_value = mock_font
|
|
@@ -7,10 +7,10 @@ import pytest
|
|
|
7
7
|
from jsonschema import ValidationError, validate
|
|
8
8
|
|
|
9
9
|
from PyPDFForm import Annotations, BlankPage, Fields, PdfArray, PdfWrapper
|
|
10
|
-
from PyPDFForm.constants import DA, UNIQUE_SUFFIX_LENGTH, T, V
|
|
11
|
-
from PyPDFForm.deprecation import deprecation_notice
|
|
12
|
-
from PyPDFForm.middleware.base import Widget
|
|
13
|
-
from PyPDFForm.template import get_widgets_by_page
|
|
10
|
+
from PyPDFForm.lib.constants import DA, UNIQUE_SUFFIX_LENGTH, T, V
|
|
11
|
+
from PyPDFForm.lib.deprecation import deprecation_notice
|
|
12
|
+
from PyPDFForm.lib.middleware.base import Widget
|
|
13
|
+
from PyPDFForm.lib.template import get_widgets_by_page
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def test_deprecation_warning():
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
README.md
|
|
3
|
-
pyproject.toml
|
|
4
|
-
PyPDFForm/__init__.py
|
|
5
|
-
PyPDFForm/adapter.py
|
|
6
|
-
PyPDFForm/constants.py
|
|
7
|
-
PyPDFForm/coordinate.py
|
|
8
|
-
PyPDFForm/deprecation.py
|
|
9
|
-
PyPDFForm/egress.py
|
|
10
|
-
PyPDFForm/filler.py
|
|
11
|
-
PyPDFForm/font.py
|
|
12
|
-
PyPDFForm/hooks.py
|
|
13
|
-
PyPDFForm/image.py
|
|
14
|
-
PyPDFForm/patterns.py
|
|
15
|
-
PyPDFForm/template.py
|
|
16
|
-
PyPDFForm/types.py
|
|
17
|
-
PyPDFForm/utils.py
|
|
18
|
-
PyPDFForm/watermark.py
|
|
19
|
-
PyPDFForm/wrapper.py
|
|
20
|
-
PyPDFForm.egg-info/PKG-INFO
|
|
21
|
-
PyPDFForm.egg-info/SOURCES.txt
|
|
22
|
-
PyPDFForm.egg-info/dependency_links.txt
|
|
23
|
-
PyPDFForm.egg-info/requires.txt
|
|
24
|
-
PyPDFForm.egg-info/top_level.txt
|
|
25
|
-
PyPDFForm/annotations/__init__.py
|
|
26
|
-
PyPDFForm/annotations/base.py
|
|
27
|
-
PyPDFForm/annotations/link.py
|
|
28
|
-
PyPDFForm/annotations/stamp.py
|
|
29
|
-
PyPDFForm/annotations/text.py
|
|
30
|
-
PyPDFForm/annotations/text_markup.py
|
|
31
|
-
PyPDFForm/assets/__init__.py
|
|
32
|
-
PyPDFForm/assets/bedrock.py
|
|
33
|
-
PyPDFForm/assets/blank.py
|
|
34
|
-
PyPDFForm/middleware/__init__.py
|
|
35
|
-
PyPDFForm/middleware/base.py
|
|
36
|
-
PyPDFForm/middleware/checkbox.py
|
|
37
|
-
PyPDFForm/middleware/dropdown.py
|
|
38
|
-
PyPDFForm/middleware/image.py
|
|
39
|
-
PyPDFForm/middleware/radio.py
|
|
40
|
-
PyPDFForm/middleware/signature.py
|
|
41
|
-
PyPDFForm/middleware/text.py
|
|
42
|
-
PyPDFForm/raw/__init__.py
|
|
43
|
-
PyPDFForm/raw/circle.py
|
|
44
|
-
PyPDFForm/raw/ellipse.py
|
|
45
|
-
PyPDFForm/raw/image.py
|
|
46
|
-
PyPDFForm/raw/line.py
|
|
47
|
-
PyPDFForm/raw/rect.py
|
|
48
|
-
PyPDFForm/raw/text.py
|
|
49
|
-
PyPDFForm/widgets/__init__.py
|
|
50
|
-
PyPDFForm/widgets/base.py
|
|
51
|
-
PyPDFForm/widgets/checkbox.py
|
|
52
|
-
PyPDFForm/widgets/dropdown.py
|
|
53
|
-
PyPDFForm/widgets/image.py
|
|
54
|
-
PyPDFForm/widgets/radio.py
|
|
55
|
-
PyPDFForm/widgets/signature.py
|
|
56
|
-
PyPDFForm/widgets/text.py
|
|
57
|
-
tests/test_bulk_create_fields.py
|
|
58
|
-
tests/test_create_widget.py
|
|
59
|
-
tests/test_draw_elements.py
|
|
60
|
-
tests/test_dropdown.py
|
|
61
|
-
tests/test_extract_middleware_attributes.py
|
|
62
|
-
tests/test_fill_max_length_text_field.py
|
|
63
|
-
tests/test_font_widths.py
|
|
64
|
-
tests/test_functional.py
|
|
65
|
-
tests/test_generate_appearance_streams.py
|
|
66
|
-
tests/test_js.py
|
|
67
|
-
tests/test_need_appearances.py
|
|
68
|
-
tests/test_paragraph.py
|
|
69
|
-
tests/test_signature.py
|
|
70
|
-
tests/test_use_full_widget_name.py
|
|
71
|
-
tests/test_widget_attr_trigger.py
|
|
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
|