I created all three PDFs and checked them. The one oddity is that the bullet characters in terms.pdf come out as (cid:127) when extracted.
Files (in the working folder, built by scripts/make.py, checked by scripts/check.py):
invoice.pdfis 1 page. It has a title for "Northwind Sample Co" and three line items, and everything is marked as sample.terms.pdfis 1 page. It has the heading "Sample Terms" and three bullet terms.combined.pdfis 2 pages, with the invoice first and the terms second. That matches 1 + 1 pages.
Text extracted from combined.pdf
- Page 1 has the invoice title, the "fictional / made-up sample data" note, the table rows, and the "SAMPLE - not a real invoice." footer.
- Page 2 has "Sample Terms" and the three terms: payment due in 30 days, 1% monthly late fee, and goods remaining sample property until paid. Each one is marked "(sample term)".
Table extracted from page 1 (one table found):
| Item | Qty | Unit Price | Amount |
|---|---|---|---|
| Sample Widget | 10 | $5.00 | $50.00 |
| Sample Gadget | 2 | $25.00 | $50.00 |
| Sample Service Hour | 4 | $30.00 | $120.00 |
| Total | $220.00 |
Verification: The line items add up: 50 + 50 + 120 = 220, which matches the stated total. The extracted table has the same 5 rows and 4 columns I built, with no merged or missing cells.
Problem: pdfplumber reads the bullet glyph as (cid:127) instead of "•". That is how the built-in Helvetica font encodes the bullet, so it is probably an extraction quirk and the bullets should display normally. I haven't rendered the pages, so I can't confirm how they look. If clean extracted text matters to you, I can switch to a plain "-" marker.
Test run: two sample one-page PDFs built with reportlab, merged with pypdf, then read back with pdfplumber, in a temporary folder. The run was allowed to write files and run python3 only. I re-opened the files myself: 1 + 1 pages merged into 2, and the table text matched. The model flagged that the bullet glyph extracts as (cid:127). Pages were not rendered, so appearance was not checked. All content is sample.
What it does
Uses three well-known libraries: pypdf for structure (merge, split, reorder, rotate, forms, metadata), pdfplumber for text and tables and reportlab for generating new PDFs. It inspects each input first (page count, sizes, encryption, form fields and how much text each page has, which shows early whether a page is a scan), then runs the task, and re-opens every output to check page counts, a text sample, form values and file size. It reports pages that have no extractable text and says they need OCR, and warns when extracted tables may be unreliable. It only opens a protected PDF with a password you give for a file you may use, and does not try to break protection.
Output
The new PDF files and the script that made them, what changed, the verification result, and problems found such as scanned pages or missing fonts.
Good for
Merging and splitting documents, pulling tables out of reports, stamping watermarks and page numbers, filling forms and generating simple invoices or reports.
Medium risk: instructions only, no scripts of its own, but it writes and runs Python that creates files in your working folder and may suggest installing pypdf, pdfplumber and reportlab in a virtual environment. It never overwrites your originals and does not break password protection. Test-run once in a temporary folder with sample PDFs: it generated two PDFs, merged them and extracted the table correctly; the bullet glyph came out as (cid:127) when extracted, and pages were not rendered, so appearance was not checked. Original by AIBars (MIT).