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

84 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 

8 

9from icalendar.attr import ( 

10 CONCEPTS_TYPE_SETTER, 

11 LINKS_TYPE_SETTER, 

12 RELATED_TO_TYPE_SETTER, 

13 attendees_property, 

14 categories_property, 

15 class_property, 

16 color_property, 

17 contacts_property, 

18 create_single_property, 

19 descriptions_property, 

20 exdates_property, 

21 images_property, 

22 organizer_property, 

23 rdates_property, 

24 rrules_property, 

25 sequence_property, 

26 status_property, 

27 summary_property, 

28 uid_property, 

29 url_property, 

30) 

31from icalendar.cal.component import Component 

32from icalendar.cal.examples import get_example 

33from icalendar.error import IncompleteComponent 

34 

35if TYPE_CHECKING: 

36 from collections.abc import Sequence 

37 

38 from icalendar.enums import CLASS, STATUS 

39 from icalendar.prop import vCalAddress 

40 

41 

42class Journal(Component): 

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

44 

45 Description: 

46 A "VJOURNAL" calendar component is a grouping of 

47 component properties that represent one or more descriptive text 

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

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

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

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

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

53 a legislative body or a journal entry of individual telephone 

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

55 day. 

56 

57 Examples: 

58 Create a new Journal: 

59 

60 >>> from icalendar import Journal 

61 >>> journal = Journal.new() 

62 >>> print(journal.to_ical()) 

63 BEGIN:VJOURNAL 

64 DTSTAMP:20250517T080612Z 

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

66 END:VJOURNAL 

67 

68 Get the example Journal. 

69 

70 .. code-block:: pycon 

71 

72 >>> from icalendar import Journal 

73 >>> journal = Journal.example() 

74 >>> print(journal.to_ical().decode()) 

75 BEGIN:VJOURNAL 

76 DESCRIPTION:Aurora project plans were reviewed. 

77 DTSTAMP:19970901T130000Z 

78 DTSTART;VALUE=DATE:19970317 

79 SUMMARY:Staff meeting minutes 

80 UID:19970901T130000Z-123405@example.com 

81 END:VJOURNAL 

82 

83 """ 

84 

85 name = "VJOURNAL" 

86 

87 required = ( 

88 "UID", 

89 "DTSTAMP", 

90 ) 

91 singletons = ( 

92 "CLASS", 

93 "COLOR", 

94 "CREATED", 

95 "DTSTART", 

96 "DTSTAMP", 

97 "LAST-MODIFIED", 

98 "ORGANIZER", 

99 "RECURRENCE-ID", 

100 "SEQUENCE", 

101 "STATUS", 

102 "SUMMARY", 

103 "UID", 

104 "URL", 

105 ) 

106 multiple = ( 

107 "ATTACH", 

108 "ATTENDEE", 

109 "CATEGORIES", 

110 "COMMENT", 

111 "CONTACT", 

112 "EXDATE", 

113 "RELATED", 

114 "RDATE", 

115 "RRULE", 

116 "RSTATUS", 

117 "DESCRIPTION", 

118 ) 

119 

120 DTSTART = create_single_property( 

121 "DTSTART", 

122 "dt", 

123 (datetime, date), 

124 date, 

125 'The "DTSTART" property for a "VJOURNAL" that specifies the exact date at which the journal entry was made.', 

126 ) 

127 

128 @property 

129 def start(self) -> date: 

130 """The start of the Journal. 

131 

132 The "DTSTART" 

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

134 journal entry is associated. 

135 """ 

136 start = self.DTSTART 

137 if start is None: 

138 raise IncompleteComponent("No DTSTART given.") 

139 return start 

140 

141 @start.setter 

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

143 """Set the start of the journal.""" 

144 self.DTSTART = value 

145 

146 end = start 

147 

148 @property 

149 def duration(self) -> timedelta: 

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

151 return timedelta(0) 

152 

153 color = color_property 

154 sequence = sequence_property 

155 categories = categories_property 

156 rdates = rdates_property 

157 exdates = exdates_property 

158 rrules = rrules_property 

159 uid = uid_property 

160 

161 summary = summary_property 

162 descriptions = descriptions_property 

163 classification = class_property 

164 url = url_property 

165 organizer = organizer_property 

166 contacts = contacts_property 

167 status = status_property 

168 attendees = attendees_property 

169 from icalendar.attr import RECURRENCE_ID 

170 

171 @property 

172 def description(self) -> str: 

173 """The concatenated descriptions of the journal. 

