Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/prop/text.py: 63%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

52 statements  

1"""TEXT values from :rfc:`5545`.""" 

2 

3from typing import Any, ClassVar 

4 

5from icalendar.compatibility import Self 

6from icalendar.error import JCalParsingError 

7from icalendar.parser import Parameters, _escape_char 

8from icalendar.parser_tools import DEFAULT_ENCODING, ICAL_TYPE, to_unicode 

9 

10 

11class vText(str): 

12 r"""vText is a data type that contains human-readable text values. 

13 

14 The vText property uses the :rfc:`5545#section-3.3.11` TEXT value type 

15 in various icalendar properties to show free-form text that others can read. 

16 This class can be created from Python strings, and can be used to add text 

17 descriptions to calendar events. 

18 

19 To create a TEXT object, pass in the string you want when creating the 

20 object. 

21 

22 To add a line break, use ``\n`` or ``\N``. 

23 

24 Use the LANGUAGE property parameter to set the language of the text. 

25 

26 When the TEXT object is serialized to an icalendar stream, certain 

27 characters are escaped or changed. 

28 These characters include the COMMA, SEMICOLON, BACKSLASH, and line breaks. 

29 

30 Contrast TEXT with the UNKNOWN value data type specified in :rfc:`7265#section-5`. 

31 UNKNOWN is implemented in the Python class :class:`~icalendar.prop.unknown.vUnknown`, 

32 which does **not** apply this escaping and preserves its value verbatim, 

33 because the escaping rules of an unrecognized value type are not known. 

34 :class:`~icalendar.prop.unknown.vUnknown` deliberately does not inherit from 

35 ``vText``, so the two don't share escaping behavior. 

36 

37 Examples: 

38 

39 vText property as a TEXT value type. 

40 

41 .. code-block:: text 

42 

43 Project XYZ Final Review\nConference Room - 3B\nCome Prepared. 

44 

45 Create a vText property, and display it in a readable format. 

46 

47 .. code-block:: pycon 

48 

49 >>> from icalendar.prop import vText 

50 >>> desc = 'Project XYZ Final Review\nConference Room - 3B\nCome Prepared.' 

51 >>> text = vText(desc) 

52 >>> text 

53 vText(b'Project XYZ Final Review\\nConference Room - 3B\\nCome Prepared.') 

54 >>> print(text.ical_value) 

55 Project XYZ Final Review 

56 Conference Room - 3B 

57 Come Prepared. 

58 

59 Add a SUMMARY to an event, then display its value as a vText property then in a readable format: 

60 

61 .. code-block:: pycon 

62 

63 >>> from icalendar import Event 

64 >>> event = Event() 

65 >>> event.add('SUMMARY', desc) 

66 >>> event['SUMMARY'] 

67 vText(b'Project XYZ Final Review\\nConference Room - 3B\\nCome Prepared.') 

68 >>> print(event.to_ical().decode()) 

69 BEGIN:VEVENT 

70 SUMMARY:Project XYZ Final Review\nConference Room - 3B\nCome Prepared. 

71 END:VEVENT 

72 

73 """ 

74 

75 default_value: ClassVar[str] = "TEXT" 

76 params: Parameters 

77 __slots__ = ("encoding", "params") 

78 

79 def __new__( 

80 cls, 

81 value: ICAL_TYPE, 

82 encoding: str = DEFAULT_ENCODING, 

83 /, 

84 params: dict[str, Any] | None = None, 

85 ) -> Self: 

86 value = to_unicode(value, encoding=encoding) 

87 self = super().__new__(cls, value) 

88 self.encoding = encoding 

89 self.params = Parameters(params) 

90 return self 

91 

92 def __repr__(self) -> str: 

93 return f"{self.__class__.__name__}({self.to_ical()!r})" 

94 

95 def to_ical(self) -> bytes: 

96 return _escape_char(self).encode(self.encoding) 

97 

98 @classmethod 

99 def from_ical(cls, ical: ICAL_TYPE) -> Self: 

100 return cls(ical) 

101 

102 @property 

103 def ical_value(self) -> str: 

104 """The string value of the text.""" 

105 return str(self) 

106 

107 from icalendar.param import ALTREP, GAP, LANGUAGE, RELTYPE, VALUE 

108 

109 def to_jcal(self, name: str) -> list: 

110 """The jCal representation of this property according to :rfc:`7265`.""" 

111 if name == "request-status": # TODO: maybe add a vRequestStatus class? 

112 return [name, {}, "text", self.split(";", 2)] 

113 return [name, self.params.to_jcal(), self.VALUE.lower(), str(self)] 

114 

115 @classmethod 

116 def examples(cls) -> list[Self]: 

117 """Examples of vText.""" 

118 return [cls("Hello World!")] 

119 

120 @classmethod 

121 def from_jcal(cls, jcal_property: list) -> Self: 

122 """Parse jCal from :rfc:`7265`. 

123 

124 Parameters: 

125 jcal_property: The jCal property to parse. 

126 

127 Raises: 

128 ~error.JCalParsingError: If the provided jCal is invalid. 

129 """ 

130 JCalParsingError.validate_property(jcal_property, cls) 

131 name = jcal_property[0] 

132 if name == "categories": 

133 from icalendar.prop import vCategory 

134 

135 return vCategory.from_jcal(jcal_property) 

136 string = jcal_property[3] # TODO: accept list or string but join with ; 

137 if name == "request-status": # TODO: maybe add a vRequestStatus class? 

138 JCalParsingError.validate_list_type(jcal_property[3], str, cls, 3) 

139 string = ";".join(jcal_property[3]) 

140 JCalParsingError.validate_value_type(string, str, cls, 3) 

141 return cls( 

142 string, 

143 params=Parameters.from_jcal_property(jcal_property), 

144 ) 

145 

146 @classmethod 

147 def parse_jcal_value(cls, jcal_value: Any) -> Self: 

148 """Parse a jCal value into a vText.""" 

149 JCalParsingError.validate_value_type(jcal_value, (str, int, float), cls) 

150 return cls(str(jcal_value)) 

151 

152 

153__all__ = ["vText"]