1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 __all__ = ['Component', 'ExtensionPoint', 'implements', 'Interface',
20 'TracError']
21
22
23 -def N_(string):
24 """No-op translation marker, inlined here to avoid importing from
25 `trac.util`.
26 """
27 return string
28
31 """Exception base class for errors in Trac."""
32
33 title = N_('Trac Error')
34
35 - def __init__(self, message, title=None, show_traceback=False):
36 """If message is a genshi.builder.tag object, everything up to the
37 first <p> will be displayed in the red box, and everything after will
38 be displayed below the red box.
39 If title is given, it will be displayed as the large header above the
40 error message.
41 """
42 from trac.util.translation import gettext
43 Exception.__init__(self, message)
44 self._message = message
45 self.title = title or gettext(self.title)
46 self.show_traceback = show_traceback
47
48 message = property(lambda self: self._message,
49 lambda self, v: setattr(self, '_message', v))
50
53
56 """Marker base class for extension point interfaces."""
57
60 """Marker class for extension points in components."""
61
63 """Create the extension point.
64
65 @param interface: the `Interface` subclass that defines the protocol
66 for the extension point
67 """
68 property.__init__(self, self.extensions)
69 self.interface = interface
70 self.__doc__ = 'List of components that implement `%s`' % \
71 self.interface.__name__
72
74 """Return a list of components that declare to implement the extension
75 point interface.
76 """
77 extensions = ComponentMeta._registry.get(self.interface, ())
78 return filter(None, [component.compmgr[cls] for cls in extensions])
79
81 """Return a textual representation of the extension point."""
82 return '<ExtensionPoint %s>' % self.interface.__name__
83
139
142 """Base class for components.
143
144 Every component can declare what extension points it provides, as well as
145 what extension points of other components it extends.
146 """
147 __metaclass__ = ComponentMeta
148
149 - def __new__(cls, *args, **kwargs):
150 """Return an existing instance of the component if it has already been
151 activated, otherwise create a new instance.
152 """
153
154 if issubclass(cls, ComponentManager):
155 self = super(Component, cls).__new__(cls)
156 self.compmgr = self
157 return self
158
159
160 compmgr = args[0]
161 self = compmgr.components.get(cls)
162 if self is None:
163 self = super(Component, cls).__new__(cls)
164 self.compmgr = compmgr
165 compmgr.component_activated(self)
166 return self
167
168 @staticmethod
170 """Can be used in the class definiton of `Component` subclasses to
171 declare the extension points that are extended.
172 """
173 import sys
174
175 frame = sys._getframe(1)
176 locals_ = frame.f_locals
177
178
179 assert locals_ is not frame.f_globals and '__module__' in locals_, \
180 'implements() can only be used in a class definition'
181
182 locals_.setdefault('_implements', []).extend(interfaces)
183
184
185 implements = Component.implements
189 """The component manager keeps a pool of active components."""
190
192 """Initialize the component manager."""
193 self.components = {}
194 self.enabled = {}
195 if isinstance(self, Component):
196 self.components[self.__class__] = self
197
199 """Return wether the given class is in the list of active components."""
200 return cls in self.components
201
203 """Activate the component instance for the given class, or return the
204 existing instance if the component has already been activated.
205 """
206 if not self.is_enabled(cls):
207 return None
208 component = self.components.get(cls)
209 if not component:
210 if cls not in ComponentMeta._components:
211 raise TracError('Component "%s" not registered' % cls.__name__)
212 try:
213 component = cls(self)
214 except TypeError, e:
215 raise TracError('Unable to instantiate component %r (%s)' %
216 (cls, e))
217 return component
218
220 """Return whether the given component class is enabled."""
221 if cls not in self.enabled:
222 self.enabled[cls] = self.is_component_enabled(cls)
223 return self.enabled[cls]
224
226 """Force a component to be disabled.
227
228 The argument `component` can be a class or an instance.
229 """
230 if not isinstance(component, type):
231 component = component.__class__
232 self.enabled[component] = False
233 self.components[component] = None
234
236 """Can be overridden by sub-classes so that special initialization for
237 components can be provided.
238 """
239
241 """Can be overridden by sub-classes to veto the activation of a
242 component.
243
244 If this method returns `False`, the component was disabled explicitly.
245 If it returns `None`, the component was neither enabled nor disabled
246 explicitly. In both cases, the component with the given class will not
247 be available.
248 """
249 return True
250