1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | Tools/framer/framer/function.py
"""Functions.""" from framer import template from framer.util import cstring, unindent METH_O = "METH_O" METH_NOARGS = "METH_NOARGS" METH_VARARGS = "METH_VARARGS" def parsefmt(fmt): for c in fmt: if c == '|': continue yield c class Argument: def __init__(self, name): self.name = name self.ctype = "PyObject *" self.default = None def __str__(self): return "%s%s" % (self.ctype, self.name) def setfmt(self, code): self.ctype = self._codes[code] if self.ctype[-1] != "*": self.ctype += " " _codes = {"O": "PyObject *", "i": "int", } def decl(self): if self.default is None: return str(self) + ";" else: return "%s = %s;" % (self, self.default) class _ArgumentList(object): # these instance variables should be initialized by subclasses ml_meth = None fmt = None def __init__(self, args): self.args = map(Argument, args) def __len__(self): return len(self.args) def __getitem__(self, i): return self.args[i] def dump_decls(self, f): pass class NoArgs(_ArgumentList): def __init__(self, args): assert len(args) == 0 super(NoArgs, self).__init__(args) self.ml_meth = METH_NOARGS def c_args(self): return "PyObject *self" class OneArg(_ArgumentList): def __init__(self, args): assert len(args) == 1 super(OneArg, self).__init__(args) self.ml_meth = METH_O def c_args(self): return "PyObject *self, %s" % self.args[0] class VarArgs(_ArgumentList): def __init__(self, args, fmt=None): super(VarArgs, self).__init__(args) self.ml_meth = METH_VARARGS if fmt is not None: self.fmt = fmt i = 0 for code in parsefmt(fmt): self.args[i].setfmt(code) i += 1 def c_args(self): return "PyObject *self, PyObject *args" def targets(self): return ", ".join(["&%s" % a.name for a in self.args]) def dump_decls(self, f): for a in self.args: print >> f, " %s" % a.decl() def ArgumentList(func, method): code = func.func_code args = code.co_varnames[:code.co_argcount] if method: args = args[1:] pyarg = getattr(func, "pyarg", None) if pyarg is not None: args = VarArgs(args, pyarg) if func.func_defaults: L = list(func.func_defaults) ndefault = len(L) i = len(args) - ndefault while L: args[i].default = L.pop(0) return args else: if len(args) == 0: return NoArgs(args) elif len(args) == 1: return OneArg(args) else: return VarArgs(args) class Function: method = False def __init__(self, func, parent): self._func = func self._parent = parent self.analyze() self.initvars() def dump(self, f): def p(templ, vars=None): # helper function to generate output if vars is None: vars = self.vars print >> f, templ % vars if self.__doc__: p(template.docstring) d = {"name" : self.vars["CName"], "args" : self.args.c_args(), } p(template.funcdef_start, d) self.args.dump_decls(f) if self.args.ml_meth == METH_VARARGS: p(template.varargs) p(template.funcdef_end) def analyze(self): self.__doc__ = self._func.__doc__ self.args = ArgumentList(self._func, self.method) def initvars(self): v = self.vars = {} v["PythonName"] = self._func.__name__ s = v["CName"] = "%s_%s" % (self._parent.name, self._func.__name__) v["DocstringVar"] = s + "_doc" v["MethType"] = self.args.ml_meth if self.__doc__: v["Docstring"] = cstring(unindent(self.__doc__)) if self.args.fmt is not None: v["ArgParse"] = self.args.fmt v["ArgTargets"] = self.args.targets() class Method(Function): method = True |