On Nov 29, 11:50 pm, Remy Blank <[email protected]> wrote:
> Remy Blank wrote:
> > Mmh, now that I re-read the code on trunk, I wonder if we haven't lost
> > that functionality (automatically calling the base class' __init__()) in
> > the refactoring...
>
> > Jun, would you mind checking that? I'm pretty sure that the
> > implementation in 0.12-stable automatically calls inherited
> > constructors, whereas this isn't the case anymore on trunk. That would
> > be a regression, and we should restore the functionality.
>
> Scratch that, I must have been dreaming. We have never called the
> overridden constructor of the base class automatically.
>
> But maybe we should? The use case presented here by Chris shows that
> it's currently awkward to override a Component constructor, as you have
> to pass the environment to a method taking no arguments, and I'm not
> even sure it's going to work on 0.12-stable due to maybe_init()
> registering the derived component instance with the key of the base class.
>
> Funnily enough, this case has never occurred in Trac, as we only rarely
> inherit from a Component subclass, and we never override the constructor.
>
> Thoughts?
Subclassing components is not an encouraged development pattern with
Trac. The one or two places where we subclass in Trac (like the
WikiMacroBase) the components are clearly marked as "abstract = True"
to ensure that responsibilities are clearly set. Making complex
hierarchies of components that implement and override methods and data
will be a painful development and maintenance experience.
Trac can only guarantee that we call the component constructor
(__init__()) and the rest must be up to you. If you can't find and
reference your own code, then you need to restructure. Trac components
are to a large extent a subclassing anti-pattern, and you should
organize your code to make each self-contained and having them call
each other instead of making a class tree of methods and data. And if
really needed you should implement your own init structure by using
other names for methods and data - like for instance checking for some
'is_initialized' setting and calling own init() if not.
With lots of components and plugins already doing their own
__init__(), it would be quite dangerous if Trac should now change to
start traversing the hierarchy looking for __init__ calls to make. We
can risk double or erroneous calls to be made, perhaps depleting
scarce resources or overwriting data.
Even though the core.py source docs say...
# Allow components to have a no-argument initializer so that
# they don't need to worry about accepting the component manager
# as argument and invoking the super-class initializer
... we really only just look for a single __init__ and break as soon
as we find it. There should just be one init entry from Trac to
Component. Hence we should not go looking for others that may be
overridden and start calling them.
"Try to avoid subclassing components" is the best advice,
really... :-)
:::simon
https://www.coderesort.com
http://trac-hacks.org/wiki/osimons
--
You received this message because you are subscribed to the Google Groups "Trac
Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/trac-users?hl=en.