|
| 1 | +from __future__ import annotations |
| 2 | + |
| 3 | +import json |
| 4 | +from pathlib import Path |
| 5 | +from typing import Any |
| 6 | + |
| 7 | +from ..hyphenation_exceptions_collection import HyphenationExceptionsCollection |
| 8 | +from ..hyphenation_override import HyphenationOverride |
| 9 | +from ..pattern import Pattern |
| 10 | +from ..patterns_collection import PatternsCollection |
| 11 | +from .pattern_cache import PatternCache |
| 12 | + |
| 13 | +_CACHE_VERSION = "2.0" |
| 14 | + |
| 15 | + |
| 16 | +class JsonPatternCache(PatternCache): |
| 17 | + def __init__(self, cache_dir: str) -> None: |
| 18 | + self._cache_dir = cache_dir |
| 19 | + |
| 20 | + def has(self, language_code: str) -> bool: |
| 21 | + return Path(self._get_file_path(language_code)).is_file() |
| 22 | + |
| 23 | + def get(self, language_code: str) -> dict[str, Any] | None: |
| 24 | + file_path = self._get_file_path(language_code) |
| 25 | + path = Path(file_path) |
| 26 | + if not path.is_file(): |
| 27 | + return None |
| 28 | + |
| 29 | + try: |
| 30 | + data: dict[str, Any] = json.loads(path.read_text(encoding="utf-8")) |
| 31 | + except (json.JSONDecodeError, OSError): |
| 32 | + return None |
| 33 | + |
| 34 | + if data.get("version") != _CACHE_VERSION: |
| 35 | + return None |
| 36 | + |
| 37 | + patterns = PatternsCollection() |
| 38 | + for p in data["patterns"]: |
| 39 | + patterns.add(Pattern(p["chars"], p["weights"])) |
| 40 | + |
| 41 | + exceptions = HyphenationExceptionsCollection() |
| 42 | + for word, hyphenated in data.get("exceptions", {}).items(): |
| 43 | + exceptions.add(HyphenationOverride(str(word), str(hyphenated))) |
| 44 | + |
| 45 | + return { |
| 46 | + "patterns": patterns, |
| 47 | + "exceptions": exceptions, |
| 48 | + "maxPatternLength": data["maxPatternLength"], |
| 49 | + } |
| 50 | + |
| 51 | + def set(self, language_code: str, data: dict[str, Any]) -> None: |
| 52 | + patterns_col: PatternsCollection = data["patterns"] |
| 53 | + exceptions_col: HyphenationExceptionsCollection = data["exceptions"] |
| 54 | + |
| 55 | + payload: dict[str, Any] = { |
| 56 | + "version": _CACHE_VERSION, |
| 57 | + "patterns": self._serialize_patterns(patterns_col), |
| 58 | + "exceptions": exceptions_col.all(), |
| 59 | + "maxPatternLength": data["maxPatternLength"], |
| 60 | + } |
| 61 | + |
| 62 | + cache_path = Path(self._get_file_path(language_code)) |
| 63 | + cache_path.parent.mkdir(parents=True, exist_ok=True) |
| 64 | + cache_path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8") |
| 65 | + |
| 66 | + def clear(self, language_code: str) -> None: |
| 67 | + path = Path(self._get_file_path(language_code)) |
| 68 | + if path.is_file(): |
| 69 | + path.unlink() |
| 70 | + |
| 71 | + def clear_all(self) -> None: |
| 72 | + cache_dir = Path(self._cache_dir) |
| 73 | + if cache_dir.is_dir(): |
| 74 | + for f in cache_dir.glob("*.json"): |
| 75 | + f.unlink() |
| 76 | + |
| 77 | + def _get_file_path(self, language_code: str) -> str: |
| 78 | + return str(Path(self._cache_dir) / f"syllable.{language_code}.json") |
| 79 | + |
| 80 | + @staticmethod |
| 81 | + def _serialize_patterns(collection: PatternsCollection) -> list[dict[str, Any]]: |
| 82 | + result: list[dict[str, Any]] = [] |
| 83 | + for key, weights in collection.all().items(): |
| 84 | + chars = list(key) |
| 85 | + weight_values = [int(d) for d in weights] |
| 86 | + result.append({"chars": chars, "weights": weight_values}) |
| 87 | + return result |
0 commit comments