2 """
3 Composite class as part of the Composite pattern.
4
5 - External Usage Documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Structural-Pattern-Usage}
6 - External Composite Pattern documentation: U{https://en.wikipedia.org/wiki/Composite_pattern}
7 """
9 """
10 Initialize a new Composite instance.
11
12 @param interface: The interface the all child components must adhere to when added to this composite.
13 @type interface: class
14 """
15 self.components = set()
16 self.interface = interface
17
19 """
20 Add a component to this composite.
21
22 @param component: The component to add to this Composite
23 @raise AttributeError: If the component does not adhere to this Composites interface.
24 """
25 valid = False
26 try:
27 if component.interface == self.interface:
28 valid = True
29 except AttributeError:
30 if self.interface in component.__class__.__mro__:
31 valid = True
32 finally:
33 if valid:
34 self.components.add(component)
35 else:
36 raise AttributeError('Component {0} does not follow this composites interface {1}'.format(
37 component.__class__, self.interface))
38
40 """
41 Remove a component from this composite.
42
43 @param component: The component to remove from this Composite.
44 """
45 try:
46 self.components.remove(component)
47 except KeyError:
48 pass
49
51 """
52 Apply a function to all child components by function name.
53
54 @param func_name: The name of the function to call with all child components.
55 @type func_name: str
56 @raise AttributeError: If a child component does not have a callable function with the given name.
57 """
58 for component in self.components:
59 attribute = getattr(component, func_name)
60 if callable(attribute):
61 attribute()
62 else:
63 raise AttributeError()
64
66 """
67 Override getattr to delegate all function calls to children.
68
69 @param item: The function to call with this composites children components.
70 @type item: str
71 @return: A function that when called will call all child functions with the given function name.
72 """
73 return lambda: self._delegate(item)
74