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

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

40 statements  

1"""A factory to create components.""" 

2 

3from __future__ import annotations 

4 

5import re 

6from typing import TYPE_CHECKING 

7 

8from icalendar.caselessdict import CaselessDict 

9 

10if TYPE_CHECKING: 

11 from icalendar import Component 

12 

13 

14class ComponentFactory(CaselessDict): 

15 """Registered components from :rfc:`7953` and :rfc:`5545`. 

16 

17 To get a component, use this class as shown below. 

18 

19 .. code-block:: pycon 

20 

21 >>> from icalendar import ComponentFactory 

22 >>> factory = ComponentFactory() 

23 >>> event_class = factory.get_component_class('VEVENT') 

24 >>> event_class() 

25 VEVENT({}) 

26 

27 Automatically creates custom component classes for unknown names (X-components, 

28 IANA-components). Custom components are never dropped per :rfc:`5545`. 

29 

30 .. code-block:: pycon 

31 

32 >>> factory = ComponentFactory() 

33 >>> custom_class = factory.get_component_class('X-VENDOR') 

34 >>> custom_class() 

35 X-VENDOR({}) 

36 

37 If a component class is not yet supported, it can be either created 

38 using :meth:`get_component_class` or added manually as a subclass of 

39 :class:`~icalendar.cal.component.Component`. 

40 See :doc:`/how-to/custom-components` for details. 

41 """ 

42 

43 def __init__(self, *args, **kwargs): 

44 """Set keys to upper for initial dict.""" 

45 super().__init__(*args, **kwargs) 

46 from icalendar.cal.alarm import Alarm 

47 from icalendar.cal.availability import Availability 

48 from icalendar.cal.available import Available 

49 from icalendar.cal.calendar import Calendar 

50 from icalendar.cal.event import Event 

51 from icalendar.cal.free_busy import FreeBusy 

52 from icalendar.cal.journal import Journal 

53 from icalendar.cal.timezone import ( 

54 Timezone, 

55 TimezoneDaylight, 

56 TimezoneStandard, 

57 ) 

58 from icalendar.cal.todo import Todo 

59 

60 self.add_component_class(Calendar) 

61 self.add_component_class(Event) 

62 self.add_component_class(Todo) 

63 self.add_component_class(Journal) 

64 self.add_component_class(FreeBusy) 

65 self.add_component_class(Timezone) 

66 self.add_component_class(TimezoneStandard) 

67 self.add_component_class(TimezoneDaylight) 

68 self.add_component_class(Alarm) 

69 self.add_component_class(Available) 

70 self.add_component_class(Availability) 

71 

72 def add_component_class(self, cls: type[Component]) -> None: 

73 """Add a component class to the factory. 

74 

75 Parameters: 

76 cls: The component class to add. 

77 """ 

78 self[cls.name] = cls 

79 

80 def get_component_class(self, name: str) -> type[Component]: 

81 """Get the component class from the factory. 

82 

83 This also creates and adds the component class if it does not exist. 

84 

85 Parameters: 

86 name: The name of the component, for example, ``"VCALENDAR"``. 

87 

88 Returns: 

89 The registered component class. 

90 """ 

91 component_class = self.get(name) 

92 if component_class is None: 

93 from icalendar.cal.component import Component 

94 

95 component_class = type( 

96 re.sub(r"[^\w]+", "", name), (Component,), {"name": name.upper()} 

97 ) 

98 self.add_component_class(component_class) 

99 return component_class 

100 

101 

102__all__ = ["ComponentFactory"]