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

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

45 statements  

1""":rfc:`5545` VFREEBUSY component.""" 

2 

3from __future__ import annotations 

4 

5import uuid 

6from datetime import date, datetime, timedelta 

7from typing import TYPE_CHECKING 

8 

9from icalendar.attr import ( 

10 CONCEPTS_TYPE_SETTER, 

11 LINKS_TYPE_SETTER, 

12 RELATED_TO_TYPE_SETTER, 

13 REQUEST_STATUS_property, 

14 contacts_property, 

15 create_single_property, 

16 organizer_property, 

17 uid_property, 

18 url_property, 

19) 

20from icalendar.cal.component import Component 

21from icalendar.cal.examples import get_example 

22 

23if TYPE_CHECKING: 

24 from icalendar.compatibility import Self 

25 from icalendar.prop import vCalAddress 

26 

27 

28class FreeBusy(Component): 

29 """ 

30 A "VFREEBUSY" calendar component is a grouping of component 

31 properties that represents either a request for free or busy time 

32 information, a reply to a request for free or busy time 

33 information, or a published set of busy time information. 

34 

35 Examples: 

36 Create a new FreeBusy: 

37 

38 >>> from icalendar import FreeBusy 

39 >>> free_busy = FreeBusy.new() 

40 >>> print(free_busy.to_ical()) 

41 BEGIN:VFREEBUSY 

42 DTSTAMP:20250517T080612Z 

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

44 END:VFREEBUSY 

45 

46 Get the example FreeBusy. 

47 

48 .. code-block:: pycon 

49 

50 >>> from icalendar import FreeBusy 

51 >>> free_busy = FreeBusy.example() 

52 >>> print(free_busy.to_ical().decode()) 

53 BEGIN:VFREEBUSY 

54 DTEND:19980410T234500Z 

55 DTSTAMP:19970901T120000Z 

56 DTSTART:19980313T141711Z 

57 FREEBUSY:19980314T233000Z/19980315T003000Z 

58 FREEBUSY:19980316T153000Z/19980316T163000Z 

59 FREEBUSY:19980318T030000Z/19980318T040000Z 

60 ORGANIZER:jsmith@example.com 

61 UID:19970901T115957Z-76A912@example.com 

62 URL:http://www.example.com/calendar/busytime/jsmith.ifb 

63 END:VFREEBUSY 

64 

65 """ 

66 

67 name = "VFREEBUSY" 

68 

69 required = ( 

70 "UID", 

71 "DTSTAMP", 

72 ) 

73 singletons = ( 

74 "CONTACT", 

75 "DTSTART", 

76 "DTEND", 

77 "DTSTAMP", 

78 "ORGANIZER", 

79 "UID", 

80 "URL", 

81 ) 

82 multiple = ( 

83 "ATTENDEE", 

84 "COMMENT", 

85 "FREEBUSY", 

86 "REQUEST-STATUS", 

87 ) 

88 uid = uid_property 

89 url = url_property 

90 organizer = organizer_property 

91 contacts = contacts_property 

92 REQUEST_STATUS = REQUEST_STATUS_property 

93 start = DTSTART = create_single_property( 

94 "DTSTART", 

95 "dt", 

96 (datetime, date), 

97 date, 

98 'The "DTSTART" property for a "VFREEBUSY" specifies the inclusive start of the component.', 

99 ) 

100 end = DTEND = create_single_property( 

101 "DTEND", 

102 "dt", 

103 (datetime, date), 

104 date, 

105 'The "DTEND" property for a "VFREEBUSY" calendar component specifies the non-inclusive end of the component.', 

106 ) 

107 

108 @property 

109 def duration(self) -> timedelta | None: 

110 """The duration computed from start and end.""" 

111 if self.DTSTART is None or self.DTEND is None: 

112 return None 

113 return self.DTEND - self.DTSTART 

114 

115 @classmethod 

116 def new( 

117 cls, 

118 /, 

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

120 concepts: CONCEPTS_TYPE_SETTER = None, 

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

122 end: date | datetime | None = None, 

123 links: LINKS_TYPE_SETTER = None, 

124 organizer: vCalAddress | str | None = None, 

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

126 related_to: RELATED_TO_TYPE_SETTER = None, 

127 request_status: list[str] | str | None = None, 

128 stamp: date | None = None, 

129 start: date | datetime | None = None, 

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

131 url: str | None = None, 

132 ) -> Self: 

133 """Create a new FreeBusy component with all required properties, 

134 in accordance with :rfc:`5545#section-3.6.4`. 

135 

136 The FreeBusy component has the required properties of UID and DTSTAMP, 

137 which may be set with the parameters of ``uid`` and ``stamp``. 

138 

139 Parameters: 

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

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

142 contacts: The :attr:`contacts` of the component. 

143 end: The :attr:`end` of the component. 

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

145 organizer: The :attr:`organizer` of the component. 

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

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

148 request_status: The :attr:`REQUEST_STATUS` of the component. 

149 stamp: The :attr:`~icalendar.cal.component.Component.DTSTAMP` of the component. 

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

151 start: The :attr:`start` of the component. 

152 uid: The :attr:`uid` of the component. 

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

154 url: The :attr:`url` of the component. 

155 

156 Returns: 

157 :class:`FreeBusy` 

158 

159 Raises: 

160 :exc:`~icalendar.error.InvalidCalendar`: If the content is not valid 

161 according to :rfc:`5545`. 

162 

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

164 """ 

165 free_busy: Self = super().new( 

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

167 comments=comments, 

168 links=links, 

169 related_to=related_to, 

170 refids=refids, 

171 concepts=concepts, 

172 ) 

173 free_busy.uid = uid if uid is not None else uuid.uuid4() 

174 free_busy.url = url 

175 free_busy.organizer = organizer 

176 free_busy.contacts = contacts 

177 free_busy.REQUEST_STATUS = request_status 

178 free_busy.end = end 

179 free_busy.start = start 

180 

181 if cls._validate_new: 

182 cls._validate_start_and_end(start, end) 

183 return free_busy 

184 

185 @classmethod 

186 def example(cls, name: str = "example") -> FreeBusy: 

187 """Return the FreeBusy example with the given name.""" 

188 return cls.from_ical(get_example("freebusy", name)) 

189 

190 

191__all__ = ["FreeBusy"]