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

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

70 statements  

1"""This implementes the VAVAILABILITY component. 

2 

3This is specified in :rfc:`7953`. 

4""" 

5 

6from __future__ import annotations 

7 

8import uuid 

9from datetime import datetime 

10from typing import TYPE_CHECKING 

11 

12from icalendar.attr import ( 

13 CONCEPTS_TYPE_SETTER, 

14 LINKS_TYPE_SETTER, 

15 RELATED_TO_TYPE_SETTER, 

16 busy_type_property, 

17 categories_property, 

18 class_property, 

19 contacts_property, 

20 description_property, 

21 duration_property, 

22 location_property, 

23 organizer_property, 

24 priority_property, 

25 rfc_7953_dtend_property, 

26 rfc_7953_dtstart_property, 

27 rfc_7953_duration_property, 

28 rfc_7953_end_property, 

29 sequence_property, 

30 summary_property, 

31 url_property, 

32) 

33from icalendar.cal.examples import get_example 

34from icalendar.error import InvalidCalendar 

35 

36from .component import Component 

37 

38if TYPE_CHECKING: 

39 from collections.abc import Sequence 

40 from datetime import date 

41 

42 from icalendar.cal.available import Available 

43 from icalendar.enums import BUSYTYPE, CLASS 

44 from icalendar.prop import vCalAddress 

45 

46 

47class Availability(Component): 

48 """VAVAILABILITY component from :rfc:`7953`. 

49 

50 This provides a grouping of component properties and 

51 subcomponents that describe the availability associated with a 

52 calendar user. 

53 

54 Description: 

55 A "VAVAILABILITY" component indicates a period of time 

56 within which availability information is provided. A 

57 "VAVAILABILITY" component can specify a start time and an end time 

58 or duration. If "DTSTART" is not present, then the start time is 

59 unbounded. If "DTEND" or "DURATION" are not present, then the end 

60 time is unbounded. Within the specified time period, availability 

61 defaults to a free-busy type of "BUSY-UNAVAILABLE" (see 

62 Section 3.2), except for any time periods corresponding to 

63 "AVAILABLE" subcomponents. 

64 

65 "AVAILABLE" subcomponents are used to indicate periods of free 

66 time within the time range of the enclosing "VAVAILABILITY" 

67 component. "AVAILABLE" subcomponents MAY include recurrence 

68 properties to specify recurring periods of time, which can be 

69 overridden using normal iCalendar recurrence behavior (i.e., use 

70 of the "RECURRENCE-ID" property). 

71 

72 If specified, the "DTSTART" and "DTEND" properties in 

73 "VAVAILABILITY" components and "AVAILABLE" subcomponents MUST be 

74 "DATE-TIME" values specified as either the date with UTC time or 

75 the date with local time and a time zone reference. 

76 

77 The iCalendar object containing the "VAVAILABILITY" component MUST 

78 contain appropriate "VTIMEZONE" components corresponding to each 

79 unique "TZID" parameter value used in any DATE-TIME properties in 

80 all components, unless [RFC7809] is in effect. 

81 

82 When used to publish available time, the "ORGANIZER" property 

83 specifies the calendar user associated with the published 

84 available time. 

85 

86 If the "PRIORITY" property is specified in "VAVAILABILITY" 

87 components, it is used to determine how that component is combined 

88 with other "VAVAILABILITY" components. See Section 4. 

89 

90 Other calendar properties MAY be specified in "VAVAILABILITY" or 

91 "AVAILABLE" components and are considered attributes of the marked 

92 block of time. Their usage is application specific. For example, 

93 the "LOCATION" property might be used to indicate that a person is 

94 available in one location for part of the week and a different 

95 location for another part of the week (but see Section 9 for when 

96 it is appropriate to add additional data like this). 

97 

98 Example: 

99 The following is an example of a "VAVAILABILITY" calendar 

100 component used to represent the availability of a user, always 

101 available Monday through Friday, 9:00 am to 5:00 pm in the 

102 America/Montreal time zone: 

103 

104 .. code-block:: text 

105 

106 BEGIN:VAVAILABILITY 

107 ORGANIZER:mailto:bernard@example.com 

108 UID:0428C7D2-688E-4D2E-AC52-CD112E2469DF 

109 DTSTAMP:20111005T133225Z 

110 BEGIN:AVAILABLE 

111 UID:34EDA59B-6BB1-4E94-A66C-64999089C0AF 

112 SUMMARY:Monday to Friday from 9:00 to 17:00 

113 DTSTART;TZID=America/Montreal:20111002T090000 

114 DTEND;TZID=America/Montreal:20111002T170000 

115 RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR 

116 END:AVAILABLE 

117 END:VAVAILABILITY 

118 

119 You can get the same example from :meth:`example`: 

120 

121 .. code-block: pycon 

122 

123 >>> from icalendar import Availability 

124 >>> a = Availability.example() 

125 >>> a.organizer 

126 vCalAddress('mailto:bernard@example.com') 

127 

128 The following is an example of a "VAVAILABILITY" calendar 

129 component used to represent the availability of a user available 

130 Monday through Thursday, 9:00 am to 5:00 pm, at the main office, 

131 and Friday, 9:00 am to 12:00 pm, in the branch office in the 

132 America/Montreal time zone between October 2nd and December 2nd 

133 2011: 

134 

135 .. code-block:: text 

136 

137 BEGIN:VAVAILABILITY 

138 ORGANIZER:mailto:bernard@example.com 

139 UID:84D0F948-7FC6-4C1D-BBF3-BA9827B424B5 

140 DTSTAMP:20111005T133225Z 

141 DTSTART;TZID=America/Montreal:20111002T000000 

142 DTEND;TZID=America/Montreal:20111202T000000 

143 BEGIN:AVAILABLE 

144 UID:7B33093A-7F98-4EED-B381-A5652530F04D 

145 SUMMARY:Monday to Thursday from 9:00 to 17:00 

146 DTSTART;TZID=America/Montreal:20111002T090000 

147 DTEND;TZID=America/Montreal:20111002T170000 

148 RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH 

149 LOCATION:Main Office 

150 END:AVAILABLE 

151 BEGIN:AVAILABLE 

152 UID:DF39DC9E-D8C3-492F-9101-0434E8FC1896 

153 SUMMARY:Friday from 9:00 to 12:00 

154 DTSTART;TZID=America/Montreal:20111006T090000 

155 DTEND;TZID=America/Montreal:20111006T120000 

156 RRULE:FREQ=WEEKLY 

157 LOCATION:Branch Office 

158 END:AVAILABLE 

159 END:VAVAILABILITY 

160 

161 For more examples, have a look at :rfc:`5545`. 

162 

163 """ 

