Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/cal/journal.py: 61%

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

76 statements  

1""":rfc:`5545` VJOURNAL component.""" 

2 

3from __future__ import annotations 

4 

5import uuid 

6from datetime import date, datetime, timedelta 

7from typing import TYPE_CHECKING, Optional, Sequence 

8 

9from icalendar.attr import ( 

10 attendees_property, 

11 categories_property, 

12 class_property, 

13 color_property, 

14 contacts_property, 

15 create_single_property, 

16 descriptions_property, 

17 exdates_property, 

18 organizer_property, 

19 rdates_property, 

20 rrules_property, 

21 sequence_property, 

22 status_property, 

23 summary_property, 

24 uid_property, 

25 url_property, 

26) 

27from icalendar.cal.component import Component 

28from icalendar.error import IncompleteComponent 

29 

30if TYPE_CHECKING: 

31 from icalendar.enums import CLASS, STATUS 

32 from icalendar.prop import vCalAddress 

33 

34 

35class Journal(Component): 

36 """A descriptive text at a certain time or associated with a component. 

37 

38 Description: 

39 A "VJOURNAL" calendar component is a grouping of 

40 component properties that represent one or more descriptive text 

41 notes associated with a particular calendar date. The "DTSTART" 

42 property is used to specify the calendar date with which the 

43 journal entry is associated. Generally, it will have a DATE value 

44 data type, but it can also be used to specify a DATE-TIME value 

45 data type. Examples of a journal entry include a daily record of 

46 a legislative body or a journal entry of individual telephone 

47 contacts for the day or an ordered list of accomplishments for the 

48 day. 

49 

50 Examples: 

51 Create a new Journal: 

52 

53 >>> from icalendar import Journal 

54 >>> journal = Journal.new() 

55 >>> print(journal.to_ical()) 

56 BEGIN:VJOURNAL 

57 DTSTAMP:20250517T080612Z 

58 UID:d755cef5-2311-46ed-a0e1-6733c9e15c63 

59 END:VJOURNAL 

60 

61 """ 

62 

63 name = "VJOURNAL" 

64 

65 required = ( 

66 "UID", 

67 "DTSTAMP", 

68 ) 

69 singletons = ( 

70 "CLASS", 

71 "COLOR", 

72 "CREATED", 

73 "DTSTART", 

74 "DTSTAMP", 

75 "LAST-MODIFIED", 

76 "ORGANIZER", 

77 "RECURRENCE-ID", 

78 "SEQUENCE", 

79 "STATUS", 

80 "SUMMARY", 

81 "UID", 

82 "URL", 

83 ) 

84 multiple = ( 

85 "ATTACH", 

86 "ATTENDEE", 

87 "CATEGORIES", 

88 "COMMENT", 

89 "CONTACT", 

90 "EXDATE", 

91 "RELATED", 

92 "RDATE", 

93 "RRULE", 

94 "RSTATUS", 

95 "DESCRIPTION", 

96 ) 

97 

98 DTSTART = create_single_property( 

99 "DTSTART", 

100 "dt", 

101 (datetime, date), 

102 date, 

103 'The "DTSTART" property for a "VJOURNAL" that specifies the exact date at which the journal entry was made.', # noqa: E501 

104 ) 

105 

106 @property 

107 def start(self) -> date: 

108 """The start of the Journal. 

109 

110 The "DTSTART" 

111 property is used to specify the calendar date with which the 

112 journal entry is associated. 

113 """ 

114 start = self.DTSTART 

115 if start is None: 

116 raise IncompleteComponent("No DTSTART given.") 

117 return start 

118 

119 @start.setter 

120 def start(self, value: datetime | date) -> None: 

121 """Set the start of the journal.""" 

122 self.DTSTART = value 

123 

124 end = start 

125 

126 @property 

127 def duration(self) -> timedelta: 

128 """The journal has no duration: timedelta(0).""" 

129 return timedelta(0) 

130 

131 color = color_property 

132 sequence = sequence_property 

133 categories = categories_property 

