PyPDFForm 5.5.0__tar.gz → 5.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {pypdfform-5.5.0 → pypdfform-5.5.1}/PKG-INFO +1 -1
  2. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/__init__.py +1 -1
  3. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/template.py +30 -4
  4. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/wrapper.py +20 -19
  5. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm.egg-info/PKG-INFO +1 -1
  6. {pypdfform-5.5.0 → pypdfform-5.5.1}/LICENSE +0 -0
  7. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/__init__.py +0 -0
  8. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/common.py +0 -0
  9. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/create.py +0 -0
  10. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/entry.py +0 -0
  11. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/inspect.py +0 -0
  12. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/remove.py +0 -0
  13. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/root.py +0 -0
  14. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/schemas/__init__.py +0 -0
  15. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/schemas/create.py +0 -0
  16. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/schemas/update.py +0 -0
  17. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/cli/update.py +0 -0
  18. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/__init__.py +0 -0
  19. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/adapter.py +0 -0
  20. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/annotations/__init__.py +0 -0
  21. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/annotations/base.py +0 -0
  22. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/annotations/link.py +0 -0
  23. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/annotations/stamp.py +0 -0
  24. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/annotations/text.py +0 -0
  25. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/annotations/text_markup.py +0 -0
  26. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/assets/__init__.py +0 -0
  27. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/assets/bedrock.py +0 -0
  28. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/assets/blank.py +0 -0
  29. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/constants.py +0 -0
  30. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/coordinate.py +0 -0
  31. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/deprecation.py +0 -0
  32. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/egress.py +0 -0
  33. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/filler.py +0 -0
  34. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/font.py +0 -0
  35. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/hooks.py +0 -0
  36. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/image.py +0 -0
  37. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/middleware/__init__.py +0 -0
  38. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/middleware/base.py +0 -0
  39. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/middleware/checkbox.py +0 -0
  40. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/middleware/dropdown.py +0 -0
  41. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/middleware/image.py +0 -0
  42. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/middleware/radio.py +0 -0
  43. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/middleware/signature.py +0 -0
  44. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/middleware/text.py +0 -0
  45. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/patterns.py +0 -0
  46. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/raw/__init__.py +0 -0
  47. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/raw/circle.py +0 -0
  48. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/raw/ellipse.py +0 -0
  49. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/raw/image.py +0 -0
  50. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/raw/line.py +0 -0
  51. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/raw/rect.py +0 -0
  52. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/raw/text.py +0 -0
  53. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/types.py +0 -0
  54. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/utils.py +0 -0
  55. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/watermark.py +0 -0
  56. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/widgets/__init__.py +0 -0
  57. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/widgets/base.py +0 -0
  58. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/widgets/checkbox.py +0 -0
  59. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/widgets/dropdown.py +0 -0
  60. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/widgets/image.py +0 -0
  61. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/widgets/radio.py +0 -0
  62. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/widgets/signature.py +0 -0
  63. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm/lib/widgets/text.py +0 -0
  64. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm.egg-info/SOURCES.txt +0 -0
  65. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm.egg-info/dependency_links.txt +0 -0
  66. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm.egg-info/entry_points.txt +0 -0
  67. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm.egg-info/requires.txt +0 -0
  68. {pypdfform-5.5.0 → pypdfform-5.5.1}/PyPDFForm.egg-info/top_level.txt +0 -0
  69. {pypdfform-5.5.0 → pypdfform-5.5.1}/README.md +0 -0
  70. {pypdfform-5.5.0 → pypdfform-5.5.1}/pyproject.toml +0 -0
  71. {pypdfform-5.5.0 → pypdfform-5.5.1}/setup.cfg +0 -0
  72. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_bulk_create_fields.py +0 -0
  73. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_create_widget.py +0 -0
  74. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_draw_elements.py +0 -0
  75. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_dropdown.py +0 -0
  76. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_extract_middleware_attributes.py +0 -0
  77. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_fill_max_length_text_field.py +0 -0
  78. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_font_widths.py +0 -0
  79. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_functional.py +0 -0
  80. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_generate_appearance_streams.py +0 -0
  81. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_js.py +0 -0
  82. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_need_appearances.py +0 -0
  83. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_paragraph.py +0 -0
  84. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_signature.py +0 -0
  85. {pypdfform-5.5.0 → pypdfform-5.5.1}/tests/test_use_full_widget_name.py +0 -0
  86. {pypdfform-5.5.0 → pypdfform-5.5.1}/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.5.0
