1"""Provides the Module and Type base classes that user code inherits from.""" 2 3__all__ = ["Module", "Type", "member"] 4 5from framer import struct, template 6from framer.function import Function, Method 7from framer.member import member 8from framer.slots import * 9from framer.util import cstring, unindent 10 11from types import FunctionType 12 13def sortitems(dict): 14 L = dict.items() 15 L.sort() 16 return L 17 18# The Module and Type classes are implemented using metaclasses, 19# because most of the methods are class methods. It is easier to use 20# metaclasses than the cumbersome classmethod() builtin. They have 21# class methods because they are exposed to user code as base classes. 22 23class BaseMetaclass(type): 24 """Shared infrastructure for generating modules and types.""" 25 26 # just methoddef so far 27 28 def dump_methoddef(self, f, functions, vars): 29 def p(templ, vars=vars): # helper function to generate output 30 print >> f, templ % vars 31 32 if not functions: 33 return 34 p(template.methoddef_start) 35 for name, func in sortitems(functions): 36 if func.__doc__: 37 p(template.methoddef_def_doc, func.vars) 38 else: 39 p(template.methoddef_def, func.vars) 40 p(template.methoddef_end) 41 42class ModuleMetaclass(BaseMetaclass): 43 """Provides methods for Module class.""" 44 45 def gen(self): 46 self.analyze() 47 self.initvars() 48 f = open(self.__filename, "w") 49 self.dump(f) 50 f.close() 51 52 def analyze(self): 53 self.name = getattr(self, "abbrev", self.__name__) 54 self.__functions = {} 55 self.__types = {} 56 self.__members = False 57 58 for name, obj in self.__dict__.iteritems(): 59 if isinstance(obj, FunctionType): 60 self.__functions[name] = Function(obj, self) 61 elif isinstance(obj, TypeMetaclass): 62 obj._TypeMetaclass__module = self.name 63 obj.analyze() 64 self.__types[name] = obj 65 if obj.has_members(): 66 self.__members = True 67 68 def initvars(self): 69 v = self.__vars = {} 70 filename = getattr(self, "__file__", None) 71 if filename is None: 72 filename = self.__name__ + "module.c" 73 self.__filename = v["FileName"] = filename 74 name = v["ModuleName"] = self.__name__ 75 v["MethodDefName"] = "%s_methods" % name 76 v["ModuleDocstring"] = cstring(unindent(self.__doc__)) 77 78 def dump(self, f): 79 def p(templ, vars=self.__vars): # helper function to generate output 80 print >> f, templ % vars 81 82 p(template.module_start) 83 if self.__members: 84 p(template.member_include) 85 print >> f 86 87 if self.__doc__: 88 p(template.module_doc) 89 90 for name, type in sortitems(self.__types): 91 type.dump(f) 92 93 for name, func in sortitems(self.__functions): 94 func.dump(f) 95 96 self.dump_methoddef(f, self.__functions, self.__vars) 97 98 p(template.module_init_start) 99 for name, type in sortitems(self.__types): 100 type.dump_init(f) 101 102 p("}") 103 104class Module: 105 __metaclass__ = ModuleMetaclass 106 107class TypeMetaclass(BaseMetaclass): 108 109 def dump(self, f): 110 self.initvars() 111 112 # defined after initvars() so that __vars is defined 113 def p(templ, vars=self.__vars): 114 print >> f, templ % vars 115 116 if self.struct is not None: 117 print >> f, unindent(self.struct, False) 118 119 if self.__doc__: 120 p(template.docstring) 121 122 for name, func in sortitems(self.__methods): 123 func.dump(f) 124 125 self.dump_methoddef(f, self.__methods, self.__vars) 126 self.dump_memberdef(f) 127 self.dump_slots(f) 128 129 def has_members(self): 130 if self.__members: 131 return True 132 else: 133 return False 134 135 def analyze(self): 136 # called by ModuleMetaclass analyze() 137 self.name = getattr(self, "abbrev", self.__name__) 138 src = getattr(self, "struct", None) 139 if src is not None: 140 self.__struct = struct.parse(src) 141 else: 142 self.__struct = None 143 self.__methods = {} 144 self.__members = {} 145 for cls in self.__mro__: 146 for k, v in cls.__dict__.iteritems(): 147 if isinstance(v, FunctionType): 148 self.__methods[k] = Method(v, self) 149 if isinstance(v, member): 150 self.__members[k] = v 151 assert self.__struct is not None 152 v.register(k, self.__struct) 153 self.analyze_slots() 154 155 def analyze_slots(self): 156 self.__slots = {} 157 for s in Slots: 158 if s.special is not None: 159 meth = self.__methods.get(s.special) 160 if meth is not None: 161 self.__slots[s] = meth 162 self.__slots[TP_NAME] = '"%s.%s"' % (self.__module, self.__name__) 163 if self.__doc__: 164 self.__slots[TP_DOC] = "%s_doc" % self.name 165 if self.__struct is not None: 166 self.__slots[TP_BASICSIZE] = "sizeof(%s)" % self.__struct.name 167 self.__slots[TP_DEALLOC] = "%s_dealloc" % self.name 168 if self.__methods: 169 self.__slots[TP_METHODS] = "%s_methods" % self.name 170 if self.__members: 171 self.__slots[TP_MEMBERS] = "%s_members" % self.name 172 173 def initvars(self): 174 v = self.__vars = {} 175 v["TypeName"] = self.__name__ 176 v["CTypeName"] = "Py%s_Type" % self.__name__ 177 v["MethodDefName"] = self.__slots[TP_METHODS] 178 if self.__doc__: 179 v["DocstringVar"] = self.__slots[TP_DOC] 180 v["Docstring"] = cstring(unindent(self.__doc__)) 181 if self.__struct is not None: 182 v["StructName"] = self.__struct.name 183 if self.__members: 184 v["MemberDefName"] = self.__slots[TP_MEMBERS] 185 186 def dump_memberdef(self, f): 187 def p(templ, vars=self.__vars): 188 print >> f, templ % vars 189 190 if not self.__members: 191 return 192 p(template.memberdef_start) 193 for name, slot in sortitems(self.__members): 194 slot.dump(f) 195 p(template.memberdef_end) 196 197 def dump_slots(self, f): 198 def p(templ, vars=self.__vars): 199 print >> f, templ % vars 200 201 if self.struct: 202 p(template.dealloc_func, {"name" : self.__slots[TP_DEALLOC]}) 203 204 p(template.type_struct_start) 205 for s in Slots[:-5]: # XXX 206 val = self.__slots.get(s, s.default) 207 ntabs = 4 - (4 + len(val)) / 8 208 line = " %s,%s/* %s */" % (val, "\t" * ntabs, s.name) 209 print >> f, line 210 p(template.type_struct_end) 211 212 def dump_init(self, f): 213 def p(templ): 214 print >> f, templ % self.__vars 215 216 p(template.type_init_type) 217 p(template.module_add_type) 218 219class Type: 220 __metaclass__ = TypeMetaclass 221