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

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

42 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 contacts_property, 

14 create_single_property, 

15 organizer_property, 

16 uid_property, 

17 url_property, 

18) 

19from icalendar.cal.component import Component 

20from icalendar.cal.examples import get_example 

21 

22if TYPE_CHECKING: 

23 from icalendar.prop import vCalAddress 

24 

25 

26class FreeBusy(Component): 

27 """ 

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

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

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

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

32 

33 Examples: 

34 Create a new FreeBusy: 

35 

36 >>> from icalendar import FreeBusy 

37 >>> free_busy = FreeBusy.new() 

38 >>> print(free_busy.to_ical()) 

39 BEGIN:VFREEBUSY 

40 DTSTAMP:20250517T080612Z 

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

42 END:VFREEBUSY 

43 

44 Get the example FreeBusy. 

45 

46 .. code-block:: pycon 

47 

48 >>> from icalendar import FreeBusy 

49 >>> free_busy = FreeBusy.example() 

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

51 BEGIN:VFREEBUSY 

52 DTEND:19980410T234500Z 

53 DTSTAMP:19970901T120000Z 

54 DTSTART:19980313T141711Z 

55 FREEBUSY:19980314T233000Z/19980315T003000Z 

56 FREEBUSY:19980316T153000Z/19980316T163000Z 

57 FREEBUSY:19980318T030000Z/19980318T040000Z 

58 ORGANIZER:jsmith@example.com 

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

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

61 END:VFREEBUSY 

62 

63 """ 

64 

65 name = "VFREEBUSY" 

66 

67 required = ( 

68 "UID", 

69 "DTSTAMP", 

70 ) 

71 singletons = ( 

72 "CONTACT", 

73 "DTSTART", 

74 "DTEND", 

75 "DTSTAMP", 

76 "ORGANIZER", 

77 "UID", 

78 "URL", 

79 ) 

80 multiple = ( 

81 "ATTENDEE", 

82 "COMMENT", 

83 "FREEBUSY", 

84 "RSTATUS", 

85 ) 

86 uid = uid_property 

87 url = url_property 

88 organizer = organizer_property 

89 contacts = contacts_property 

90 start = DTSTART = create_single_property( 

91 "DTSTART", 

92 "dt", 

93 (datetime, date), 

94 date, 

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

96 ) 

97 end = DTEND = create_single_property( 

98 "DTEND", 

99 "dt", 

100 (datetime, date), 

101 date, 

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

103 ) 

104 

105 @property 

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

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

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

109 return None 

110 return self.DTEND - self.DTSTART 

111 

112 @classmethod 

113 def new( 

114 cls, 

115 /, 

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

117 concepts: CONCEPTS_TYPE_SETTER = None, 

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

119 end: date | datetime | None = None, 

120 links: LINKS_TYPE_SETTER = None, 

121 organizer: vCalAddress | str | None = None, 

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

123 related_to: RELATED_TO_TYPE_SETTER = None, 

124 stamp: date | None = None, 

125 start: date | datetime | None = None, 

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

127 url: str | None = None, 

128 ): 

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

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

131 

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

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

134 

135 Parameters: 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

150 

151 Returns: 

152 :class:`FreeBusy` 

153 

154 Raises: 

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

156 according to :rfc:`5545`. 

157 

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

159 """ 

160 free_busy: FreeBusy = super().new( 

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

162 comments=comments, 

163 links=links, 

164 related_to=related_to, 

165 refids=refids, 

166 concepts=concepts, 

167 ) 

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

169 free_busy.url = url 

170 free_busy.organizer = organizer 

171 free_busy.contacts = contacts 

172 free_busy.end = end 

173 free_busy.start = start 

174 

175 if cls._validate_new: 

176 cls._validate_start_and_end(start, end) 

177 return free_busy 

178 

179 @classmethod 

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

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

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

183 

184 

185__all__ = ["FreeBusy"]