diff --git a/PyPDFForm/filler.py b/PyPDFForm/filler.py index b032da16..c9a53e9f 100644 --- a/PyPDFForm/filler.py +++ b/PyPDFForm/filler.py @@ -148,20 +148,20 @@ def simple_fill( key = get_widget_key(annot.get_object()) widget = widgets.get(key) - if widget is None: + if widget is None or widget.value is None: continue - if type(widget) is Checkbox and widget.value is True: - simple_update_checkbox_value(annot) + if type(widget) is Checkbox: + simple_update_checkbox_value(annot, widget.value) 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: simple_update_radio_value(annot) - elif isinstance(widget, Dropdown) and widget.value is not None: + elif isinstance(widget, Dropdown): simple_update_dropdown_value(annot, widget) - elif isinstance(widget, Text) and widget.value: + elif isinstance(widget, Text): simple_update_text_value(annot, widget) if flatten: diff --git a/PyPDFForm/patterns.py b/PyPDFForm/patterns.py index 46488fba..6ac6cd2e 100644 --- a/PyPDFForm/patterns.py +++ b/PyPDFForm/patterns.py @@ -80,12 +80,13 @@ ] -def simple_update_checkbox_value(annot: DictionaryObject) -> None: +def simple_update_checkbox_value(annot: DictionaryObject, check: bool = False) -> None: """Patterns to update values for checkbox annotations.""" for each in annot[AP][D]: # noqa - if str(each) != Off: + if (check and str(each) != Off) or (not check and str(each) == Off): annot[NameObject(AS)] = NameObject(each) + annot[NameObject(V)] = NameObject(each) break diff --git a/pdf_samples/simple/dropdown/dropdown_four.pdf b/pdf_samples/simple/dropdown/dropdown_four.pdf index 436f93d5..3ed825f3 100644 Binary files a/pdf_samples/simple/dropdown/dropdown_four.pdf and b/pdf_samples/simple/dropdown/dropdown_four.pdf differ diff --git a/pdf_samples/simple/dropdown/dropdown_one.pdf b/pdf_samples/simple/dropdown/dropdown_one.pdf index 7220c4e8..a53b0c1d 100644 Binary files a/pdf_samples/simple/dropdown/dropdown_one.pdf and b/pdf_samples/simple/dropdown/dropdown_one.pdf differ diff --git a/pdf_samples/simple/dropdown/dropdown_three.pdf b/pdf_samples/simple/dropdown/dropdown_three.pdf index 37fa892c..a2b92691 100644 Binary files a/pdf_samples/simple/dropdown/dropdown_three.pdf and b/pdf_samples/simple/dropdown/dropdown_three.pdf differ diff --git a/pdf_samples/simple/dropdown/dropdown_two.pdf b/pdf_samples/simple/dropdown/dropdown_two.pdf index f854eda8..8801899c 100644 Binary files a/pdf_samples/simple/dropdown/dropdown_two.pdf and b/pdf_samples/simple/dropdown/dropdown_two.pdf differ diff --git a/pdf_samples/simple/dropdown/dropdown_two_simple.pdf b/pdf_samples/simple/dropdown/dropdown_two_simple.pdf index 6807ad95..22eabe29 100644 Binary files a/pdf_samples/simple/dropdown/dropdown_two_simple.pdf and b/pdf_samples/simple/dropdown/dropdown_two_simple.pdf differ diff --git a/pdf_samples/simple/max_length_text_field_related/comb_text_field_all_chars.pdf b/pdf_samples/simple/max_length_text_field_related/comb_text_field_all_chars.pdf index 51c266c2..1912916f 100644 Binary files a/pdf_samples/simple/max_length_text_field_related/comb_text_field_all_chars.pdf and b/pdf_samples/simple/max_length_text_field_related/comb_text_field_all_chars.pdf differ diff --git a/pdf_samples/simple/max_length_text_field_related/comb_text_field_even_chars.pdf b/pdf_samples/simple/max_length_text_field_related/comb_text_field_even_chars.pdf index 03f97339..88421ecf 100644 Binary files a/pdf_samples/simple/max_length_text_field_related/comb_text_field_even_chars.pdf and b/pdf_samples/simple/max_length_text_field_related/comb_text_field_even_chars.pdf differ diff --git a/pdf_samples/simple/max_length_text_field_related/comb_text_field_even_chars_right_aligned.pdf b/pdf_samples/simple/max_length_text_field_related/comb_text_field_even_chars_right_aligned.pdf index 586fb1e1..ddbcdece 100644 Binary files a/pdf_samples/simple/max_length_text_field_related/comb_text_field_even_chars_right_aligned.pdf and b/pdf_samples/simple/max_length_text_field_related/comb_text_field_even_chars_right_aligned.pdf differ diff --git a/pdf_samples/simple/max_length_text_field_related/comb_text_field_odd_chars.pdf b/pdf_samples/simple/max_length_text_field_related/comb_text_field_odd_chars.pdf index 191cfc95..62bf7c12 100644 Binary files a/pdf_samples/simple/max_length_text_field_related/comb_text_field_odd_chars.pdf and b/pdf_samples/simple/max_length_text_field_related/comb_text_field_odd_chars.pdf differ diff --git a/pdf_samples/simple/max_length_text_field_related/max_length_text_field_all_chars.pdf b/pdf_samples/simple/max_length_text_field_related/max_length_text_field_all_chars.pdf index b9ee238d..17331e52 100644 Binary files a/pdf_samples/simple/max_length_text_field_related/max_length_text_field_all_chars.pdf and b/pdf_samples/simple/max_length_text_field_related/max_length_text_field_all_chars.pdf differ diff --git a/pdf_samples/simple/max_length_text_field_related/max_length_text_field_even_chars.pdf b/pdf_samples/simple/max_length_text_field_related/max_length_text_field_even_chars.pdf index 19d39c55..0a171c73 100644 Binary files a/pdf_samples/simple/max_length_text_field_related/max_length_text_field_even_chars.pdf and b/pdf_samples/simple/max_length_text_field_related/max_length_text_field_even_chars.pdf differ diff --git a/pdf_samples/simple/max_length_text_field_related/max_length_text_field_odd_chars.pdf b/pdf_samples/simple/max_length_text_field_related/max_length_text_field_odd_chars.pdf index 86453320..b5f85db6 100644 Binary files a/pdf_samples/simple/max_length_text_field_related/max_length_text_field_odd_chars.pdf and b/pdf_samples/simple/max_length_text_field_related/max_length_text_field_odd_chars.pdf differ diff --git a/pdf_samples/simple/paragraph/sample_filled_sejda_complex.pdf b/pdf_samples/simple/paragraph/sample_filled_sejda_complex.pdf index 89a94b28..4137174f 100644 Binary files a/pdf_samples/simple/paragraph/sample_filled_sejda_complex.pdf and b/pdf_samples/simple/paragraph/sample_filled_sejda_complex.pdf differ diff --git a/pdf_samples/simple/paragraph/sample_filled_sejda_complex_flatten.pdf b/pdf_samples/simple/paragraph/sample_filled_sejda_complex_flatten.pdf index 1246d38d..5e58aaa2 100644 Binary files a/pdf_samples/simple/paragraph/sample_filled_sejda_complex_flatten.pdf and b/pdf_samples/simple/paragraph/sample_filled_sejda_complex_flatten.pdf differ diff --git a/pdf_samples/simple/sample_filled.pdf b/pdf_samples/simple/sample_filled.pdf index 4305f5a4..425511ac 100644 Binary files a/pdf_samples/simple/sample_filled.pdf and b/pdf_samples/simple/sample_filled.pdf differ diff --git a/pdf_samples/simple/sample_filled_sejda.pdf b/pdf_samples/simple/sample_filled_sejda.pdf index 131005ed..b67bacde 100644 Binary files a/pdf_samples/simple/sample_filled_sejda.pdf and b/pdf_samples/simple/sample_filled_sejda.pdf differ diff --git a/pdf_samples/simple/scenario/existed/illinois-gun-bill-of-sale_expected.pdf b/pdf_samples/simple/scenario/existed/illinois-gun-bill-of-sale_expected.pdf index e96bc1c2..b95151cf 100644 Binary files a/pdf_samples/simple/scenario/existed/illinois-gun-bill-of-sale_expected.pdf and b/pdf_samples/simple/scenario/existed/illinois-gun-bill-of-sale_expected.pdf differ diff --git a/pdf_samples/simple/scenario/issues/437_expected.pdf b/pdf_samples/simple/scenario/issues/437_expected.pdf index e4a54eea..d858327c 100644 Binary files a/pdf_samples/simple/scenario/issues/437_expected.pdf and b/pdf_samples/simple/scenario/issues/437_expected.pdf differ diff --git a/pdf_samples/simple/scenario/tools/docfly_expected.pdf b/pdf_samples/simple/scenario/tools/docfly_expected.pdf index 671afc77..e87dc45f 100644 Binary files a/pdf_samples/simple/scenario/tools/docfly_expected.pdf and b/pdf_samples/simple/scenario/tools/docfly_expected.pdf differ diff --git a/pdf_samples/simple/scenario/tools/pdf_escape_expected.pdf b/pdf_samples/simple/scenario/tools/pdf_escape_expected.pdf index 17dd0f32..67cb91a0 100644 Binary files a/pdf_samples/simple/scenario/tools/pdf_escape_expected.pdf and b/pdf_samples/simple/scenario/tools/pdf_escape_expected.pdf differ diff --git a/pdf_samples/simple/undo/sample_template_filled.pdf b/pdf_samples/simple/undo/sample_template_filled.pdf new file mode 100644 index 00000000..471f851d Binary files /dev/null and b/pdf_samples/simple/undo/sample_template_filled.pdf differ diff --git a/pdf_samples/simple/undo/test_undo_checkbox.pdf b/pdf_samples/simple/undo/test_undo_checkbox.pdf new file mode 100644 index 00000000..0adae696 Binary files /dev/null and b/pdf_samples/simple/undo/test_undo_checkbox.pdf differ diff --git a/tests/test_functional_simple.py b/tests/test_functional_simple.py index 49a81c5b..fbb5301e 100644 --- a/tests/test_functional_simple.py +++ b/tests/test_functional_simple.py @@ -127,3 +127,25 @@ def test_fill_complex_fonts(sample_template_with_complex_fonts, pdf_samples, req if os.name != "nt": assert len(obj.read()) == len(expected) assert obj.stream == expected + + +def test_undo_checkbox(pdf_samples, request): + expected_path = os.path.join(pdf_samples, "simple", "undo", "test_undo_checkbox.pdf") + with open(expected_path, "rb+") as f: + obj = FormWrapper( + os.path.join(pdf_samples, "simple", "undo", "sample_template_filled.pdf") + ).fill( + { + "check": False, + "check_2": False, + "check_3": False, + }, + ) + + request.config.results["expected_path"] = expected_path + request.config.results["stream"] = obj.read() + + expected = f.read() + + assert len(obj.stream) == len(expected) + assert obj.stream == expected