blob: 5788b955796c7e4e9092dc51b8c8bd750e2eb1a5 [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
Guido van Rossumd2112201995-03-02 14:05:29 +000023
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',
Guido van Rossuma16a5091998-04-10 19:15:27 +000030 'tp_compare', 'tp_repr', 'tp_hash', 'tp_call', 'tp_str']
Guido van Rossumd2112201995-03-02 14:05:29 +000031TYPELIST = ['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):
Guido van Rossuma16a5091998-04-10 19:15:27 +000039 self._subst = None
Guido van Rossumd2112201995-03-02 14:05:29 +000040
41 def makesubst(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +000042 if not self._subst:
43 if not self.__dict__.has_key('abbrev'):
44 self.abbrev = self.name
Walter Dörwaldaaab30e2002-09-11 20:36:02 +000045 self.Abbrev = self.abbrev[0].upper()+self.abbrev[1:]
Guido van Rossuma16a5091998-04-10 19:15:27 +000046 subst = varsubst.Varsubst(self.__dict__)
47 subst.useindent(1)
48 self._subst = subst.subst
Guido van Rossumd2112201995-03-02 14:05:29 +000049
50 def addcode(self, name, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +000051 ifp = self.opentemplate(name)
52 self.makesubst()
53 d = ifp.read()
54 d = self._subst(d)
55 fp.write(d)
Guido van Rossumd2112201995-03-02 14:05:29 +000056
57 def opentemplate(self, name):
Guido van Rossuma16a5091998-04-10 19:15:27 +000058 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
Guido van Rossumd2112201995-03-02 14:05:29 +000069class module(writer):
70 _type = 'module'
71
72 def writecode(self, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +000073 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)
Guido van Rossumd2112201995-03-02 14:05:29 +000088
89class object(writer):
90 _type = 'object'
91 def __init__(self):
Guido van Rossuma16a5091998-04-10 19:15:27 +000092 self.typelist = []
93 self.methodlist = []
94 self.funclist = ['new']
95 writer.__init__(self)
Guido van Rossumd2112201995-03-02 14:05:29 +000096
97 def writecode(self, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +000098 self.addcode('copyright', fp)
99 self.writehead(fp)
100 self.writebody(fp)
Guido van Rossumd2112201995-03-02 14:05:29 +0000101
102 def writehead(self, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000103 self.addcode('object_head', fp)
Guido van Rossumd2112201995-03-02 14:05:29 +0000104
105 def writebody(self, fp):
Guido van Rossuma16a5091998-04-10 19:15:27 +0000106 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)
Guido van Rossumd2112201995-03-02 14:05:29 +0000115
Guido van Rossuma16a5091998-04-10 19:15:27 +0000116 # 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')
Guido van Rossumd2112201995-03-02 14:05:29 +0000122
Guido van Rossuma16a5091998-04-10 19:15:27 +0000123 #
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)
Guido van Rossumd2112201995-03-02 14:05:29 +0000145
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)