From a5934e45b2d51355119359f78fdcc30061cd5edc Mon Sep 17 00:00:00 2001 From: local Date: Mon, 19 Jan 2026 23:06:56 +0000 Subject: [PATCH] improved pdfcreator 1- use CLI 2- refactor code --- python/.vscode/launch.json | 9 +- python/pdfcreator/README.md | 161 +++++++++++++ python/pdfcreator/driver.py | 99 ++++++++ python/pdfcreator/extracted_section.pdf | Bin 155409 -> 0 bytes python/pdfcreator/main.py | 289 +++++++++++++++--------- python/pdfcreator/pdfaggregator.py | 231 +++++++++++++++++++ python/pdfcreator/terminal.sh | 6 + python/pdfcreator/tests.py | 128 +++++++++++ 8 files changed, 810 insertions(+), 113 deletions(-) create mode 100644 python/pdfcreator/README.md create mode 100644 python/pdfcreator/driver.py delete mode 100644 python/pdfcreator/extracted_section.pdf create mode 100644 python/pdfcreator/pdfaggregator.py create mode 100755 python/pdfcreator/terminal.sh create mode 100644 python/pdfcreator/tests.py diff --git a/python/.vscode/launch.json b/python/.vscode/launch.json index 7774467..dac6996 100644 --- a/python/.vscode/launch.json +++ b/python/.vscode/launch.json @@ -4,12 +4,17 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { - "name": "Python Debugger: Current File", + "name": "Debug PDF Aggregator", "type": "debugpy", "request": "launch", "program": "${file}", + "args": [ + "-o", + "${workspaceFolder}/pdfcreator/out.pdf", + "-i", + "${workspaceFolder}/pdfcreator/input.pdf:5,@50-60", + ], "console": "integratedTerminal" } ] diff --git a/python/pdfcreator/README.md b/python/pdfcreator/README.md new file mode 100644 index 0000000..bab4f6e --- /dev/null +++ b/python/pdfcreator/README.md @@ -0,0 +1,161 @@ +# PDF Aggregator & Section Extractor + +## Purpose + +This Python tool allows you to **extract sections or page ranges from one or more PDFs** and aggregate them into a **single PDF** with: + +- Table of Contents (TOC) reflecting section headings +- Optional bookmarks corresponding to TOC entries +- Cropped pages to remove headers and footers for a clean layout +- Flat TOC structure with unnumbered section titles + +It is designed for **research papers, reports, or multi-chapter PDFs** where you need to assemble a subset of content into a new document, while preserving readability and navigation. + +--- + +## Key Features + +- **Section-based extraction:** Extract sections (e.g., `1.3`, `5`) and all subsections automatically. +- **Page-range extraction:** Extract explicit page ranges using a special syntax (e.g., `@10-20`). +- **Header/Footer cropping:** Automatically removes unwanted headers and footers while maintaining consistent page sizes across multiple PDFs. +- **Flat Table of Contents:** TOC shows only the section titles from the original PDFs; numbering and indentation are stripped. +- **Bookmarks:** Optional PDF bookmarks that match the TOC entries for easy navigation. +- **Multi-source aggregation:** Accepts multiple PDFs and merges the specified sections or page ranges into a single output file. +- **Command-line driven:** Fully configurable via CLI arguments and compatible with debugging in VS Code. + +--- + +## Design Choices + +1. **Separation of concerns** + - `pdfaggregator.py`: All core PDF handling functions (section extraction, cropping, TOC creation). + - `driver.py`: CLI entry point that parses arguments, validates inputs, and orchestrates aggregation. + - `test_pdfaggregator.py`: Unit tests for parsing, extraction, TOC, and page handling. + +2. **Level-aware section matching** + - Section numbers (e.g., `5`) match only top-level chapters, not subsections like `5.1`. + - Page ranges (prefixed with `@`) are treated explicitly and bypass section matching. + +3. **Argument parsing** + - Uses Python’s standard `argparse` for CLI argument handling. + - Input format supports multiple PDFs and multiple sections per file, e.g.: + + ``` + -i input.pdf:5,@50-60 input2.pdf:3.2 + ``` + +4. **Debug-friendly and testable** + - CLI parsing separated from `main()` for easier unit testing. + - Compatible with VS Code debugging (`launch.json` with `${file}` for portable paths). + +5. **TOC and bookmark handling** + - TOC entries reflect **section headings only**; numbering stripped. + - Bookmarks are linked to corresponding pages in the final PDF. + - Cropping and page normalization ensures consistent layout. + +6. **Unit tests** + - Core functions, including `parse_inputs`, page extraction, cropping, and TOC creation, are covered. + - Uses `unittest` and avoids direct CLI dependency for testability. + +--- + +## How it Works (High-Level Flow) + +1. **Parse CLI inputs** + - Extract PDF file paths and associated sections or page ranges. + - Normalize section references (e.g., `@10-20`). + +2. **Iterate through PDFs** + - Load PDF using `PyPDF2`. + - Build outline tree (hierarchical sections) if available. + +3. **Process sections/page ranges** + - For each requested section: + - Find matching section heading in outline (level-aware). + - Determine start and end pages, including all subsections. + - For page ranges prefixed with `@`, extract exact pages. + +4. **Crop pages** + - Remove headers and footers based on configurable ratios. + - Normalize page size across all PDFs for visual consistency. + +5. **Assemble final PDF** + - Add a Table of Contents as the first pages. + - Merge all extracted pages. + - Add bookmarks corresponding to TOC entries. + +6. **Write output** + - Save aggregated PDF to specified output path. + - TOC shows **titles only**, flat structure, and correct page references. + +--- + + +---------------------+ + | CLI / Inputs | + | - PDF files | + | - Sections/@pages | + +----------+----------+ + | + v + +---------------------+ + | parse_inputs() | + | Normalize sections | + | Detect page ranges | + +----------+----------+ + | + v + +---------------------+ + | Iterate PDFs | + | Load PDF with | + | PyPDF2 | + +----------+----------+ + | + +-------------+--------------+ + | | + v v + +-------------------+ +------------------+ + | Section Extraction| | Page Range (@) | + | - Match outline | | - Extract pages | + | - Level-aware | | directly | + | - Subsections | +------------------+ + +--------+----------+ + | + v + +----------------------+ + | Crop Pages | + | - Remove headers | + | - Remove footers | + | - Normalize size | + +----------+-----------+ + | + v + +----------------------+ + | TOC & Bookmarks | + | - Extracted section | + | titles only | + | - Flat TOC structure | + | - Bookmarks linked | + +----------+-----------+ + | + v + +----------------------+ + | Merge PDF Pages | + | - TOC pages first | + | - All extracted pages| + +----------+-----------+ + | + v + +----------------------+ + | Output PDF | + | - TOC & bookmarks | + | - Cropped & normalized| + +----------------------+ + + +--- +## Example Usage + +```bash +python driver.py \ + -o aggregated.pdf \ + -i input.pdf:5,@50-60 input2.pdf:3.2 diff --git a/python/pdfcreator/driver.py b/python/pdfcreator/driver.py new file mode 100644 index 0000000..14376e9 --- /dev/null +++ b/python/pdfcreator/driver.py @@ -0,0 +1,99 @@ +# driver.py +from pypdf import PageObject +from pdfaggregator import * +from pypdf import PdfReader, PdfWriter +import argparse + + +PDF_INPUTS = [ + {"file": "pdfcreator/input.pdf", "sections": ["5", "@20-30"]}, + # {"file": "pdfcreator/input2.pdf", + # "sections": ["3.1"]} +] + +OUTPUT_PDF = "pdfcreator/extracted_sections.pdf" + +# crop ratios +HEADER_CROP = 0.1 +FOOTER_CROP = 0.03 + + +def main(pdf_inputs, output_pdf): + + content_writer = PdfWriter() + toc_entries = [] + current_page = 0 + + for pdf_info in pdf_inputs: # or change + REFERENCE_BOX = None + reader = PdfReader(pdf_info["file"]) + outline_tree = build_outline_tree(reader) + total_pages = len(reader.pages) + + for entry in pdf_info["sections"]: + page_indices = parse_page_range(entry) + + if page_indices: + # Explicit page range + current_page, REFERENCE_BOX, toc_entry = extract_page_range( + entry, reader, content_writer, current_page, REFERENCE_BOX, + HEADER_CROP, FOOTER_CROP + ) + else: + # Section prefix + current_page, REFERENCE_BOX, toc_entry = extract_section_prefix( + entry, reader, content_writer, current_page, REFERENCE_BOX, + outline_tree, HEADER_CROP, FOOTER_CROP + ) + + if toc_entry: + toc_entries.append(toc_entry) + + # Create TOC PDF + toc_pdf = create_toc_pdf(toc_entries) + toc_page_count = len(toc_pdf.pages) + + final_writer = PdfWriter() + # add TOC pages + for page in toc_pdf.pages: + final_writer.add_page(page) + # add content pages + for page in content_writer.pages: + final_writer.add_page(page) + + # Add bookmarks + bookmark_stack = {} + for entry in toc_entries: + parent = bookmark_stack.get(entry["level"] - 1) + bm = final_writer.add_outline_item( + title=entry["title"], + page_number=(entry["page"] - 1) + toc_page_count, + parent=parent + ) + bookmark_stack[entry["level"]] = bm + + with open(output_pdf, "wb") as f: + final_writer.write(f) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Extract sections and page ranges from PDFs and aggregate into a new PDF with TOC and bookmarks." + ) + + parser.add_argument( + "-o", "--output", + required=True, + help="Output PDF file" + ) + + parser.add_argument( + "-i", "--inputs", + nargs="+", + help="Inputs in the form file.pdf:section1,section2 or file.pdf:@1-10" + ) + + args = parser.parse_args() + pdf_inputs = parse_inputs(args) + + main(pdf_inputs, args.output) diff --git a/python/pdfcreator/extracted_section.pdf b/python/pdfcreator/extracted_section.pdf deleted file mode 100644 index ee3736a30e919b8d9d7d1274b08e55ba448a87f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155409 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%0A9eEXD|=40~G} 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%0A2ULTIU8>qOwQ{Ex?k1??-&#Hqb%Y-DA?9_W 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 l&%CsJ1zn7XX#_+SC95 diff --git a/python/pdfcreator/main.py b/python/pdfcreator/main.py index d4448cd..3448bb2 100644 --- a/python/pdfcreator/main.py +++ b/python/pdfcreator/main.py @@ -1,23 +1,50 @@ -from pypdf import PdfReader -from io import BytesIO -from reportlab.lib.pagesizes import LETTER +import re +from pypdf import PdfReader, PdfWriter from reportlab.pdfgen import canvas -from pypdf import PdfReader, PdfWriter, PageObject +from reportlab.lib.pagesizes import LETTER +from io import BytesIO + +# ================= CONFIG ================= -# ----------- CONFIG ------------- PDF_INPUTS = [ - {"file": "pdfcreator/input.pdf", "sections": ["1", "2.2", "3"]}, - {"file": "pdfcreator/input2.pdf", "sections": ["3", "4"]}, + {"file": "pdfcreator/input.pdf", "sections": ["1.3", "2.1", "@111-114"]}, + {"file": "pdfcreator/input2.pdf", "sections": ["3.2"]}, ] -OUTPUT_PDF = "pdfcreator/combined_sections.pdf" + +OUTPUT_PDF = "pdfcreator/extracted_sections.pdf" + +HEADER_CROP = 0.12 # top of first page of section +FOOTER_CROP = 0.06 # bottom of all pages + +# ========================================= -# Cropping ratios -HEADER_CROP = 0.1 # top of first page of section -FOOTER_CROP = 0.0 # bottom of pages -# -------------------------------- +def strip_numbering(title): + """ + Remove leading numbering from a string like '1.3 Background' + Returns 'Background'. + """ + return re.sub(r'^\d+(\.\d+)*\s+', '', title) -# ----- HELPER FUNCTIONS --------- + +# ---------- Outline utilities ------------ +def parse_page_range(entry): + """ + Returns a list of zero-based page indices if entry is a page range. + Page ranges must be prefixed with '@', e.g., "@1-10". + Otherwise returns None (treated as section prefix). + """ + if entry.startswith("@"): + s = entry[1:] # remove the @ + try: + start, end = s.split("-") + start = int(start) - 1 # zero-based + end = int(end) # inclusive in range + return list(range(start, end)) + except ValueError: + print(f"[WARN] Invalid page range: {entry}") + return None + return None # not a page range def build_outline_tree(reader): @@ -36,14 +63,14 @@ def build_outline_tree(reader): return _build(reader.outline) -def find_section(nodes, title): +def find_section_with_level(nodes, prefix, level=0): for node in nodes: - if node["title"] == title or node["title"].startswith(title + " "): - return node - found = find_section(node["children"], title) - if found: + if node["title"].startswith(prefix): + return node, level + found = find_section_with_level(node["children"], prefix, level + 1) + if found[0]: return found - return None + return None, None def collect_subtree_pages(node, pages=None): @@ -66,138 +93,178 @@ def flatten_outline_pages(nodes, pages=None): def find_end_page(target_node, outline_tree, total_pages): subtree_pages = collect_subtree_pages(target_node) - last_section_page = max(subtree_pages) - all_outline_pages = flatten_outline_pages(outline_tree) - all_outline_pages = sorted(set(all_outline_pages)) - for page in all_outline_pages: - if page > last_section_page: - return page + last_page = max(subtree_pages) + + all_pages = sorted(set(flatten_outline_pages(outline_tree))) + for p in all_pages: + if p > last_page: + return p return total_pages +# ---------- Page manipulation ------------ + def crop_page(page, top_ratio=0.0, bottom_ratio=0.0): llx, lly, urx, ury = page.mediabox height = ury - lly + new_lly = lly + height * bottom_ratio new_ury = ury - height * top_ratio - if new_ury <= new_lly: - raise ValueError("Invalid crop ratios: page height would be negative") + page.cropbox.lower_left = (llx, new_lly) page.cropbox.upper_right = (urx, new_ury) -def normalize_page_size(page, reference_box): - """ - Force page MediaBox and CropBox to match reference. - """ - page.mediabox.lower_left = reference_box.lower_left - page.mediabox.upper_right = reference_box.upper_right +# ---------- TOC generation --------------- +def create_toc_pdf(toc_entries, heading): + buffer = BytesIO() + c = canvas.Canvas(buffer, pagesize=LETTER) - page.cropbox.lower_left = reference_box.lower_left - page.cropbox.upper_right = reference_box.upper_right + c.setFont("Helvetica-Bold", 16) + c.drawString(50, 750, heading) -# -------------------------------- + c.setFont("Helvetica", 12) + y = 720 + + for entry in toc_entries: + line = f"{strip_numbering(entry['title'])} ........................ {entry['page']}" + c.drawString(50, y, line) # flat: no indentation + y -= 18 + + if y < 50: + c.showPage() + c.setFont("Helvetica", 12) + y = 750 + + c.save() + buffer.seek(0) + return PdfReader(buffer) -# --------- MAIN PROCESS ---------- -writer = PdfWriter() -toc_entries = [] # To build TOC later -current_page_index = 0 +# ================= MAIN =================== + +content_writer = PdfWriter() +toc_entries = [] +current_page = 0 +REFERENCE_BOX = None for pdf_info in PDF_INPUTS: - file_path = pdf_info["file"] - sections_to_extract = pdf_info["sections"] - - reader = PdfReader(file_path) + reader = PdfReader(pdf_info["file"]) outline_tree = build_outline_tree(reader) total_pages = len(reader.pages) - for section_title in sections_to_extract: - target = find_section(outline_tree, section_title) - if not target: - print(f"[WARN] Section '{section_title}' not found in {file_path}") - continue + for entry in pdf_info["sections"]: - start_page = target["page"] - end_page = find_end_page(target, outline_tree, total_pages) + page_indices = parse_page_range(entry) - REFERENCE_BOX = None - # Add pages to combined PDF - for i, p in enumerate(range(start_page, end_page)): - page = reader.pages[p] + if page_indices: + # --- Explicit page range --- + toc_entries.append({ + "title": f"Pages {entry[1:]}", # remove '@' for display + "page": current_page + 1, + "level": 0 + }) + + for i, p in enumerate(page_indices): + if p < 0 or p >= total_pages: + print( + f"[WARN] Page {p+1} out of range in {pdf_info['file']}") + continue + page = reader.pages[p] - # Crop first page header+footer - if i == 0: crop_page(page, top_ratio=HEADER_CROP, bottom_ratio=FOOTER_CROP) - else: - crop_page(page, top_ratio=HEADER_CROP, - bottom_ratio=FOOTER_CROP) - # crop_page(page, bottom_ratio=FOOTER_CROP) + if REFERENCE_BOX is None: + REFERENCE_BOX = ( + page.cropbox.lower_left, + page.cropbox.upper_right + ) + page.mediabox.lower_left = REFERENCE_BOX[0] + page.mediabox.upper_right = REFERENCE_BOX[1] + page.cropbox.lower_left = REFERENCE_BOX[0] + page.cropbox.upper_right = REFERENCE_BOX[1] - if REFERENCE_BOX is None: - # Make a copy, not a reference - REFERENCE_BOX = ( - page.cropbox.lower_left, - page.cropbox.upper_right - ) - # Step 3: Normalize page size - page.mediabox.lower_left = REFERENCE_BOX[0] - page.mediabox.upper_right = REFERENCE_BOX[1] - page.cropbox.lower_left = REFERENCE_BOX[0] - page.cropbox.upper_right = REFERENCE_BOX[1] + content_writer.add_page(page) + current_page += 1 + else: - writer.add_page(page) + target, level = find_section_with_level( + outline_tree, entry) + if not target: + print( + f"[WARN] Section {entry} not found in {pdf_info['file']}") + continue - # Track TOC - toc_entries.append({ - "title": f"{section_title} ({file_path})", - "page": current_page_index + 1 # 1-based page number - }) - current_page_index += (end_page - start_page) + start_page = target["page"] + end_page = find_end_page(target, outline_tree, total_pages) -# --------- ADD TOC PAGE(S) ---------- + toc_entries.append({ + "title": target["title"], # EXACT heading text + "page": current_page + 1, # 1-based + "level": level + }) + + for i, p in enumerate(range(start_page, end_page)): + page = reader.pages[p] + + if i == 0: + crop_page(page, HEADER_CROP, FOOTER_CROP) + else: + crop_page(page, bottom_ratio=FOOTER_CROP) + + # Capture reference AFTER cropping + if REFERENCE_BOX is None: + REFERENCE_BOX = ( + page.cropbox.lower_left, + page.cropbox.upper_right + ) + + # Normalize page size + page.mediabox.lower_left = REFERENCE_BOX[0] + page.mediabox.upper_right = REFERENCE_BOX[1] + page.cropbox.lower_left = REFERENCE_BOX[0] + page.cropbox.upper_right = REFERENCE_BOX[1] + + content_writer.add_page(page) + current_page += 1 -def create_toc_pdf(toc_entries): - packet = BytesIO() - c = canvas.Canvas(packet, pagesize=LETTER) - c.setFont("Helvetica-Bold", 16) - c.drawString(50, 750, "Table of Contents") - c.setFont("Helvetica", 12) - y = 720 - for entry in toc_entries: - text = f"{entry['title']} .... {entry['page']}" - c.drawString(50, y, text) - y -= 20 - if y < 50: - c.showPage() - y = 750 - c.save() - packet.seek(0) - return PdfReader(packet) +# ---------- Build final PDF --------------- - -toc_pdf = create_toc_pdf(toc_entries) - -# Combine TOC + extracted sections final_writer = PdfWriter() -# TOC first +# Derive TOC heading from first source document +first_reader = PdfReader(PDF_INPUTS[0]["file"]) +toc_heading = "Contents" if first_reader.outline else "Table of Contents" + +# Visible TOC pages +toc_pdf = create_toc_pdf(toc_entries, toc_heading) +toc_page_count = len(toc_pdf.pages) + for page in toc_pdf.pages: final_writer.add_page(page) -# Then extracted content -for page in writer.pages: +# Content pages +for page in content_writer.pages: final_writer.add_page(page) -# Save +bookmark_stack = {} + +for entry in toc_entries: + parent = bookmark_stack.get(entry["level"] - 1) + + bm = final_writer.add_outline_item( + title=entry["title"], # exact heading text + page_number=(entry["page"] - 1) + toc_page_count, + parent=parent + ) + + bookmark_stack[entry["level"]] = bm + + +# ---------- Write output ------------------ + with open(OUTPUT_PDF, "wb") as f: final_writer.write(f) - -# --------- WRITE OUTPUT ----------- -with open(OUTPUT_PDF, "wb") as f: - final_writer.write(f) - -print(f"[INFO] Combined PDF written to {OUTPUT_PDF} with TOC.") +print(f"[OK] Created {OUTPUT_PDF}") diff --git a/python/pdfcreator/pdfaggregator.py b/python/pdfcreator/pdfaggregator.py new file mode 100644 index 0000000..9039188 --- /dev/null +++ b/python/pdfcreator/pdfaggregator.py @@ -0,0 +1,231 @@ +# pdfaggregator.py +import re +from io import BytesIO +from pypdf import PdfReader, PdfWriter, PageObject +from reportlab.pdfgen import canvas +from reportlab.lib.pagesizes import LETTER + +# ----------------------------- +# Parsing / Section Utilities +# ----------------------------- + + +def parse_page_range(entry): + """Return list of zero-based page indices if entry is a page range (@1-10).""" + if entry.startswith("@"): + s = entry[1:] + try: + start, end = s.split("-") + start = int(start) - 1 + end = int(end) + return list(range(start, end)) + except ValueError: + print(f"[WARN] Invalid page range: {entry}") + return None + return None + + +def strip_numbering(title): + """Remove leading numbering like '1.3 Background' -> 'Background'""" + return re.sub(r'^\d+(\.\d+)*\s+', '', title) + + +def crop_page(page, top_ratio=0.0, bottom_ratio=0.0): + """Crop the top/bottom of a page using ratios.""" + llx, lly, urx, ury = page.mediabox + height = ury - lly + new_lly = lly + height * bottom_ratio + new_ury = ury - height * top_ratio + page.cropbox.lower_left = (llx, new_lly) + page.cropbox.upper_right = (urx, new_ury) + +# ----------------------------- +# Outline / Section Tree +# ----------------------------- + + +def find_section_with_level(nodes, prefix, level=0): + """Find a section node by prefix in outline tree.""" + for node in nodes: + if node["title"].startswith(prefix): + return node, level + found = find_section_with_level( + node.get("children", []), prefix, level + 1) + if found[0]: + return found + return None, None + + +def collect_subtree_pages(node, pages=None): + """Recursively collect pages of node and all its children.""" + if pages is None: + pages = [] + pages.append(node["page"]) + for child in node.get("children", []): + collect_subtree_pages(child, pages) + return pages + + +def flatten_outline_pages(nodes, pages=None): + """Flatten all pages from the outline tree.""" + if pages is None: + pages = [] + for node in nodes: + pages.append(node["page"]) + flatten_outline_pages(node.get("children", []), pages) + return pages + + +def find_end_page(target_node, outline_tree, total_pages): + """Find the last page of a section including its subsections.""" + subtree_pages = collect_subtree_pages(target_node) + last_page = max(subtree_pages) + all_pages = sorted(set(flatten_outline_pages(outline_tree))) + for p in all_pages: + if p > last_page: + return p + return total_pages + + +def build_outline_tree(reader): + """ + Build a normalized outline tree from pypdf's reader.outline. + + Each node: + { + "title": str, + "page": int, + "children": [ ... ] + } + """ + def walk(items): + tree = [] + for item in items: + if isinstance(item, list): + # children of previous item + if tree: + tree[-1]["children"] = walk(item) + else: + tree.append({ + "title": item.title.strip(), + "page": reader.get_destination_page_number(item), + "children": [] + }) + return tree + + try: + outline = reader.outline + except Exception: + return [] + + if not outline: + return [] + + return walk(outline) + + +# ----------------------------- +# TOC Generation +# ----------------------------- + + +def create_toc_pdf(toc_entries, heading="Table of Contents"): + """Generate a flat, unnumbered TOC PDF page in memory.""" + buffer = BytesIO() + c = canvas.Canvas(buffer, pagesize=LETTER) + + c.setFont("Helvetica-Bold", 16) + c.drawString(50, 750, heading) + + c.setFont("Helvetica", 12) + y = 720 + + for entry in toc_entries: + line = f"{strip_numbering(entry['title'])} ........................ {entry['page']}" + c.drawString(50, y, line) + y -= 18 + if y < 50: + c.showPage() + c.setFont("Helvetica", 12) + y = 750 + + c.save() + buffer.seek(0) + return PdfReader(buffer) + + +def extract_page_range(entry, reader, content_writer, current_page, REFERENCE_BOX, header_crop=0.05, footer_crop=0.03): + """Extract pages from an explicit @page-range entry.""" + page_indices = parse_page_range(entry) + if not page_indices: + return current_page, REFERENCE_BOX, None # nothing extracted + + toc_entry = {"title": f"Pages {entry[1:]}", + "page": current_page + 1, "level": 0} + + for i, p in enumerate(page_indices): + if p < 0 or p >= len(reader.pages): + continue + page = reader.pages[p] + crop_page(page, header_crop, footer_crop) + if REFERENCE_BOX is None: + REFERENCE_BOX = (page.cropbox.lower_left, page.cropbox.upper_right) + page.mediabox.lower_left = REFERENCE_BOX[0] + page.mediabox.upper_right = REFERENCE_BOX[1] + page.cropbox.lower_left = REFERENCE_BOX[0] + page.cropbox.upper_right = REFERENCE_BOX[1] + content_writer.add_page(page) + current_page += 1 + + return current_page, REFERENCE_BOX, toc_entry + + +def extract_section_prefix(entry, reader, content_writer, current_page, REFERENCE_BOX, outline_tree, header_crop=0.05, footer_crop=0.03): + """Extract pages from a section prefix entry in the PDF outline.""" + target, level = find_section_with_level(outline_tree, entry) + if not target: + print( + f"[WARN] Section {entry} not found in PDF {reader.stream.name if hasattr(reader.stream, 'name') else ''}") + return current_page, REFERENCE_BOX, None + + start_page = target["page"] + end_page = find_end_page(target, outline_tree, len(reader.pages)) + toc_entry = {"title": target["title"], + "page": current_page + 1, "level": level} + + for i, p in enumerate(range(start_page, end_page)): + page = reader.pages[p] + crop_page(page, header_crop if i == 0 else 0, footer_crop) + if REFERENCE_BOX is None: + REFERENCE_BOX = (page.cropbox.lower_left, page.cropbox.upper_right) + page.mediabox.lower_left = REFERENCE_BOX[0] + page.mediabox.upper_right = REFERENCE_BOX[1] + page.cropbox.lower_left = REFERENCE_BOX[0] + page.cropbox.upper_right = REFERENCE_BOX[1] + content_writer.add_page(page) + current_page += 1 + + return current_page, REFERENCE_BOX, toc_entry + + +def parse_inputs(args): + """ + Parse CLI positional arguments into PDF_INPUTS structure. + """ + pdf_inputs = [] + + for item in args.inputs: + if ":" not in item: + raise ValueError( + f"Invalid input '{item}'. Expected format: file.pdf:section1,section2" + ) + + file_path, sections = item.split(":", 1) + section_list = [s.strip() for s in sections.split(",") if s.strip()] + + pdf_inputs.append({ + "file": file_path, + "sections": section_list + }) + + return pdf_inputs diff --git a/python/pdfcreator/terminal.sh b/python/pdfcreator/terminal.sh new file mode 100755 index 0000000..d7016a9 --- /dev/null +++ b/python/pdfcreator/terminal.sh @@ -0,0 +1,6 @@ +#!/bin/bash +export CT2_CUDA_ALLOW_FP16=1 + +# 'mamba run' executes the command within the context of the environment +# without needing to source .bashrc or shell hooks manually. +mamba run -n base python ~/family-repo/Code/python/pdfcreator/driver.py "$@" \ No newline at end of file diff --git a/python/pdfcreator/tests.py b/python/pdfcreator/tests.py new file mode 100644 index 0000000..4150dc2 --- /dev/null +++ b/python/pdfcreator/tests.py @@ -0,0 +1,128 @@ +import unittest +from pypdf import PdfWriter, PageObject +from types import SimpleNamespace +from pdfaggregator import parse_inputs, strip_numbering, crop_page, extract_page_range, extract_section_prefix, parse_page_range, find_section_with_level, find_end_page + + +class TestPdfExtractionFunctions(unittest.TestCase): + def setUp(self): + # Dummy PDF with 5 blank pages + self.writer = PdfWriter() + for _ in range(5): + self.writer.add_page( + PageObject.create_blank_page(width=600, height=800)) + self.reader = self.writer # pypdf writer can be used as reader for pages list + self.content_writer = PdfWriter() + self.outline_tree = [{"title": "Section1", "page": 0, "children": [ + {"title": "Section1.1", "page": 1, "children": []}]}] + + def test_extract_page_range(self): + current_page, REFERENCE_BOX, toc = extract_page_range( + "@1-3", self.reader, self.content_writer, 0, None) + self.assertEqual(len(self.content_writer.pages), 3) # pages 0 and 1 + self.assertEqual(toc["title"], "Pages 1-3") + self.assertEqual(current_page, 3) + + def test_extract_section_prefix(self): + current_page, REFERENCE_BOX, toc = extract_section_prefix( + "Section1", self.reader, self.content_writer, 0, None, self.outline_tree) + self.assertEqual(len(self.content_writer.pages), + 5) # page 0 + subsection 1 + self.assertEqual(toc["title"], "Section1") + self.assertEqual(current_page, 5) + + +class TestPdfAggregator(unittest.TestCase): + + def test_parse_page_range(self): + self.assertEqual(parse_page_range("@1-5"), [0, 1, 2, 3, 4]) + self.assertEqual(parse_page_range("@10-12"), [9, 10, 11]) + self.assertIsNone(parse_page_range("1.3")) + self.assertIsNone(parse_page_range("Introduction-Overview")) + + def test_strip_numbering(self): + self.assertEqual(strip_numbering("1.3 Background"), "Background") + self.assertEqual(strip_numbering( + "2.1.5 Experimental Setup"), "Experimental Setup") + self.assertEqual(strip_numbering("NoNumberingHere"), "NoNumberingHere") + + def test_crop_page(self): + page = PageObject.create_blank_page(width=600, height=800) + crop_page(page, top_ratio=0.1, bottom_ratio=0.05) + llx, lly = page.cropbox.lower_left + urx, ury = page.cropbox.upper_right + self.assertAlmostEqual(ury - lly, 800 * 0.85) + + +class TestParseInputs(unittest.TestCase): + + def test_single_pdf_single_section(self): + args = SimpleNamespace( + inputs=["doc1.pdf:1.3"] + ) + + result = parse_inputs(args) + + self.assertEqual(result, [ + { + "file": "doc1.pdf", + "sections": ["1.3"] + } + ]) + + def test_single_pdf_multiple_sections(self): + args = SimpleNamespace( + inputs=["doc1.pdf:1.3,2.1,@10-20"] + ) + + result = parse_inputs(args) + + self.assertEqual(result, [ + { + "file": "doc1.pdf", + "sections": ["1.3", "2.1", "@10-20"] + } + ]) + + def test_multiple_pdfs(self): + args = SimpleNamespace( + inputs=[ + "doc1.pdf:1.3,@5-10", + "doc2.pdf:Introduction,3.2" + ] + ) + + result = parse_inputs(args) + + self.assertEqual(result, [ + { + "file": "doc1.pdf", + "sections": ["1.3", "@5-10"] + }, + { + "file": "doc2.pdf", + "sections": ["Introduction", "3.2"] + } + ]) + + def test_whitespace_is_trimmed(self): + args = SimpleNamespace( + inputs=["doc1.pdf: 1.3 , @5-10 , Introduction "] + ) + + result = parse_inputs(args) + + self.assertEqual(result[0]["sections"], [ + "1.3", "@5-10", "Introduction"]) + + def test_missing_colon_raises_error(self): + args = SimpleNamespace( + inputs=["doc1.pdf"] + ) + + with self.assertRaises(ValueError): + parse_inputs(args) + + +if __name__ == "__main__": + unittest.main()