schizoid.py

Go to the documentation of this file.
00001 ###############################################################################
00002 
00003 import inspect, new, sys
00004 
00005 registry = {}
00006 
00007 # master registry for methodnames, decorators, and proxy scope dummy object
00008 ###############################################################################
00009 
00010 class proxy(object): pass
00011 
00012 ##
00013 #  we have to save func in the registry so each duplicate 
00014 #             function name doesnt just overwrite the previous one 
00015 #    
00016 #             NOTE: "whichSelf" is the name of the variable used where 
00017 #                   "self" is usually found in instancemethod definitions
00018 #    
00019 def personalityDependant(func):
00020    whichSelf = inspect.getargspec(func)[0][0]  
00021    if whichSelf not in registry:        registry[whichSelf] = {}
00022    registry[whichSelf][func.__name__] = func            
00023    return func  
00024 
00025 ##
00026 #  tag a function as schizophrenic so the metaclass knows when to 
00027 #       effect the scope mangling. 
00028 def schizophrenic(func):
00029    func.schizophrenic=True
00030    return func
00031 
00032 # metaclass for all schizoids
00033 ###############################################################################
00034 
00035 ##
00036 #  
00037 class schizotypal(type):                
00038    @staticmethod
00039    def __new__(mcls, name, bases, clsdict):
00040       err1 ='expected a schizotypal object would have a list of personalities.'
00041       try:                      assert 'personalities' in clsdict
00042       except AssertionError:    raise Exception, err1
00043       else:                     
00044             personalities = clsdict['personalities']
00045             replacement   = {}
00046             for pName in personalities: replacement[pName] = registry[pName]
00047             personalities = replacement
00048             clsdict['personalities'] = personalities
00049             klassobj = type.__new__(mcls, name, bases, clsdict)
00050       return klassobj
00051         
00052    def __call__(cls, *args, **kargs):
00053       inst = type.__call__(cls, *args, **kargs)
00054       for var in dir(inst):
00055             val  = getattr(inst, var)
00056             test = var!='__metaclass__' and var!='__class__'
00057             if hasattr(val, 'schizophrenic') and test:
00058                for pName in inst.personalities:
00059                         val.func_globals[pName] = inst.as_(pName)
00060       return inst
00061 
00062 # base schizoid object (inherit from this)
00063 ###############################################################################
00064 
00065 ##
00066 #  
00067 class schizoid(object):
00068    __metaclass__ = schizotypal
00069    personalities = []
00070    
00071    ##
00072    #  obtain a representation of self with respect to some personality 
00073    def as_(self, pName):
00074       cls = self.__class__
00075       err = 'illegal personality for '+str(cls) + ': ' + pName
00076       assert pName in cls.personalities, err
00077       out   = cls.personalities[pName]
00078       P = proxy()
00079       for funcname in out:
00080             func = out[funcname]
00081             func = new.instancemethod(func,self,cls)
00082             setattr(P, funcname, func)
00083       return P
00084                         
00085 # a demo
00086 ###############################################################################
00087 
00088 if __name__=='__main__':                
00089    ##
00090    #  a simple demo.
00091    #    
00092    #          note that without the decorators, each status() definition would simply
00093    #          overwrite the previous one.  notice also under normal python semantics
00094    #          how theres no reason the philosopher names in the run() method should 
00095    #          be in scope.
00096    #       
00097    class myschizoid(schizoid):          
00098       personalities = ['kant','heidegger','wittgenstein','schlegel']
00099       
00100       @personalityDependant
00101       def status(kant):          return "a real pissant"
00102       
00103       @personalityDependant 
00104       def status(heidegger):     return "a boozy beggar" 
00105       
00106       @personalityDependant 
00107       def status(wittgenstein):  return "beery swine"
00108       
00109       @personalityDependant 
00110       def status(schlegel):      return "schloshed"
00111       
00112       @schizophrenic
00113       def run(self):
00114          print
00115          print 'kant:\t\t\t',           kant.status()
00116          print 'heidegger:\t\t',                heidegger.status()
00117          print 'wittgenstein:\t\t',     wittgenstein.status()
00118          print 'schlegel:\t\t',         schlegel.status()
00119          print
00120 
00121    s = myschizoid()
00122    s.run()
00123 
00124 
00125 
00126 
00127 

© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved; If you reference this document or any part of this document you must use the citation verbatim (including the link) "© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved."

Notice: This source code contained in this document is NOT open source and is NOT being distributed as open source.

122,241 lines of code and growing...