faqts : Computers : Programming : Languages : Python : Snippets

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

3 of 4 people (75%) answered Yes
Recently 2 of 3 people (67%) answered Yes

Entry

Python mimics Morphic

Jul 5th, 2000 10:01
Nathan Wallace, Hans Nowak, Snippet 221, Peter Sommerfeld


"""
Packages: miscellaneous
"""
"""
"Release early and often" is a slogan of the Open Source Community.
Ok, here I am with a first rough outline for an object model derived
from the Self Morphic model <http://self.sunlabs.com/>.
I've made several unseccessfull attempts to simplify the std
class/instance model for a visual application builder using
Meta-Classes (actually mind-breaking;).  Lately Terry Reedy
pointed me to the idea to emulate the Self object model in
Python (thanks Terry !). This model avoids the destinction
between classes and instances and substitutes it by the idea
of cloning and modifying of objects. Objects which seem to
be worth to be handeled as generic template are stored in
a special module named traits. To derive from objects means
to make a copy or clone respectivly of a traits object and
to modify it. Of course, you can modify an arbitary object.
The traits module isn't more than a convention for object
sharing which might be extended by local traits modules.
This first experimental implementation is somewhat q&d
and leaves much room for improvement and refinement. This
is especially true because I'm still on the learning curve and
more experianced pythoneers will probably  know better
solutions for many details. Please let me know :)
A more generic question is, weather the idea of cloning
of objects has serious drawbacks I don't know of and
which might stop further exploration.
Thanks for your patience
-- Peter
mail: peter.sommerfeld@gmx.de
PS: Sorry for this long message but I havent't setup
a website yet.
"""
#-----------------------------------------------------------
#                                     mimic.py
#-----------------------------------------------------------
from imp import new_module
import sys
x = intern('traits')
sys.modules[x] = new_module (x)
del new_module
del sys
import traits
from copy import deepcopy
from types import FunctionType, InstanceType
class _method_:
    def __init__(self, method):
        self.clone = None
        self.methods = method
    def __call__(self,**kw):
        for m in self.methods:
            apply(m,(self.clone,),kw)
def cloneable():
    class clone:
        ''' How is multiple definition of __setattr__ avoided ? '''
        def __setattr__(self,key,val):
            if type(val) == FunctionType:
                 func = (val,)
                 if  self.__class__.__dict__.has_key(key):
                         func = self.__class__.__dict__[key].methods + func
                 self.__class__.__dict__[key] = _method_(func)
            else:
                self.__dict__[key] = val
    return clone()
def clone(obj):
    clone = cloneable()
    clone.__dict__ = deepcopy(obj.__dict__)
    clone.__class__.__dict__ = obj.__class__.__dict__
    for m in clone.__class__.__dict__.values():
        if isinstance(m,_method_):
            m.clone = clone # rebind methods
    return clone
#-----------------------------
#
#        e x a m p l e    c o d e
#
#-----------------------------
def move(self, hrz = 0, vrt = 0):
    self.x = self.x + hrz
    self.y = self.y + vrt
    print '\nautomatic method overriding :\n--> object.move called'
#
#	 x y   (coords)
#
x  = cloneable()  # base of all cloneable objects
x.x = 0                # which makes x clonable
x.y = 0                # ... add data members
x.move = move    # ... add method
traits.xy = x       # ... and make it a template
del move
#
#          c o l o r s
#
white = cloneable()
white.red = 255
white.green = 255
white.blue = 255
black = clone(white)
black.red = 0
black.green = 0
black.blue = 0
x = cloneable()
x.white = clone(white)
x.black = clone(black)
traits.color = x
del black, white
from traits import color
#
#        f o r m
#
def move(self, hrz = 0, vrt = 0):
    # silly example for overriding, form.color
    # changes if the object is moved
    self.color.red = self.color.red - hrz
    self.color.green = self.color.green - vrt
    self.color.green = self.color.green - vrt - hrz
    print '--> form.move called'
x = clone(traits.xy)
x.color	= clone(color.white)	# bg color
x.width	= 0
x.height	= 0
x.move 	= move
traits.form = x
del move
#
#         o u t p u t
#
def out(obj):	# 1 level deep only
    s = '\ncloned object at %s' % (hex(id(obj)))
    print s
    items = obj.__dict__.items()
    items.sort()
    for key, item in items:
        if type(item) == InstanceType:
            s = "\t%s: cloned object at %s" % (key,hex(id(item)))
            print s
            for k,i in item.__dict__.items():
                   s = '\t\t%s:\t%s' % (k,i)
                   print s
        else:
             s = '\t%s:\t%s' % (key,item)
             print s
#
#          t e s t
#
x = clone(traits.form)
x.width 	= 100
x.height	= 100
x.move(hrz = 5, vrt = 5)
out(x)