PyPDFForm 2.2.5__py3-none-any.whl → 2.2.6__py3-none-any.whl

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/__init__.py CHANGED
@@ -5,7 +5,7 @@ This package provides tools for filling PDF forms, drawing text and images,
5
5
  and manipulating PDF form elements programmatically.
6
6
  """
7
7
 
8
- __version__ = "2.2.5"
8
+ __version__ = "2.2.6"
9
9
 
10
10
  from .wrapper import FormWrapper, PdfWrapper
11
11
 
PyPDFForm/constants.py CHANGED
@@ -50,6 +50,7 @@ Ff = "/Ff"
50
50
  Tx = "/Tx"
51
51
  V = "/V"
52
52
  AP = "/AP"
53
+ I = "/I" # noqa: E741
53
54
  N = "/N"
54
55
  Sig = "/Sig"
55
56
  DA = "/DA"
@@ -75,6 +76,7 @@ Off = "/Off"
75
76
  # For Adobe Acrobat
76
77
  AcroForm = "/AcroForm"
77
78
  Root = "/Root"
79
+ Fields = "/Fields"
78
80
  NeedAppearances = "/NeedAppearances"
79
81
 
80
82
  # Field flag bits
PyPDFForm/filler.py CHANGED
@@ -16,10 +16,11 @@ from io import BytesIO
16
16
  from typing import Dict, Tuple, Union, cast
17
17
 
18
18
  from pypdf import PdfReader, PdfWriter
19
- from pypdf.generic import BooleanObject, DictionaryObject, NameObject
19
+ from pypdf.generic import (ArrayObject, BooleanObject, DictionaryObject,
20
+ IndirectObject, NameObject)
20
21
 
21
22
  from .constants import (BUTTON_STYLES, DEFAULT_RADIO_STYLE, WIDGET_TYPES,
22
- AcroForm, Annots, NeedAppearances, Root, U)
23
+ AcroForm, Annots, Fields, NeedAppearances, Root, U)
23
24
  from .coordinate import (get_draw_border_coordinates,
24
25
  get_draw_checkbox_radio_coordinates,
25
26
  get_draw_image_coordinates_resolutions,
@@ -305,19 +306,34 @@ def fill(
305
306
  return result
306
307
 
307
308
 
308
- def enable_adobe_mode(pdf: PdfReader, adobe_mode: bool) -> None:
309
- """Configures PDF for Adobe Acrobat compatibility.
309
+ def enable_adobe_mode(reader: PdfReader, writer: PdfWriter, adobe_mode: bool) -> None:
310
+ """Configures the PDF for Adobe Acrobat compatibility by setting the NeedAppearances flag
311
+ and ensuring the AcroForm structure is properly initialized.
310
312
 
311
313
  Args:
312
- pdf: PdfReader instance of the PDF
313
- adobe_mode: If True, sets NeedAppearances flag for Acrobat
314
+ reader: PdfReader instance of the PDF
315
+ writer: PdfWriter instance to configure
316
+ adobe_mode: If True, enables Adobe Acrobat compatibility mode
314
317
  """
315
318
 
