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

77 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 images_property, 

19 organizer_property, 

20 rdates_property, 

21 rrules_property, 

22 sequence_property, 

23 status_property, 

24 summary_property, 

25 uid_property, 

26 url_property, 

27) 

28from icalendar.cal.component import Component 

29from icalendar.error import IncompleteComponent 

30 

31if TYPE_CHECKING: 

32 from icalendar.enums import CLASS, STATUS 

33 from icalendar.prop import vCalAddress 

34 

35 

36class Journal(Component): 

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

38 

39 Description: 

40 A "VJOURNAL" calendar component is a grouping of 

41 component properties that represent one or more descriptive text 

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

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

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

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

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

47 a legislative body or a journal entry of individual telephone 

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

49 day. 

50 

51 Examples: 

52 Create a new Journal: 

53 

54 >>> from icalendar import Journal 

55 >>> journal = Journal.new() 

56 >>> print(journal.to_ical()) 

57 BEGIN:VJOURNAL 

58 DTSTAMP:20250517T080612Z 

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

60 END:VJOURNAL 

61 

62 """ 

63 

64 name = "VJOURNAL" 

65 

66 required = ( 

67 "UID", 

68 "DTSTAMP", 

69 ) 

70 singletons = ( 

71 "CLASS", 

72 "COLOR", 

73 "CREATED", 

74 "DTSTART", 

75 "DTSTAMP", 

76 "LAST-MODIFIED", 

77 "ORGANIZER", 

78 "RECURRENCE-ID", 

79 "SEQUENCE", 

80 "STATUS", 

81 "SUMMARY", 

82 "UID", 

83 "URL", 

84 ) 

85 multiple = ( 

86 "ATTACH", 

87 "ATTENDEE", 

88 "CATEGORIES", 

89 "COMMENT", 

90 "CONTACT", 

91 "EXDATE", 

92 "RELATED", 

93 "RDATE", 

94 "RRULE", 

95 "RSTATUS", 

96 "DESCRIPTION", 

97 ) 

98 

99 DTSTART = create_single_property( 

100 "DTSTART", 

101 "dt", 

102 (datetime, date), 

103 date, 

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

105 ) 

106 

107 @property 

108 def start(self) -> date: 

109 """The start of the Journal. 

110 

111 The "DTSTART" 

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

113 journal entry is associated. 

114 """ 

115 start = self.DTSTART 

116 if start is None: 

117 raise IncompleteComponent("No DTSTART given.") 

118 return start 

119 

120 @start.setter 

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

122 """Set the start of the journal.""" 

123 self.DTSTART = value 

124 

125 end = start 

126 

127 @property 

128 def duration(self) -> timedelta: 

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

130 return timedelta(0) 

131 

132 color = color_property 

133 sequence = sequence_property 

134 categories = categories_property 

135 rdates = rdates_property 

136 exdates = exdates_property 

137 rrules = rrules_property 

138 uid = uid_property 

139 

140 summary = summary_property 

141 descriptions = descriptions_property 

142 classification = class_property 

143 url = url_property 

144 organizer = organizer_property 

145 contacts = contacts_property 

146 status = status_property 

147 attendees = attendees_property 

148 

149 @property 

150 def description(self) -> str: 

151 """The concatenated descriptions of the journal. 

152 

153 A Journal can have several descriptions. 

154 This is a compatibility method. 

155 """ 

156 descriptions = self.descriptions 

157 if not descriptions: 

158 return None 

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

160 

161 @description.setter 

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

163 """Set the description""" 

164 self.descriptions = description 

165 

166 @description.deleter 

167 def description(self): 

168 """Delete all descriptions.""" 

169 del self.descriptions 

170 

171 images = images_property 

172 

173 @classmethod 

174 def new( 

175 cls, 

176 /, 

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

178 categories: Sequence[str] = (), 

179 classification: Optional[CLASS] = None, 

180 color: Optional[str] = None, 

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

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

183 created: Optional[date] = None, 

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

185 last_modified: Optional[date] = None, 

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

187 sequence: Optional[int] = None, 

188 stamp: Optional[date] = None, 

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

190 status: Optional[STATUS] = None, 

191 summary: Optional[str] = None, 

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

193 url: Optional[str] = None, 

194 ): 

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

196 

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

198 

199 Arguments: 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

219 

220 Returns: 

221 :class:`Journal` 

222 

223 Raises: 

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

225 

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

227 """ 

228 journal = super().new( 

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

230 created=created, 

231 last_modified=last_modified, 

232 comments=comments, 

233 ) 

234 journal.summary = summary 

235 journal.descriptions = description 

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

237 journal.start = start 

238 journal.color = color 

239 journal.categories = categories 

240 journal.sequence = sequence 

241 journal.classification = classification 

242 journal.url = url 

243 journal.organizer = organizer 

244 journal.contacts = contacts 

245 journal.start = start 

246 journal.status = status 

247 journal.attendees = attendees 

248 return journal 

249 

250 

251__all__ = ["Journal"]