blob: 19745029b6624f10ed2eabd0b59650851de801fb [file] [log] [blame]
Guido van Rossumd2112201995-03-02 14:05:29 +00001#
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
23import string
24
25error = 'genmodule.error'
26
27#
28# Names of functions in the object-description struct.
29#
30FUNCLIST = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
Guido van Rossuma16a5091998-04-10 19:15:27 +000031 'tp_compare', 'tp_repr', 'tp_hash', 'tp_call', 'tp_str']
Guido van Rossumd2112201995-03-02 14:05:29 +000032TYPELIST = ['tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'structure']
33
34#
35# writer is a base class for the object and module classes
36# it contains code common to both.
37#
38class writer:
39 def __init__(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +000040 self._subst = None
Guido van Rossumd2112201995-03-02 14:05:29 +000041
42 def makesubst(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +000043 if not self._subst:
44 if not self.__dict__.has_key('abbrev'):
45 self.abbrev = self.name
46 self.Abbrev = string.upper(self.abbrev[0])+self.abbrev[1:]
47 subst = varsubst.Varsubst(self.__dict__)
48 subst.useindent(1)
49 self._subst = subst.subst
Guido van Rossumd2112201995-03-02 14:05:29 +000050
51 def addcode(self, name, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +000052 ifp = self.opentemplate(name)
53 self.makesubst()
54 d = ifp.read()
55 d = self._subst(d)
56 fp.write(d)
Guido van Rossumd2112201995-03-02 14:05:29 +000057
58 def opentemplate(self, name):
Guido van Rossuma16a5091998-04-10 19:15:27 +000059 for p in sys.path:
60 fn = os.path.join(p, name)
61 if os.path.exists(fn):
62 return open(fn, 'r')
63 fn = os.path.join(p, 'Templates')
64 fn = os.path.join(fn, name)
65 if os.path.exists(fn):
66 return open(fn, 'r')
67 raise error, 'Template '+name+' not found for '+self._type+' '+ \
68 self.name
69
Guido van Rossumd2112201995-03-02 14:05:29 +000070class module(writer):
71 _type = 'module'
72
73 def writecode(self, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +000074 self.addcode('copyright', fp)
75 self.addcode('module_head', fp)
76 for o in self.objects:
77 o.writehead(fp)
78 for o in self.objects:
79 o.writebody(fp)
80 new_ml = ''
81 for fn in self.methodlist:
82 self.method = fn
83 self.addcode('module_method', fp)
84 new_ml = new_ml + (
85 '{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
86 %(fn, self.abbrev, fn, self.abbrev, fn))
87 self.methodlist = new_ml
88 self.addcode('module_tail', fp)
Guido van Rossumd2112201995-03-02 14:05:29 +000089
90class object(writer):
91 _type = 'object'
92 def __init__(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +000093 self.typelist = []
94 self.methodlist = []
95 self.funclist = ['new']
96 writer.__init__(self)
Guido van Rossumd2112201995-03-02 14:05:29 +000097
98 def writecode(self, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +000099 self.addcode('copyright', fp)
100 self.writehead(fp)
101 self.writebody(fp)
Guido van Rossumd2112201995-03-02 14:05:29 +0000102
103 def writehead(self, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000104 self.addcode('object_head', fp)
Guido van Rossumd2112201995-03-02 14:05:29 +0000105
106 def writebody(self, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000107 new_ml = ''
108 for fn in self.methodlist:
109 self.method = fn
110 self.addcode('object_method', fp)
111 new_ml = new_ml + (
112 '{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
113 %(fn, self.abbrev, fn, self.abbrev, fn))
114 self.methodlist = new_ml
115 self.addcode('object_mlist', fp)
Guido van Rossumd2112201995-03-02 14:05:29 +0000116
Guido van Rossuma16a5091998-04-10 19:15:27 +0000117 # Add getattr if we have methods
118 if self.methodlist and not 'tp_getattr' in self.funclist:
119 self.funclist.insert(0, 'tp_getattr')
120
121 for fn in FUNCLIST:
122 setattr(self, fn, '0')
Guido van Rossumd2112201995-03-02 14:05:29 +0000123
Guido van Rossuma16a5091998-04-10 19:15:27 +0000124 #
125 # Special case for structure-access objects: put getattr in the
126 # list of functions but don't generate code for it directly,
127 # the code is obtained from the object_structure template.
128 # The same goes for setattr.
129 #
130 if 'structure' in self.typelist:
131 if 'tp_getattr' in self.funclist:
132 self.funclist.remove('tp_getattr')
133 if 'tp_setattr' in self.funclist:
134 self.funclist.remove('tp_setattr')
135 self.tp_getattr = self.abbrev + '_getattr'
136 self.tp_setattr = self.abbrev + '_setattr'
137 for fn in self.funclist:
138 self.addcode('object_'+fn, fp)
139 setattr(self, fn, '%s_%s'%(self.abbrev, fn[3:]))
140 for tn in TYPELIST:
141 setattr(self, tn, '0')
142 for tn in self.typelist:
143 self.addcode('object_'+tn, fp)
144 setattr(self, tn, '&%s_%s'%(self.abbrev, tn[3:]))
145 self.addcode('object_tail', fp)
Guido van Rossumd2112201995-03-02 14:05:29 +0000146
147def write(fp, obj):
148 obj.writecode(fp)
149
150if __name__ == '__main__':
151 o = object()
152 o.name = 'dwarve object'
153 o.abbrev = 'dw'
154 o.funclist = ['new', 'tp_dealloc']
155 o.methodlist = ['dig']
156 m = module()
157 m.name = 'beings'
158 m.abbrev = 'be'
159 m.methodlist = ['newdwarve']
160 m.objects = [o]
161 write(sys.stdout, m)