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

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

71 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 Iterable, Sequence 

40 from datetime import date 

41 

42 from icalendar.cal import Available 

43 from icalendar.compatibility import Self 

44 from icalendar.enums import BUSYTYPE, CLASS 

45 from icalendar.prop import vCalAddress 

46 

47 

48class Availability(Component): 

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

50 

51 This provides a grouping of component properties and 

52 subcomponents that describe the availability associated with a 

53 calendar user. 

54 

55 Description: 

56 A "VAVAILABILITY" component indicates a period of time 

57 within which availability information is provided. A 

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

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

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

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

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

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

64 "AVAILABLE" subcomponents. 

65 

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

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

68 component. "AVAILABLE" subcomponents MAY include recurrence 

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

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

71 of the "RECURRENCE-ID" property). 

72 

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

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

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

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

77 

78 The iCalendar object containing the "VAVAILABILITY" component MUST 

79 contain appropriate "VTIMEZONE" components corresponding to each 

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

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

82 

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

84 specifies the calendar user associated with the published 

85 available time. 

86 

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

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

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

90 

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

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

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

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

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

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

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

98 

99 Example: 

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

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

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

103 America/Montreal time zone: 

104 

105 .. code-block:: ics 

106 

107 BEGIN:VAVAILABILITY 

108 ORGANIZER:mailto:bernard@example.com 

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

110 DTSTAMP:20111005T133225Z 

111 BEGIN:AVAILABLE 

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

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

114 DTSTART;TZID=America/Montreal:20111002T090000 

115 DTEND;TZID=America/Montreal:20111002T170000 

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

117 END:AVAILABLE 

118 END:VAVAILABILITY 

119 

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

121 

122 .. code-block: pycon 

123 

124 >>> from icalendar import Availability 

125 >>> a = Availability.example() 

126 >>> a.organizer 

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

128 

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

130 component used to represent the availability of a user available 

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

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

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

134 2011: 

135 

136 .. code-block:: ics 

137 

138 BEGIN:VAVAILABILITY 

139 ORGANIZER:mailto:bernard@example.com 

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

141 DTSTAMP:20111005T133225Z 

142 DTSTART;TZID=America/Montreal:20111002T000000 

143 DTEND;TZID=America/Montreal:20111202T000000 

144 BEGIN:AVAILABLE 

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

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

147 DTSTART;TZID=America/Montreal:20111002T090000 

148 DTEND;TZID=America/Montreal:20111002T170000 

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

150 LOCATION:Main Office 

151 END:AVAILABLE 

152 BEGIN:AVAILABLE 

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

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

155 DTSTART;TZID=America/Montreal:20111006T090000 

156 DTEND;TZID=America/Montreal:20111006T120000 

157 RRULE:FREQ=WEEKLY 

158 LOCATION:Branch Office 

159 END:AVAILABLE 

160 END:VAVAILABILITY 

161 

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

163 

164 """ 

165 

166 name = "VAVAILABILITY" 

167 

168 canonical_order = ( 

169 "DTSTART", 

170 "DTEND", 

171 "DURATION", 

172 "DTSTAMP", 

173 "UID", 

174 "SEQUENCE", 

175 "SUMMARY", 

176 "DESCRIPTION", 

177 "ORGANIZER", 

178 ) 

179 

180 required = ( 

181 "DTSTART", 

182 "DTSTAMP", 

183 "UID", 

184 ) 

185 

186 singletons = ( 

187 "DTSTAMP", 

188 "UID", 

189 "BUSYTYPE", 

190 "CLASS", 

191 "CREATED", 

192 "DESCRIPTION", 

193 "DTSTART", 

194 "LAST-MODIFIED", 

195 "LOCATION", 

196 "ORGANIZER", 

197 "PRIORITY", 

198 "SEQUENCE", 

199 "SUMMARY", 

200 "URL", 

201 "DTEND", 

202 "DURATION", 

203 ) 

204 

205 exclusive = ( 

206 "DTEND", 

207 "DURATION", 

208 ) 

209 

210 organizer = organizer_property 

211 busy_type = busy_type_property 

212 summary = summary_property 

213 description = description_property 

214 sequence = sequence_property 

215 classification = class_property 

216 url = url_property 

217 location = location_property 

218 categories = categories_property 

219 priority = priority_property 

220 contacts = contacts_property 

221 

222 start = DTSTART = rfc_7953_dtstart_property 

223 DTEND = rfc_7953_dtend_property 

224 DURATION = duration_property("Availability") 

225 duration = rfc_7953_duration_property 

226 end = rfc_7953_end_property 

227 

228 @property 

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

230 """All VAVAILABLE sub-components. 

