diff --git a/machine/corpora/file_paratext_project_settings_parser.py b/machine/corpora/file_paratext_project_settings_parser.py index a80f84dc..ddfec490 100644 --- a/machine/corpora/file_paratext_project_settings_parser.py +++ b/machine/corpora/file_paratext_project_settings_parser.py @@ -11,7 +11,7 @@ def __init__(self, project_dir: StrPath) -> None: self._project_dir = Path(project_dir) def _create_stylesheet(self, file_name: StrPath) -> UsfmStylesheet: - custom_stylesheet_filename = self._project_dir / file_name + custom_stylesheet_filename = self._project_dir / "custom.sty" return UsfmStylesheet( file_name, custom_stylesheet_filename if custom_stylesheet_filename.is_file() else None, diff --git a/machine/corpora/zip_paratext_project_settings_parser_base.py b/machine/corpora/zip_paratext_project_settings_parser_base.py index 2c2b8a32..58ef8733 100644 --- a/machine/corpora/zip_paratext_project_settings_parser_base.py +++ b/machine/corpora/zip_paratext_project_settings_parser_base.py @@ -1,4 +1,5 @@ -from tempfile import TemporaryFile +import os +from tempfile import mkstemp from typing import Optional from .paratext_project_settings_parser_base import ParatextProjectSettingsParserBase @@ -7,15 +8,36 @@ class ZipParatextProjectSettingsParserBase(ParatextProjectSettingsParserBase): def _create_stylesheet(self, file_name: str) -> UsfmStylesheet: - with TemporaryFile() as stylesheet_temp_file, TemporaryFile() as custom_stylesheet_temp_file: + stylesheet_temp_path: Optional[str] = None + stylesheet_temp_fd: Optional[int] = None + custom_stylesheet_temp_path: Optional[str] = None + custom_stylesheet_temp_fd: Optional[int] = None + try: stylesheet_path: str = file_name if self._exists(file_name): - with self._open(file_name) as source: + stylesheet_temp_fd, stylesheet_temp_path = mkstemp() + with ( + self._open(file_name) as source, + open(stylesheet_temp_fd, "wb", closefd=False) as stylesheet_temp_file, + ): stylesheet_temp_file.write(source.read()) - stylesheet_path = stylesheet_temp_file.name + stylesheet_path = stylesheet_temp_path custom_stylesheet_path: Optional[str] = None if self._exists("custom.sty"): - with self._open("custom.sty") as source: + custom_stylesheet_temp_fd, custom_stylesheet_temp_path = mkstemp() + with ( + self._open("custom.sty") as source, + open(custom_stylesheet_temp_fd, "wb", closefd=False) as custom_stylesheet_temp_file, + ): custom_stylesheet_temp_file.write(source.read()) - custom_stylesheet_path = custom_stylesheet_temp_file.name + custom_stylesheet_path = custom_stylesheet_temp_path return UsfmStylesheet(stylesheet_path, custom_stylesheet_path) + finally: + if stylesheet_temp_fd is not None: + os.close(stylesheet_temp_fd) + if stylesheet_temp_path is not None: + os.remove(stylesheet_temp_path) + if custom_stylesheet_temp_fd is not None: + os.close(custom_stylesheet_temp_fd) + if custom_stylesheet_temp_path is not None: + os.remove(custom_stylesheet_temp_path) diff --git a/tests/corpora/test_file_paratext_project_settings_parser.py b/tests/corpora/test_file_paratext_project_settings_parser.py new file mode 100644 index 00000000..56bb1fdc --- /dev/null +++ b/tests/corpora/test_file_paratext_project_settings_parser.py @@ -0,0 +1,11 @@ +from testutils.corpora_test_helpers import USFM_TEST_PROJECT_PATH + +from machine.corpora import FileParatextProjectSettingsParser, UsfmStyleType, UsfmTextType + + +def test_parse_custom_stylesheet() -> None: + parser = FileParatextProjectSettingsParser(USFM_TEST_PROJECT_PATH) + settings = parser.parse() + test_tag = settings.stylesheet.get_tag("test") + assert test_tag.style_type is UsfmStyleType.CHARACTER + assert test_tag.text_type is UsfmTextType.OTHER diff --git a/tests/corpora/test_zip_paratext_project_settings_parser.py b/tests/corpora/test_zip_paratext_project_settings_parser.py new file mode 100644 index 00000000..abf300f0 --- /dev/null +++ b/tests/corpora/test_zip_paratext_project_settings_parser.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +from pathlib import Path +from tempfile import TemporaryDirectory +from typing import Any, ContextManager +from zipfile import ZipFile + +from testutils.corpora_test_helpers import create_test_paratext_backup + +from machine.corpora import UsfmStyleType, UsfmTextType, ZipParatextProjectSettingsParser + + +def test_parse_custom_stylesheet() -> None: + with _TestEnvironment() as env: + settings = env.parser.parse() + test_tag = settings.stylesheet.get_tag("test") + assert test_tag.style_type is UsfmStyleType.CHARACTER + assert test_tag.text_type is UsfmTextType.OTHER + + +class _TestEnvironment(ContextManager["_TestEnvironment"]): + def __init__(self) -> None: + self._temp_dir = TemporaryDirectory() + archive_filename = create_test_paratext_backup(Path(self._temp_dir.name)) + self._zip_file = ZipFile(archive_filename) + self._parser = ZipParatextProjectSettingsParser(self._zip_file) + + @property + def parser(self) -> ZipParatextProjectSettingsParser: + return self._parser + + def __enter__(self) -> _TestEnvironment: + return self + + def __exit__(self, type: Any, value: Any, traceback: Any) -> None: + self._zip_file.close() + self._temp_dir.cleanup() diff --git a/tests/testutils/data/usfm/Tes/custom.sty b/tests/testutils/data/usfm/Tes/custom.sty new file mode 100644 index 00000000..24c0602f --- /dev/null +++ b/tests/testutils/data/usfm/Tes/custom.sty @@ -0,0 +1,4 @@ +\Marker test +\Endmarker test* +\TextType Other +\StyleType Character