A new generic interface for extending Trac - before Trac, before Dispatch and before Render.
|Reported by:||Owned by:||Jonas Borgström|
In general I have a number of features in Trac that I extend or override, and prefer using own plugins or outside hacks rather than change the Trac source as that leaves much easier upgrades - it keeps my changes easily contained.
Some things are difficult to change from the outside as they depend on runtime information and cannot eaily be done through plugins only with current interfaces. For instance, I would like to be able to add information to the HDF object that gets to be part of all pages - and not just seeing the HDF object when it passes by one of my modules. A workaround is to put this code in
get_navigation_items of a custom plugin as by then the HDF is initialised with basic values, but not yet dispatched through an actual handler. If I add to it, it gets to be part of all HDF to the template - allowing me to put runtime information into header or footer for instance. However, it is not pretty…
Problem: I don't know when various modules get initialised and populated with relevant data, and dare not reference runtime variables directly as
a) it can result in runtime errors I never imagined depending on module logic and initialisaton order, and
b) trapping or overriding the various places in Trac code will result in code that is awkward and hard to manage over time as Trac changes.
Proposal: A generic interface for
IRequestChangeProvider allowing me to run all code at specific times - after "core" but before "main" Trac (unclear definitions), when the runtime environment is set up by Trac but before it is dispatched to an individual component for handling - and again before the request gets sent to rendering. This means three methods that the interface supports:
def req_change_before_trac(self, req): ''' Allows manipulating request and runtime data before main Trac. Add or change information that is guaranteed to be available for all modules.''' pass def req_change_after_trac(self, req, env): ''' Trac and environment is all finished set up. Can add to or modify before it gets dispatched to a specific handler.''' pass def req_change_before_render(self, req, env): ''' Manipulate req object after Trac and modules, but before it gets rendered. Can use it to translate text and navigation items, and other variables or logic used for output.''' pass
Note: I have not implemented it or tested it - it is still just a theory, and see it as a general proposal for clean interface changes. It is mentally simplified, and would likely not work directly as suggested above - and it probably would also require some refactoring of Trac to clean up the code. Some of the main Trac code would also be better implemented as components through an interface like this.
A sound reason for NOT doing this is that it is too general. Maybe it should be a large number of interfaces for all the specific areas. But keeping up with the definition of "all" will always be a challenge… Interested to hear from others on this.