Coverage for src / local_deep_research / exporters / ris_exporter.py: 100%
29 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-14 23:55 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-14 23:55 +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
15@ExporterRegistry.register
16class RISExporter(BaseExporter):
17 """RIS exporter using the existing RISExporter implementation.
19 This exporter extracts references from markdown content and converts
20 them to RIS (Research Information Systems) format, which can be
21 imported into reference managers like Zotero, Mendeley, or EndNote.
22 """
24 def __init__(self):
25 """Initialize RIS exporter."""
26 # Import here to avoid circular imports
27 from ..text_optimization.citation_formatter import (
28 RISExporter as LegacyRISExporter,
29 )
31 self._legacy = LegacyRISExporter()
33 @property
34 def format_name(self) -> str:
35 return "ris"
37 @property
38 def file_extension(self) -> str:
39 return ".ris"
41 @property
42 def mimetype(self) -> str:
43 return "text/plain"
45 def export(
46 self,
47 markdown_content: str,
48 options: Optional[ExportOptions] = None,
49 ) -> ExportResult:
50 """Extract references from markdown and convert to RIS format.
52 Args:
53 markdown_content: The markdown text containing sources/references
54 options: Optional export options (title, metadata)
56 Returns:
57 ExportResult with RIS content as UTF-8 bytes, filename, and mimetype
59 Raises:
60 ValueError: If content exceeds maximum size limit
61 """
62 try:
63 # Check content size limit to prevent OOM errors
64 self._validate_content_size(markdown_content)
66 options = options or ExportOptions()
68 content = self._legacy.export_to_ris(markdown_content)
69 filename = self._generate_safe_filename(options.title)
71 logger.info(f"Generated RIS in memory, size: {len(content)} bytes")
73 return ExportResult(
74 content=content.encode("utf-8"),
75 filename=filename,
76 mimetype=self.mimetype,
77 )
79 except Exception:
80 logger.exception("Error generating RIS")
81 raise