1
2
3 """
4 This module can be used to generate python source code. It has an interface
5 similar to the "new" module.
6
7 """
8
9 import sys, os
10
11 BANGLINE = "#!/usr/bin/env python\n"
12
14 return ", ".join(map(str, tup))
15
16
17
18
19
20 -def genClass(klassname, parents, attribs=None, doc=None, methods=None):
21 """genClass(name, parents, [attribs, [doc, [methods]]])
22 Return a string of Python source code defineing a class object.
23 Where:
24 name = class name (string)
25 parents = tuple of parent class objects or strings.
26 attribs = class-global attributes to define, contained in a dictionary.
27 doc = a doc string (optional)
28 methods = list of methods strings.
29 """
30 s = []
31 if parents:
32 s.append( "class %s(%s):" % (klassname, _tuplestr(parents)) )
33 else:
34 s.append( "class %s:" % (klassname) )
35 if doc:
36 s.append('\t"""%s"""' % doc)
37 if attribs:
38 for key, val in attribs.items():
39 s.append( "\t%s = %r" % (key, val) )
40 if methods is not None:
41 s.extend(map(str, list(methods)))
42 if len(s) == 1:
43 s.append("\tpass")
44 s.append("\n")
45 return "\n".join(s)
46
47 -def genFunc(funcname, params, body=None, globals=None, doc=None):
60
61 -def genMethod(funcname, params, body=None, globals=None, doc=None):
62 s = []
63 s.append( "def %s(self, %s):" % (funcname, _tuplestr(params)) )
64 if doc:
65 s.append('\t"""%s"""' % doc)
66 if globals is not None:
67 s.append("\tglobal %s" % _tuplestr(globals))
68 if body is None:
69 s.append("\tpass")
70 elif type(body) is str:
71 s.extend( map(lambda l: "\t%s"%l, body.split("\n")) )
72 elif type(body) is list or type(body) is tuple:
73 s.extend( map(lambda l: "\t%s"%l, body) )
74 else:
75 raise TypeError, "invalid type for body text"
76 s.append("\n")
77
78 return "\n".join(map(lambda l: "\t%s"%l, s))
79
84
86 if type(module) is type(sys):
87 module = module.__name__
88 if obj:
89 if type(obj) is tuple or type(obj) is list:
90 obj = _tuplestr(obj)
91 return "%sfrom %s import %s\n" % ("\t"*indent, module, obj)
92 else:
93 return "%simport %s\n" % ("\t"*indent, module)
94
95
96
98 """SourceGen(outfile, [bangline])
99 An instance of this SourceGen class is a factory for generating python
100 source code, by writing to a file object.
101
102 """
103 - def __init__(self, outfile, bangline=None):
104 self.outfile = outfile
105 bangline = bangline or BANGLINE
106 self.outfile.write(bangline)
107
108 - def genClass(self, klassname, parents=None, attribs=None, doc=None, methods=None):
110
111 - def genFunc(self, funcname, params, attribs=None, doc=None):
112 self.outfile.write( genFunc(funcname, params, attribs, doc) )
113
114 - def genMethod(self, funcname, params, body=None, globals=None, doc=None):
115 self.outfile.write( genMethod(funcname, params, body, globals, doc) )
116
119
122
124 self.outfile.write("\n")
125
128
132
133
134
135
137 if type(outfile) is str:
138 outfile = open(outfile, "w")
139 return SourceGen(outfile)
140
141
143 if type(outfile) is str:
144 outfile = open(outfile, "w")
145 return SourceFile(outfile, bangline)
146
147
148
164
165
167 - def __init__(self, funcname, params=None, body=None, globals=None, doc=None):
168 self.name = funcname
169 self.params = params or ()
170 self.body = body
171 self.globals = globals
172 self.doc = doc
173
175 return genMethod(self.name, self.params, self.body, self.globals, self.doc)
176
177
179 - def __init__(self, klassname, parents=None, attributes=None, doc=None, methods=None):
187
188 - def add_method(self, funcname, params, body=None, globals=None, doc=None):
189 mh = MethodHolder(funcname, params, body, globals, doc)
190 self.methods.append(mh)
191 return mh
192
195 set_attribute = add_attribute
200
201
202
204 - def __init__(self, fo=None, bangline=None):
205 print "Writing to", fo
206 self.fo = fo
207 self.elements = []
208 self.docstring = None
209 self.bangline = bangline or BANGLINE
211 s = [self.bangline]
212 if self.docstring:
213 s.append('"""\n%s\n"""\n\n' % (self.docstring))
214 s.extend(map(str, self.elements))
215 return "\n".join(s)
216
218 self.docstring = docstring
225
226 - def add_function(self, funcname, params, attribs=None, doc=None):
230
231 - def add_class(self, klassname, parents, attributes=None, doc=None, methods=None):
235
238
239 - def write(self, fo=None):
240 fo = fo or self.fo
241 fo.write(str(self))
243 filename = filename or self.filename
244 if filename:
245 fo = open(filename, "w")
246 self.write(fo)
247 else:
248 raise ValueError, "SourceFile: no filename given to write to!"
249
250
251
252 if __name__ == "__main__":
255 print "generated classes"
256 print "-----------------"
257 print genComment(__doc__)
258 print genClass("test1", (), {})
259 print genClass("test2", ("sub1",), {})
260 print genClass("test3", ("sub1","sub2"), {})
261 print genClass("test4", (SUBCLASS,), {})
262 print genClass("test5", (), {"attr1": 1})
263 print genClass("test6", (), {}, "One docstring")
264 print genClass("test7", (), {"attr1": 1}, "another docstring")
265
266 print "Holder classes"
267 print "--------------"
268 print genImport(sys.modules[__name__])
269 print genImport(sys)
270 print genImport(sys, "open")
271 ch = ClassHolder("holdclass", ("sub1",))
272 print ch
273 print "--------------"
274 ch.add_method("holdmethod1", ("param1",))
275 print ch
276 print "--------------"
277 ch.add_method("holdmethod2", ("hm2p1",), "print 'body code'", doc="Some docstring")
278 print ch
279 print "--------------"
280 ch.doc = "Documentation for holdclass."
281 print ch
282 print "--------------"
283 sf = SourceFile()
284 sf.add_doc("Testing the generator.")
285 sf.add_import(sys)
286 sf.append(ch)
287 sf.write(sys.stdout)
288