231 

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

233 Modifications do not change the calendar. 

234 Use :meth:`~icalendar.cal.component.Component.add_component`. 

235 """ 

236 return self.walk("AVAILABLE") 

237 

238 @classmethod 

239 def new( 

240 cls, 

241 /, 

242 busy_type: BUSYTYPE | None = None, 

243 categories: Sequence[str] = (), 

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

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

246 concepts: CONCEPTS_TYPE_SETTER = None, 

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

248 created: date | None = None, 

249 classification: CLASS | None = None, 

250 description: str | None = None, 

251 end: datetime | None = None, 

252 last_modified: date | None = None, 

253 links: LINKS_TYPE_SETTER = None, 

254 location: str | None = None, 

255 organizer: vCalAddress | str | None = None, 

256 priority: int | None = None, 

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

258 related_to: RELATED_TO_TYPE_SETTER = None, 

259 sequence: int | None = None, 

260 stamp: date | None = None, 

261 start: datetime | None = None, 

262 subcomponents: Iterable[Component] | None = None, 

263 summary: str | None = None, 

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

265 url: str | None = None, 

266 ) -> Self: 

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

268 

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

270 

271 Parameters: 

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

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

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

275 comments: The :attr:`~icalendar.cal.component.Component.comments` of the availability. 

276 concepts: The :attr:`~icalendar.cal.component.Component.concepts` of the availability. 

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

278 created: The :attr:`~icalendar.cal.component.Component.created` of the availability. 

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

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

281 last_modified: The :attr:`~icalendar.cal.component.Component.last_modified` of the 

282 availability. 

283 links: The :attr:`~icalendar.cal.component.Component.links` of the availability. 

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

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

286 refids: :attr:`~icalendar.cal.component.Component.refids` of the availability. 

287 related_to: :attr:`~icalendar.cal.component.Component.related_to` of the availability. 

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

289 stamp: The :attr:`~icalendar.cal.component.Component.stamp` of the availability. 

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

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

292 subcomponents: The :attr:`~icalendar.cal.component.Component.subcomponents` of the availability. 

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

294 uid: The :attr:`~icalendar.cal.component.Component.uid` of the availability. 

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

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

297 

298 Returns: 

299 :class:`Availability` 

300 

301 Raises: 

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

303 according to :rfc:`7953`. 

304 

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

306 """ 

307 availability: Self = super().new( 

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

309 created=created, 

310 comments=comments, 

311 last_modified=last_modified, 

312 links=links, 

313 related_to=related_to, 

314 refids=refids, 

315 concepts=concepts, 

316 subcomponents=subcomponents, 

317 ) 

318 availability.summary = summary 

319 availability.description = description 

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

321 availability.sequence = sequence 

322 availability.categories = categories 

323 availability.classification = classification 

324 availability.url = url 

325 availability.busy_type = busy_type 

326 availability.organizer = organizer 

327 availability.location = location 

328 availability.priority = priority 

329 availability.contacts = contacts 

330 for subcomponent in components: 

331 availability.add_component(subcomponent) 

332 if cls._validate_new: 

333 if start is not None and ( 

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

335 ): 

336 raise InvalidCalendar( 

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

338 ) 

339 if end is not None and ( 

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

341 ): 

342 raise InvalidCalendar( 

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

344 ) 

345 availability._validate_start_and_end(start, end) 

346 availability.start = start 

347 availability.end = end 

348 return availability 

349 

350 @classmethod 

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

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

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

354 

355 

356__all__ = ["Availability"]