From d5901772a1eebda4707a45707fcdfe3479689b84 Mon Sep 17 00:00:00 2001 From: chinapandaman Date: Sun, 24 Mar 2024 21:39:53 -0500 Subject: [PATCH 1/3] PPF-535: moved to patterns.py --- PyPDFForm/filler.py | 47 +++++++++----------------------------- PyPDFForm/patterns.py | 53 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 37 deletions(-) diff --git a/PyPDFForm/filler.py b/PyPDFForm/filler.py index 0084bbbb..6d3f849f 100644 --- a/PyPDFForm/filler.py +++ b/PyPDFForm/filler.py @@ -5,13 +5,9 @@ from typing import Dict, cast from pypdf import PdfReader, PdfWriter -from pypdf.generic import (DictionaryObject, NameObject, NumberObject, - TextStringObject) +from pypdf.generic import DictionaryObject -from .constants import (ANNOTATION_KEY, CHECKBOX_SELECT, FIELD_FLAG_KEY, - PARENT_KEY, READ_ONLY, SELECTED_IDENTIFIER, - TEXT_VALUE_IDENTIFIER, TEXT_VALUE_SHOW_UP_IDENTIFIER, - WIDGET_TYPES) +from .constants import ANNOTATION_KEY, WIDGET_TYPES from .coordinate import (get_draw_checkbox_radio_coordinates, get_draw_sig_coordinates_resolutions, get_draw_text_coordinates, @@ -23,6 +19,9 @@ from .middleware.radio import Radio from .middleware.signature import Signature from .middleware.text import Text +from .patterns import (simple_update_checkbox_value, simple_update_radio_value, + simple_update_dropdown_value, simple_update_text_value, + simple_flatten_radio, simple_flatten_generic) from .template import get_widget_key, get_widgets_by_page from .utils import checkbox_radio_to_draw, stream_to_io from .watermark import create_watermarks_and_draw, merge_watermarks_with_pdf @@ -152,47 +151,23 @@ def simple_fill( continue if type(widget) is Checkbox and widget.value is True: - annot[NameObject(SELECTED_IDENTIFIER)] = NameObject(CHECKBOX_SELECT) + simple_update_checkbox_value(annot) elif isinstance(widget, Radio): if key not in radio_button_tracker: radio_button_tracker[key] = 0 radio_button_tracker[key] += 1 if widget.value == radio_button_tracker[key] - 1: - annot[NameObject(SELECTED_IDENTIFIER)] = NameObject( - f"/{widget.value}" - ) + simple_update_radio_value(annot, widget) elif isinstance(widget, Dropdown) and widget.value is not None: - annot[NameObject(TEXT_VALUE_IDENTIFIER)] = TextStringObject( - widget.choices[widget.value] - ) - annot[NameObject(TEXT_VALUE_SHOW_UP_IDENTIFIER)] = TextStringObject( - widget.choices[widget.value] - ) + simple_update_dropdown_value(annot, widget) elif isinstance(widget, Text) and widget.value: - annot[NameObject(TEXT_VALUE_IDENTIFIER)] = TextStringObject( - widget.value - ) - annot[NameObject(TEXT_VALUE_SHOW_UP_IDENTIFIER)] = TextStringObject( - widget.value - ) + simple_update_text_value(annot, widget) if flatten: if isinstance(widget, Radio): - annot[NameObject(PARENT_KEY)][ # noqa - NameObject(FIELD_FLAG_KEY) - ] = NumberObject( - int( - annot[NameObject(PARENT_KEY)].get( # noqa - NameObject(FIELD_FLAG_KEY), 0 - ) - ) - | READ_ONLY - ) + simple_flatten_radio(annot) else: - annot[NameObject(FIELD_FLAG_KEY)] = NumberObject( - int(annot.get(NameObject(FIELD_FLAG_KEY), 0)) - | READ_ONLY # noqa - ) + simple_flatten_generic(annot) with BytesIO() as f: out.write(f) diff --git a/PyPDFForm/patterns.py b/PyPDFForm/patterns.py index e13c19e1..a34af61d 100644 --- a/PyPDFForm/patterns.py +++ b/PyPDFForm/patterns.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- """Contains patterns used for identifying properties of widgets.""" +from pypdf.generic import DictionaryObject, NameObject, TextStringObject, NumberObject + from .constants import (ANNOTATION_FIELD_KEY, BUTTON_IDENTIFIER, BUTTON_STYLE_IDENTIFIER, CHOICE_FIELD_IDENTIFIER, CHOICES_IDENTIFIER, FIELD_FLAG_KEY, PARENT_KEY, @@ -8,7 +10,8 @@ SUBTYPE_KEY, TEXT_FIELD_ALIGNMENT_IDENTIFIER, TEXT_FIELD_APPEARANCE_IDENTIFIER, TEXT_FIELD_IDENTIFIER, WIDGET_SUBTYPE_KEY, - WIDGET_TYPE_KEY) + WIDGET_TYPE_KEY, CHECKBOX_SELECT, SELECTED_IDENTIFIER, TEXT_VALUE_IDENTIFIER, + TEXT_VALUE_SHOW_UP_IDENTIFIER, READ_ONLY) from .middleware.checkbox import Checkbox from .middleware.dropdown import Dropdown from .middleware.radio import Radio @@ -81,3 +84,51 @@ BUTTON_STYLE_PATTERNS = [ {BUTTON_IDENTIFIER: {BUTTON_STYLE_IDENTIFIER: True}}, ] + + +def simple_update_checkbox_value(annot: DictionaryObject) -> None: + annot[NameObject(SELECTED_IDENTIFIER)] = NameObject(CHECKBOX_SELECT) + + +def simple_update_radio_value(annot: DictionaryObject, widget: Radio) -> None: + annot[NameObject(SELECTED_IDENTIFIER)] = NameObject( + f"/{widget.value}" + ) + + +def simple_update_dropdown_value(annot: DictionaryObject, widget: Dropdown) -> None: + annot[NameObject(TEXT_VALUE_IDENTIFIER)] = TextStringObject( + widget.choices[widget.value] + ) + annot[NameObject(TEXT_VALUE_SHOW_UP_IDENTIFIER)] = TextStringObject( + widget.choices[widget.value] + ) + + +def simple_update_text_value(annot: DictionaryObject, widget: Text) -> None: + annot[NameObject(TEXT_VALUE_IDENTIFIER)] = TextStringObject( + widget.value + ) + annot[NameObject(TEXT_VALUE_SHOW_UP_IDENTIFIER)] = TextStringObject( + widget.value + ) + + +def simple_flatten_radio(annot: DictionaryObject) -> None: + annot[NameObject(PARENT_KEY)][ # noqa + NameObject(FIELD_FLAG_KEY) + ] = NumberObject( + int( + annot[NameObject(PARENT_KEY)].get( # noqa + NameObject(FIELD_FLAG_KEY), 0 + ) + ) + | READ_ONLY + ) + + +def simple_flatten_generic(annot: DictionaryObject) -> None: + annot[NameObject(FIELD_FLAG_KEY)] = NumberObject( + int(annot.get(NameObject(FIELD_FLAG_KEY), 0)) + | READ_ONLY # noqa + ) From 5c3daf1820923de0697dbe66ef515edf18558f9f Mon Sep 17 00:00:00 2001 From: chinapandaman Date: Sun, 24 Mar 2024 21:47:40 -0500 Subject: [PATCH 2/3] PPF-535: rename a lot of constants --- PyPDFForm/constants.py | 44 +++++++++---------- PyPDFForm/coordinate.py | 40 +++++++++--------- PyPDFForm/filler.py | 11 ++--- PyPDFForm/font.py | 14 +++--- PyPDFForm/patterns.py | 94 +++++++++++++++-------------------------- PyPDFForm/template.py | 18 ++++---- 6 files changed, 99 insertions(+), 122 deletions(-) diff --git a/PyPDFForm/constants.py b/PyPDFForm/constants.py index ca37a19b..14a2ecd3 100644 --- a/PyPDFForm/constants.py +++ b/PyPDFForm/constants.py @@ -26,27 +26,27 @@ DEPRECATION_NOTICE = "{} will be deprecated soon. Use {} instead." -ANNOTATION_KEY = "/Annots" -ANNOTATION_FIELD_KEY = "/T" -ANNOTATION_RECTANGLE_KEY = "/Rect" -SUBTYPE_KEY = "/Subtype" -WIDGET_SUBTYPE_KEY = "/Widget" -WIDGET_TYPE_KEY = "/FT" -PARENT_KEY = "/Parent" -FIELD_FLAG_KEY = "/Ff" -TEXT_FIELD_IDENTIFIER = "/Tx" -TEXT_VALUE_IDENTIFIER = "/V" -TEXT_VALUE_SHOW_UP_IDENTIFIER = "/AP" -SIGNATURE_FIELD_IDENTIFIER = "/Sig" -TEXT_FIELD_APPEARANCE_IDENTIFIER = "/DA" -SELECTABLE_IDENTIFIER = "/Btn" -TEXT_FIELD_MAX_LENGTH_KEY = "/MaxLen" -TEXT_FIELD_ALIGNMENT_IDENTIFIER = "/Q" -CHOICE_FIELD_IDENTIFIER = "/Ch" -CHOICES_IDENTIFIER = "/Opt" -BUTTON_IDENTIFIER = "/MK" -BUTTON_STYLE_IDENTIFIER = "/CA" -SELECTED_IDENTIFIER = "/AS" +Annots = "/Annots" +T = "/T" +Rect = "/Rect" +Subtype = "/Subtype" +Widget = "/Widget" +FT = "/FT" +Parent = "/Parent" +Ff = "/Ff" +Tx = "/Tx" +V = "/V" +AP = "/AP" +Sig = "/Sig" +DA = "/DA" +Btn = "/Btn" +MaxLen = "/MaxLen" +Q = "/Q" +Ch = "/Ch" +Opt = "/Opt" +MK = "/MK" +CA = "/CA" +AS = "/AS" # Field flag bits READ_ONLY = 1 << 0 @@ -70,6 +70,6 @@ "l": "\u25CF", # circle } -CHECKBOX_SELECT = "/Yes" +Yes = "/Yes" COORDINATE_GRID_FONT_SIZE_MARGIN_RATIO = DEFAULT_FONT_SIZE / 100 diff --git a/PyPDFForm/coordinate.py b/PyPDFForm/coordinate.py index d7e7f336..f781e912 100644 --- a/PyPDFForm/coordinate.py +++ b/PyPDFForm/coordinate.py @@ -7,7 +7,7 @@ from pypdf import PdfReader from reportlab.pdfbase.pdfmetrics import stringWidth -from .constants import (ANNOTATION_RECTANGLE_KEY, +from .constants import (Rect, COORDINATE_GRID_FONT_SIZE_MARGIN_RATIO, DEFAULT_FONT) from .middleware.text import Text from .template import (get_char_rect_width, get_widget_alignment, @@ -24,12 +24,12 @@ def get_draw_checkbox_radio_coordinates( string_height = widget_middleware.font_size * 96 / 72 width_mid_point = ( - float(widget[ANNOTATION_RECTANGLE_KEY][0]) - + float(widget[ANNOTATION_RECTANGLE_KEY][2]) + float(widget[Rect][0]) + + float(widget[Rect][2]) ) / 2 height_mid_point = ( - float(widget[ANNOTATION_RECTANGLE_KEY][1]) - + float(widget[ANNOTATION_RECTANGLE_KEY][3]) + float(widget[Rect][1]) + + float(widget[Rect][3]) ) / 2 return ( @@ -51,15 +51,15 @@ def get_draw_sig_coordinates_resolutions( Returns coordinates and resolutions to draw signature at given a PDF form signature widget. """ - x = float(widget[ANNOTATION_RECTANGLE_KEY][0]) - y = float(widget[ANNOTATION_RECTANGLE_KEY][1]) + x = float(widget[Rect][0]) + y = float(widget[Rect][1]) width = abs( - float(widget[ANNOTATION_RECTANGLE_KEY][0]) - - float(widget[ANNOTATION_RECTANGLE_KEY][2]) + float(widget[Rect][0]) + - float(widget[Rect][2]) ) height = abs( - float(widget[ANNOTATION_RECTANGLE_KEY][1]) - - float(widget[ANNOTATION_RECTANGLE_KEY][3]) + float(widget[Rect][1]) + - float(widget[Rect][3]) ) return x, y, width, height @@ -72,8 +72,8 @@ def get_draw_text_coordinates( if widget_middleware.preview: return ( - float(widget[ANNOTATION_RECTANGLE_KEY][0]), - float(widget[ANNOTATION_RECTANGLE_KEY][3]) + 5, + float(widget[Rect][0]), + float(widget[Rect][3]) + 5, ) text_value = widget_middleware.value or "" @@ -94,12 +94,12 @@ def get_draw_text_coordinates( ) alignment = get_widget_alignment(widget) or 0 - x = float(widget[ANNOTATION_RECTANGLE_KEY][0]) + x = float(widget[Rect][0]) if int(alignment) != 0: width_mid_point = ( - float(widget[ANNOTATION_RECTANGLE_KEY][0]) - + float(widget[ANNOTATION_RECTANGLE_KEY][2]) + float(widget[Rect][0]) + + float(widget[Rect][2]) ) / 2 string_width = stringWidth( text_value, @@ -116,7 +116,7 @@ def get_draw_text_coordinates( if int(alignment) == 1: x = width_mid_point - string_width / 2 elif int(alignment) == 2: - x = float(widget[ANNOTATION_RECTANGLE_KEY][2]) - string_width + x = float(widget[Rect][2]) - string_width if length > 0 and widget_middleware.comb is True: x -= ( get_char_rect_width(widget, widget_middleware) @@ -129,12 +129,12 @@ def get_draw_text_coordinates( string_height = widget_middleware.font_size * 96 / 72 height_mid_point = ( - float(widget[ANNOTATION_RECTANGLE_KEY][1]) - + float(widget[ANNOTATION_RECTANGLE_KEY][3]) + float(widget[Rect][1]) + + float(widget[Rect][3]) ) / 2 y = (height_mid_point - string_height / 2 + height_mid_point) / 2 if is_text_multiline(widget): - y = float(widget[ANNOTATION_RECTANGLE_KEY][3]) - string_height / 1.5 + y = float(widget[Rect][3]) - string_height / 1.5 if int(alignment) == 1 and widget_middleware.comb is True and length != 0: x -= character_paddings[0] / 2 diff --git a/PyPDFForm/filler.py b/PyPDFForm/filler.py index 6d3f849f..69343ae9 100644 --- a/PyPDFForm/filler.py +++ b/PyPDFForm/filler.py @@ -7,7 +7,7 @@ from pypdf import PdfReader, PdfWriter from pypdf.generic import DictionaryObject -from .constants import ANNOTATION_KEY, WIDGET_TYPES +from .constants import WIDGET_TYPES, Annots from .coordinate import (get_draw_checkbox_radio_coordinates, get_draw_sig_coordinates_resolutions, get_draw_text_coordinates, @@ -19,9 +19,10 @@ from .middleware.radio import Radio from .middleware.signature import Signature from .middleware.text import Text -from .patterns import (simple_update_checkbox_value, simple_update_radio_value, - simple_update_dropdown_value, simple_update_text_value, - simple_flatten_radio, simple_flatten_generic) +from .patterns import (simple_flatten_generic, simple_flatten_radio, + simple_update_checkbox_value, + simple_update_dropdown_value, simple_update_radio_value, + simple_update_text_value) from .template import get_widget_key, get_widgets_by_page from .utils import checkbox_radio_to_draw, stream_to_io from .watermark import create_watermarks_and_draw, merge_watermarks_with_pdf @@ -142,7 +143,7 @@ def simple_fill( radio_button_tracker = {} for page in out.pages: - for annot in page.get(ANNOTATION_KEY, []): # noqa + for annot in page.get(Annots, []): # noqa annot = cast(DictionaryObject, annot.get_object()) key = get_widget_key(annot.get_object()) diff --git a/PyPDFForm/font.py b/PyPDFForm/font.py index ff40d92c..9561951c 100644 --- a/PyPDFForm/font.py +++ b/PyPDFForm/font.py @@ -10,7 +10,7 @@ from reportlab.pdfbase.pdfmetrics import registerFont, standardFonts from reportlab.pdfbase.ttfonts import TTFError, TTFont -from .constants import (ANNOTATION_RECTANGLE_KEY, DEFAULT_FONT, +from .constants import (Rect, DEFAULT_FONT, FONT_COLOR_IDENTIFIER, FONT_SIZE_IDENTIFIER) from .patterns import TEXT_FIELD_APPEARANCE_PATTERNS from .utils import traverse_pattern @@ -83,8 +83,8 @@ def text_field_font_size(widget: dict) -> Union[float, int]: """ height = abs( - float(widget[ANNOTATION_RECTANGLE_KEY][1]) - - float(widget[ANNOTATION_RECTANGLE_KEY][3]) + float(widget[Rect][1]) + - float(widget[Rect][3]) ) return height * 2 / 3 @@ -97,11 +97,11 @@ def checkbox_radio_font_size(widget: dict) -> Union[float, int]: """ area = abs( - float(widget[ANNOTATION_RECTANGLE_KEY][0]) - - float(widget[ANNOTATION_RECTANGLE_KEY][2]) + float(widget[Rect][0]) + - float(widget[Rect][2]) ) * abs( - float(widget[ANNOTATION_RECTANGLE_KEY][1]) - - float(widget[ANNOTATION_RECTANGLE_KEY][3]) + float(widget[Rect][1]) + - float(widget[Rect][3]) ) return sqrt(area) * 72 / 96 diff --git a/PyPDFForm/patterns.py b/PyPDFForm/patterns.py index a34af61d..a1e4c196 100644 --- a/PyPDFForm/patterns.py +++ b/PyPDFForm/patterns.py @@ -1,17 +1,11 @@ # -*- coding: utf-8 -*- """Contains patterns used for identifying properties of widgets.""" -from pypdf.generic import DictionaryObject, NameObject, TextStringObject, NumberObject - -from .constants import (ANNOTATION_FIELD_KEY, BUTTON_IDENTIFIER, - BUTTON_STYLE_IDENTIFIER, CHOICE_FIELD_IDENTIFIER, - CHOICES_IDENTIFIER, FIELD_FLAG_KEY, PARENT_KEY, - SELECTABLE_IDENTIFIER, SIGNATURE_FIELD_IDENTIFIER, - SUBTYPE_KEY, TEXT_FIELD_ALIGNMENT_IDENTIFIER, - TEXT_FIELD_APPEARANCE_IDENTIFIER, - TEXT_FIELD_IDENTIFIER, WIDGET_SUBTYPE_KEY, - WIDGET_TYPE_KEY, CHECKBOX_SELECT, SELECTED_IDENTIFIER, TEXT_VALUE_IDENTIFIER, - TEXT_VALUE_SHOW_UP_IDENTIFIER, READ_ONLY) +from pypdf.generic import (DictionaryObject, NameObject, NumberObject, + TextStringObject) + +from .constants import (AP, AS, CA, DA, FT, MK, READ_ONLY, Btn, Ch, Ff, Opt, + Parent, Q, Sig, Subtype, T, Tx, V, Widget, Yes) from .middleware.checkbox import Checkbox from .middleware.dropdown import Dropdown from .middleware.radio import Radio @@ -20,115 +14,97 @@ WIDGET_TYPE_PATTERNS = [ ( - ({WIDGET_TYPE_KEY: SIGNATURE_FIELD_IDENTIFIER},), + ({FT: Sig},), Signature, ), ( - ({WIDGET_TYPE_KEY: TEXT_FIELD_IDENTIFIER},), + ({FT: Tx},), Text, ), ( - ({WIDGET_TYPE_KEY: SELECTABLE_IDENTIFIER},), + ({FT: Btn},), Checkbox, ), ( - ({WIDGET_TYPE_KEY: CHOICE_FIELD_IDENTIFIER},), + ({FT: Ch},), Dropdown, ), ( - ({PARENT_KEY: {WIDGET_TYPE_KEY: CHOICE_FIELD_IDENTIFIER}},), + ({Parent: {FT: Ch}},), Dropdown, ), ( - ({PARENT_KEY: {WIDGET_TYPE_KEY: TEXT_FIELD_IDENTIFIER}},), + ({Parent: {FT: Tx}},), Text, ), ( ( - {PARENT_KEY: {WIDGET_TYPE_KEY: SELECTABLE_IDENTIFIER}}, - {PARENT_KEY: {SUBTYPE_KEY: WIDGET_SUBTYPE_KEY}}, + {Parent: {FT: Btn}}, + {Parent: {Subtype: Widget}}, ), Checkbox, ), ( - ({PARENT_KEY: {WIDGET_TYPE_KEY: SELECTABLE_IDENTIFIER}},), + ({Parent: {FT: Btn}},), Radio, ), ] WIDGET_KEY_PATTERNS = [ - {ANNOTATION_FIELD_KEY: True}, - {PARENT_KEY: {ANNOTATION_FIELD_KEY: True}}, + {T: True}, + {Parent: {T: True}}, ] DROPDOWN_CHOICE_PATTERNS = [ - {CHOICES_IDENTIFIER: True}, - {PARENT_KEY: {CHOICES_IDENTIFIER: True}}, + {Opt: True}, + {Parent: {Opt: True}}, ] WIDGET_ALIGNMENT_PATTERNS = [ - {TEXT_FIELD_ALIGNMENT_IDENTIFIER: True}, - {PARENT_KEY: {TEXT_FIELD_ALIGNMENT_IDENTIFIER: True}}, + {Q: True}, + {Parent: {Q: True}}, ] TEXT_FIELD_FLAG_PATTERNS = [ - {FIELD_FLAG_KEY: True}, - {PARENT_KEY: {FIELD_FLAG_KEY: True}}, + {Ff: True}, + {Parent: {Ff: True}}, ] TEXT_FIELD_APPEARANCE_PATTERNS = [ - {TEXT_FIELD_APPEARANCE_IDENTIFIER: True}, - {PARENT_KEY: {TEXT_FIELD_APPEARANCE_IDENTIFIER: True}}, + {DA: True}, + {Parent: {DA: True}}, ] BUTTON_STYLE_PATTERNS = [ - {BUTTON_IDENTIFIER: {BUTTON_STYLE_IDENTIFIER: True}}, + {MK: {CA: True}}, ] def simple_update_checkbox_value(annot: DictionaryObject) -> None: - annot[NameObject(SELECTED_IDENTIFIER)] = NameObject(CHECKBOX_SELECT) + annot[NameObject(AS)] = NameObject(Yes) def simple_update_radio_value(annot: DictionaryObject, widget: Radio) -> None: - annot[NameObject(SELECTED_IDENTIFIER)] = NameObject( - f"/{widget.value}" - ) + annot[NameObject(AS)] = NameObject(f"/{widget.value}") def simple_update_dropdown_value(annot: DictionaryObject, widget: Dropdown) -> None: - annot[NameObject(TEXT_VALUE_IDENTIFIER)] = TextStringObject( - widget.choices[widget.value] - ) - annot[NameObject(TEXT_VALUE_SHOW_UP_IDENTIFIER)] = TextStringObject( - widget.choices[widget.value] - ) + annot[NameObject(V)] = TextStringObject(widget.choices[widget.value]) + annot[NameObject(AP)] = TextStringObject(widget.choices[widget.value]) def simple_update_text_value(annot: DictionaryObject, widget: Text) -> None: - annot[NameObject(TEXT_VALUE_IDENTIFIER)] = TextStringObject( - widget.value - ) - annot[NameObject(TEXT_VALUE_SHOW_UP_IDENTIFIER)] = TextStringObject( - widget.value - ) + annot[NameObject(V)] = TextStringObject(widget.value) + annot[NameObject(AP)] = TextStringObject(widget.value) def simple_flatten_radio(annot: DictionaryObject) -> None: - annot[NameObject(PARENT_KEY)][ # noqa - NameObject(FIELD_FLAG_KEY) - ] = NumberObject( - int( - annot[NameObject(PARENT_KEY)].get( # noqa - NameObject(FIELD_FLAG_KEY), 0 - ) - ) - | READ_ONLY + annot[NameObject(Parent)][NameObject(Ff)] = NumberObject( # noqa + int(annot[NameObject(Parent)].get(NameObject(Ff), 0)) | READ_ONLY # noqa ) def simple_flatten_generic(annot: DictionaryObject) -> None: - annot[NameObject(FIELD_FLAG_KEY)] = NumberObject( - int(annot.get(NameObject(FIELD_FLAG_KEY), 0)) - | READ_ONLY # noqa + annot[NameObject(Ff)] = NumberObject( + int(annot.get(NameObject(Ff), 0)) | READ_ONLY # noqa ) diff --git a/PyPDFForm/template.py b/PyPDFForm/template.py index f274f799..04dfdc51 100644 --- a/PyPDFForm/template.py +++ b/PyPDFForm/template.py @@ -7,8 +7,8 @@ from pypdf import PdfReader from reportlab.pdfbase.pdfmetrics import stringWidth -from .constants import (ANNOTATION_RECTANGLE_KEY, COMB, DEFAULT_FONT_SIZE, - MULTILINE, NEW_LINE_SYMBOL, TEXT_FIELD_MAX_LENGTH_KEY, +from .constants import (Rect, COMB, DEFAULT_FONT_SIZE, + MULTILINE, NEW_LINE_SYMBOL, MaxLen, WIDGET_TYPES) from .font import (auto_detect_font, get_text_field_font_color, get_text_field_font_size, text_field_font_size) @@ -82,7 +82,7 @@ def widget_rect_watermarks(pdf: bytes) -> List[bytes]: for page, widgets in get_widgets_by_page(pdf).items(): to_draw = [] for widget in widgets: - rect = widget[ANNOTATION_RECTANGLE_KEY] + rect = widget[Rect] x = rect[0] y = rect[1] width = abs(rect[0] - rect[2]) @@ -207,8 +207,8 @@ def get_text_field_max_length(widget: dict) -> Union[int, None]: """Returns the max length of the text field if presented or None.""" return ( - int(widget[TEXT_FIELD_MAX_LENGTH_KEY]) or None - if TEXT_FIELD_MAX_LENGTH_KEY in widget + int(widget[MaxLen]) or None + if MaxLen in widget else None ) @@ -270,8 +270,8 @@ def get_char_rect_width(widget: dict, widget_middleware: Text) -> float: """Returns rectangular width of each character for combed text fields.""" rect_width = abs( - float(widget[ANNOTATION_RECTANGLE_KEY][0]) - - float(widget[ANNOTATION_RECTANGLE_KEY][2]) + float(widget[Rect][0]) + - float(widget[Rect][2]) ) return rect_width / widget_middleware.max_length @@ -307,8 +307,8 @@ def get_paragraph_lines(widget: dict, widget_middleware: Text) -> List[str]: value = value[: widget_middleware.max_length] width = abs( - float(widget[ANNOTATION_RECTANGLE_KEY][0]) - - float(widget[ANNOTATION_RECTANGLE_KEY][2]) + float(widget[Rect][0]) + - float(widget[Rect][2]) ) split_by_new_line_symbol = value.split(NEW_LINE_SYMBOL) From 057681a6771d5eb7d3d5d9231f424be409bd34d3 Mon Sep 17 00:00:00 2001 From: chinapandaman Date: Sun, 24 Mar 2024 22:04:38 -0500 Subject: [PATCH 3/3] PPF-535: adding docstrings --- PyPDFForm/patterns.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/PyPDFForm/patterns.py b/PyPDFForm/patterns.py index a1e4c196..b3b5726a 100644 --- a/PyPDFForm/patterns.py +++ b/PyPDFForm/patterns.py @@ -81,30 +81,42 @@ def simple_update_checkbox_value(annot: DictionaryObject) -> None: + """Patterns to update values for checkbox annotations.""" + annot[NameObject(AS)] = NameObject(Yes) def simple_update_radio_value(annot: DictionaryObject, widget: Radio) -> None: + """Patterns to update values for radio annotations.""" + annot[NameObject(AS)] = NameObject(f"/{widget.value}") def simple_update_dropdown_value(annot: DictionaryObject, widget: Dropdown) -> None: + """Patterns to update values for dropdown annotations.""" + annot[NameObject(V)] = TextStringObject(widget.choices[widget.value]) annot[NameObject(AP)] = TextStringObject(widget.choices[widget.value]) def simple_update_text_value(annot: DictionaryObject, widget: Text) -> None: + """Patterns to update values for text annotations.""" + annot[NameObject(V)] = TextStringObject(widget.value) annot[NameObject(AP)] = TextStringObject(widget.value) def simple_flatten_radio(annot: DictionaryObject) -> None: + """Patterns to flatten checkbox annotations.""" + annot[NameObject(Parent)][NameObject(Ff)] = NumberObject( # noqa int(annot[NameObject(Parent)].get(NameObject(Ff), 0)) | READ_ONLY # noqa ) def simple_flatten_generic(annot: DictionaryObject) -> None: + """Patterns to flatten generic annotations.""" + annot[NameObject(Ff)] = NumberObject( int(annot.get(NameObject(Ff), 0)) | READ_ONLY # noqa )