[Edu-sig] Big thanks to Ian Bicking for metaclass ideas for PataPata
Paul D. Fernhout
pdfernhout at kurtz-fernhout.com
Mon Jul 3 02:58:20 CEST 2006
Ian-
I just wanted to publicly thank you for your suggestions, help, and
patience here on this Edusig list getting me (and PataPata) started with
using metaclasses to define prototypes (using the "class ProtoFoo:"
syntax), for example your note here:
http://mail.python.org/pipermail/edu-sig/2006-May/006383.html
I just started using a metaclass approach inspired by your comment there
for the main WorldCommonTK.py library, viewable here:
http://svn.sourceforge.net/viewcvs.cgi/patapata/trunk/PataPata/WorldCommonTK.py?view=log
After a lot of work :-) I could just open the old code written by hand in
a more procedural way in PataPata and write it out that live world of
prototypes in the new metaclass way. (I did lose some comments I may want
to put back in eventually though, probably in some sort of overall
"comment" property or in the documentation for specific properties.)
For reference, you can see the old approach here:
http://svn.sourceforge.net/viewcvs.cgi/patapata/trunk/PataPata/WorldCommonTK.py?view=markup&rev=237
So, here is an example from that WorldCommonTK.py file (again, wrapping
Gregor Lingl's xturtle library) of how you can now define a prototype in
PataPata using the "class" syntax (and stored as a global to use
elsewhere) somewhat along the lines your outlined:
class XTurtleCanvas("Morph"):
__metaclass__ = world.buildPrototype
pen = None
size = (200, 200)
def _destroyEmbeddedWidget(self):
if self.widget:
if xturtle._canvas == self.widget:
xturtle._canvas = None
if xturtle.pen == self.pen:
xturtle._pen = None
self.widget.destroy()
self.widget = None
self.setAttributeWithoutSideEffects("pen", None)
def _newWidget(self):
xturtle._root = self.world.widget
newCanvas = xturtle.ScrolledCanvas(self.container.widget)
xturtle._canvas = newCanvas
self.setAttributeWithoutSideEffects("pen", xturtle.Pen())
xturtle._pen = self.pen
return newCanvas
def userInterrupt(self):
xturtle.TurtleScreen._RUNNING = 0
def windowFocusIn(self):
if self.widget:
xturtle._canvas = self.widget
xturtle._pen = self.pen
_property_writeFunction_pen = '_store_None'
_property_copyFunction_pen = '_store_None'
world.worldGlobals['XTurtleCanvas'] = XTurtleCanvas
[You can also see the older xturtle wrapping approach in my earlier "re:
News about turtle graphics" post to the Edusig list.]
Notice how I also added inline support for defining properties (anything
starting with _property_ is processed as a property directive). I also
used a builder function "__metaclass__ = world.buildPrototype" instead of
a metaclass, and that builder function is actually a method of an existing
world; all prototypes need a link back to the world they are in, in the
current approach, so it was either that or some other initialization code
with a module or class global. Notice also how what would normally be
shared class variables (e.g. "pen" or "size") are instead now more like
local prototype "instance" variables.
And here is actually using the global prototype in another file
(WorldExampleTK.py):
http://svn.sourceforge.net/viewcvs.cgi/patapata/trunk/PataPata/WorldExampleTK.py?view=markup
class proto17("XTurtleCanvas"):
__metaclass__ = world.buildPrototype
pen = None
position = (38, 377)
widget = None
For reference, I made a decision a long while back to explicitly require
naming prototypes before you could derive from them (for development
clarity). There is no reason you could not link directly to other
prototypes, and I used to do that, and it was more work to make the
indirect lookup through a globals dictionary, but I'm hoping that
explicitness make "documentation of intent" clearer. So, what is going on
here isn't quite copying or cloning, it is setting a "self.traits" array
to have one or more strings, which are then used to look up properties and
values if they are not locally defined in the prototype itself, so
something like multiple inheritance from named base classes. You can then
override behavior locally or otherwise modify the globally named prototype
you have as a trait.
Anyway, thanks again for your help and suggestions, Ian.
All the best.
--Paul Fernhout
More information about the Edu-sig
mailing list