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 Iterable, 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:: ics 

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:: ics 

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 subcomponents: Iterable[Component] | None = None, 

262 summary: str | None = None, 

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

264 url: str | None = None, 

265 ): 

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

267 

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

269 

270 Parameters: 

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

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

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

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

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

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

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

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

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

280 last_modified: The :attr:`last_modified` of the 

281 availability. 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

296 

297 Returns: 

298 :class:`Availability` 

299 

300 Raises: 

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

302 according to :rfc:`7953`. 

303 

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

305 """ 

306 availability: Availability = super().new( 

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

308 created=created, 

309 comments=comments, 

310 last_modified=last_modified, 

311 links=links, 

312 related_to=related_to, 

313 refids=refids, 

314 concepts=concepts, 

315 subcomponents=subcomponents, 

316 ) 

317 availability.summary = summary 

318 availability.description = description 

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

320 availability.sequence = sequence 

321 availability.categories = categories 

322 availability.classification = classification 

323 availability.url = url 

324 availability.busy_type = busy_type 

325 availability.organizer = organizer 

326 availability.location = location 

327 availability.priority = priority 

328 availability.contacts = contacts 

329 for subcomponent in components: 

330 availability.add_component(subcomponent) 

331 if cls._validate_new: 

332 if start is not None and ( 

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

334 ): 

335 raise InvalidCalendar( 

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

337 ) 

338 if end is not None and ( 

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

340 ): 

341 raise InvalidCalendar( 

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

343 ) 

344 availability._validate_start_and_end(start, end) 

345 availability.start = start 

346 availability.end = end 

347 return availability 

348 

349 @classmethod 

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

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

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

353 

354 

355__all__ = ["Availability"]