3
+ Version: 5.5.1
4
4
  Summary: The Python library & CLI for PDF forms.
5
5
  Author: Jinge Li
6
6
  License-Expression: MIT
@@ -18,7 +18,7 @@ from Python code or from the command line.
18
18
 
19
19
  import logging
20
20
 
21
- __version__ = "5.5.0"
21
+ __version__ = "5.5.1"
22
22
 
23
23
  from .lib.annotations import Annotations
24
24
  from .lib.assets.blank import BlankPage
@@ -64,11 +64,12 @@ def get_metadata(pdf: bytes) -> dict:
64
64
  Returns:
65
65
  dict: A dictionary containing the PDF's metadata.
66
66
  """
67
- if not pdf:
68
- return {}
67
+ result = {}
68
+ if pdf:
69
+ reader = PdfReader(BytesIO(pdf))
70
+ result = reader.metadata or {}
69
71
 
70
- reader = PdfReader(BytesIO(pdf))
71
- return reader.metadata or {}
72
+ return result
72
73
 
73
74
 
74
75
  def get_title(pdf: bytes) -> str | None:
@@ -84,6 +85,31 @@ def get_title(pdf: bytes) -> str | None:
84
85
  return get_metadata(pdf).get(Title)
85
86
 
86
87
 
88
+ @lru_cache(maxsize=128)
89
+ def get_on_open_javascript(pdf: bytes) -> str | None:
90
+ """
91
+ Retrieves the JavaScript configured to run when a PDF is opened.
92
+
93
+ Results are cached by PDF stream. Only a document-catalog `/OpenAction`
94
+ whose action type is JavaScript is returned.
95
+
96
+ Args:
97
+ pdf (bytes): The PDF stream to inspect for a document-open action.
98
+
99
+ Returns:
100
+ str | None: The JavaScript source, or None when the stream is empty or
101
+ does not contain a JavaScript document-open action.
102
+ """
103
+ result = None
104
+ if pdf:
105
+ reader = PdfReader(BytesIO(pdf))
106
+ root_object = reader.root_object
107
+ if OpenAction in root_object and root_object[OpenAction].get(S) == JavaScript:
108
+ result = root_object[OpenAction].get(JS)
109
+
110
+ return result
111
+
112
+
87
113
  def set_metadata(pdf: bytes, metadata: dict) -> bytes:
88
114
  """
89
115
  Merges metadata into a PDF's existing document metadata.
