Coverage for src / local_deep_research / exporters / ris_exporter.py: 100%
31 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-25 01:07 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-25 01:07 +0000
1"""RIS export service.
3This module provides the RISExporter class that wraps the existing
4RISExporter implementation from text_optimization.citation_formatter.
5"""
7from typing import Optional
9from loguru import logger
11from .base import BaseExporter, ExportOptions, ExportResult
12from .registry import ExporterRegistry
14# Maximum content size (50 MB) to prevent OOM errors
15MAX_CONTENT_SIZE = 50 * 1024 * 1024
18@ExporterRegistry.register
19class RISExporter(BaseExporter):
20 """RIS exporter using the existing RISExporter implementation.
22 This exporter extracts references from markdown content and converts
23 them to RIS (Research Information Systems) format, which can be
24 imported into reference managers like Zotero, Mendeley, or EndNote.
25 """
27 def __init__(self):
28 """Initialize RIS exporter."""
29 # Import here to avoid circular imports
30 from ..text_optimization.citation_formatter import (
31 RISExporter as LegacyRISExporter,
32 )
34 self._legacy = LegacyRISExporter()
36 @property
37 def format_name(self) -> str:
38 return "ris"
40 @property
41 def file_extension(self) -> str:
42 return ".ris"
44 @property
45 def mimetype(self) -> str:
46 return "text/plain"
48 def export(
49 self,
50 markdown_content: str,
51 options: Optional[ExportOptions] = None,
52 ) -> ExportResult:
53 """Extract references from markdown and convert to RIS format.
55 Args:
56 markdown_content: The markdown text containing sources/references
57 options: Optional export options (title, metadata)
59 Returns:
60 ExportResult with RIS content as UTF-8 bytes, filename, and mimetype
62 Raises:
63 ValueError: If content exceeds maximum size limit
64 """
65 try:
66 # Check content size limit to prevent OOM errors
67 if len(markdown_content) > MAX_CONTENT_SIZE:
68 raise ValueError(
69 f"Content exceeds maximum size of "
70 f"{MAX_CONTENT_SIZE // (1024 * 1024)} MB"
71 )
73 options = options or ExportOptions()
75 content = self._legacy.export_to_ris(markdown_content)
76 filename = self._generate_safe_filename(options.title)
78 logger.info(f"Generated RIS in memory, size: {len(content)} bytes")
80 return ExportResult(
81 content=content.encode("utf-8"),
82 filename=filename,
83 mimetype=self.mimetype,
84 )
86 except Exception:
87 logger.exception("Error generating RIS")
88 raise