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

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

51 statements  

1"""This implements the sub-component "AVAILABLE" of "VAVAILABILITY". 

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, Optional, Sequence 

11 

12from icalendar.attr import ( 

13 CONCEPTS_TYPE_SETTER, 

14 LINKS_TYPE_SETTER, 

15 RELATED_TO_TYPE_SETTER, 

16 categories_property, 

17 contacts_property, 

18 description_property, 

19 duration_property, 

20 exdates_property, 

21 location_property, 

22 rdates_property, 

23 rfc_7953_dtend_property, 

24 rfc_7953_dtstart_property, 

25 rfc_7953_duration_property, 

26 rfc_7953_end_property, 

27 rrules_property, 

28 sequence_property, 

29 summary_property, 

30 uid_property, 

31) 

32from icalendar.cal.examples import get_example 

33from icalendar.error import InvalidCalendar 

34 

35from .component import Component 

36 

37if TYPE_CHECKING: 

38 from datetime import date 

39 

40 

41class Available(Component): 

42 """Sub-component of "VAVAILABILITY from :rfc:`7953`. 

43 

44 Description: 

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

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

47 component. "AVAILABLE" subcomponents MAY include recurrence 

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

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

50 of the "RECURRENCE-ID" property). 

51 

52 Examples: 

53 This is a recurring "AVAILABLE" subcomponent: 

54 

55 .. code-block:: text 

56 

57 BEGIN:AVAILABLE 

58 UID:57DD4AAF-3835-46B5-8A39-B3B253157F01 

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

60 DTSTART;TZID=America/Denver:20111023T090000 

61 DTEND;TZID=America/Denver:20111023T170000 

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

63 LOCATION:Denver 

64 END:AVAILABLE 

65 

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

67 

68 .. code-block: pycon 

69 

70 >>> from icalendar import Available 

71 >>> a = Available.example() 

72 >>> str(a.summary) 

73 'Monday to Friday from 9:00 to 17:00' 

74 

75 """ 

76 

77 name = "VAVAILABLE" 

78 

79 summary = summary_property 

80 description = description_property 

81 sequence = sequence_property 

82 categories = categories_property 

83 uid = uid_property 

84 location = location_property 

85 contacts = contacts_property 

86 exdates = exdates_property 

87 rdates = rdates_property 

88 rrules = rrules_property 

89 

90 start = DTSTART = rfc_7953_dtstart_property 

91 DTEND = rfc_7953_dtend_property 

92 DURATION = duration_property("Available") 

93 duration = rfc_7953_duration_property 

94 end = rfc_7953_end_property 

95 

96 @classmethod 

97 def new( 

98 cls, 

99 /, 

100 categories: Sequence[str] = (), 

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

102 concepts: CONCEPTS_TYPE_SETTER = None, 

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

104 created: Optional[date] = None, 

105 description: Optional[str] = None, 

106 end: Optional[datetime] = None, 

107 last_modified: Optional[date] = None, 

108 links: LINKS_TYPE_SETTER = None, 

109 location: Optional[str] = None, 

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

111 related_to: RELATED_TO_TYPE_SETTER = None, 

112 sequence: Optional[int] = None, 

113 stamp: Optional[date] = None, 

114 start: Optional[datetime] = None, 

115 summary: Optional[str] = None, 

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

117 ): 

118 """Create a new Available component with all required properties. 

119 

120 This creates a new Available component in accordance with :rfc:`7953`. 

121 

122 Arguments: 

123 categories: The :attr:`categories` of the Available component. 

124 comments: The :attr:`~icalendar.Component.comments` of the Available 

125 component. 

126 concepts: The :attr:`~icalendar.Component.concepts` of the Available 

127 component. 

128 contacts: The :attr:`contacts` of the Available component. 

129 created: The :attr:`~icalendar.Component.created` of the Available 

130 component. 

131 description: The :attr:`description` of the Available component. 

132 end: The :attr:`end` of the Available component. 

133 last_modified: The :attr:`~icalendar.Component.last_modified` of the 

134 Available component. 

135 links: The :attr:`~icalendar.Component.links` of the Available component. 

136 location: The :attr:`location` of the Available component. 

137 refids: :attr:`~icalendar.Component.refids` of the Available component. 

138 related_to: :attr:`~icalendar.Component.related_to` of the Available 

139 component. 

140 sequence: The :attr:`sequence` of the Available component. 

141 stamp: The :attr:`~icalendar.Component.stamp` of the Available component. 

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

143 start: The :attr:`start` of the Available component. 

144 summary: The :attr:`summary` of the Available component. 

145 uid: The :attr:`uid` of the Available component. 

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

147 

148 Returns: 

149 :class:`Available` 

150 

151 Raises: 

152 InvalidCalendar: If the content is not valid according to :rfc:`7953`. 

153 

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

155 """ 

156 available: Available = super().new( 

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

158 created=created, 

159 last_modified=last_modified, 

160 comments=comments, 

161 links=links, 

162 related_to=related_to, 

163 refids=refids, 

164 concepts=concepts, 

165 ) 

166 available.summary = summary 

167 available.description = description 

168 available.uid = uid if uid is not None else uuid.uuid4() 

169 available.sequence = sequence 

170 available.categories = categories 

171 available.location = location 

172 available.contacts = contacts 

173 

174 if cls._validate_new: 

175 if end is not None and ( 

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

177 ): 

178 raise InvalidCalendar( 

179 "Available end must be a datetime with a timezone" 

180 ) 

181 if not isinstance(start, datetime) or start.tzinfo is None: 

182 raise InvalidCalendar( 

183 "Available start must be a datetime with a timezone" 

184 ) 

185 available._validate_start_and_end(start, end) 

186 available.start = start 

187 available.end = end 

188 return available 

189 

190 @classmethod 

191 def example(cls, name: str = "rfc_7953_1") -> Available: 

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

193 return cls.from_ical(get_example("availabilities", name)).available[0] 

194 

195 

196__all__ = ["Available"]