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 using :meth:`get_component_class` or added manually as a subclass of :class:`~icalendar.cal.component.Component`. 

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

39 """ 

40 

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

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

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

44 from icalendar.cal.alarm import Alarm 

45 from icalendar.cal.availability import Availability 

46 from icalendar.cal.available import Available 

47 from icalendar.cal.calendar import Calendar 

48 from icalendar.cal.event import Event 

49 from icalendar.cal.free_busy import FreeBusy 

50 from icalendar.cal.journal import Journal 

51 from icalendar.cal.timezone import Timezone, TimezoneDaylight, TimezoneStandard 

52 from icalendar.cal.todo import Todo 

53 

54 self.add_component_class(Calendar) 

55 self.add_component_class(Event) 

56 self.add_component_class(Todo) 

57 self.add_component_class(Journal) 

58 self.add_component_class(FreeBusy) 

59 self.add_component_class(Timezone) 

60 self.add_component_class(TimezoneStandard) 

61 self.add_component_class(TimezoneDaylight) 

62 self.add_component_class(Alarm) 

63 self.add_component_class(Available) 

64 self.add_component_class(Availability) 

65 

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

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

68 

69 Args: 

70 cls: The component class to add. 

71 """ 

72 self[cls.name] = cls 

73 

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

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

76 

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

78 

79 Args: 

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

81 

82 Returns: 

83 The registered component class. 

84 """ 

85 component_class = self.get(name) 

86 if component_class is None: 

87 from icalendar.cal.component import Component 

88 

89 component_class = type( 

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

91 ) 

92 self.add_component_class(component_class) 

93 return component_class 

94 

95 

96__all__ = ["ComponentFactory"]