164 

165 name = "VAVAILABILITY" 

166 

167 canonical_order = ( 

168 "DTSTART", 

169 "DTEND", 

170 "DURATION", 

171 "DTSTAMP", 

172 "UID", 

173 "SEQUENCE", 

174 "SUMMARY", 

175 "DESCRIPTION", 

176 "ORGANIZER", 

177 ) 

178 

179 required = ( 

180 "DTSTART", 

181 "DTSTAMP", 

182 "UID", 

183 ) 

184 

185 singletons = ( 

186 "DTSTAMP", 

187 "UID", 

188 "BUSYTYPE", 

189 "CLASS", 

190 "CREATED", 

191 "DESCRIPTION", 

192 "DTSTART", 

193 "LAST-MODIFIED", 

194 "LOCATION", 

195 "ORGANIZER", 

196 "PRIORITY", 

197 "SEQUENCE", 

198 "SUMMARY", 

199 "URL", 

200 "DTEND", 

201 "DURATION", 

202 ) 

203 

204 exclusive = ( 

205 "DTEND", 

206 "DURATION", 

207 ) 

208 

209 organizer = organizer_property 

210 busy_type = busy_type_property 

211 summary = summary_property 

212 description = description_property 

213 sequence = sequence_property 

214 classification = class_property 

215 url = url_property 

216 location = location_property 

217 categories = categories_property 

218 priority = priority_property 

219 contacts = contacts_property 

220 

221 start = DTSTART = rfc_7953_dtstart_property 

222 DTEND = rfc_7953_dtend_property 

223 DURATION = duration_property("Availability") 

224 duration = rfc_7953_duration_property 

225 end = rfc_7953_end_property 

226 

227 @property 

228 def available(self) -> list[Available]: 