134 rdates = rdates_property 

135 exdates = exdates_property 

136 rrules = rrules_property 

137 uid = uid_property 

138 

139 summary = summary_property 

140 descriptions = descriptions_property 

141 classification = class_property 

142 url = url_property 

143 organizer = organizer_property 

144 contacts = contacts_property 

145 status = status_property 

146 attendees = attendees_property 

147 

148 @property 

149 def description(self) -> str: 

150 """The concatenated descriptions of the journal. 

151 

152 A Journal can have several descriptions. 

153 This is a compatibility method. 

154 """ 

155 descriptions = self.descriptions 

156 if not descriptions: 

157 return None 

158 return "\r\n\r\n".join(descriptions) 

159 

160 @description.setter 

161 def description(self, description: Optional[str]): 

162 """Set the description""" 

163 self.descriptions = description 

164 

165 @description.deleter 

166 def description(self): 

167 """Delete all descriptions.""" 

168 del self.descriptions 

169 

170 @classmethod 

171 def new( 

172 cls, 

173 /, 

174 attendees: Optional[list[vCalAddress]] = None, 

175 categories: Sequence[str] = (), 

176 classification: Optional[CLASS] = None, 

177 color: Optional[str] = None, 

178 comments: list[str] | str | None = None, 

179 contacts: list[str] | str | None = None, 

180 created: Optional[date] = None, 

181 description: Optional[str | Sequence[str]] = None, 

182 last_modified: Optional[date] = None, 

183 organizer: Optional[vCalAddress | str] = None, 

184 sequence: Optional[int] = None, 

185 stamp: Optional[date] = None, 

186 start: Optional[date | datetime] = None, 

187 status: Optional[STATUS] = None, 

188 summary: Optional[str] = None, 

189 uid: Optional[str | uuid.UUID] = None, 

190 url: Optional[str] = None, 

191 ): 

192 """Create a new journal entry with all required properties. 

193 

194 This creates a new Journal in accordance with :rfc:`5545`. 

195 

196 Arguments: 

197 attendees: The :attr:`attendees` of the journal. 

198 categories: The :attr:`categories` of the journal. 

199 classification: The :attr:`classification` of the journal. 

200 color: The :attr:`color` of the journal. 

201 comments: The :attr:`Component.comments` of the journal. 

202 created: The :attr:`Component.created` of the journal. 

203 description: The :attr:`description` of the journal. 

204 end: The :attr:`end` of the journal. 

205 last_modified: The :attr:`Component.last_modified` of the journal. 

206 organizer: The :attr:`organizer` of the journal. 

207 sequence: The :attr:`sequence` of the journal. 

208 stamp: The :attr:`Component.stamp` of the journal. 

209 If None, this is set to the current time. 

210 start: The :attr:`start` of the journal. 

211 status: The :attr:`status` of the journal. 

212 summary: The :attr:`summary` of the journal. 

213 uid: The :attr:`uid` of the journal. 

214 If None, this is set to a new :func:`uuid.uuid4`. 

215 url: The :attr:`url` of the journal. 

216 

217 Returns: 

218 :class:`Journal` 

219 

220 Raises: 

221 InvalidCalendar: If the content is not valid according to :rfc:`5545`. 

222 

223 .. warning:: As time progresses, we will be stricter with the validation. 

224 """ 

225 journal = super().new( 

226 stamp=stamp if stamp is not None else cls._utc_now(), 

227 created=created, 

228 last_modified=last_modified, 

229 comments=comments, 

230 ) 

231 journal.summary = summary 

232 journal.descriptions = description 

233 journal.uid = uid if uid is not None else uuid.uuid4() 

234 journal.start = start 

235 journal.color = color 

236 journal.categories = categories 

237 journal.sequence = sequence 

238 journal.classification = classification 

239 journal.url = url 

240 journal.organizer = organizer 

241 journal.contacts = contacts 

242 journal.start = start 

243 journal.status = status 

244 journal.attendees = attendees 

245 return journal 

246 

247 

248__all__ = ["Journal"]