Coverage for src/kwai/core/domain/value_objects/text.py: 91%
43 statements
« prev ^ index » next coverage.py v7.6.10, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2024-01-01 00:00 +0000
1"""Module that defines a value object for text content."""
3from dataclasses import dataclass, field
4from enum import Enum
5from typing import Self
7from kwai.core.domain.value_objects.owner import Owner
8from kwai.core.domain.value_objects.traceable_time import TraceableTime
11class Locale(Enum):
12 """Value object for a Locale."""
14 NL = "nl"
15 EN = "en"
18class DocumentFormat(Enum):
19 """Value object for a document format."""
21 HTML = "html"
22 MARKDOWN = "md"
25@dataclass(frozen=True, kw_only=True, slots=True)
26class LocaleText:
27 """Value object for text.
29 Several entities, like news stories, trainings, contain text. This value object
30 represents a text for a certain locale.
32 Attributes:
33 locale: The locale of the content.
34 format: The format of the content.
35 title: The title of the content.
36 content: The long text of the content.
37 summary: The summary of the content.
38 author: The author of the content.
39 traceable_time: The creation and modification timestamp of the content.
40 """
42 locale: Locale
43 format: DocumentFormat
44 title: str
45 content: str
46 summary: str
47 author: Owner
48 traceable_time: TraceableTime = field(default_factory=TraceableTime)
51class Text:
52 """A value object containing content in several locales.
54 This class is immutable. A new Text instance will be created and returned when
55 content is added, changed or removed.
56 """
58 def __init__(self, content: dict[Locale, LocaleText] = None):
59 """Initialize the text value object with content.
61 Args:
62 content: A dictionary with content and locale as key.
63 """
64 self._content = {} if content is None else content.copy()
66 def contains_translation(self, locale: Locale) -> bool:
67 """Check if the given locale is available as translation.
69 Returns:
70 True when the translation is available.
71 """
72 return locale in self._content
74 def get_translation(self, locale: Locale) -> LocaleText:
75 """Get a translation.
77 Args:
78 locale: The locale of the content
80 Returns:
81 The content, when available.
83 Raises:
84 KeyError: when the locale is not available.
85 """
86 if locale in self._content:
87 return self._content[locale]
88 raise KeyError(f"{locale} is not found.")
90 def add_translation(self, content: LocaleText) -> "Text":
91 """Add a new translation.
93 Args:
94 content: The translated content.
96 Returns:
97 A new Text value object that also contains the translated content.
99 Raises:
100 KeyError: when a translation already existed.
101 """
102 if content.locale not in self._content:
103 return Text(self._content | {content.locale: content})
105 raise KeyError(f"{content.locale} was already used.")
107 def remove_translation(self, content: LocaleText) -> "Text":
108 """Remove a translation.
110 Args:
111 content: The content to remove.
113 Returns:
114 A new Text value object that also contains the rest of the translated
115 content.
117 Raises:
118 KeyError: when the translation does not exist.
119 """
120 if content.locale not in self._content:
121 raise KeyError(f"{content.locale} is not found.")
122 new_dict = self._content.copy()
123 new_dict.pop(content.locale)
124 return Text(new_dict)
126 def replace_translation(self, content: LocaleText) -> Self:
127 """Replace a translation.
129 Args:
130 content: The content to remove.
132 Returns:
133 A new Text value object that also contains the rest of the translated
134 content.
136 Raises:
137 KeyError: when the translation does not exist.
139 """
140 if content.locale not in self._content:
141 raise KeyError(f"{content.locale} is not found.")
142 return Text(self._content | {content.locale: content})