@@ -56,7 +56,7 @@ from .middleware.text import Text
56
56
  from .template import (
57
57
  build_widgets,
58
58
  create_annotations,
59
- get_metadata,
59
+ get_on_open_javascript,
60
60
  get_title,
61
61
  remove_widgets_by_keys,
62
62
  set_on_open_javascript,
@@ -110,7 +110,7 @@ class PdfWrapper:
110
110
  - `need_appearances` (bool): Whether to set the `NeedAppearances` flag in the PDF's AcroForm dictionary.
111
111
  - `generate_appearance_streams` (bool): Whether to explicitly generate appearance streams for all form fields using pikepdf.
112
112
  - `preserve_metadata` (bool): Deprecated compatibility attribute;
113
- input PDF metadata is captured automatically.
113
+ input PDF metadata is preserved automatically.
114
114
  - `title` (str | None): The title stored in the PDF's document
115
115
  metadata. A non-None value replaces the existing title; None
116
116
  preserves it.
@@ -134,11 +134,12 @@ class PdfWrapper:
134
134
  Constructor method for the `PdfWrapper` class.
135
135
 
136
136
  Initializes a new `PdfWrapper` object with the given template PDF and optional keyword arguments.
137
- The template is normalized to bytes, existing widgets are loaded immediately,
138
- and the original metadata and title are read. A non-None `title` keyword
139
- updates the title in the PDF stream; None preserves the title read from the
140
- template. The deprecated `preserve_metadata` keyword is accepted for backward
141
- compatibility and emits a deprecation warning. Enabling
137
+ The template is normalized to bytes and existing widgets are loaded immediately.
138
+ The title and document-open JavaScript remain in the PDF stream and are read
139
+ lazily when their properties are accessed. A non-None `title` keyword updates
140
+ the title in the PDF stream; None leaves the template's title unchanged. The
141
+ deprecated `preserve_metadata` keyword is accepted for backward compatibility
142
+ and emits a deprecation warning. Enabling
142
143
  `generate_appearance_streams` also enables `need_appearances`.
143
144
 
144
145
  Args:
@@ -158,9 +159,6 @@ class PdfWrapper:
158
159
  self.widgets = {}
159
160
 
160
161
  self._version = None
161
- self._metadata = get_metadata(self._read())
162
- self._title = get_title(self._read())
163
- self._on_open_javascript = None
164
162
  self._available_fonts = {} # for setting /F1
165
163
  self._available_fonts_loaded = None # for lazy loading fonts
166
164
  self._font_register_events = [] # for reregister
@@ -332,11 +330,15 @@ class PdfWrapper:
332
330
  """
333
331
  Gets the title stored in the PDF's document metadata.
334
332
 
333
+ The title is read lazily from the current PDF stream. Metadata extraction
334
+ is cached for each distinct stream.
335
+
335
336
  Returns:
336
337
  str | None: The current document title, or None when no title exists.
337
338
  """
338
339
 
339
- return str(self._title) if self._title is not None else None
340
+ result = get_title(self._read())
341
+ return str(result) if result is not None else None
340
342
 
341
343
  @title.setter
342
344
  def title(self, value: str | None) -> None:
@@ -353,7 +355,6 @@ class PdfWrapper:
353
355
 
354
356
  if value is not None:
355
357
  self._stream = set_title(self._read(), value)
356
- self._title = value
357
358
 
358
359
  @property
359
360
  def schema(self) -> dict:
@@ -468,17 +469,18 @@ class PdfWrapper:
468
469
  @property
469
470
  def on_open_javascript(self) -> str | None:
470
471
  """
471
- Returns the on-open JavaScript most recently assigned to this wrapper.
472
+ Gets the JavaScript stored in the PDF's document-open action.
472
473
 
473
- This property tracks assignments made through the wrapper; it does not
474
- inspect the template PDF for an existing `/OpenAction`.
474
+ The script is read lazily from the current PDF stream, including an existing
475
+ JavaScript `/OpenAction` in the input template. Extraction is cached for each
476
+ distinct stream.
475
477
 
476
478
  Returns:
477
- str | None: The assigned JavaScript, or None if no script has been
478
- assigned through this wrapper.
479
+ str | None: The current document-open JavaScript, or None when the PDF
480
+ does not contain a JavaScript document-open action.
479
481
  """
480
482
 
481
- return self._on_open_javascript
483
+ return get_on_open_javascript(self._read())
482
484
 
483
485
  @on_open_javascript.setter
484
486
  def on_open_javascript(self, value: str | TextIO) -> None:
@@ -496,7 +498,6 @@ class PdfWrapper:
496
498
 
497
499
  script = fp_or_f_obj_or_f_content_to_content(value)
498
500
  self._stream = set_on_open_javascript(self._read(), script)
499
- self._on_open_javascript = script
500
501
 
501
502
  def read(self) -> bytes:
502
503
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPDFForm
3
- Version: 5.5.0
3
+ Version: 5.5.1
4
4
  Summary: The Python library & CLI for PDF forms.
5
5
  Author: Jinge Li
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes
File without changes
File without changes