229 """All VAVAILABLE sub-components. 

230 

231 This is a shortcut to get all VAVAILABLE sub-components. 

232 Modifications do not change the calendar. 

233 Use :py:meth:`Component.add_component`. 

234 """ 

235 return self.walk("AVAILABLE") 

236 

237 @classmethod 

238 def new( 

239 cls, 

240 /, 

241 busy_type: BUSYTYPE | None = None, 

242 categories: Sequence[str] = (), 

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

244 components: Sequence[Available] | None = (), 

245 concepts: CONCEPTS_TYPE_SETTER = None, 

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

247 created: date | None = None, 

248 classification: CLASS | None = None, 

249 description: str | None = None, 

250 end: datetime | None = None, 

251 last_modified: date | None = None, 

252 links: LINKS_TYPE_SETTER = None, 

253 location: str | None = None, 

254 organizer: vCalAddress | str | None = None, 

255 priority: int | None = None, 

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

257 related_to: RELATED_TO_TYPE_SETTER = None, 

258 sequence: int | None = None, 

259 stamp: date | None = None, 

260 start: datetime | None = None, 

261 summary: str | None = None, 

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

263 url: str | None = None, 

264 ): 

265 """Create a new event with all required properties. 

266 

267 This creates a new Availability in accordance with :rfc:`7953`. 

268 

269 Parameters: 

270 busy_type: The :attr:`busy_type` of the availability. 

271 categories: The :attr:`categories` of the availability. 

272 classification: The :attr:`classification` of the availability. 

273 comments: The :attr:`comments` of the availability. 

274 concepts: The :attr:`concepts` of the availability. 

275 contacts: The :attr:`contacts` of the availability. 

276 created: The :attr:`created` of the availability. 

277 description: The :attr:`description` of the availability. 

278 end: The :attr:`end` of the availability. 

279 last_modified: The :attr:`last_modified` of the 

280 availability. 

281 links: The :attr:`links` of the availability. 

282 location: The :attr:`location` of the availability. 

283 organizer: The :attr:`organizer` of the availability. 

284 refids: :attr:`refids` of the availability. 

285 related_to: :attr:`related_to` of the availability. 

286 sequence: The :attr:`sequence` of the availability. 

287 stamp: The :attr:`stamp` of the availability. 

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

289 start: The :attr:`start` of the availability. 

290 summary: The :attr:`summary` of the availability. 

291 uid: The :attr:`uid` of the availability. 

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

293 url: The :attr:`url` of the availability. 

294 

295 Returns: 

296 :class:`Availability` 

297 

298 Raises: 

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

300 according to :rfc:`7953`. 

301 

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

303 """ 

304 availability: Availability = super().new( 

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

306 created=created, 

307 comments=comments, 

308 last_modified=last_modified, 

309 links=links, 

310 related_to=related_to, 

311 refids=refids, 

312 concepts=concepts, 

313 ) 

314 availability.summary = summary 

315 availability.description = description 

316 availability.uid = uid if uid is not None else uuid.uuid4() 

317 availability.sequence = sequence 

318 availability.categories = categories 

319 availability.classification = classification 

320 availability.url = url 

321 availability.busy_type = busy_type 

322 availability.organizer = organizer 

323 availability.location = location 

324 availability.priority = priority 

325 availability.contacts = contacts 

326 for subcomponent in components: 

327 availability.add_component(subcomponent) 

328 if cls._validate_new: 

329 if start is not None and ( 

330 not isinstance(start, datetime) or start.tzinfo is None 

331 ): 

332 raise InvalidCalendar( 

333 "Availability start must be a datetime with a timezone" 

334 ) 

335 if end is not None and ( 

336 not isinstance(end, datetime) or end.tzinfo is None 

337 ): 

338 raise InvalidCalendar( 

339 "Availability end must be a datetime with a timezone" 

340 ) 

341 availability._validate_start_and_end(start, end) 

342 availability.start = start 

343 availability.end = end 

344 return availability 

345 

346 @classmethod 

347 def example(cls, name: str = "rfc_7953_1") -> Availability: 

348 """Return the calendar example with the given name.""" 

349 return cls.from_ical(get_example("availabilities", name)) 

350 

351 

352__all__ = ["Availability"]