[PEAK] component metaclasses

Jason sphexy at gmail.com
Wed Apr 6 13:56:54 EDT 2005


Thanks for the quick reply.

> >at least for me.  What is Component's metaclass? :)
> 
> type(binding.Component) or binding.Component.__class__.  :)  In general in
> PEAK it's best not to make assumptions about the exact metaclass, because
> PEAK can create metaclasses on the fly, to support e.g. 'binding.classAttr'
> (which attaches a binding to the metaclass rather than the class, so that
> the attribute has a per-class value rather than a per-instance value).

I figured "ComponentClass" was being dynamically created somehow and I
wasn't sure if I could then extend it.

> By the way, depending on the kind of metaclass you're creating, you might
> not need it at all.  The binding framework's metadata facilities eliminate
> most of the common reasons to have a metaclass, in my experience, and the
> ability to define "class attributes" takes care of automatically creating
> them for you under other circumstances.  Perhaps you could explain what
> you're trying to do with your metaclass.

Sure.  I'd be happy to get rid of my metaclass.  I'm trying to use
peak with pygtk and I wanted my base class representing elements of
the gui (many of which are designed using glade) to do a couple
things.  I'm new to peak, and fairly new to gtk+glade so I imagine I'm
getting a number of things wrong.  Overlong description follows, but
you asked. :)

First, to create the callbacks that are invoked by gui events.  I was
playing with using signals, having every callback just emit a signal
which the rest of the app can observe.  So in glade if I've tied a
button click to a callback named on_help_button_clicked, in the class
I define something like

handlers = [('on_help_button_clicked', 'help')]

Which is the name of the callback to be created and the signal it
should emit.  The class that creates the handlers is basically just
making Broadcast objects for each signal, and can return a function
that will call broadcast.send.

Right now each class has a list of these handlers to be created.  I
originally had the metaclass to handle this, but since the class that
manages the signals and subscriptions and stuff is a component, and I
wasn't sure how the metaclass could have access to the hierarchy, I've
since moved this initialization to an uponAssemby method.  But that
doesn't seem ideal since it should be done upon assembly of the class,
not each object.

The other use of the metaclass is to allow subclasses to easily define
what methods should be run during setup and shutdown.  Each class will
inherit some setup procedures and can define their own.  The base
class makes a generator out of all the methods that need to be run and
uses gtk idle_add function to run through them.  (The combined setup()
yields after each method, plus individual methods can yield).  This
allows the gui to remain fairly responsive while loading plugins. 
Forgot to mention, the system is pretty much all about plugins.

So the metaclass is used mostly for convenience: to help the base
class create the setup generator; but also to allow sublcasses to
define methods following a naming convention, or specify a list of
methods to run, and have the metaclass merge these with those from its
ancestors.  No need for new classes to call super(...).setup(). 
Typically there are different steps for creating the view, the model,
populating the the model, etc.

class GenericPluginA(Base):
    handlers = [('on_help_button_clicked', 'help')]
    setup = ['run_me', 'then_me']

    def run_me(self): ...
    def then_me(self):...

class Plugin(GenericPluginA):
    setup = ['run_me_too']
    ...

So... I think that's about it.  Any suggestions you have will be much
appreciated.  I won't get into my misuse/lack of understanding of
peak.events yet. :)

Thanks,
Jason



More information about the PEAK mailing list