PageRenderTime 26ms CodeModel.GetById 9ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Tools/modulator/genmodule.py

http://unladen-swallow.googlecode.com/
Python | 160 lines | 121 code | 10 blank | 29 comment | 26 complexity | 0a8fe024b8ba829cfeb97fbc9f3ffbf6 MD5 | raw file
  1#
  2# Genmodule - A python program to help you build (template) modules.
  3#
  4# Usage:
  5#
  6# o = genmodule.object()
  7# o.name = 'dwarve object'
  8# o.abbrev = 'dw'
  9# o.funclist = ['new', 'dealloc', 'getattr', 'setattr']
 10# o.methodlist = ['dig']
 11#
 12# m = genmodule.module()
 13# m.name = 'beings'
 14# m.abbrev = 'be'
 15# m.methodlist = ['newdwarve']
 16# m.objects = [o]
 17#
 18# genmodule.write(sys.stdout, m)
 19#
 20import sys
 21import os
 22import varsubst
 23
 24error = 'genmodule.error'
 25
 26#
 27# Names of functions in the object-description struct.
 28#
 29FUNCLIST = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
 30            'tp_compare', 'tp_repr', 'tp_hash', 'tp_call', 'tp_str']
 31TYPELIST = ['tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'structure']
 32
 33#
 34# writer is a base class for the object and module classes
 35# it contains code common to both.
 36#
 37class writer:
 38    def __init__(self):
 39        self._subst = None
 40
 41    def makesubst(self):
 42        if not self._subst:
 43            if not self.__dict__.has_key('abbrev'):
 44                self.abbrev = self.name
 45            self.Abbrev = self.abbrev[0].upper()+self.abbrev[1:]
 46            subst = varsubst.Varsubst(self.__dict__)
 47            subst.useindent(1)
 48            self._subst = subst.subst
 49
 50    def addcode(self, name, fp):
 51        ifp = self.opentemplate(name)
 52        self.makesubst()
 53        d = ifp.read()
 54        d = self._subst(d)
 55        fp.write(d)
 56
 57    def opentemplate(self, name):
 58        for p in sys.path:
 59            fn = os.path.join(p, name)
 60            if os.path.exists(fn):
 61                return open(fn, 'r')
 62            fn = os.path.join(p, 'Templates')
 63            fn = os.path.join(fn, name)
 64            if os.path.exists(fn):
 65                return open(fn, 'r')
 66        raise error, 'Template '+name+' not found for '+self._type+' '+ \
 67                     self.name
 68
 69class module(writer):
 70    _type = 'module'
 71
 72    def writecode(self, fp):
 73        self.addcode('copyright', fp)
 74        self.addcode('module_head', fp)
 75        for o in self.objects:
 76            o.writehead(fp)
 77        for o in self.objects:
 78            o.writebody(fp)
 79        new_ml = ''
 80        for fn in self.methodlist:
 81            self.method = fn
 82            self.addcode('module_method', fp)
 83            new_ml = new_ml + (
 84                      '{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
 85                      %(fn, self.abbrev, fn, self.abbrev, fn))
 86        self.methodlist = new_ml
 87        self.addcode('module_tail', fp)
 88
 89class object(writer):
 90    _type = 'object'
 91    def __init__(self):
 92        self.typelist = []
 93        self.methodlist = []
 94        self.funclist = ['new']
 95        writer.__init__(self)
 96
 97    def writecode(self, fp):
 98        self.addcode('copyright', fp)
 99        self.writehead(fp)
100        self.writebody(fp)
101
102    def writehead(self, fp):
103        self.addcode('object_head', fp)
104
105    def writebody(self, fp):
106        new_ml = ''
107        for fn in self.methodlist:
108            self.method = fn
109            self.addcode('object_method', fp)
110            new_ml = new_ml + (
111                      '{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
112                      %(fn, self.abbrev, fn, self.abbrev, fn))
113        self.methodlist = new_ml
114        self.addcode('object_mlist', fp)
115
116        # Add getattr if we have methods
117        if self.methodlist and not 'tp_getattr' in self.funclist:
118            self.funclist.insert(0, 'tp_getattr')
119
120        for fn in FUNCLIST:
121            setattr(self, fn, '0')
122
123        #
124        # Special case for structure-access objects: put getattr in the
125        # list of functions but don't generate code for it directly,
126        # the code is obtained from the object_structure template.
127        # The same goes for setattr.
128        #
129        if 'structure' in self.typelist:
130            if 'tp_getattr' in self.funclist:
131                self.funclist.remove('tp_getattr')
132            if 'tp_setattr' in self.funclist:
133                self.funclist.remove('tp_setattr')
134            self.tp_getattr = self.abbrev + '_getattr'
135            self.tp_setattr = self.abbrev + '_setattr'
136        for fn in self.funclist:
137            self.addcode('object_'+fn, fp)
138            setattr(self, fn, '%s_%s'%(self.abbrev, fn[3:]))
139        for tn in TYPELIST:
140            setattr(self, tn, '0')
141        for tn in self.typelist:
142            self.addcode('object_'+tn, fp)
143            setattr(self, tn, '&%s_%s'%(self.abbrev, tn[3:]))
144        self.addcode('object_tail', fp)
145
146def write(fp, obj):
147    obj.writecode(fp)
148
149if __name__ == '__main__':
150    o = object()
151    o.name = 'dwarve object'
152    o.abbrev = 'dw'
153    o.funclist = ['new', 'tp_dealloc']
154    o.methodlist = ['dig']
155    m = module()
156    m.name = 'beings'
157    m.abbrev = 'be'
158    m.methodlist = ['newdwarve']
159    m.objects = [o]
160    write(sys.stdout, m)