Mercurial > hgrepos > Python2 > PyMuPDF
view tests/test_widgets.py @ 44:0a8b06e38e19
Need "packaging" at wheel build time too.
Parsing of version_p into a tuple now is done at build time.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sat, 11 Oct 2025 17:16:23 +0200 |
| parents | 1d09e1dec1d9 |
| children |
line wrap: on
line source
# -*- coding: utf-8 -*- """ Test PDF field (widget) insertion. """ import pymupdf import os scriptdir = os.path.abspath(os.path.dirname(__file__)) filename = os.path.join(scriptdir, "resources", "widgettest.pdf") file_2333 = os.path.join(scriptdir, "resources", "test-2333.pdf") file_4055 = os.path.join(scriptdir, "resources", "test-4055.pdf") doc = pymupdf.open() page = doc.new_page() gold = (1, 1, 0) # define some colors blue = (0, 0, 1) gray = (0.9, 0.9, 0.9) fontsize = 11.0 # define a fontsize lineheight = fontsize + 4.0 rect = pymupdf.Rect(50, 72, 400, 200) def test_text(): doc = pymupdf.open() page = doc.new_page() widget = pymupdf.Widget() # create a widget object widget.border_color = blue # border color widget.border_width = 0.3 # border width widget.border_style = "d" widget.border_dashes = (2, 3) widget.field_name = "Textfield-1" # field name widget.field_label = "arbitrary text - e.g. to help filling the field" widget.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT # field type widget.fill_color = gold # field background widget.rect = rect # set field rectangle widget.text_color = blue # rext color widget.text_font = "TiRo" # use font Times-Roman widget.text_fontsize = fontsize # set fontsize widget.text_maxlen = 50 # restrict number of characters widget.field_value = "Times-Roman" page.add_widget(widget) # create the field field = page.first_widget assert field.field_type_string == "Text" def test_checkbox(): doc = pymupdf.open() page = doc.new_page() widget = pymupdf.Widget() widget.border_style = "b" widget.field_name = "Button-1" widget.field_label = "a simple check box button" widget.field_type = pymupdf.PDF_WIDGET_TYPE_CHECKBOX widget.fill_color = gold widget.rect = rect widget.text_color = blue widget.text_font = "ZaDb" widget.field_value = True page.add_widget(widget) # create the field field = page.first_widget assert field.field_type_string == "CheckBox" # Check #2350 - setting checkbox to readonly. # widget.field_flags |= pymupdf.PDF_FIELD_IS_READ_ONLY widget.update() path = f"{scriptdir}/test_checkbox.pdf" doc.save(path) doc = pymupdf.open(path) page = doc[0] widget = page.first_widget assert widget assert widget.field_flags == pymupdf.PDF_FIELD_IS_READ_ONLY def test_listbox(): doc = pymupdf.open() page = doc.new_page() widget = pymupdf.Widget() widget.field_name = "ListBox-1" widget.field_label = "is not a drop down: scroll with cursor in field" widget.field_type = pymupdf.PDF_WIDGET_TYPE_LISTBOX widget.field_flags = pymupdf.PDF_CH_FIELD_IS_COMMIT_ON_SEL_CHANGE widget.fill_color = gold widget.choice_values = ( "Frankfurt", "Hamburg", "Stuttgart", "Hannover", "Berlin", "München", "Köln", "Potsdam", ) widget.rect = rect widget.text_color = blue widget.text_fontsize = fontsize widget.field_value = widget.choice_values[-1] print("About to add '%s'" % widget.field_name) page.add_widget(widget) # create the field field = page.first_widget assert field.field_type_string == "ListBox" def test_combobox(): doc = pymupdf.open() page = doc.new_page() widget = pymupdf.Widget() widget.field_name = "ComboBox-1" widget.field_label = "an editable combo box ..." widget.field_type = pymupdf.PDF_WIDGET_TYPE_COMBOBOX widget.field_flags = ( pymupdf.PDF_CH_FIELD_IS_COMMIT_ON_SEL_CHANGE | pymupdf.PDF_CH_FIELD_IS_EDIT ) widget.fill_color = gold widget.choice_values = ( "Spanien", "Frankreich", "Holland", "Dänemark", "Schweden", "Norwegen", "England", "Polen", "Russland", "Italien", "Portugal", "Griechenland", ) widget.rect = rect widget.text_color = blue widget.text_fontsize = fontsize widget.field_value = widget.choice_values[-1] page.add_widget(widget) # create the field field = page.first_widget assert field.field_type_string == "ComboBox" def test_text2(): doc = pymupdf.open() doc.new_page() page = [p for p in doc.pages()][0] widget = pymupdf.Widget() widget.field_name = "textfield-2" widget.field_label = "multi-line text with tabs is also possible!" widget.field_flags = pymupdf.PDF_TX_FIELD_IS_MULTILINE widget.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT widget.fill_color = gray widget.rect = rect widget.text_color = blue widget.text_font = "TiRo" widget.text_fontsize = fontsize widget.field_value = "This\n\tis\n\t\ta\n\t\t\tmulti-\n\t\tline\n\ttext." page.add_widget(widget) # create the field widgets = [w for w in page.widgets()] field = widgets[0] assert field.field_type_string == "Text" def test_2333(): doc = pymupdf.open(file_2333) page = doc[0] def values(): return set( ( doc.xref_get_key(635, "AS")[1], doc.xref_get_key(636, "AS")[1], doc.xref_get_key(637, "AS")[1], doc.xref_get_key(638, "AS")[1], doc.xref_get_key(127, "V")[1], ) ) for i, xref in enumerate((635, 636, 637, 638)): w = page.load_widget(xref) w.field_value = True w.update() assert values() == set(("/Off", f"{i}", f"/{i}")) w.field_value = False w.update() assert values() == set(("Off", "/Off")) def test_2411(): """Add combobox values in different formats.""" doc = pymupdf.open() page = doc.new_page() rect = pymupdf.Rect(100, 100, 300, 200) widget = pymupdf.Widget() widget.field_flags = ( pymupdf.PDF_CH_FIELD_IS_COMBO | pymupdf.PDF_CH_FIELD_IS_EDIT | pymupdf.PDF_CH_FIELD_IS_COMMIT_ON_SEL_CHANGE ) widget.field_name = "ComboBox-1" widget.field_label = "an editable combo box ..." widget.field_type = pymupdf.PDF_WIDGET_TYPE_COMBOBOX widget.fill_color = pymupdf.pdfcolor["gold"] widget.rect = rect widget.choice_values = [ ["Spain", "ES"], # double value as list ("Italy", "I"), # double value as tuple "Portugal", # single value ] page.add_widget(widget) def test_2391(): """Confirm that multiple times setting a checkbox to ON/True/Yes will work.""" doc = pymupdf.open(f"{scriptdir}/resources/widgettest.pdf") page = doc[0] # its work when we update first-time for field in page.widgets(types=[pymupdf.PDF_WIDGET_TYPE_CHECKBOX]): field.field_value = True field.update() for i in range(5): pdfdata = doc.tobytes() doc.close() doc = pymupdf.open("pdf", pdfdata) page = doc[0] for field in page.widgets(types=[pymupdf.PDF_WIDGET_TYPE_CHECKBOX]): assert field.field_value == field.on_state() field_field_value = field.on_state() field.update() def test_3216(): document = pymupdf.open(filename) for page in document: while 1: w = page.first_widget print(f"{w=}") if not w: break page.delete_widget(w) def test_add_widget(): doc = pymupdf.open() page = doc.new_page() w = pymupdf.Widget() w.field_type = pymupdf.PDF_WIDGET_TYPE_BUTTON w.rect = pymupdf.Rect(5, 5, 20, 20) w.field_flags = pymupdf.PDF_BTN_FIELD_IS_PUSHBUTTON w.field_name = "button" w.fill_color = (0, 0, 1) w.script = "app.alert('Hello, PDF!');" page.add_widget(w) def test_interfield_calculation(): """Confirm correct working of interfield calculations. We are going to create three pages with a computed result field each. Tests the fix for https://github.com/pymupdf/PyMuPDF/issues/3402. """ # Field bboxes (same on each page) r1 = pymupdf.Rect(100, 100, 300, 120) r2 = pymupdf.Rect(100, 130, 300, 150) r3 = pymupdf.Rect(100, 180, 300, 200) doc = pymupdf.open() pdf = pymupdf._as_pdf_document(doc) # we need underlying PDF document # Make PDF name object for "CO" because it is not defined in MuPDF. CO_name = pymupdf.mupdf.pdf_new_name("CO") # = PDF_NAME(CO) for i in range(3): page = doc.new_page() w = pymupdf.Widget() w.field_name = f"NUM1{page.number}" w.rect = r1 w.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT w.field_value = f"{i*100+1}" w.field_flags = 2 page.add_widget(w) w = pymupdf.Widget() w.field_name = f"NUM2{page.number}" w.rect = r2 w.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT w.field_value = "200" w.field_flags = 2 page.add_widget(w) w = pymupdf.Widget() w.field_name = f"RESULT{page.number}" w.rect = r3 w.field_type = pymupdf.PDF_WIDGET_TYPE_TEXT w.field_value = "Result?" # Script that adds previous two fields. w.script_calc = f"""AFSimple_Calculate("SUM", new Array("NUM1{page.number}", "NUM2{page.number}"));""" page.add_widget(w) # Access the inter-field calculation array. It contains a reference to # all fields which have a JavaScript stored in their "script_calc" # property, i.e. an "AA/C" entry. # Every iteration adds another such field, so this array's length must # always equal the loop index. if i == 0: # only need to execute this on first time through CO = pymupdf.mupdf.pdf_dict_getl( pymupdf.mupdf.pdf_trailer(pdf), pymupdf.PDF_NAME("Root"), pymupdf.PDF_NAME("AcroForm"), CO_name, ) # we confirm CO is an array of foreseeable length assert pymupdf.mupdf.pdf_array_len(CO) == i + 1 # the xref of the i-th item must equal that of the last widget assert ( pymupdf.mupdf.pdf_to_num(pymupdf.mupdf.pdf_array_get(CO, i)) == list(page.widgets())[-1].xref ) def test_3950(): path = os.path.normpath(f'{__file__}/../../tests/resources/test_3950.pdf') items = list() with pymupdf.open(path) as document: for page in document: for widget in page.widgets(): items.append(widget.field_label) print(f'test_3950(): {widget.field_label=}.') assert items == [ '{{ named_insured }}', '{{ policy_period_start_date }}', '{{ policy_period_end_date }}', '{{ insurance_line }}', ] def test_4004(): import collections def get_widgets_by_name(doc): """ Extracts and returns a dictionary of widgets indexed by their names. """ widgets_by_name = collections.defaultdict(list) for page_num in range(len(doc)): page = doc.load_page(page_num) for field in page.widgets(): widgets_by_name[field.field_name].append({ "page_num": page_num, "widget": field }) return widgets_by_name # Open document and get widgets path = os.path.normpath(f'{__file__}/../../tests/resources/test_4004.pdf') doc = pymupdf.open(path) widgets_by_name = get_widgets_by_name(doc) # Print widget information for name, widgets in widgets_by_name.items(): print(f"Widget Name: {name}") for entry in widgets: widget = entry["widget"] page_num = entry["page_num"] print(f" Page: {page_num + 1}, Type: {widget.field_type}, Value: {widget.field_value}, Rect: {widget.rect}") # Attempt to update field value w = widgets_by_name["Text1"][0] field = w['widget'] field.value = "1234567890" try: field.update() except Exception as e: assert str(e) == 'Annot is not bound to a page' doc.close() def test_4055(): """Check correct setting of CheckBox "Yes" values. Test scope: * setting on with any of 'True' / 'Yes' / built-in values works * setting off with any of 'False' or 'Off' works """ # this PDF has digits as "Yes" values. doc = pymupdf.open(file_4055) page = doc[0] # Round 1: confirm all check boxes are off for w in page.widgets(types=[2]): # check that this file doesn't use the "Yes" standard assert w.on_state() != "Yes" assert w.field_value == "Off" # all check boxes are off w.field_value = w.on_state() w.update() page = doc.reload_page(page) # reload page to make sure we start fresh # Round 2: confirm that fields contain the PDF's own on values for w in page.widgets(types=[2]): # confirm each value coincides with the "Yes" value assert w.field_value == w.on_state() w.field_value = False # switch to "Off" using False w.update() page = doc.reload_page(page) # Round 3: confirm that 'False' achieved "Off" values for w in page.widgets(types=[2]): assert w.field_value == "Off" w.field_value = True # use True for the next round w.update() page = doc.reload_page(page) # Round 4: confirm that setting to True also worked for w in page.widgets(types=[2]): assert w.field_value == w.on_state() w.field_value = "Off" # set off again w.update() w.field_value = "Yes" w.update() page = doc.reload_page(page) # Round 5: final check: setting to "Yes" also does work for w in page.widgets(types=[2]): assert w.field_value == w.on_state()