174 

175 A Journal can have several descriptions. 

176 This is a compatibility method. 

177 """ 

178 descriptions = self.descriptions 

179 if not descriptions: 

180 return None 

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

182 

183 @description.setter 

184 def description(self, description: str | None): 

185 """Set the description""" 

186 self.descriptions = description 

187 

188 @description.deleter 

189 def description(self): 

190 """Delete all descriptions.""" 

191 del self.descriptions 

192 

193 images = images_property 

194 

195 @classmethod 

196 def new( 

197 cls, 

198 /, 

199 attendees: list[vCalAddress] | None = None, 

200 categories: Sequence[str] = (), 

201 classification: CLASS | None = None, 

202 color: str | None = None, 

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

204 concepts: CONCEPTS_TYPE_SETTER = None, 

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

206 created: date | None = None, 

207 description: str | Sequence[str] | None = None, 

208 last_modified: date | None = None, 

209 links: LINKS_TYPE_SETTER = None, 

210 organizer: vCalAddress | str | None = None, 

211 recurrence_id: date | datetime | None = None, 

212 refids: list[str] | str | None = None, 

213 related_to: RELATED_TO_TYPE_SETTER = None, 

214 sequence: int | None = None, 

215 stamp: date | None = None, 

216 start: date | datetime | None = None, 

217 status: STATUS | None = None, 

218 summary: str | None = None, 

219 uid: str | uuid.UUID | None = None, 

220 url: str | None = None, 

221 ): 

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

223 

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

225 

226 Parameters: 

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

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

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

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

231 comments: The :attr:`~icalendar.Component.comments` of the journal. 

232 concepts: The :attr:`~icalendar.Component.concepts` of the journal. 

233 contacts: The :attr:`contacts` of the journal. 

234 created: The :attr:`~icalendar.Component.created` of the journal. 

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

236 last_modified: The :attr:`~icalendar.Component.last_modified` of 

237 the journal. 

238 links: The :attr:`~icalendar.Component.links` of the journal. 

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

240 recurrence_id: The :attr:`RECURRENCE_ID` of the journal. 

241 refids: :attr:`~icalendar.Component.refids` of the journal. 

242 related_to: :attr:`~icalendar.Component.related_to` of the journal. 

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

244 stamp: The :attr:`~icalendar.Component.stamp` of the journal. 

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

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

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

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

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

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

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

252 

253 Returns: 

254 :class:`Journal` 

255 

256 Raises: 

257 ~error.InvalidCalendar: If the content is not valid 

258 according to :rfc:`5545`. 

259 

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

261 """ 

262 journal: Journal = super().new( 

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

264 created=created, 

265 last_modified=last_modified, 

266 comments=comments, 

267 links=links, 

268 related_to=related_to, 

269 refids=refids, 

270 concepts=concepts, 

271 ) 

272 journal.summary = summary 

273 journal.descriptions = description 

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

275 journal.start = start 

276 journal.color = color 

277 journal.categories = categories 

278 journal.sequence = sequence 

279 journal.classification = classification 

280 journal.url = url 

281 journal.organizer = organizer 

282 journal.contacts = contacts 

283 journal.start = start 

284 journal.status = status 

285 journal.attendees = attendees 

286 journal.RECURRENCE_ID = recurrence_id 

287 

288 return journal 

289 

290 @classmethod 

291 def example(cls, name: str = "example") -> Journal: 

292 """Return the journal example with the given name.""" 

293 return cls.from_ical(get_example("journals", name)) 

294 

295 

296__all__ = ["Journal"]