def test_append_items(outlines_doc): # Simple check that we can write new objects # without failing the object duplicate checks with outlines_doc.open_outline(strict=True) as outline: new_item = OutlineItem('Four') new_item.children.extend([OutlineItem('Four-A'), OutlineItem('Four-B')]) outline.root.append(new_item) with outlines_doc.open_outline(strict=True): list(outline.root)
def test_new_item(resources, title, page_num, page_loc): doc = Pdf.open(resources / 'outlines.pdf') kwargs = dict.fromkeys(ALL_PAGE_LOCATION_KWARGS, 100) page_ref = doc.pages[page_num] new_item = OutlineItem(title, page_num, page_loc, **kwargs) with doc.open_outline() as outline: outline.root.append(new_item) if isinstance(page_loc, PageLocation): loc_str = page_loc.name else: loc_str = page_loc if loc_str == 'FitR': kwarg_len = 4 elif loc_str == 'XYZ': kwarg_len = 3 elif loc_str in ('FitH', 'FitV', 'FitBH', 'FitBV'): kwarg_len = 1 else: kwarg_len = 0 expected_dest = [page_ref, Name('/{0}'.format(loc_str))] expected_dest.extend(repeat(100, kwarg_len)) assert new_item.destination == expected_dest new_obj = new_item.obj assert new_obj.Title == title assert new_obj.Dest == expected_dest assert new_obj.is_indirect is True
def test_new_item(resources, title, page_num, page_loc): # @given precludes use of outlines_doc fixture - causes hypothesis health check to # fail with Pdf.open(resources / 'outlines.pdf') as doc: kwargs = dict.fromkeys(ALL_PAGE_LOCATION_KWARGS, 100) page_ref = doc.pages[page_num] new_item = OutlineItem(title, page_num, page_loc, **kwargs) with doc.open_outline() as outline: outline.root.append(new_item) if isinstance(page_loc, PageLocation): loc_str = page_loc.name else: loc_str = page_loc if loc_str == 'FitR': kwarg_len = 4 elif loc_str == 'XYZ': kwarg_len = 3 elif loc_str in ('FitH', 'FitV', 'FitBH', 'FitBV'): kwarg_len = 1 else: kwarg_len = 0 expected_dest = [page_ref, Name(f'/{loc_str}')] expected_dest.extend(repeat(100, kwarg_len)) assert new_item.destination == expected_dest new_obj = new_item.obj assert new_obj.Title == title assert new_obj.Dest == expected_dest assert new_obj.is_indirect is True
def test_outlineitem_str(resources): with Pdf.open(resources / 'outlines.pdf') as pdf: with pdf.open_outline() as outline: assert str(outline.root[0]) == '[+] One -> <Action>' assert str(outline.root[1]) == '[ ] Two -> <Action>' item = OutlineItem('Test', make_page_destination(pdf, 0)) assert '[ ] Test -> 1' == str(item)
def dict_to_outline_item(item): oi = OutlineItem(item['title'], item['page'] - 1) if 'children' in item: for child in item['children']: ci = dict_to_outline_item(child) oi.children.append(ci) return oi
def append_subnodes(outline, nodes): for node in nodes: if "title" in node and "page" in node: print(node["title"], node["page"]) outline.append(OutlineItem(node["title"], node["page"])) if "children" in node: append_subnodes(outline, node["children"])
def test_create_from_scratch(outlines_doc): # Simple check that we can discard the existing outline # and create a new one. del outlines_doc.Root.Outlines with outlines_doc.open_outline(strict=True) as outline: new_item = OutlineItem('One') new_item.children.extend([OutlineItem('One-A'), OutlineItem('One-B')]) outline.root.append(new_item) with outlines_doc.open_outline(strict=True): list(outline.root) # Should also work while the outline is open with outlines_doc.open_outline(strict=True) as outline: del outlines_doc.Root.Outlines new_item = OutlineItem('One') outline.root.append(new_item) with outlines_doc.open_outline(strict=True): list(outline.root)
def test_outlineitem_str(outlines_doc): with outlines_doc.open_outline() as outline: assert str(outline.root[0]) == '[+] One -> <Action>' assert str(outline.root[1]) == '[ ] Two -> <Action>' outline.root[0].is_closed = False assert str(outline.root[0]) == '[-] One -> <Action>' item = OutlineItem('Test', make_page_destination(outlines_doc, 0)) assert '[ ] Test -> 1' == str(item) assert str(outline) != ''
def mergeFiles(self): # Only try to combine if files have been added to the list # Allow for a single pdf to be 'combined', in this case it will just remove security if there is any if self.ui.lstFiles.count(): outfile = self.openSaveFileDialog() # Only merge the pdfs if there is an output filename if outfile: self.ui.statusbar.showMessage("Combining...") output = Pdf.new() page_count = 0 try: with output.open_outline() as outline: # Combine PDFs for i in range(0, self.ui.lstFiles.count()): filename = self.ui.lstFiles.item(i).text() with Pdf.open(filename) as pdf: oi = OutlineItem(os.path.basename(filename), page_count) outline.root.append(oi) page_count += len(pdf.pages) output.pages.extend(pdf.pages) # Save file output.save(outfile) # Clear files from list self.clearFilesFromList() # Update statusbar with success message self.ui.statusbar.showMessage("Success. Saved file '%s'" % (os.path.basename(outfile))) # If combining the PDFs fails except: # Update the statusbar with an error message with the file that caused it to fail self.ui.statusbar.showMessage("Error processing '%s'" % (os.path.basename(filename))) output.close()
def add_tree(parent_list: list[OutlineItem], tree: Tree[PaginatedAnchor], pages: list[Path]) -> int: page_number = -1 if tree.value.pages: page_number = len(pages) pages.extend(tree.value.pages) children: list[OutlineItem] = [] child_page_numbers = [ add_tree(children, child_tree, pages) for child_tree in tree.children ] if page_number < 0: page_number = child_page_numbers[0] outline_item = OutlineItem(tree.value.text, page_number) outline_item.children.extend(children) parent_list.append(outline_item) return page_number
def removeSecurityFromFiles(self): # Only try to combine if files have been added to the list # Allow for a single pdf to be 'combined', in this case it will just remove security if there is any if self.ui.lstFiles.count(): self.ui.statusbar.showMessage("Removing security from PDFs...") try: for i in range(0, self.ui.lstFiles.count()): output = Pdf.new() page_count = 0 filename = self.ui.lstFiles.item(i).text() outfile = filename.replace(".pdf", "-UNSECURED.pdf") with output.open_outline() as outline: with Pdf.open(filename) as pdf: oi = OutlineItem(os.path.basename(filename), page_count) outline.root.append(oi) page_count += len(pdf.pages) output.pages.extend(pdf.pages) # Save the file output.save(outfile) # Clear files from list self.clearFilesFromList() # Update statusbar with success message self.ui.statusbar.showMessage( "Success. Removed security from %d pdfs" % (i + 1)) except: # Update the statusbar with an error message with the file that caused it to fail self.ui.statusbar.showMessage("Error processing '%s'" % (os.path.basename(filename))) output.close()
def test_recursion_depth_zero(outlines_doc): # Only keeps root level with outlines_doc.open_outline(max_depth=0) as outline: # No more than the root level should be read for root_element in outline.root: assert len(root_element.children) == 0 # Attach an item to the first root level element # that should be ignored when writing outline.root[0].children.append(OutlineItem('New', 0)) root_obj = outlines_doc.Root.Outlines first_obj = root_obj.First second_obj = first_obj.Next third_obj = second_obj.Next for obj in [first_obj, second_obj, third_obj]: assert '/First' not in obj assert '/Last' not in obj
def test_duplicated_object(outlines_doc): # Fails on reoccurring element with pytest.raises(OutlineStructureError): with outlines_doc.open_outline(strict=True) as outline: # Copy and object reference from one node to another obj_b_ii = outline.root[0].children[1].children[0].obj outline.root[2].children[0].obj = obj_b_ii # Silently creates a copy of the outline node with outlines_doc.open_outline() as outline: # Append duplicate object reference to existing outline obj_b_ii = outline.root[0].children[1].children[0].obj outline.root[2].children.append( OutlineItem.from_dictionary_object(obj_b_ii)) # Should not fail at this point anymore with outlines_doc.open_outline(strict=True) as outline: assert len(outline.root[2].children) == 3 assert (outline.root[2].children[2].title == outline.root[0].children[1].children[0].title)
def test_recursion_depth_one(outlines_doc): # Only keeps first level from root with outlines_doc.open_outline(max_depth=1) as outline: # Only children of first level should be present for root_element, first_level_count in zip(outline.root, (2, 0, 2)): assert len(root_element.children) == first_level_count for sub_element in root_element.children: assert len(sub_element.children) == 0 # Attach an item to the first sub level element # that should be ignored when writing outline.root[0].children[1].children.append(OutlineItem('New', 0)) root_obj = outlines_doc.Root.Outlines first_obj = root_obj.First first_obj_a = first_obj.First first_obj_b = first_obj_a.Next second_obj = first_obj.Next third_obj = second_obj.Next third_obj_a = third_obj.First third_obj_b = third_obj_a.Next for obj in [first_obj_a, first_obj_b, third_obj_a, third_obj_b]: assert '/First' not in obj assert '/Last' not in obj
def test_noop(outlines_doc): with outlines_doc.open_outline(strict=True): # Forget to attach it - should simply not modify. OutlineItem('New')
import pikepdf from pikepdf import Pdf, OutlineItem with Pdf.open('TampaFD_TemporalPDF-4.pdf') as pdf: with pdf.open_outline() as outline: new_action = pikepdf.Dictionary() new_action['/S'] = pikepdf.Name('/JavaScript') new_action['/JS'] = "app.alert(\"Hello from Robin\");" test_item = OutlineItem('Test Alert Robin', action=new_action) outline.root.append(test_item) pdf.save('output1.pdf')
def test_outline_destination_name_object_types(): # See issues 258, 261 obj = Dictionary(Title='foo', Dest=Name.Bar) item = OutlineItem.from_dictionary_object(obj) assert '.Root.Dests' in str(item)