async def ingest(
        self, data: str | bytes, **kwargs
    ) -> AsyncGenerator[str, None]:
        """Ingest EPUB data and yield book content."""
        if isinstance(data, str):
            raise ValueError("EPUB data must be in bytes format.")

        from io import BytesIO

        file_obj = BytesIO(data)

        try:
            book = self.epub.open_epub(file_obj)

            # Safely extract metadata
            metadata = []
            for field, label in [
                ("title", "Title"),
                ("creator", "Author"),
                ("language", "Language"),
                ("publisher", "Publisher"),
                ("date", "Date"),
            ]:
                if value := self._safe_get_metadata(book, field):
                    metadata.append(f"{label}: {value}")

            if metadata:
                yield "\n".join(metadata)

            # Extract content from items
            try:
                manifest = getattr(book.opf, "manifest", {}) or {}
                for item in manifest.values():
                    try:
                        if (
                            getattr(item, "mime_type", "")
                            == "application/xhtml+xml"
                        ):
                            if content := book.read_item(item):
                                if cleaned_text := self._clean_text(content):
                                    yield cleaned_text
                    except Exception as e:
                        logger.warning(f"Error processing item: {e}")
                        continue

            except Exception as e:
                logger.warning(f"Error accessing manifest: {e}")
                # Fallback: try to get content directly
                if hasattr(book, "read_item"):
                    for item_id in getattr(book, "items", []):
                        try:
                            if content := book.read_item(item_id):
                                if cleaned_text := self._clean_text(content):
                                    yield cleaned_text
                        except Exception as e:
                            logger.warning(f"Error in fallback reading: {e}")
                            continue

        except Exception as e:
            logger.error(f"Error processing EPUB file: {str(e)}")
            raise ValueError(f"Error processing EPUB file: {str(e)}") from e
        finally:
            try:
                file_obj.close()
            except Exception as e:
                logger.warning(f"Error closing file: {e}")
Ingest EPUB data and yield book content.
py/core/parsers/structured/epub_parser.py