#2403 closed enhancement (fixed)
Proposal to modify ExtensionPoint to allow specialisation
Reported by: | Owned by: | Christopher Lenz | |
---|---|---|---|
Priority: | low | Milestone: | 0.10 |
Component: | general | Version: | 0.9 |
Severity: | minor | Keywords: | |
Cc: | Branch: | ||
Release Notes: | |||
API Changes: | |||
Internal Changes: |
Description
By turning ExtensionPoint into a descriptor it moves the decision of what to return, into the ExtensionPoint object. This allows one to sub-class ExtensionPoint and customise its behaviour. It has no negative side-effects that I can think of.
To illustrate how this could be useful, the following example lets the user choose a single active interface implementation out of the set of available extensions.
This is useful for user-configurable extension selection, say of a database backend, or a UI front-end; any situation where only a single implementation should be used.
class SingletonExtensionPoint(ExtensionPoint): def __get__(self, instance, owner): xtnpt = instance._extension_points.get(self.name) if xtnpt: extensions = ComponentMeta._registry.get(xtnpt.interface, []) seek = instance.compmgr._active_components.get(xtnpt.interface, None) if seek: for extension in extensions: if extension.__name__ == seek: return extension raise AttributeError("can't find active interface '%s' named '%s'" % (xtnpt.interface.__name__, seek)) else: raise AttributeError("no component active for '%s' interface" % xtnpt.interface.__name__) class AnInterface(Interface): def do_stuff(): pass class ImplementationOfAnInterface(Component): implements(AnInterface) def do_stuff(self): print "ImplementationOfAnInterface.do_stuff()" class M(ComponentManager, Component): _active_components = {} aninterface = SingletonExtensionPoint(AnInterface) def set_active(self, interface, component): self._active_components[interface] = component m = M() m.set_active(AnInterface, 'ImplementationOfAnInterface') i = m.aninterface
Attachments (1)
Change History (12)
by , 19 years ago
Attachment: | extension-specialisation.diff added |
---|
comment:1 by , 19 years ago
Type: | defect → enhancement |
---|
comment:2 by , 19 years ago
Slight bug-fix in the SingletonExtensionPoint example:
return extension
should be
return instance.compmgr[extension]
comment:3 by , 19 years ago
Milestone: | → 1.0 |
---|---|
Owner: | changed from | to
Status: | new → assigned |
Yeah, changing ExtensionPoint
to a descriptor is a good idea.
comment:5 by , 19 years ago
Also, the patch/proposal doesn't seem to be complete, I tested it on top of the FlexibleWikiPageNames branch, and it raises the following error:
Traceback (most recent call last): ... File "D:\Workspace\install\lib\python\trac\devel\Lib\site-packages\trac\wiki\api.py", line 204, in get_wiki_syntax p = self.wikipagenames_providers File "D:\Workspace\install\lib\python\trac\devel\Lib\site-packages\trac\core.py", line 63, in __get__ seek = instance.compmgr._active_components.get(xtnpt.interface, AttributeError: 'Environment' object has no attribute '_active_components'
The Environment.set_active
method seems to be missing as well.
Also, what would you suggest for a standard way to assign the appropriate implementation. There should be a simple (automated?) way to get them from the TracIni, or otherwise pick a default implementation.
comment:6 by , 19 years ago
In the example above, M is the ComponentManager and implements set_active and _active_components. The patch is intentionally minimal, behaving identically to the existing code, but allows the possibility of alternative ExtensionPoint semantics, such as the example SingletonExtensionPoint above. I can provide a more complete implementation if interested.
SingletonExtensionPoint was just an example, but if something similar were to be implemented it would require modifications to Environment, perhaps with a default method in ComponentManager.
I had envisaged using TracIni as you suggest; it would seem to be quite intuitive.
Perhaps something like the following?
[selected_components] IDatabaseProvider = SQLiteDB ISourceControlSystem = SubversionSCS
comment:7 by , 19 years ago
Have a look at r2563, which integrates the proposed implementation
for ExtensionPoint
and introduces a SingleExtensionPoint
which implements a similar way for selecting a single
implementation for a given interface to what I already did as a
special case, in the FlexibleWikiPageNames branch.
Everything works fine.
comment:9 by , 19 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
[2603] makes extension points descriptors as to your proposal.
I don't think a generic singleton-style extension point implementation makes much sense right now, and selecting one component by disabling the others doesn't seem that elegant IMO.
comment:10 by , 19 years ago
Milestone: | 1.0 → 0.10 |
---|
comment:11 by , 19 years ago
An implementation of the SingletonExtensionPoint
has been added in [2866].
Implementation of proposal