muryshev's picture
update
86c402d
raw
history blame
6.21 kB
"""
Модуль с абстрактным классом парсера.
"""
import os
from abc import ABC, abstractmethod
from typing import BinaryIO
from ..data_classes import ParsedDocument
from .file_types import FileType
class AbstractParser(ABC):
"""
Абстрактный класс парсера документов.
Все конкретные парсеры должны наследоваться от этого класса
и реализовывать метод parse.
"""
def __init__(self, file_types: FileType | list[FileType] | str | list[str] | None = None):
"""
Инициализирует парсер.
Args:
file_types: Поддерживаемые типы файлов. Может быть одним из:
- FileType - объект перечисления
- list[FileType] - список объектов перечисления
- str - строка с расширением файла (с точкой, например ".xml")
- list[str] - список строк с расширениями
- None - если не указан, парсер не ограничен типами
"""
self.file_types = []
if file_types is None:
return
# Преобразуем одиночный FileType в список
if isinstance(file_types, FileType):
self.file_types = [file_types]
# Преобразуем список FileType в список
elif isinstance(file_types, list) and all(isinstance(ft, FileType) for ft in file_types):
self.file_types = file_types
# Преобразуем строку расширения в FileType
elif isinstance(file_types, str):
try:
self.file_types = [FileType.from_extension(file_types)]
except ValueError:
# Если не удалось найти подходящий FileType, создаем пустой список
self.file_types = []
# Преобразуем список строк расширений в список FileType
elif isinstance(file_types, list) and all(isinstance(ft, str) for ft in file_types):
self.file_types = []
for ext in file_types:
try:
self.file_types.append(FileType.from_extension(ext))
except ValueError:
pass
def _supported_extension(self, ext: str) -> bool:
"""
Проверяет, поддерживается ли расширение файла.
Этот метод должен быть переопределен в наследниках
для указания поддерживаемых расширений.
Args:
ext (str): Расширение файла с точкой (.pdf, .docx и т.д.).
Returns:
bool: True, если расширение поддерживается, иначе False.
"""
if not self.file_types:
try:
FileType.from_extension(ext)
return True
except ValueError:
return False
ext = ext.lower()
for file_type in self.file_types:
for supported_ext in file_type.value:
if ext == supported_ext.lower():
return True
return False
def supports_file(self, file: str | BinaryIO | FileType) -> bool:
"""
Проверяет, может ли парсер обработать файл.
Args:
file: Может быть одним из:
- str: Путь к файлу
- BinaryIO: Объект файла
- FileType: Конкретный тип файла
Returns:
bool: True, если парсер поддерживает файл, иначе False.
"""
# Если передан FileType, проверяем его наличие в списке поддерживаемых
if isinstance(file, FileType):
return file in self.file_types
# Если переданы пустые file_types и не строка, не можем определить тип
if not self.file_types and not isinstance(file, str):
return False
# Если передан путь к файлу, проверяем расширение
if isinstance(file, str):
_, ext = os.path.splitext(file)
return self._supported_extension(ext)
# Если передан бинарный объект, считаем что подходит
# (конкретный тип будет проверен при вызове parse)
return True
@abstractmethod
def parse(self, file: BinaryIO, file_type: FileType | None = None) -> ParsedDocument:
"""
Парсит документ из объекта файла и возвращает его структурное представление.
Args:
file (BinaryIO): Объект файла для парсинга.
file_type (FileType | None): Тип файла, если известен.
Returns:
ParsedDocument: Структурное представление документа.
"""
pass
@abstractmethod
def parse_by_path(self, file_path: str) -> ParsedDocument:
"""
Парсит документ по пути к файлу и возвращает его структурное представление.
Args:
file_path (str): Путь к файлу для парсинга.
Returns:
ParsedDocument: Структурное представление документа.
"""
pass