doocus first ver
This commit is contained in:
66
doocus/registry.py
Normal file
66
doocus/registry.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
Extension → extractor dispatch.
|
||||
|
||||
Maps a file extension to an extractor "family" module under doocus/extractors/.
|
||||
Families are imported lazily so an app that only handles text files doesn't need
|
||||
the office/pdf/image dependencies installed. Unknown extensions (and families
|
||||
whose optional deps are missing) are reported as "unhandled" — never fatal.
|
||||
"""
|
||||
import importlib
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional
|
||||
|
||||
from .extractors.base import ExtractionResult
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# extension (no dot, lowercase) → family module name under doocus.extractors
|
||||
EXT_FAMILY: Dict[str, str] = {
|
||||
"md": "text", "markdown": "text", "txt": "text",
|
||||
"yaml": "text", "yml": "text", "json": "text",
|
||||
"csv": "tabular",
|
||||
"docx": "office", "pptx": "office", "xlsx": "office",
|
||||
"pdf": "pdf",
|
||||
"html": "web", "htm": "web",
|
||||
"jpg": "image", "jpeg": "image", "png": "image",
|
||||
"mp4": "media",
|
||||
}
|
||||
|
||||
|
||||
def ext_of(source: Path) -> str:
|
||||
return source.suffix.lower().lstrip(".")
|
||||
|
||||
|
||||
def family_for(source: Path) -> Optional[str]:
|
||||
return EXT_FAMILY.get(ext_of(source))
|
||||
|
||||
|
||||
def extract(source: Path, options: dict) -> ExtractionResult:
|
||||
"""Dispatch to the right family extractor.
|
||||
|
||||
Returns an ExtractionResult in all cases — unhandled types and import/extract
|
||||
failures come back as an empty result carrying a warning, so a batch keeps
|
||||
going.
|
||||
"""
|
||||
family = family_for(source)
|
||||
if family is None:
|
||||
return ExtractionResult(
|
||||
extractor="unhandled",
|
||||
warnings=[f"no extractor for extension '.{ext_of(source)}'"],
|
||||
)
|
||||
try:
|
||||
module = importlib.import_module(f".extractors.{family}", package=__package__)
|
||||
except ImportError as e:
|
||||
return ExtractionResult(
|
||||
extractor=f"{family}/unavailable",
|
||||
warnings=[f"extractor '{family}' unavailable (missing dependency): {e}"],
|
||||
)
|
||||
try:
|
||||
return module.extract(source, options)
|
||||
except Exception as e: # isolate: one bad file must not abort the batch
|
||||
logger.warning("extractor '%s' failed on %s: %s", family, source.name, e)
|
||||
return ExtractionResult(
|
||||
extractor=f"{family}/error",
|
||||
warnings=[f"extraction failed: {e}"],
|
||||
)
|
||||
Reference in New Issue
Block a user