PyPDFForm 4.6.2__tar.gz → 4.7.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-4.6.2 → pypdfform-4.7.0}/PKG-INFO +5 -2
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/__init__.py +1 -1
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/annotations/__init__.py +3 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/annotations/link.py +12 -4
- pypdfform-4.7.0/PyPDFForm/annotations/stamp.py +77 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/constants.py +0 -9
- pypdfform-4.6.2/PyPDFForm/ap.py → pypdfform-4.7.0/PyPDFForm/egress.py +21 -13
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/filler.py +2 -1
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/middleware/__init__.py +2 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/middleware/base.py +21 -18
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/template.py +2 -23
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/wrapper.py +8 -10
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm.egg-info/PKG-INFO +5 -2
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm.egg-info/SOURCES.txt +2 -1
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm.egg-info/requires.txt +2 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/README.md +2 -1
- {pypdfform-4.6.2 → pypdfform-4.7.0}/pyproject.toml +2 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_functional.py +129 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/LICENSE +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/adapter.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/annotations/base.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/annotations/text.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/annotations/text_markup.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/assets/__init__.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/assets/bedrock.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/assets/blank.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/coordinate.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/deprecation.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/font.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/hooks.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/image.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/middleware/checkbox.py +1 -1
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/middleware/dropdown.py +2 -2
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/middleware/image.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/middleware/radio.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/middleware/signature.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/middleware/text.py +1 -1
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/patterns.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/raw/__init__.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/raw/circle.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/raw/ellipse.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/raw/image.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/raw/line.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/raw/rect.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/raw/text.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/types.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/utils.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/watermark.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/widgets/__init__.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/widgets/base.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/widgets/checkbox.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/widgets/dropdown.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/widgets/image.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/widgets/radio.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/widgets/signature.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm/widgets/text.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm.egg-info/dependency_links.txt +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/PyPDFForm.egg-info/top_level.txt +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/setup.cfg +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_bulk_create_fields.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_create_widget.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_draw_elements.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_dropdown.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_extract_middleware_attributes.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_fill_max_length_text_field.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_font_widths.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_generate_appearance_streams.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_js.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_need_appearances.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_paragraph.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_signature.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.0}/tests/test_use_full_widget_name.py +0 -0
- {pypdfform-4.6.2 → pypdfform-4.7.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: 4.
|
|
3
|
+
Version: 4.7.0
|
|
4
4
|
Summary: The Python library for PDF forms.
|
|
5
5
|
Author: Jinge Li
|
|
6
6
|
License-Expression: MIT
|
|
@@ -31,6 +31,8 @@ Requires-Dist: black<27.0.0,>=25.11.0; extra == "dev"
|
|
|
31
31
|
Requires-Dist: coverage<8.0.0,>=7.12.0; extra == "dev"
|
|
32
32
|
Requires-Dist: isort<9.0.0,>=7.0.0; extra == "dev"
|
|
33
33
|
Requires-Dist: jsonschema<5.0.0,>=4.25.1; extra == "dev"
|
|
34
|
+
Requires-Dist: mike<3.0.0,>=2.1.3; extra == "dev"
|
|
35
|
+
Requires-Dist: mkdocs<2.0.0,>=1.6.1; extra == "dev"
|
|
34
36
|
Requires-Dist: mkdocs-material<10.0.0,>=9.7.0; extra == "dev"
|
|
35
37
|
Requires-Dist: pudb<2026.0.0,>=2025.1.3; extra == "dev"
|
|
36
38
|
Requires-Dist: pylint<5.0.0,>=4.0.3; extra == "dev"
|
|
@@ -48,7 +50,7 @@ Dynamic: license-file
|
|
|
48
50
|
<a href="https://pypi.org/project/PyPDFForm/"><img src="https://img.shields.io/pypi/v/pypdfform?label=version&color=magenta"></a>
|
|
49
51
|
<a href="https://chinapandaman.github.io/PyPDFForm/"><img src="https://img.shields.io/github/v/release/chinapandaman/pypdfform?label=docs&color=cyan"></a>
|
|
50
52
|
<a href="https://github.com/chinapandaman/PyPDFForm/actions/workflows/python-package.yml"><img src="https://img.shields.io/badge/coverage-100%25-green"></a>
|
|
51
|
-
<a href="https://github.com/chinapandaman/PyPDFForm/
|
|
53
|
+
<a href="https://github.com/chinapandaman/PyPDFForm/blob/master/LICENSE"><img src="https://img.shields.io/github/license/chinapandaman/pypdfform?label=license&color=orange"></a>
|
|
52
54
|
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/pypi/pyversions/pypdfform?label=python&color=gold"></a>
|
|
53
55
|
<a href="https://pepy.tech/projects/pypdfform"><img src="https://static.pepy.tech/badge/pypdfform/month"></a>
|
|
54
56
|
</p>
|
|
@@ -102,6 +104,7 @@ The official documentation can be found on [the GitHub page](https://chinapandam
|
|
|
102
104
|
|
|
103
105
|
## Other Resources
|
|
104
106
|
|
|
107
|
+
<!-- TODO: remove WIP when finish recording -->
|
|
105
108
|
* [(WIP) Video Tutorials](https://youtube.com/playlist?list=PLNz_PBu1QA-gzYg5BvyOO98q15u5Xve1L&si=8MWasKEckBzY-NRQ)
|
|
106
109
|
* [Chicago Python User Group - Dec 14, 2023](https://youtu.be/8t1RdAKwr9w?si=TLgumBNXv9H8szSn)
|
|
107
110
|
|
|
@@ -20,7 +20,7 @@ The library supports various PDF form features, including:
|
|
|
20
20
|
PyPDFForm aims to simplify PDF form manipulation, making it accessible to developers of all skill levels.
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
__version__ = "4.
|
|
23
|
+
__version__ = "4.7.0"
|
|
24
24
|
|
|
25
25
|
from .annotations import Annotations
|
|
26
26
|
from .assets.blank import BlankPage
|
|
@@ -12,6 +12,7 @@ annotations, facilitating their creation and manipulation within PDF documents.
|
|
|
12
12
|
from dataclasses import dataclass
|
|
13
13
|
|
|
14
14
|
from .link import LinkAnnotation
|
|
15
|
+
from .stamp import RubberStampAnnotation
|
|
15
16
|
from .text import TextAnnotation
|
|
16
17
|
from .text_markup import (HighlightAnnotation, SquigglyAnnotation,
|
|
17
18
|
StrikeOutAnnotation, UnderlineAnnotation)
|
|
@@ -23,6 +24,7 @@ AnnotationTypes = (
|
|
|
23
24
|
| UnderlineAnnotation
|
|
24
25
|
| SquigglyAnnotation
|
|
25
26
|
| StrikeOutAnnotation
|
|
27
|
+
| RubberStampAnnotation
|
|
26
28
|
)
|
|
27
29
|
|
|
28
30
|
|
|
@@ -41,3 +43,4 @@ class Annotations:
|
|
|
41
43
|
UnderlineAnnotation = UnderlineAnnotation
|
|
42
44
|
SquigglyAnnotation = SquigglyAnnotation
|
|
43
45
|
StrikeOutAnnotation = StrikeOutAnnotation
|
|
46
|
+
RubberStampAnnotation = RubberStampAnnotation
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
This module defines the class for link annotations in PyPDFForm.
|
|
5
5
|
|
|
6
6
|
It provides a structure for representing and interacting with PDF link
|
|
7
|
-
annotations, which allow users to click and navigate to a URI.
|
|
7
|
+
annotations, which allow users to click and navigate to a URI or an internal page.
|
|
8
8
|
|
|
9
9
|
Classes:
|
|
10
10
|
- `LinkAnnotation`: A dataclass representing the properties of a PDF link annotation.
|
|
@@ -13,7 +13,8 @@ Classes:
|
|
|
13
13
|
from dataclasses import dataclass
|
|
14
14
|
from typing import Optional
|
|
15
15
|
|
|
16
|
-
from pypdf.generic import DictionaryObject, NameObject,
|
|
16
|
+
from pypdf.generic import (ArrayObject, DictionaryObject, NameObject,
|
|
17
|
+
NumberObject, TextStringObject)
|
|
17
18
|
|
|
18
19
|
from ..constants import A, S
|
|
19
20
|
from .base import Annotation
|
|
@@ -25,21 +26,24 @@ class LinkAnnotation(Annotation):
|
|
|
25
26
|
A dataclass representing the properties of a PDF link annotation.
|
|
26
27
|
|
|
27
28
|
This class extends the `Annotation` base class to specifically handle
|
|
28
|
-
link annotations, including the target URI.
|
|
29
|
+
link annotations, including the target URI or an internal page.
|
|
29
30
|
|
|
30
31
|
Attributes:
|
|
31
32
|
uri (str): The URI that the link annotation points to. Defaults to None.
|
|
33
|
+
page (int): The 1-based page number that the link annotation points to. Defaults to None.
|
|
32
34
|
"""
|
|
33
35
|
|
|
34
36
|
_annotation_type: str = "/Link"
|
|
35
37
|
|
|
36
38
|
uri: Optional[str] = None
|
|
39
|
+
page: Optional[int] = None
|
|
37
40
|
|
|
38
41
|
def get_specific_properties(self) -> dict:
|
|
39
42
|
"""
|
|
40
43
|
Gets properties specific to the link annotation.
|
|
41
44
|
|
|
42
|
-
This method extends the base properties with
|
|
45
|
+
This method extends the base properties with either a URI action
|
|
46
|
+
or a destination for an internal page link.
|
|
43
47
|
|
|
44
48
|
Returns:
|
|
45
49
|
dict: A dictionary of PDF properties specific to the link annotation.
|
|
@@ -52,5 +56,9 @@ class LinkAnnotation(Annotation):
|
|
|
52
56
|
NameObject("/URI"): TextStringObject(self.uri),
|
|
53
57
|
}
|
|
54
58
|
)
|
|
59
|
+
elif self.page is not None:
|
|
60
|
+
result[NameObject("/Dest")] = ArrayObject(
|
|
61
|
+
[NumberObject(self.page - 1), NameObject("/Fit")]
|
|
62
|
+
)
|
|
55
63
|
|
|
56
64
|
return result
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
This module defines the `RubberStampAnnotation` class, which is used to represent
|
|
4
|
+
a rubber stamp annotation in a PDF document.
|
|
5
|
+
|
|
6
|
+
The `RubberStampAnnotation` class encapsulates the properties of a rubber stamp
|
|
7
|
+
annotation, such as its location, dimensions, content, and the stamp name.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
from pypdf.generic import NameObject
|
|
14
|
+
|
|
15
|
+
from .base import Annotation
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class RubberStampAnnotation(Annotation):
|
|
20
|
+
"""
|
|
21
|
+
Represents a rubber stamp annotation in a PDF document.
|
|
22
|
+
|
|
23
|
+
This dataclass extends the base `Annotation` class and defines the specific
|
|
24
|
+
attributes and metadata associated with a rubber stamp annotation.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
_annotation_type (str): The PDF internal type of the annotation, which is "/Stamp".
|
|
28
|
+
approved (str): The identifier for an "Approved" stamp.
|
|
29
|
+
experimental (str): The identifier for an "Experimental" stamp.
|
|
30
|
+
not_approved (str): The identifier for a "NotApproved" stamp.
|
|
31
|
+
as_is (str): The identifier for an "AsIs" stamp.
|
|
32
|
+
expired (str): The identifier for an "Expired" stamp.
|
|
33
|
+
not_for_public_release (str): The identifier for a "NotForPublicRelease" stamp.
|
|
34
|
+
confidential (str): The identifier for a "Confidential" stamp.
|
|
35
|
+
final (str): The identifier for a "Final" stamp.
|
|
36
|
+
sold (str): The identifier for a "Sold" stamp.
|
|
37
|
+
departmental (str): The identifier for a "Departmental" stamp.
|
|
38
|
+
for_comment (str): The identifier for a "ForComment" stamp.
|
|
39
|
+
top_secret (str): The identifier for a "TopSecret" stamp.
|
|
40
|
+
draft (str): The identifier for a "Draft" stamp.
|
|
41
|
+
for_public_release (str): The identifier for a "ForPublicRelease" stamp.
|
|
42
|
+
name (Optional[str]): The name of the stamp to be used.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
_annotation_type: str = "/Stamp"
|
|
46
|
+
|
|
47
|
+
approved = "/Approved"
|
|
48
|
+
experimental = "/Experimental"
|
|
49
|
+
not_approved = "/NotApproved"
|
|
50
|
+
as_is = "/AsIs"
|
|
51
|
+
expired = "/Expired"
|
|
52
|
+
not_for_public_release = "/NotForPublicRelease"
|
|
53
|
+
confidential = "/Confidential"
|
|
54
|
+
final = "/Final"
|
|
55
|
+
sold = "/Sold"
|
|
56
|
+
departmental = "/Departmental"
|
|
57
|
+
for_comment = "/ForComment"
|
|
58
|
+
top_secret = "/TopSecret"
|
|
59
|
+
draft = "/Draft"
|
|
60
|
+
for_public_release = "/ForPublicRelease"
|
|
61
|
+
|
|
62
|
+
name: Optional[str] = None
|
|
63
|
+
|
|
64
|
+
def get_specific_properties(self) -> dict:
|
|
65
|
+
"""
|
|
66
|
+
Gets properties specific to the rubber stamp annotation.
|
|
67
|
+
|
|
68
|
+
This method extends the base properties with the stamp name if it is provided.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
dict: A dictionary of PDF properties specific to the rubber stamp annotation.
|
|
72
|
+
"""
|
|
73
|
+
result = super().get_specific_properties()
|
|
74
|
+
if self.name is not None:
|
|
75
|
+
result[NameObject("/Name")] = NameObject(self.name)
|
|
76
|
+
|
|
77
|
+
return result
|
|
@@ -15,13 +15,6 @@ Using constants improves code readability and maintainability by providing
|
|
|
15
15
|
meaningful names for frequently used values and reducing the risk of typos.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from .middleware.checkbox import Checkbox
|
|
19
|
-
from .middleware.dropdown import Dropdown
|
|
20
|
-
from .middleware.image import Image
|
|
21
|
-
from .middleware.radio import Radio
|
|
22
|
-
from .middleware.signature import Signature
|
|
23
|
-
from .middleware.text import Text
|
|
24
|
-
|
|
25
18
|
VERSION_IDENTIFIERS = [
|
|
26
19
|
b"%PDF-1.0",
|
|
27
20
|
b"%PDF-1.1",
|
|
@@ -35,8 +28,6 @@ VERSION_IDENTIFIERS = [
|
|
|
35
28
|
]
|
|
36
29
|
VERSION_IDENTIFIER_PREFIX = "%PDF-".encode("utf-8")
|
|
37
30
|
|
|
38
|
-
WIDGET_TYPES = Text | Checkbox | Radio | Dropdown | Signature | Image
|
|
39
|
-
|
|
40
31
|
DEPRECATION_NOTICE = "{} will be deprecated soon. Use {} instead."
|
|
41
32
|
|
|
42
33
|
Title = "/Title"
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""
|
|
3
|
-
A module for
|
|
4
|
-
|
|
5
|
-
This module provides
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
A module for egress functions.
|
|
4
|
+
|
|
5
|
+
This module provides functionalities that prepare the final PDF for output (egress),
|
|
6
|
+
ensuring that it is properly formatted and ready for the end-user. This includes
|
|
7
|
+
managing appearance streams (so form fields display correctly after being filled),
|
|
8
|
+
handling the /NeedAppearances flag, and preserving or updating document-level
|
|
9
|
+
properties like metadata, title, and OpenAction scripts. These functions are typically
|
|
10
|
+
called right before the final PDF byte stream is returned by the wrapper module.
|
|
8
11
|
"""
|
|
9
12
|
|
|
10
13
|
from functools import lru_cache
|
|
@@ -66,18 +69,20 @@ def appearance_streams_handler(pdf: bytes, generate_appearance_streams: bool) ->
|
|
|
66
69
|
return result
|
|
67
70
|
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
def preserve_pdf_properties(
|
|
73
|
+
pdf: bytes, title: str, script: str, metadata: dict
|
|
74
|
+
) -> bytes:
|
|
71
75
|
"""
|
|
72
|
-
Preserves and updates PDF properties such as title and OpenAction scripts.
|
|
76
|
+
Preserves and updates PDF properties such as metadata, title, and OpenAction scripts.
|
|
73
77
|
|
|
74
|
-
This function allows setting or updating the PDF's title
|
|
78
|
+
This function allows setting or updating the PDF's title and metadata, and
|
|
75
79
|
attaching a JavaScript script that executes when the PDF is opened.
|
|
76
80
|
|
|
77
81
|
Args:
|
|
78
82
|
pdf (bytes): The PDF file content as a bytes stream.
|
|
79
83
|
title (str): The title to be set in the PDF metadata.
|
|
80
84
|
script (str): JavaScript code to be executed when the PDF is opened.
|
|
85
|
+
metadata (dict): The original metadata to preserve.
|
|
81
86
|
|
|
82
87
|
Returns:
|
|
83
88
|
bytes: The modified PDF content as a bytes stream.
|
|
@@ -86,11 +91,14 @@ def preserve_pdf_properties(pdf: bytes, title: str, script: str) -> bytes:
|
|
|
86
91
|
writer = PdfWriter()
|
|
87
92
|
writer.append(reader)
|
|
88
93
|
|
|
89
|
-
if title:
|
|
90
|
-
|
|
91
|
-
metadata
|
|
94
|
+
if title or metadata:
|
|
95
|
+
_metadata = reader.metadata or {}
|
|
96
|
+
if metadata:
|
|
97
|
+
_metadata.update(metadata)
|
|
98
|
+
if title:
|
|
99
|
+
_metadata[NameObject(Title)] = TextStringObject(title)
|
|
92
100
|
|
|
93
|
-
writer.add_metadata(
|
|
101
|
+
writer.add_metadata(_metadata)
|
|
94
102
|
|
|
95
103
|
if script:
|
|
96
104
|
open_action = DictionaryObject()
|
|
@@ -14,9 +14,10 @@ from typing import Dict, cast
|
|
|
14
14
|
from pypdf import PdfReader, PdfWriter
|
|
15
15
|
from pypdf.generic import DictionaryObject
|
|
16
16
|
|
|
17
|
-
from .constants import
|
|
17
|
+
from .constants import Annots
|
|
18
18
|
from .hooks import flatten_field
|
|
19
19
|
from .image import get_draw_image_resolutions, get_image_dimensions
|
|
20
|
+
from .middleware import WIDGET_TYPES
|
|
20
21
|
from .middleware.checkbox import Checkbox
|
|
21
22
|
from .middleware.dropdown import Dropdown
|
|
22
23
|
from .middleware.image import Image
|
|
@@ -21,23 +21,6 @@ class Widget:
|
|
|
21
21
|
as name, value, and schema definition.
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
SET_ATTR_TRIGGER_HOOK_MAP = {
|
|
25
|
-
"x": "update_field_x",
|
|
26
|
-
"y": "update_field_y",
|
|
27
|
-
"width": "update_field_width",
|
|
28
|
-
"height": "update_field_height",
|
|
29
|
-
"readonly": "flatten_field",
|
|
30
|
-
"required": "update_field_required",
|
|
31
|
-
"hidden": "update_field_hidden",
|
|
32
|
-
"tooltip": "update_field_tooltip",
|
|
33
|
-
"on_hovered_over_javascript": "update_field_on_hovered_over_javascript",
|
|
34
|
-
"on_hovered_off_javascript": "update_field_on_hovered_off_javascript",
|
|
35
|
-
"on_mouse_pressed_javascript": "update_field_on_mouse_pressed_javascript",
|
|
36
|
-
"on_mouse_released_javascript": "update_field_on_mouse_released_javascript",
|
|
37
|
-
"on_focused_javascript": "update_field_on_focused_javascript",
|
|
38
|
-
"on_blurred_javascript": "update_field_on_blurred_javascript",
|
|
39
|
-
}
|
|
40
|
-
|
|
41
24
|
def __init__(
|
|
42
25
|
self,
|
|
43
26
|
name: str,
|
|
@@ -51,6 +34,22 @@ class Widget:
|
|
|
51
34
|
value (Any): The initial value of the widget. Defaults to None.
|
|
52
35
|
"""
|
|
53
36
|
super().__init__()
|
|
37
|
+
self.SET_ATTR_TRIGGER_HOOK_MAP = {
|
|
38
|
+
"x": "update_field_x",
|
|
39
|
+
"y": "update_field_y",
|
|
40
|
+
"width": "update_field_width",
|
|
41
|
+
"height": "update_field_height",
|
|
42
|
+
"readonly": "flatten_field",
|
|
43
|
+
"required": "update_field_required",
|
|
44
|
+
"hidden": "update_field_hidden",
|
|
45
|
+
"tooltip": "update_field_tooltip",
|
|
46
|
+
"on_hovered_over_javascript": "update_field_on_hovered_over_javascript",
|
|
47
|
+
"on_hovered_off_javascript": "update_field_on_hovered_off_javascript",
|
|
48
|
+
"on_mouse_pressed_javascript": "update_field_on_mouse_pressed_javascript",
|
|
49
|
+
"on_mouse_released_javascript": "update_field_on_mouse_released_javascript",
|
|
50
|
+
"on_focused_javascript": "update_field_on_focused_javascript",
|
|
51
|
+
"on_blurred_javascript": "update_field_on_blurred_javascript",
|
|
52
|
+
}
|
|
54
53
|
self.attr_set_tracker = {}
|
|
55
54
|
|
|
56
55
|
self._name = name
|
|
@@ -88,7 +87,11 @@ class Widget:
|
|
|
88
87
|
name (str): The name of the attribute.
|
|
89
88
|
value (Any): The value of the attribute.
|
|
90
89
|
"""
|
|
91
|
-
if
|
|
90
|
+
if (
|
|
91
|
+
hasattr(self, "SET_ATTR_TRIGGER_HOOK_MAP")
|
|
92
|
+
and name in self.SET_ATTR_TRIGGER_HOOK_MAP
|
|
93
|
+
and value is not None
|
|
94
|
+
):
|
|
92
95
|
self.hooks_to_trigger.append((self.SET_ATTR_TRIGGER_HOOK_MAP[name], value))
|
|
93
96
|
|
|
94
97
|
if (
|
|
@@ -16,8 +16,8 @@ from pypdf import PdfReader, PdfWriter
|
|
|
16
16
|
from pypdf.generic import ArrayObject, DictionaryObject, NameObject
|
|
17
17
|
|
|
18
18
|
from .annotations import AnnotationTypes
|
|
19
|
-
from .constants import
|
|
20
|
-
|
|
19
|
+
from .constants import COMB, MULTILINE, READ_ONLY, REQUIRED, Annots
|
|
20
|
+
from .middleware import WIDGET_TYPES
|
|
21
21
|
from .middleware.checkbox import Checkbox
|
|
22
22
|
from .middleware.dropdown import Dropdown
|
|
23
23
|
from .middleware.radio import Radio
|
|
@@ -49,27 +49,6 @@ def get_metadata(pdf: bytes) -> dict:
|
|
|
49
49
|
return reader.metadata or {}
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
def set_metadata(pdf: bytes, metadata: dict) -> bytes:
|
|
53
|
-
"""
|
|
54
|
-
Sets the metadata of a PDF.
|
|
55
|
-
|
|
56
|
-
Args:
|
|
57
|
-
pdf (bytes): The PDF stream to set metadata for.
|
|
58
|
-
metadata (dict): A dictionary containing the metadata to be set.
|
|
59
|
-
|
|
60
|
-
Returns:
|
|
61
|
-
bytes: The updated PDF stream with the new metadata.
|
|
62
|
-
"""
|
|
63
|
-
reader = PdfReader(stream_to_io(pdf))
|
|
64
|
-
writer = PdfWriter(clone_from=reader)
|
|
65
|
-
writer.add_metadata(metadata)
|
|
66
|
-
|
|
67
|
-
with BytesIO() as f:
|
|
68
|
-
writer.write(f)
|
|
69
|
-
f.seek(0)
|
|
70
|
-
return f.read()
|
|
71
|
-
|
|
72
|
-
|
|
73
52
|
def build_widgets(
|
|
74
53
|
pdf_stream: bytes,
|
|
75
54
|
use_full_widget_name: bool,
|
|
@@ -27,9 +27,9 @@ from typing import (TYPE_CHECKING, BinaryIO, Dict, Optional, Sequence, TextIO,
|
|
|
27
27
|
|
|
28
28
|
from .adapter import (fp_or_f_obj_or_f_content_to_content,
|
|
29
29
|
fp_or_f_obj_or_stream_to_stream)
|
|
30
|
-
from .ap import appearance_streams_handler, preserve_pdf_properties
|
|
31
30
|
from .constants import VERSION_IDENTIFIER_PREFIX, VERSION_IDENTIFIERS
|
|
32
31
|
from .coordinate import generate_coordinate_grid
|
|
32
|
+
from .egress import appearance_streams_handler, preserve_pdf_properties
|
|
33
33
|
from .filler import fill
|
|
34
34
|
from .font import (get_all_available_fonts, register_font,
|
|
35
35
|
register_font_acroform)
|
|
@@ -38,7 +38,7 @@ from .middleware.dropdown import Dropdown
|
|
|
38
38
|
from .middleware.signature import Signature
|
|
39
39
|
from .middleware.text import Text
|
|
40
40
|
from .template import (build_widgets, create_annotations, get_metadata,
|
|
41
|
-
|
|
41
|
+
update_widget_keys)
|
|
42
42
|
from .types import PdfArray
|
|
43
43
|
from .utils import (generate_unique_suffix, get_page_streams, merge_pdfs,
|
|
44
44
|
remove_all_widgets)
|
|
@@ -362,9 +362,8 @@ class PdfWrapper:
|
|
|
362
362
|
2. If `need_appearances` is enabled, it handles appearance streams and the
|
|
363
363
|
`/NeedAppearances` flag, which may include removing XFA and explicitly
|
|
364
364
|
generating appearance streams.
|
|
365
|
-
3. If `preserve_metadata
|
|
366
|
-
|
|
367
|
-
accordingly.
|
|
365
|
+
3. If `preserve_metadata`, title, or on-open JavaScript are set, it preserves
|
|
366
|
+
or updates the corresponding PDF properties accordingly.
|
|
368
367
|
|
|
369
368
|
Returns:
|
|
370
369
|
bytes: The processed PDF document content as a byte string.
|
|
@@ -376,15 +375,14 @@ class PdfWrapper:
|
|
|
376
375
|
result, getattr(self, "generate_appearance_streams")
|
|
377
376
|
) # cached
|
|
378
377
|
|
|
379
|
-
if
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
if any([self.title, self.on_open_javascript]):
|
|
378
|
+
if any(
|
|
379
|
+
[getattr(self, "preserve_metadata"), self.title, self.on_open_javascript]
|
|
380
|
+
):
|
|
384
381
|
result = preserve_pdf_properties(
|
|
385
382
|
result,
|
|
386
383
|
self.title,
|
|
387
384
|
self.on_open_javascript,
|
|
385
|
+
self._metadata if getattr(self, "preserve_metadata") else None,
|
|
388
386
|
)
|
|
389
387
|
|
|
390
388
|
return result
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPDFForm
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.7.0
|
|
4
4
|
Summary: The Python library for PDF forms.
|
|
5
5
|
Author: Jinge Li
|
|
6
6
|
License-Expression: MIT
|
|
@@ -31,6 +31,8 @@ Requires-Dist: black<27.0.0,>=25.11.0; extra == "dev"
|
|
|
31
31
|
Requires-Dist: coverage<8.0.0,>=7.12.0; extra == "dev"
|
|
32
32
|
Requires-Dist: isort<9.0.0,>=7.0.0; extra == "dev"
|
|
33
33
|
Requires-Dist: jsonschema<5.0.0,>=4.25.1; extra == "dev"
|
|
34
|
+
Requires-Dist: mike<3.0.0,>=2.1.3; extra == "dev"
|
|
35
|
+
Requires-Dist: mkdocs<2.0.0,>=1.6.1; extra == "dev"
|
|
34
36
|
Requires-Dist: mkdocs-material<10.0.0,>=9.7.0; extra == "dev"
|
|
35
37
|
Requires-Dist: pudb<2026.0.0,>=2025.1.3; extra == "dev"
|
|
36
38
|
Requires-Dist: pylint<5.0.0,>=4.0.3; extra == "dev"
|
|
@@ -48,7 +50,7 @@ Dynamic: license-file
|
|
|
48
50
|
<a href="https://pypi.org/project/PyPDFForm/"><img src="https://img.shields.io/pypi/v/pypdfform?label=version&color=magenta"></a>
|
|
49
51
|
<a href="https://chinapandaman.github.io/PyPDFForm/"><img src="https://img.shields.io/github/v/release/chinapandaman/pypdfform?label=docs&color=cyan"></a>
|
|
50
52
|
<a href="https://github.com/chinapandaman/PyPDFForm/actions/workflows/python-package.yml"><img src="https://img.shields.io/badge/coverage-100%25-green"></a>
|
|
51
|
-
<a href="https://github.com/chinapandaman/PyPDFForm/
|
|
53
|
+
<a href="https://github.com/chinapandaman/PyPDFForm/blob/master/LICENSE"><img src="https://img.shields.io/github/license/chinapandaman/pypdfform?label=license&color=orange"></a>
|
|
52
54
|
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/pypi/pyversions/pypdfform?label=python&color=gold"></a>
|
|
53
55
|
<a href="https://pepy.tech/projects/pypdfform"><img src="https://static.pepy.tech/badge/pypdfform/month"></a>
|
|
54
56
|
</p>
|
|
@@ -102,6 +104,7 @@ The official documentation can be found on [the GitHub page](https://chinapandam
|
|
|
102
104
|
|
|
103
105
|
## Other Resources
|
|
104
106
|
|
|
107
|
+
<!-- TODO: remove WIP when finish recording -->
|
|
105
108
|
* [(WIP) Video Tutorials](https://youtube.com/playlist?list=PLNz_PBu1QA-gzYg5BvyOO98q15u5Xve1L&si=8MWasKEckBzY-NRQ)
|
|
106
109
|
* [Chicago Python User Group - Dec 14, 2023](https://youtu.be/8t1RdAKwr9w?si=TLgumBNXv9H8szSn)
|
|
107
110
|
|
|
@@ -3,10 +3,10 @@ README.md
|
|
|
3
3
|
pyproject.toml
|
|
4
4
|
PyPDFForm/__init__.py
|
|
5
5
|
PyPDFForm/adapter.py
|
|
6
|
-
PyPDFForm/ap.py
|
|
7
6
|
PyPDFForm/constants.py
|
|
8
7
|
PyPDFForm/coordinate.py
|
|
9
8
|
PyPDFForm/deprecation.py
|
|
9
|
+
PyPDFForm/egress.py
|
|
10
10
|
PyPDFForm/filler.py
|
|
11
11
|
PyPDFForm/font.py
|
|
12
12
|
PyPDFForm/hooks.py
|
|
@@ -25,6 +25,7 @@ PyPDFForm.egg-info/top_level.txt
|
|
|
25
25
|
PyPDFForm/annotations/__init__.py
|
|
26
26
|
PyPDFForm/annotations/base.py
|
|
27
27
|
PyPDFForm/annotations/link.py
|
|
28
|
+
PyPDFForm/annotations/stamp.py
|
|
28
29
|
PyPDFForm/annotations/text.py
|
|
29
30
|
PyPDFForm/annotations/text_markup.py
|
|
30
31
|
PyPDFForm/assets/__init__.py
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<a href="https://pypi.org/project/PyPDFForm/"><img src="https://img.shields.io/pypi/v/pypdfform?label=version&color=magenta"></a>
|
|
7
7
|
<a href="https://chinapandaman.github.io/PyPDFForm/"><img src="https://img.shields.io/github/v/release/chinapandaman/pypdfform?label=docs&color=cyan"></a>
|
|
8
8
|
<a href="https://github.com/chinapandaman/PyPDFForm/actions/workflows/python-package.yml"><img src="https://img.shields.io/badge/coverage-100%25-green"></a>
|
|
9
|
-
<a href="https://github.com/chinapandaman/PyPDFForm/
|
|
9
|
+
<a href="https://github.com/chinapandaman/PyPDFForm/blob/master/LICENSE"><img src="https://img.shields.io/github/license/chinapandaman/pypdfform?label=license&color=orange"></a>
|
|
10
10
|
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/pypi/pyversions/pypdfform?label=python&color=gold"></a>
|
|
11
11
|
<a href="https://pepy.tech/projects/pypdfform"><img src="https://static.pepy.tech/badge/pypdfform/month"></a>
|
|
12
12
|
</p>
|
|
@@ -60,6 +60,7 @@ The official documentation can be found on [the GitHub page](https://chinapandam
|
|
|
60
60
|
|
|
61
61
|
## Other Resources
|
|
62
62
|
|
|
63
|
+
<!-- TODO: remove WIP when finish recording -->
|
|
63
64
|
* [(WIP) Video Tutorials](https://youtube.com/playlist?list=PLNz_PBu1QA-gzYg5BvyOO98q15u5Xve1L&si=8MWasKEckBzY-NRQ)
|
|
64
65
|
* [Chicago Python User Group - Dec 14, 2023](https://youtu.be/8t1RdAKwr9w?si=TLgumBNXv9H8szSn)
|
|
65
66
|
|
|
@@ -884,3 +884,132 @@ def test_annotate_no_annotations(pdf_samples, request):
|
|
|
884
884
|
|
|
885
885
|
assert len(obj.read()) == len(expected)
|
|
886
886
|
assert obj.read() == expected
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
def test_rubber_stamp_annotation(template_stream, pdf_samples, request):
|
|
890
|
+
expected_path = os.path.join(pdf_samples, "test_rubber_stamp_annotation.pdf")
|
|
891
|
+
with open(expected_path, "rb+") as f:
|
|
892
|
+
obj = PdfWrapper(template_stream).annotate(
|
|
893
|
+
[
|
|
894
|
+
Annotations.RubberStampAnnotation(
|
|
895
|
+
1,
|
|
896
|
+
0,
|
|
897
|
+
400,
|
|
898
|
+
width=50,
|
|
899
|
+
height=50,
|
|
900
|
+
name=Annotations.RubberStampAnnotation.approved,
|
|
901
|
+
),
|
|
902
|
+
Annotations.RubberStampAnnotation(
|
|
903
|
+
1,
|
|
904
|
+
100,
|
|
905
|
+
400,
|
|
906
|
+
width=50,
|
|
907
|
+
height=50,
|
|
908
|
+
name=Annotations.RubberStampAnnotation.experimental,
|
|
909
|
+
),
|
|
910
|
+
Annotations.RubberStampAnnotation(
|
|
911
|
+
1,
|
|
912
|
+
200,
|
|
913
|
+
400,
|
|
914
|
+
width=50,
|
|
915
|
+
height=50,
|
|
916
|
+
name=Annotations.RubberStampAnnotation.not_approved,
|
|
917
|
+
),
|
|
918
|
+
Annotations.RubberStampAnnotation(
|
|
919
|
+
1,
|
|
920
|
+
300,
|
|
921
|
+
400,
|
|
922
|
+
width=50,
|
|
923
|
+
height=50,
|
|
924
|
+
name=Annotations.RubberStampAnnotation.as_is,
|
|
925
|
+
),
|
|
926
|
+
Annotations.RubberStampAnnotation(
|
|
927
|
+
1,
|
|
928
|
+
400,
|
|
929
|
+
400,
|
|
930
|
+
width=50,
|
|
931
|
+
height=50,
|
|
932
|
+
name=Annotations.RubberStampAnnotation.expired,
|
|
933
|
+
),
|
|
934
|
+
Annotations.RubberStampAnnotation(
|
|
935
|
+
1,
|
|
936
|
+
0,
|
|
937
|
+
500,
|
|
938
|
+
width=50,
|
|
939
|
+
height=50,
|
|
940
|
+
name=Annotations.RubberStampAnnotation.not_for_public_release,
|
|
941
|
+
),
|
|
942
|
+
Annotations.RubberStampAnnotation(
|
|
943
|
+
1,
|
|
944
|
+
100,
|
|
945
|
+
500,
|
|
946
|
+
width=50,
|
|
947
|
+
height=50,
|
|
948
|
+
name=Annotations.RubberStampAnnotation.confidential,
|
|
949
|
+
),
|
|
950
|
+
Annotations.RubberStampAnnotation(
|
|
951
|
+
1,
|
|
952
|
+
200,
|
|
953
|
+
500,
|
|
954
|
+
width=50,
|
|
955
|
+
height=50,
|
|
956
|
+
name=Annotations.RubberStampAnnotation.final,
|
|
957
|
+
),
|
|
958
|
+
Annotations.RubberStampAnnotation(
|
|
959
|
+
1,
|
|
960
|
+
300,
|
|
961
|
+
500,
|
|
962
|
+
width=50,
|
|
963
|
+
height=50,
|
|
964
|
+
name=Annotations.RubberStampAnnotation.sold,
|
|
965
|
+
),
|
|
966
|
+
Annotations.RubberStampAnnotation(
|
|
967
|
+
1,
|
|
968
|
+
400,
|
|
969
|
+
500,
|
|
970
|
+
width=50,
|
|
971
|
+
height=50,
|
|
972
|
+
name=Annotations.RubberStampAnnotation.departmental,
|
|
973
|
+
),
|
|
974
|
+
Annotations.RubberStampAnnotation(
|
|
975
|
+
1,
|
|
976
|
+
0,
|
|
977
|
+
600,
|
|
978
|
+
width=50,
|
|
979
|
+
height=50,
|
|
980
|
+
name=Annotations.RubberStampAnnotation.for_comment,
|
|
981
|
+
),
|
|
982
|
+
Annotations.RubberStampAnnotation(
|
|
983
|
+
1,
|
|
984
|
+
100,
|
|
985
|
+
600,
|
|
986
|
+
width=50,
|
|
987
|
+
height=50,
|
|
988
|
+
name=Annotations.RubberStampAnnotation.top_secret,
|
|
989
|
+
),
|
|
990
|
+
Annotations.RubberStampAnnotation(
|
|
991
|
+
1,
|
|
992
|
+
200,
|
|
993
|
+
600,
|
|
994
|
+
width=50,
|
|
995
|
+
height=50,
|
|
996
|
+
name=Annotations.RubberStampAnnotation.draft,
|
|
997
|
+
),
|
|
998
|
+
Annotations.RubberStampAnnotation(
|
|
999
|
+
1,
|
|
1000
|
+
300,
|
|
1001
|
+
600,
|
|
1002
|
+
width=50,
|
|
1003
|
+
height=50,
|
|
1004
|
+
name=Annotations.RubberStampAnnotation.for_public_release,
|
|
1005
|
+
),
|
|
1006
|
+
]
|
|
1007
|
+
)
|
|
1008
|
+
|
|
1009
|
+
request.config.results["expected_path"] = expected_path
|
|
1010
|
+
request.config.results["stream"] = obj.read()
|
|
1011
|
+
|
|
1012
|
+
expected = f.read()
|
|
1013
|
+
|
|
1014
|
+
assert len(obj.read()) == len(expected)
|
|
1015
|
+
assert obj.read() == expected
|
|
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
|
|
@@ -35,12 +35,12 @@ class Checkbox(Widget):
|
|
|
35
35
|
Attributes:
|
|
36
36
|
size (int): The size of the checkbox. Defaults to None.
|
|
37
37
|
"""
|
|
38
|
+
super().__init__(name, value)
|
|
38
39
|
self.SET_ATTR_TRIGGER_HOOK_MAP.update(
|
|
39
40
|
{
|
|
40
41
|
"size": "update_check_radio_size",
|
|
41
42
|
}
|
|
42
43
|
)
|
|
43
|
-
super().__init__(name, value)
|
|
44
44
|
|
|
45
45
|
self.size: Optional[float] = None
|
|
46
46
|
|
|
@@ -44,15 +44,15 @@ class Dropdown(Widget):
|
|
|
44
44
|
font (str): The font of the dropdown field.
|
|
45
45
|
choices (List[str]): The list of choices for the dropdown.
|
|
46
46
|
"""
|
|
47
|
+
super().__init__(name, value)
|
|
47
48
|
self.SET_ATTR_TRIGGER_HOOK_MAP.update(
|
|
48
49
|
{
|
|
49
50
|
"font": "update_text_field_font",
|
|
51
|
+
"choices": "update_dropdown_choices",
|
|
50
52
|
"font_size": "update_text_field_font_size",
|
|
51
53
|
"font_color": "update_text_field_font_color",
|
|
52
|
-
"choices": "update_dropdown_choices",
|
|
53
54
|
}
|
|
54
55
|
)
|
|
55
|
-
super().__init__(name, value)
|
|
56
56
|
|
|
57
57
|
self.font: Optional[str] = None
|
|
58
58
|
self.font_size: Optional[float] = None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -45,6 +45,7 @@ class Text(Widget):
|
|
|
45
45
|
multiline (bool): Whether the text field is multiline. Defaults to None.
|
|
46
46
|
max_length (int): The maximum length of the text field. Defaults to None.
|
|
47
47
|
"""
|
|
48
|
+
super().__init__(name, value)
|
|
48
49
|
self.SET_ATTR_TRIGGER_HOOK_MAP.update(
|
|
49
50
|
{
|
|
50
51
|
"font": "update_text_field_font",
|
|
@@ -56,7 +57,6 @@ class Text(Widget):
|
|
|
56
57
|
"max_length": "update_text_field_max_length",
|
|
57
58
|
}
|
|
58
59
|
)
|
|
59
|
-
super().__init__(name, value)
|
|
60
60
|
|
|
61
61
|
self.font: Optional[str] = None
|
|
62
62
|
self.font_size: Optional[float] = None
|
|
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
|