# # Genmodule - A python program to help you build (template) modules. # # Usage: # # o = genmodule.object() # o.name = 'dwarve object' # o.abbrev = 'dw' # o.funclist = ['new', 'dealloc', 'getattr', 'setattr'] # o.methodlist = ['dig'] # # m = genmodule.module() # m.name = 'beings' # m.abbrev = 'be' # m.methodlist = ['newdwarve'] # m.objects = [o] # # genmodule.write(sys.stdout, m) # import sys import os import varsubst error = 'genmodule.error' # # Names of functions in the object-description struct. # FUNCLIST = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr', 'tp_compare', 'tp_repr', 'tp_hash', 'tp_call', 'tp_str'] TYPELIST = ['tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'structure'] # # writer is a base class for the object and module classes # it contains code common to both. # class writer: def __init__(self): self._subst = None def makesubst(self): if not self._subst: if 'abbrev' not in self.__dict__: self.abbrev = self.name self.Abbrev = self.abbrev[0].upper()+self.abbrev[1:] subst = varsubst.Varsubst(self.__dict__) subst.useindent(1) self._subst = subst.subst def addcode(self, name, fp): ifp = self.opentemplate(name) self.makesubst() d = ifp.read() d = self._subst(d) fp.write(d) def opentemplate(self, name): for p in sys.path: fn = os.path.join(p, name) if os.path.exists(fn): return open(fn, 'r') fn = os.path.join(p, 'Templates') fn = os.path.join(fn, name) if os.path.exists(fn): return open(fn, 'r') raise error('Template '+name+' not found for '+self._type+' '+ \ self.name) class module(writer): _type = 'module' def writecode(self, fp): self.addcode('copyright', fp) self.addcode('module_head', fp) for o in self.objects: o.writehead(fp) for o in self.objects: o.writebody(fp) new_ml = '' for fn in self.methodlist: self.method = fn self.addcode('module_method', fp) new_ml = new_ml + ( '{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n' %(fn, self.abbrev, fn, self.abbrev, fn)) self.methodlist = new_ml self.addcode('module_tail', fp) class object(writer): _type = 'object' def __init__(self): self.typelist = [] self.methodlist = [] self.funclist = ['new'] writer.__init__(self) def writecode(self, fp): self.addcode('copyright', fp) self.writehead(fp) self.writebody(fp) def writehead(self, fp): self.addcode('object_head', fp) def writebody(self, fp): new_ml = '' for fn in self.methodlist: self.method = fn self.addcode('object_method', fp) new_ml = new_ml + ( '{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n' %(fn, self.abbrev, fn, self.abbrev, fn)) self.methodlist = new_ml self.addcode('object_mlist', fp) # Add getattr if we have methods if self.methodlist and not 'tp_getattr' in self.funclist: self.funclist.insert(0, 'tp_getattr') for fn in FUNCLIST: setattr(self, fn, '0') # # Special case for structure-access objects: put getattr in the # list of functions but don't generate code for it directly, # the code is obtained from the object_structure template. # The same goes for setattr. # if 'structure' in self.typelist: if 'tp_getattr' in self.funclist: self.funclist.remove('tp_getattr') if 'tp_setattr' in self.funclist: self.funclist.remove('tp_setattr') self.tp_getattr = self.abbrev + '_getattr' self.tp_setattr = self.abbrev + '_setattr' for fn in self.funclist: self.addcode('object_'+fn, fp) setattr(self, fn, '%s_%s'%(self.abbrev, fn[3:])) for tn in TYPELIST: setattr(self, tn, '0') for tn in self.typelist: self.addcode('object_'+tn, fp) setattr(self, tn, '&%s_%s'%(self.abbrev, tn[3:])) self.addcode('object_tail', fp) def write(fp, obj): obj.writecode(fp) if __name__ == '__main__': o = object() o.name = 'dwarve object' o.abbrev = 'dw' o.funclist = ['new', 'tp_dealloc'] o.methodlist = ['dig'] m = module() m.name = 'beings' m.abbrev = 'be' m.methodlist = ['newdwarve'] m.objects = [o] write(sys.stdout, m)