316
- if adobe_mode and AcroForm in pdf.trailer[Root]:
317
- pdf.trailer[Root][AcroForm].update(
319
+ if not adobe_mode:
320
+ return
321
+
322
+ # https://stackoverflow.com/questions/47288578/pdf-form-filled-with-pypdf2-does-not-show-in-print
323
+ if AcroForm in reader.trailer[Root]:
324
+ reader.trailer[Root][AcroForm].update(
318
325
  {NameObject(NeedAppearances): BooleanObject(True)}
319
326
  )
320
327
 
328
+ if AcroForm not in writer.root_object:
329
+ writer.root_object.update(
330
+ {NameObject(AcroForm): IndirectObject(len(writer.root_object), 0, writer)}
331
+ )
332
+ writer.root_object[AcroForm][NameObject(NeedAppearances)] = BooleanObject( # noqa
333
+ True
334
+ )
335
+ writer.root_object[AcroForm][NameObject(Fields)] = ArrayObject() # noqa
336
+
321
337
 
322
338
  def simple_fill(
323
339
  template: bytes,
@@ -343,8 +359,8 @@ def simple_fill(
343
359
  """
344
360
 
345
361
  pdf = PdfReader(stream_to_io(template))
346
- enable_adobe_mode(pdf, adobe_mode)
347
362
  out = PdfWriter()
363
+ enable_adobe_mode(pdf, out, adobe_mode)
348
364
  out.append(pdf)
349
365
 
350
366
  radio_button_tracker = {}
PyPDFForm/patterns.py CHANGED
@@ -15,13 +15,13 @@ The module also contains utility functions for common PDF form operations
15
15
  like updating field values and flattening form fields.
16
16
  """
17
17
 
18
- from pypdf.generic import (DictionaryObject, NameObject, NumberObject,
19
- TextStringObject)
18
+ from pypdf.generic import (ArrayObject, DictionaryObject, NameObject,
19
+ NumberObject, TextStringObject)
20
20
 
21
21
  from .constants import (AP, AS, BC, BG, BS, CA, DA, DV, FT,
22
22
  IMAGE_FIELD_IDENTIFIER, JS, MK, MULTILINE, READ_ONLY,
23
- TU, A, Btn, Ch, D, Ff, N, Off, Opt, Parent, Q, S, Sig,
24
- T, Tx, V, W, Yes)
23
+ TU, A, Btn, Ch, D, Ff, I, N, Off, Opt, Parent, Q, S,
24
+ Sig, T, Tx, V, W, Yes)
25
25
  from .middleware.checkbox import Checkbox
26
26
  from .middleware.dropdown import Dropdown
27
27
  from .middleware.image import Image
@@ -160,13 +160,17 @@ def simple_update_radio_value(annot: DictionaryObject) -> None:
160
160
  """Update radio button annotation values to selected state.
161
161
 
162
162
  Modifies the appearance state (AS) of a radio button annotation and updates
163
- the parent's value (V) to reflect the selected state. Uses the annotation's
164
- appearance dictionary (AP/N) to determine valid states.
163
+ the parent's value (V) to reflect the selected state. Removes 'Opt' entry
164
+ from parent dictionary if present. Uses the annotation's appearance
165
+ dictionary (AP/N) to determine valid states.
165
166
 
166
167
  Args:
167
168
  annot: PDF radio button annotation dictionary to modify
168
169
  """
169
170
 
171
+ if Opt in annot[Parent]:
172
+ del annot[Parent][Opt] # noqa
173
+
170
174
  for each in annot[AP][N]: # noqa
171
175
  if str(each) != Off:
172
176
  annot[NameObject(AS)] = NameObject(each)
@@ -177,9 +181,9 @@ def simple_update_radio_value(annot: DictionaryObject) -> None:
177
181
  def simple_update_dropdown_value(annot: DictionaryObject, widget: Dropdown) -> None:
178
182
  """Update dropdown annotation values based on widget selection.
179
183
 
180
- Modifies the value (V) and appearance (AP) of a dropdown annotation to
181
- reflect the currently selected choice from the widget. Handles both
182
- standalone dropdowns and those with parent annotations.
184
+ Modifies the value (V), appearance (AP), and index (I) of a dropdown
185
+ annotation to reflect the currently selected choice from the widget.
186
+ Handles both standalone dropdowns and those with parent annotations.
183
187
 
184
188
  Args:
185
189
  annot: PDF dropdown annotation dictionary to modify
@@ -194,6 +198,7 @@ def simple_update_dropdown_value(annot: DictionaryObject, widget: Dropdown) -> N
194
198
  else:
195
199
  annot[NameObject(V)] = TextStringObject(widget.choices[widget.value])
196
200
  annot[NameObject(AP)] = TextStringObject(widget.choices[widget.value])
201
+ annot[NameObject(I)] = ArrayObject([NumberObject(widget.value)])
197
202
 
198
203
 
199
204
  def simple_update_text_value(annot: DictionaryObject, widget: Text) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPDFForm
3
- Version: 2.2.5
3
+ Version: 2.2.6
4
4
  Summary: The Python library for PDF forms.
5
5
  Author: Jinge Li
6
6
  License-Expression: MIT
@@ -1,11 +1,11 @@
1
- PyPDFForm/__init__.py,sha256=Ulyaw2X0oRHS1yjzGumWDaCeTzvMeqy0nBfrWQkXDF0,328
1
+ PyPDFForm/__init__.py,sha256=cCocr2KFIvseeYcsUJhTvM4m8Z8eo3aJLamlTpjYOqg,328
2
2
  PyPDFForm/adapter.py,sha256=_5fP5UR-NzjDDayJmBRO36DgbnbUzNbjZtHZtPvSM14,1909
3
- PyPDFForm/constants.py,sha256=C83k7Hz0LFzYGy--qGG7rfEQrtXfZCgBBnWMhe7L73A,2300
3
+ PyPDFForm/constants.py,sha256=3ed0j11cWd9Uo4s-XvZwwJojPSz8aqdmZgaEishWjqE,2342
4
4
  PyPDFForm/coordinate.py,sha256=gQI7z-GsdCO33Qny5kXLBs6Y2TW5KO_mJ2in64fvXcg,16412
5
- PyPDFForm/filler.py,sha256=K-8JFhS4I7aiK8ZRKtovJ9QsUFgM2DjQ1n6B0P6qyaU,13264
5
+ PyPDFForm/filler.py,sha256=VnxRdSP2NpiQsGkDfAuFA6oS2dmARQA3ArO8q_O0o1o,14006
6
6
  PyPDFForm/font.py,sha256=eRbDyQFhXUkHzyZvCtru9Ypg_ukfbBAnSM5xNzPb5ss,7280
7
7
  PyPDFForm/image.py,sha256=aYk7BC-AHiqt73durGIQ3e6gE5Ggbdr8jmkCUaQdsk8,1627
8
- PyPDFForm/patterns.py,sha256=iChwqR-aZUKhEdnbQ8OEwnES2-NaMhBUy4dUrnuDPpA,9243
8
+ PyPDFForm/patterns.py,sha256=Zv80gZswYFlFuo6eXL1j8bMyckavXPuw55D8IzcvIW0,9472
9
9
  PyPDFForm/template.py,sha256=v1ZM52xHCzO8Xm7EXinbTepm2G7MU7StUgCFtuUdcbI,18899
10
10
  PyPDFForm/utils.py,sha256=M07Q_2defFGmhBqvgEoQ9pt_IYZwXCsqrMljlKYYwIM,8487
11
11
  PyPDFForm/watermark.py,sha256=Ni6Y2-DSaAaxqXtCSTrmDOMO0XW7-u3Hucr6J4njtG8,12475
@@ -27,8 +27,8 @@ PyPDFForm/widgets/image.py,sha256=6y8Ysmk49USr_qWOXD6KGL6cch516cUIlrxoj0pJy9Q,79
27
27
  PyPDFForm/widgets/radio.py,sha256=ipadJyHbgftDUvjGk15kapzgHPN3HjdF_iB_7amXR6o,2737
28
28
  PyPDFForm/widgets/signature.py,sha256=EndajR-SQWDZyVfbvDoz5Bjuer5KbURjFlRGqxeXYeY,5115
29
29
  PyPDFForm/widgets/text.py,sha256=HP2cPEUAzK5QL3kDfMz7gQcC3svCpmYuyFItBjlrBpI,1233
30
- pypdfform-2.2.5.dist-info/licenses/LICENSE,sha256=43awmYkI6opyTpg19me731iO1WfXZwViqb67oWtCsFY,1065
31
- pypdfform-2.2.5.dist-info/METADATA,sha256=5iVR9CNMRq8Srj3SjGGxppWg7Cso03Jl9ea4hNuTbzA,5605
32
- pypdfform-2.2.5.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
33
- pypdfform-2.2.5.dist-info/top_level.txt,sha256=GQQKuWqPUjT9YZqwK95NlAQzxjwoQrsxQ8ureM8lWOY,10
34
- pypdfform-2.2.5.dist-info/RECORD,,
30
+ pypdfform-2.2.6.dist-info/licenses/LICENSE,sha256=43awmYkI6opyTpg19me731iO1WfXZwViqb67oWtCsFY,1065
31
+ pypdfform-2.2.6.dist-info/METADATA,sha256=OHfkmG1BfxJVEDUNV8h8DpPl7c-Jbwmsyteln69rkFY,5605
32
+ pypdfform-2.2.6.dist-info/WHEEL,sha256=wXxTzcEDnjrTwFYjLPcsW_7_XihufBwmpiBeiXNBGEA,91
33
+ pypdfform-2.2.6.dist-info/top_level.txt,sha256=GQQKuWqPUjT9YZqwK95NlAQzxjwoQrsxQ8ureM8lWOY,10
34
+ pypdfform-2.2.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.0.0)
2
+ Generator: setuptools (80.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5