1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import sys
20
21 __all__ = ['Component', 'ExtensionPoint', 'implements', 'Interface',
22 'TracBaseError', 'TracError', 'TracValueError']
23
24
25 -def N_(string):
26 """No-op translation marker, inlined here to avoid importing from
27 `trac.util`.
28 """
29 return string
30
33 """Base class for all exceptions defined in Trac."""
34
35 title = N_("Trac Error")
36
39 """Standard exception for errors in Trac."""
40
41 - def __init__(self, message, title=None, show_traceback=False):
42 """If the `message` contains a `p` or `div` element it will be
43 rendered directly. Use the `message` class on the `p` or `div`
44 element to style as a red box. Otherwise, the message should be
45 plain text or contain only inline elements and will be wrapped
46 in a `p` element and rendered in a red box.
47
48 If title is given, it will be displayed as the large header
49 above the error message.
50 """
51 from trac.util.translation import gettext
52 super(TracError, self).__init__(message)
53 self._message = message
54 self.title = title or gettext(self.title)
55 self.show_traceback = show_traceback
56
57 message = property(lambda self: self._message,
58 lambda self, v: setattr(self, '_message', v))
59
62
65 """Raised when a function or operator receives an argument that is
66 the correct type, but inappropriate value.
67
68 :since: 1.2.1
69 """
70
73 """Marker base class for extension point interfaces."""
74
77 """Marker class for extension points in components."""
78
80 """Create the extension point.
81
82 :param interface: the `Interface` subclass that defines the
83 protocol for the extension point
84 """
85 property.__init__(self, self.extensions)
86 self.interface = interface
87 self.__doc__ = ("List of components that implement `~%s.%s`" %
88 (self.interface.__module__, self.interface.__name__))
89
91 """Return a list of components that declare to implement the
92 extension point interface.
93 """
94 classes = ComponentMeta._registry.get(self.interface, ())
95 components = [component.compmgr[cls] for cls in classes]
96 return [c for c in components if c]
97
99 """Return a textual representation of the extension point."""
100 return '<ExtensionPoint %s>' % self.interface.__name__
101
176
179 """Base class for components.
180
181 Every component can declare what extension points it provides, as
182 well as what extension points of other components it extends.
183 """
184 __metaclass__ = ComponentMeta
185
186 @staticmethod
188 """Can be used in the class definition of `Component`
189 subclasses to declare the extension points that are extended.
190 """
191 frame = sys._getframe(1)
192 locals_ = frame.f_locals
193
194
195 assert locals_ is not frame.f_globals and '__module__' in locals_, \
196 'implements() can only be used in a class definition'
197
198 locals_.setdefault('_implements', []).extend(interfaces)
199
201 """Return a textual representation of the component."""
202 return '<Component %s.%s>' % (self.__class__.__module__,
203 self.__class__.__name__)
204
205 implements = Component.implements
209 """The component manager keeps a pool of active components."""
210
212 """Initialize the component manager."""
213 self.components = {}
214 self.enabled = {}
215 if isinstance(self, Component):
216 self.components[self.__class__] = self
217
219 """Return whether the given class is in the list of active
220 components."""
221 return cls in self.components
222
224 """Activate the component instance for the given class, or
225 return the existing instance if the component has already been
226 activated.
227
228 Note that `ComponentManager` components can't be activated
229 that way.
230 """
231 if not self.is_enabled(cls):
232 return None
233 component = self.components.get(cls)
234 if not component and not issubclass(cls, ComponentManager):
235 if cls not in ComponentMeta._components:
236 raise TracError('Component "%s" not registered' % cls.__name__)
237 try:
238 component = cls(self)
239 except TypeError as e:
240 raise TracError("Unable to instantiate component %r (%s)" %
241 (cls, e))
242 return component
243
245 """Return whether the given component class is enabled."""
246 if cls not in self.enabled:
247 self.enabled[cls] = self.is_component_enabled(cls)
248 return self.enabled[cls]
249
251 """Force a component to be disabled.
252
253 :param component: can be a class or an instance.
254 """
255 if not isinstance(component, type):
256 component = component.__class__
257 self.enabled[component] = False
258 self.components[component] = None
259
261 """Force a component to be enabled.
262
263 :param component: can be a class or an instance.
264
265 :since: 1.0.13
266 """
267 if not isinstance(component, type):
268 component = component.__class__
269 self.enabled[component] = True
270
272 """Can be overridden by sub-classes so that special
273 initialization for components can be provided.
274 """
275
277 """Can be overridden by sub-classes to veto the activation of
278 a component.
279
280 If this method returns `False`, the component was disabled
281 explicitly. If it returns `None`, the component was neither
282 enabled nor disabled explicitly. In both cases, the component
283 with the given class will not be available.
284 """
285 return True
286