Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/cal/free_busy.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

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

8 

9from icalendar.attr import ( 

10 contacts_property, 

11 create_single_property, 

12 organizer_property, 

13 uid_property, 

14 url_property, 

15) 

16from icalendar.cal.component import Component 

17 

18if TYPE_CHECKING: 

19 from icalendar.prop import vCalAddress 

20 

21 

22class FreeBusy(Component): 

23 """ 

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

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

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

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

28 

29 Examples: 

30 Create a new FreeBusy: 

31 

32 >>> from icalendar import FreeBusy 

33 >>> free_busy = FreeBusy.new() 

34 >>> print(free_busy.to_ical()) 

35 BEGIN:VFREEBUSY 

36 DTSTAMP:20250517T080612Z 

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

38 END:VFREEBUSY 

39 

40 """ 

41 

42 name = "VFREEBUSY" 

43 

44 required = ( 

45 "UID", 

46 "DTSTAMP", 

47 ) 

48 singletons = ( 

49 "CONTACT", 

50 "DTSTART", 

51 "DTEND", 

52 "DTSTAMP", 

53 "ORGANIZER", 

54 "UID", 

55 "URL", 

56 ) 

57 multiple = ( 

58 "ATTENDEE", 

59 "COMMENT", 

60 "FREEBUSY", 

61 "RSTATUS", 

62 ) 

63 uid = uid_property 

64 url = url_property 

65 organizer = organizer_property 

66 contacts = contacts_property 

67 start = DTSTART = create_single_property( 

68 "DTSTART", 

69 "dt", 

70 (datetime, date), 

71 date, 

72 'The "DTSTART" property for a "VFREEBUSY" specifies the inclusive start of the component.', # noqa: E501 

73 ) 

74 end = DTEND = create_single_property( 

75 "DTEND", 

76 "dt", 

77 (datetime, date), 

78 date, 

79 'The "DTEND" property for a "VFREEBUSY" calendar component specifies the non-inclusive end of the component.', # noqa: E501 

80 ) 

81 

82 @property 

83 def duration(self) -> Optional[timedelta]: 

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

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

86 return None 

87 return self.DTEND - self.DTSTART 

88 

89 @classmethod 

90 def new( 

91 cls, 

92 /, 

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

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

95 end: Optional[date | datetime] = None, 

96 organizer: Optional[vCalAddress | str] = None, 

97 stamp: Optional[date] = None, 

98 start: Optional[date | datetime] = None, 

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

100 url: Optional[str] = None, 

101 ): 

102 """Create a new alarm with all required properties. 

103 

104 This creates a new Alarm in accordance with :rfc:`5545`. 

105 

106 Arguments: 

107 comments: The :attr:`Component.comments` of the component. 

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

109 stamp: The :attr:`DTSTAMP` of the component. 

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

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

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

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

114 

115 Returns: 

116 :class:`FreeBusy` 

117 

118 Raises: 

119 InvalidCalendar: If the content is not valid according to :rfc:`5545`. 

120 

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

122 """ 

123 free_busy = super().new( 

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

125 ) 

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

127 free_busy.url = url 

128 free_busy.organizer = organizer 

129 free_busy.contacts = contacts 

130 free_busy.end = end 

131 free_busy.start = start 

132 if cls._validate_new: 

133 cls._validate_start_and_end(start, end) 

134 return free_busy 

135 

136 

137__all__ = ["FreeBusy"]