Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## rtflite 2.3.1

### New features

- Added `executable_path` parameter to write_docx() method.
- Added `/tmp/soffice` and `/tmp/libreoffice` paths for Linux.

## rtflite 2.3.0

### New features
Expand Down
7 changes: 7 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## rtflite 2.3.1

### New features

- Added `executable_path` parameter to write_docx() method.
- Added `/tmp/soffice` and `/tmp/libreoffice` paths for Linux.

## rtflite 2.3.0

### New features
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "rtflite"
version = "2.3.0"
version = "2.3.1"
description = "Lightweight RTF composer for Python"
authors = [
{ name = "Yilong Zhang", email = "[email protected]" },
Expand Down
2 changes: 2 additions & 0 deletions src/rtflite/dictionary/libreoffice.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"/Applications/LibreOffice.app/Contents/MacOS/soffice",
],
"Linux": [
"/tmp/soffice",
"/tmp/libreoffice",
"/usr/bin/soffice",
"/usr/bin/libreoffice",
"/snap/bin/libreoffice",
Expand Down
8 changes: 6 additions & 2 deletions src/rtflite/encode.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,9 @@ def write_rtf(self, file_path: str | Path) -> None:
rtf_code = self.rtf_encode()
target_path.write_text(rtf_code, encoding="utf-8")

def write_docx(self, file_path: str | Path) -> None:
def write_docx(
self, file_path: str | Path, executable_path: str | None = None
) -> None:
"""Write the document as a DOCX file.

Writes the document to a temporary RTF file first, and then converts
Expand All @@ -458,6 +460,8 @@ def write_docx(self, file_path: str | Path) -> None:
file_path: Destination path for the DOCX file.
Accepts string or Path input. Can be absolute or relative.
Directories are created if they do not already exist.
executable_path: Optional path to the LibreOffice executable.
If not provided, the default system path will be used.

Examples:
```python
Expand All @@ -476,7 +480,7 @@ def write_docx(self, file_path: str | Path) -> None:
rtf_code = self.rtf_encode()
rtf_path.write_text(rtf_code, encoding="utf-8")

converter = LibreOfficeConverter()
converter = LibreOfficeConverter(executable_path=executable_path)
with tempfile.TemporaryDirectory() as convert_tmpdir:
docx_path = converter.convert(
input_files=rtf_path,
Expand Down
47 changes: 47 additions & 0 deletions tests/test_write_docx_args.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from pathlib import Path
from unittest.mock import patch

import polars as pl
import pytest

from rtflite.encode import RTFDocument
from rtflite.input import RTFBody, RTFTitle


@pytest.fixture
def sample_document() -> RTFDocument:
"""Create a small RTFDocument for DOCX export tests."""
df = pl.DataFrame({"A": ["alpha"]})
return RTFDocument(
df=df,
rtf_title=RTFTitle(text="Sample Title"),
rtf_body=RTFBody(col_rel_width=[1]),
)


@patch("rtflite.encode.LibreOfficeConverter")
def test_write_docx_passes_executable_path(
mock_converter_cls, sample_document, tmp_path
):
"""Verify that executable_path is correctly passed to LibreOfficeConverter."""
# Setup mock
mock_instance = mock_converter_cls.return_value
mock_instance.convert.return_value = Path("dummy.docx")

# Create dummy docx file that would be moved
output_path = tmp_path / "output.docx"

# We need to mock shutil.move as well since the converter is mocked
# and won't actually create files
with patch("shutil.move"):
sample_document.write_docx(
output_path, executable_path="/custom/path/to/soffice"
)

# Verify LibreOfficeConverter was initialized with the correct path
mock_converter_cls.assert_called_once_with(
executable_path="/custom/path/to/soffice"
)

# Verify convert was called
mock_instance.convert.assert_called_once()
Loading