+++ /dev/null
-"""Functions."""\r
-\r
-from framer import template\r
-from framer.util import cstring, unindent\r
-\r
-METH_O = "METH_O"\r
-METH_NOARGS = "METH_NOARGS"\r
-METH_VARARGS = "METH_VARARGS"\r
-\r
-def parsefmt(fmt):\r
- for c in fmt:\r
- if c == '|':\r
- continue\r
- yield c\r
-\r
-class Argument:\r
-\r
- def __init__(self, name):\r
- self.name = name\r
- self.ctype = "PyObject *"\r
- self.default = None\r
-\r
- def __str__(self):\r
- return "%s%s" % (self.ctype, self.name)\r
-\r
- def setfmt(self, code):\r
- self.ctype = self._codes[code]\r
- if self.ctype[-1] != "*":\r
- self.ctype += " "\r
-\r
- _codes = {"O": "PyObject *",\r
- "i": "int",\r
- }\r
-\r
- def decl(self):\r
- if self.default is None:\r
- return str(self) + ";"\r
- else:\r
- return "%s = %s;" % (self, self.default)\r
-\r
-class _ArgumentList(object):\r
-\r
- # these instance variables should be initialized by subclasses\r
- ml_meth = None\r
- fmt = None\r
-\r
- def __init__(self, args):\r
- self.args = map(Argument, args)\r
-\r
- def __len__(self):\r
- return len(self.args)\r
-\r
- def __getitem__(self, i):\r
- return self.args[i]\r
-\r
- def dump_decls(self, f):\r
- pass\r
-\r
-class NoArgs(_ArgumentList):\r
-\r
- def __init__(self, args):\r
- assert len(args) == 0\r
- super(NoArgs, self).__init__(args)\r
- self.ml_meth = METH_NOARGS\r
-\r
- def c_args(self):\r
- return "PyObject *self"\r
-\r
-class OneArg(_ArgumentList):\r
-\r
- def __init__(self, args):\r
- assert len(args) == 1\r
- super(OneArg, self).__init__(args)\r
- self.ml_meth = METH_O\r
-\r
- def c_args(self):\r
- return "PyObject *self, %s" % self.args[0]\r
-\r
-class VarArgs(_ArgumentList):\r
-\r
- def __init__(self, args, fmt=None):\r
- super(VarArgs, self).__init__(args)\r
- self.ml_meth = METH_VARARGS\r
- if fmt is not None:\r
- self.fmt = fmt\r
- i = 0\r
- for code in parsefmt(fmt):\r
- self.args[i].setfmt(code)\r
- i += 1\r
-\r
- def c_args(self):\r
- return "PyObject *self, PyObject *args"\r
-\r
- def targets(self):\r
- return ", ".join(["&%s" % a.name for a in self.args])\r
-\r
- def dump_decls(self, f):\r
- for a in self.args:\r
- print >> f, " %s" % a.decl()\r
-\r
-def ArgumentList(func, method):\r
- code = func.func_code\r
- args = code.co_varnames[:code.co_argcount]\r
- if method:\r
- args = args[1:]\r
- pyarg = getattr(func, "pyarg", None)\r
- if pyarg is not None:\r
- args = VarArgs(args, pyarg)\r
- if func.func_defaults:\r
- L = list(func.func_defaults)\r
- ndefault = len(L)\r
- i = len(args) - ndefault\r
- while L:\r
- args[i].default = L.pop(0)\r
- return args\r
- else:\r
- if len(args) == 0:\r
- return NoArgs(args)\r
- elif len(args) == 1:\r
- return OneArg(args)\r
- else:\r
- return VarArgs(args)\r
-\r
-class Function:\r
-\r
- method = False\r
-\r
- def __init__(self, func, parent):\r
- self._func = func\r
- self._parent = parent\r
- self.analyze()\r
- self.initvars()\r
-\r
- def dump(self, f):\r
- def p(templ, vars=None): # helper function to generate output\r
- if vars is None:\r
- vars = self.vars\r
- print >> f, templ % vars\r
-\r
- if self.__doc__:\r
- p(template.docstring)\r
-\r
- d = {"name" : self.vars["CName"],\r
- "args" : self.args.c_args(),\r
- }\r
- p(template.funcdef_start, d)\r
-\r
- self.args.dump_decls(f)\r
-\r
- if self.args.ml_meth == METH_VARARGS:\r
- p(template.varargs)\r
-\r
- p(template.funcdef_end)\r
-\r
- def analyze(self):\r
- self.__doc__ = self._func.__doc__\r
- self.args = ArgumentList(self._func, self.method)\r
-\r
- def initvars(self):\r
- v = self.vars = {}\r
- v["PythonName"] = self._func.__name__\r
- s = v["CName"] = "%s_%s" % (self._parent.name, self._func.__name__)\r
- v["DocstringVar"] = s + "_doc"\r
- v["MethType"] = self.args.ml_meth\r
- if self.__doc__:\r
- v["Docstring"] = cstring(unindent(self.__doc__))\r
- if self.args.fmt is not None:\r
- v["ArgParse"] = self.args.fmt\r
- v["ArgTargets"] = self.args.targets()\r
-\r
-class Method(Function):\r
-\r
- method = True\r