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

1"""Module that defines a value object for text content.""" 

2 

3from dataclasses import dataclass, field 

4from enum import Enum 

5from typing import Self 

6 

7from kwai.core.domain.value_objects.owner import Owner 

8from kwai.core.domain.value_objects.traceable_time import TraceableTime 

9 

10 

11class Locale(Enum): 

12 """Value object for a Locale.""" 

13 

14 NL = "nl" 

15 EN = "en" 

16 

17 

18class DocumentFormat(Enum): 

19 """Value object for a document format.""" 

20 

21 HTML = "html" 

22 MARKDOWN = "md" 

23 

24 

25@dataclass(frozen=True, kw_only=True, slots=True) 

26class LocaleText: 

27 """Value object for text. 

28 

29 Several entities, like news stories, trainings, contain text. This value object 

30 represents a text for a certain locale. 

31 

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 """ 

41 

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) 

49 

50 

51class Text: 

52 """A value object containing content in several locales. 

53 

54 This class is immutable. A new Text instance will be created and returned when 

55 content is added, changed or removed. 

56 """ 

57 

58 def __init__(self, content: dict[Locale, LocaleText] = None): 

59 """Initialize the text value object with content. 

60 

61 Args: 

62 content: A dictionary with content and locale as key. 

63 """ 

64 self._content = {} if content is None else content.copy() 

65 

66 def contains_translation(self, locale: Locale) -> bool: 

67 """Check if the given locale is available as translation. 

68 

69 Returns: 

70 True when the translation is available. 

71 """ 

72 return locale in self._content 

73 

74 def get_translation(self, locale: Locale) -> LocaleText: 

75 """Get a translation. 

76 

77 Args: 

78 locale: The locale of the content 

79 

80 Returns: 

81 The content, when available. 

82 

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.") 

89 

90 def add_translation(self, content: LocaleText) -> "Text": 

91 """Add a new translation. 

92 

93 Args: 

94 content: The translated content. 

95 

96 Returns: 

97 A new Text value object that also contains the translated content. 

98 

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}) 

104 

105 raise KeyError(f"{content.locale} was already used.") 

106 

107 def remove_translation(self, content: LocaleText) -> "Text": 

108 """Remove a translation. 

109 

110 Args: 

111 content: The content to remove. 

112 

113 Returns: 

114 A new Text value object that also contains the rest of the translated 

115 content. 

116 

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) 

125 

126 def replace_translation(self, content: LocaleText) -> Self: 

127 """Replace a translation. 

128 

129 Args: 

130 content: The content to remove. 

131 

132 Returns: 

133 A new Text value object that also contains the rest of the translated 

134 content. 

135 

136 Raises: 

137 KeyError: when the translation does not exist. 

138 

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})