| 1756 | |
| 1757 | |
| 1758 | def pdf_coverage_summary(pdf_path: Path, max_pages: int | None = None) -> dict[str, Any]: |
| 1759 | summary: dict[str, Any] = { |
| 1760 | "total_pages": None, |
| 1761 | "text_max_pages": max_pages, |
| 1762 | "text_pages_scanned": 0, |
| 1763 | "truncated_due_to_page_limit": False, |
| 1764 | "appendix_detected": False, |
| 1765 | "appendix_start_page": None, |
| 1766 | "references_start_page": None, |
| 1767 | "section_stop_reason": "", |
| 1768 | "section_stop_page": None, |
| 1769 | } |
| 1770 | if fitz is None or not pdf_path.is_file(): |
| 1771 | return summary |
| 1772 | |
| 1773 | try: |
| 1774 | doc = fitz.open(pdf_path) |
| 1775 | except Exception: |
| 1776 | return summary |
| 1777 | |
| 1778 | try: |
| 1779 | total_pages = len(doc) |
| 1780 | page_limit = total_pages if max_pages is None else min(total_pages, max_pages) |
| 1781 | summary["total_pages"] = total_pages |
| 1782 | summary["text_pages_scanned"] = page_limit |
| 1783 | summary["truncated_due_to_page_limit"] = max_pages is not None and total_pages > max_pages |
| 1784 | |
| 1785 | for page_index in range(total_pages): |
| 1786 | page_number = page_index + 1 |
| 1787 | text = doc[page_index].get_text("text") |
| 1788 | for raw_line in text.splitlines(): |
| 1789 | line = clean_pdf_line(raw_line) |
| 1790 | if not line: |
| 1791 | continue |
| 1792 | exact_reason = stop_section_reason(line) |
| 1793 | detected_reason = exact_reason or stop_section_reason(line, allow_prefix=True) |
| 1794 | if not detected_reason: |
| 1795 | continue |
| 1796 | if detected_reason == "references" and summary["references_start_page"] is None: |
| 1797 | summary["references_start_page"] = page_number |
| 1798 | if detected_reason == "appendix" and summary["appendix_start_page"] is None: |
| 1799 | summary["appendix_start_page"] = page_number |
| 1800 | summary["appendix_detected"] = True |
| 1801 | if exact_reason and not summary["section_stop_reason"]: |
| 1802 | summary["section_stop_reason"] = exact_reason |
| 1803 | summary["section_stop_page"] = page_number |
| 1804 | break |
| 1805 | finally: |
| 1806 | doc.close() |
| 1807 | return summary |
| 1808 | |
| 1809 | |
| 1810 | def extract_appendix_page_texts( |