e41fcae248
Sostituisce i file monolitici pipeline.py e validate.py con il package _pipeline/ a responsabilità separate. Entry point unificato in __main__.py (convert + validate dallo stesso comando). Moduli aggiunti: - __main__.py — CLI unificata (--stem, --force, validate, --detail) - _pipeline/__init__.py — re-export pubblico - _pipeline/checker.py — validazione PDF - _pipeline/deps.py — verifica dipendenze Java + opendataloader - _pipeline/structure.py — analyze() + strategia chunking Moduli già committati in precedenza: - _pipeline/converter.py, transforms.py, report.py, runner.py, validator.py Aggiornamenti collaterali: - .gitignore: exception !conversione/_pipeline/** per tracciare il package - CLAUDE.md: documentazione aggiornata alla nuova architettura; fix riferimenti obsoleti a conversione/pipeline.py → conversione/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
52 lines
2.1 KiB
Python
52 lines
2.1 KiB
Python
from pathlib import Path
|
|
|
|
|
|
def check_pdf(pdf_path: Path) -> tuple[bool, str]:
|
|
"""Validazione rapida: esistenza, leggibilità, testo estraibile."""
|
|
if not pdf_path.exists():
|
|
return False, f"File non trovato: {pdf_path}"
|
|
if pdf_path.suffix.lower() != ".pdf":
|
|
return False, f"Non è un PDF: {pdf_path.name}"
|
|
size = pdf_path.stat().st_size
|
|
if size == 0:
|
|
return False, "File vuoto"
|
|
if size < 1024:
|
|
return False, f"File troppo piccolo ({size} byte) — probabilmente corrotto"
|
|
|
|
try:
|
|
import pdfplumber
|
|
with pdfplumber.open(pdf_path) as pdf:
|
|
n_pages = len(pdf.pages)
|
|
if n_pages == 0:
|
|
return False, "PDF senza pagine"
|
|
sample = min(5, n_pages)
|
|
pages_with_text = sum(
|
|
1 for i in range(sample)
|
|
if len((pdf.pages[i].extract_text() or "").strip()) > 50
|
|
)
|
|
if pages_with_text == 0:
|
|
extended = min(15, n_pages)
|
|
if extended > sample:
|
|
ext_with_text = sum(
|
|
1 for i in range(sample, extended)
|
|
if len((pdf.pages[i].extract_text() or "").strip()) > 50
|
|
)
|
|
if ext_with_text > 0:
|
|
return True, (
|
|
f"{n_pages} pagine — prime {sample} vuote, "
|
|
f"testo trovato in pagine successive "
|
|
f"(possibile copertina immagine)"
|
|
)
|
|
return False, (
|
|
f"Nessun testo nelle prime {extended} pagine "
|
|
f"— probabilmente scansionato (OCR non supportato)"
|
|
)
|
|
return True, f"{n_pages} pagine, testo digitale confermato"
|
|
except MemoryError:
|
|
return False, "Memoria esaurita durante l'apertura del PDF"
|
|
except Exception as e:
|
|
msg = str(e).lower()
|
|
if "password" in msg or "encrypted" in msg:
|
|
return False, "PDF protetto da password"
|
|
return False, f"Impossibile aprire: {e}"
|