[Stackless-checkins] CVS: slpdev/src/2.2/src/Tools/framer/framer __init__.py, NONE, 1.1 bases.py, NONE, 1.1 function.py, NONE, 1.1 member.py, NONE, 1.1 slots.py, NONE, 1.1 struct.py, NONE, 1.1 structparse.py, NONE, 1.1 template.py, NONE, 1.1 util.py, NONE, 1.1
Christian Tismer
tismer at centera.de
Sat May 1 02:54:49 CEST 2004
- Previous message: [Stackless-checkins] CVS: slpdev/src/2.2/src/Tools/framer README.txt, NONE, 1.1 TODO.txt, NONE, 1.1 example.py, NONE, 1.1
- Next message: [Stackless-checkins] CVS: slpdev/src/2.2/src/Tools/scripts byext.py, NONE, 1.1 combinerefs.py, NONE, 1.1 db2pickle.py, NONE, 1.1 diff.py, NONE, 1.1 gprof2html.py, NONE, 1.1 hotshotmain.py, NONE, 1.1 idle, NONE, 1.1 pickle2db.py, NONE, 1.1 setup.py, NONE, 1.1 texcheck.py, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/slpdev/src/2.2/src/Tools/framer/framer
In directory centera.de:/home/tismer/slpdev/src/2.2/src/Tools/framer/framer
Added Files:
__init__.py bases.py function.py member.py slots.py struct.py
structparse.py template.py util.py
Log Message:
added files
--- NEW FILE: __init__.py ---
"""A tool to generate basic framework for C extension types.
The basic ideas is the same as modulator, but the code generates code
using many of the new features introduced in Python 2.2. It also
takes a more declarative approach to generating code.
"""
--- NEW FILE: bases.py ---
"""Provides the Module and Type base classes that user code inherits from."""
__all__ = ["Module", "Type", "member"]
from framer import struct, template
from framer.function import Function, Method
from framer.member import member
from framer.slots import *
from framer.util import cstring, unindent
from types import FunctionType
def sortitems(dict):
L = dict.items()
L.sort()
return L
# The Module and Type classes are implemented using metaclasses,
# because most of the methods are class methods. It is easier to use
# metaclasses than the cumbersome classmethod() builtin. They have
# class methods because they are exposed to user code as base classes.
class BaseMetaclass(type):
"""Shared infrastructure for generating modules and types."""
# just methoddef so far
def dump_methoddef(self, f, functions, vars):
def p(templ, vars=vars): # helper function to generate output
print >> f, templ % vars
if not functions:
return
p(template.methoddef_start)
for name, func in sortitems(functions):
if func.__doc__:
p(template.methoddef_def_doc, func.vars)
else:
p(template.methoddef_def, func.vars)
p(template.methoddef_end)
class ModuleMetaclass(BaseMetaclass):
"""Provides methods for Module class."""
def gen(self):
self.analyze()
self.initvars()
f = open(self.__filename, "w")
self.dump(f)
f.close()
def analyze(self):
self.name = getattr(self, "abbrev", self.__name__)
self.__functions = {}
self.__types = {}
self.__members = False
for name, obj in self.__dict__.iteritems():
if isinstance(obj, FunctionType):
self.__functions[name] = Function(obj, self)
elif isinstance(obj, TypeMetaclass):
obj._TypeMetaclass__module = self.name
obj.analyze()
self.__types[name] = obj
if obj.has_members():
self.__members = True
def initvars(self):
v = self.__vars = {}
filename = getattr(self, "__file__", None)
if filename is None:
filename = self.__name__ + "module.c"
self.__filename = v["FileName"] = filename
name = v["ModuleName"] = self.__name__
v["MethodDefName"] = "%s_methods" % name
v["ModuleDocstring"] = cstring(unindent(self.__doc__))
def dump(self, f):
def p(templ, vars=self.__vars): # helper function to generate output
print >> f, templ % vars
p(template.module_start)
if self.__members:
p(template.member_include)
print >> f
if self.__doc__:
p(template.module_doc)
for name, type in sortitems(self.__types):
type.dump(f)
for name, func in sortitems(self.__functions):
func.dump(f)
self.dump_methoddef(f, self.__functions, self.__vars)
p(template.module_init_start)
for name, type in sortitems(self.__types):
type.dump_init(f)
p("}")
class Module:
__metaclass__ = ModuleMetaclass
class TypeMetaclass(BaseMetaclass):
def dump(self, f):
self.initvars()
# defined after initvars() so that __vars is defined
def p(templ, vars=self.__vars):
print >> f, templ % vars
if self.struct is not None:
print >> f, unindent(self.struct, False)
if self.__doc__:
p(template.docstring)
for name, func in sortitems(self.__methods):
func.dump(f)
self.dump_methoddef(f, self.__methods, self.__vars)
self.dump_memberdef(f)
self.dump_slots(f)
def has_members(self):
if self.__members:
return True
else:
return False
def analyze(self):
# called by ModuleMetaclass analyze()
self.name = getattr(self, "abbrev", self.__name__)
src = getattr(self, "struct", None)
if src is not None:
self.__struct = struct.parse(src)
else:
self.__struct = None
self.__methods = {}
self.__members = {}
for cls in self.__mro__:
for k, v in cls.__dict__.iteritems():
if isinstance(v, FunctionType):
self.__methods[k] = Method(v, self)
if isinstance(v, member):
self.__members[k] = v
assert self.__struct is not None
v.register(k, self.__struct)
self.analyze_slots()
def analyze_slots(self):
self.__slots = {}
for s in Slots:
if s.special is not None:
meth = self.__methods.get(s.special)
if meth is not None:
self.__slots[s] = meth
self.__slots[TP_NAME] = '"%s.%s"' % (self.__module, self.__name__)
if self.__doc__:
self.__slots[TP_DOC] = "%s_doc" % self.name
if self.__struct is not None:
self.__slots[TP_BASICSIZE] = "sizeof(%s)" % self.__struct.name
self.__slots[TP_DEALLOC] = "%s_dealloc" % self.name
if self.__methods:
self.__slots[TP_METHODS] = "%s_methods" % self.name
if self.__members:
self.__slots[TP_MEMBERS] = "%s_members" % self.name
def initvars(self):
v = self.__vars = {}
v["TypeName"] = self.__name__
v["CTypeName"] = "Py%s_Type" % self.__name__
v["MethodDefName"] = self.__slots[TP_METHODS]
if self.__doc__:
v["DocstringVar"] = self.__slots[TP_DOC]
v["Docstring"] = cstring(unindent(self.__doc__))
if self.__struct is not None:
v["StructName"] = self.__struct.name
if self.__members:
v["MemberDefName"] = self.__slots[TP_MEMBERS]
def dump_memberdef(self, f):
def p(templ, vars=self.__vars):
print >> f, templ % vars
if not self.__members:
return
p(template.memberdef_start)
for name, slot in sortitems(self.__members):
slot.dump(f)
p(template.memberdef_end)
def dump_slots(self, f):
def p(templ, vars=self.__vars):
print >> f, templ % vars
if self.struct:
p(template.dealloc_func, {"name" : self.__slots[TP_DEALLOC]})
p(template.type_struct_start)
for s in Slots[:-5]: # XXX
val = self.__slots.get(s, s.default)
ntabs = 4 - (4 + len(val)) / 8
line = " %s,%s/* %s */" % (val, "\t" * ntabs, s.name)
print >> f, line
p(template.type_struct_end)
def dump_init(self, f):
def p(templ):
print >> f, templ % self.__vars
p(template.type_init_type)
p(template.module_add_type)
class Type:
__metaclass__ = TypeMetaclass
--- NEW FILE: 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
--- NEW FILE: member.py ---
from framer import template
from framer.util import cstring, unindent
T_SHORT = "T_SHORT"
T_INT = "T_INT"
T_LONG = "T_LONG"
T_FLOAT = "T_FLOAT"
T_DOUBLE = "T_DOUBLE"
T_STRING = "T_STRING"
T_OBJECT = "T_OBJECT"
T_CHAR = "T_CHAR"
T_BYTE = "T_BYTE"
T_UBYTE = "T_UBYTE"
T_UINT = "T_UINT"
T_ULONG = "T_ULONG"
T_STRING_INPLACE = "T_STRING_INPLACE"
T_OBJECT_EX = "T_OBJECT_EX"
RO = READONLY = "READONLY"
READ_RESTRICTED = "READ_RESTRICTED"
WRITE_RESTRICTED = "WRITE_RESTRICTED"
RESTRICT = "RESTRICTED"
c2t = {"int" : T_INT,
"unsigned int" : T_UINT,
"long" : T_LONG,
"unsigned long" : T_LONG,
"float" : T_FLOAT,
"double" : T_DOUBLE,
"char *" : T_CHAR,
"PyObject *" : T_OBJECT,
}
class member(object):
def __init__(self, cname=None, type=None, flags=None, doc=None):
self.type = type
self.flags = flags
self.cname = cname
self.doc = doc
self.name = None
self.struct = None
def register(self, name, struct):
self.name = name
self.struct = struct
self.initvars()
def initvars(self):
v = self.vars = {}
v["PythonName"] = self.name
if self.cname is not None:
v["CName"] = self.cname
else:
v["CName"] = self.name
v["Flags"] = self.flags or "0"
v["Type"] = self.get_type()
if self.doc is not None:
v["Docstring"] = cstring(unindent(self.doc))
v["StructName"] = self.struct.name
def get_type(self):
"""Deduce type code from struct specification if not defined"""
if self.type is not None:
return self.type
ctype = self.struct.get_type(self.name)
return c2t[ctype]
def dump(self, f):
if self.doc is None:
print >> f, template.memberdef_def % self.vars
else:
print >> f, template.memberdef_def_doc % self.vars
--- NEW FILE: slots.py ---
"""Descriptions of all the slots in Python's type objects."""
class Slot(object):
def __init__(self, name, cast=None, special=None, default="0"):
self.name = name
self.cast = cast
self.special = special
self.default = default
Slots = (Slot("ob_size"),
Slot("tp_name"),
Slot("tp_basicsize"),
Slot("tp_itemsize"),
Slot("tp_dealloc", "destructor"),
Slot("tp_print", "printfunc"),
Slot("tp_getattr", "getattrfunc"),
Slot("tp_setattr", "setattrfunc"),
Slot("tp_compare", "cmpfunc", "__cmp__"),
Slot("tp_repr", "reprfunc", "__repr__"),
Slot("tp_as_number"),
Slot("tp_as_sequence"),
Slot("tp_as_mapping"),
Slot("tp_hash", "hashfunc", "__hash__"),
Slot("tp_call", "ternaryfunc", "__call__"),
Slot("tp_str", "reprfunc", "__str__"),
Slot("tp_getattro", "getattrofunc", "__getattr__", # XXX
"PyObject_GenericGetAttr"),
Slot("tp_setattro", "setattrofunc", "__setattr__"),
Slot("tp_as_buffer"),
Slot("tp_flags", default="Py_TPFLAGS_DEFAULT"),
Slot("tp_doc"),
Slot("tp_traverse", "traverseprox"),
Slot("tp_clear", "inquiry"),
Slot("tp_richcompare", "richcmpfunc"),
Slot("tp_weaklistoffset"),
Slot("tp_iter", "getiterfunc", "__iter__"),
Slot("tp_iternext", "iternextfunc", "__next__"), # XXX
Slot("tp_methods"),
Slot("tp_members"),
Slot("tp_getset"),
Slot("tp_base"),
Slot("tp_dict"),
Slot("tp_descr_get", "descrgetfunc"),
Slot("tp_descr_set", "descrsetfunc"),
Slot("tp_dictoffset"),
Slot("tp_init", "initproc", "__init__"),
Slot("tp_alloc", "allocfunc"),
Slot("tp_new", "newfunc"),
Slot("tp_free", "freefunc"),
Slot("tp_is_gc", "inquiry"),
Slot("tp_bases"),
Slot("tp_mro"),
Slot("tp_cache"),
Slot("tp_subclasses"),
Slot("tp_weaklist"),
)
# give some slots symbolic names
TP_NAME = Slots[1]
TP_BASICSIZE = Slots[2]
TP_DEALLOC = Slots[4]
TP_DOC = Slots[20]
TP_METHODS = Slots[27]
TP_MEMBERS = Slots[28]
--- NEW FILE: struct.py ---
"""Rudimentary parser for C struct definitions."""
import re
PyObject_HEAD = "PyObject_HEAD"
PyObject_VAR_HEAD = "PyObject_VAR_HEAD"
rx_name = re.compile("} (\w+);")
class Struct:
def __init__(self, name, head, members):
self.name = name
self.head = head
self.members = members
def get_type(self, name):
for _name, type in self.members:
if name == _name:
return type
raise ValueError, "no member named %s" % name
def parse(s):
"""Parse a C struct definition.
The parser is very restricted in what it will accept.
"""
lines = filter(None, s.split("\n")) # get non-empty lines
assert lines[0].strip() == "typedef struct {"
pyhead = lines[1].strip()
assert (pyhead.startswith("PyObject") and
pyhead.endswith("HEAD"))
members = []
for line in lines[2:]:
line = line.strip()
if line.startswith("}"):
break
assert line.endswith(";")
line = line[:-1]
words = line.split()
name = words[-1]
type = " ".join(words[:-1])
if name[0] == "*":
name = name[1:]
type += " *"
members.append((name, type))
name = None
mo = rx_name.search(line)
assert mo is not None
name = mo.group(1)
return Struct(name, pyhead, members)
--- NEW FILE: structparse.py ---
"""Rudimentary parser for C struct definitions."""
import re
PyObject_HEAD = "PyObject_HEAD"
PyObject_VAR_HEAD = "PyObject_VAR_HEAD"
rx_name = re.compile("} (\w+);")
class Struct:
def __init__(self, name, head, members):
self.name = name
self.head = head
self.members = members
def parse(s):
"""Parse a C struct definition.
The parser is very restricted in what it will accept.
"""
lines = filter(None, s.split("\n")) # get non-empty lines
assert lines[0].strip() == "typedef struct {"
pyhead = lines[1].strip()
assert (pyhead.startswith("PyObject") and
pyhead.endswith("HEAD"))
members = []
for line in lines[2:]:
line = line.strip()
if line.startswith("}"):
break
assert line.endswith(";")
line = line[:-1]
words = line.split()
name = words[-1]
type = " ".join(words[:-1])
if name[0] == "*":
name = name[1:]
type += " *"
members.append((name, type))
name = None
mo = rx_name.search(line)
assert mo is not None
name = mo.group(1)
return Struct(name, pyhead, members)
--- NEW FILE: template.py ---
"""framer's C code templates.
Templates use the following variables:
FileName: name of the file that contains the C source code
ModuleName: name of the module, as in "import ModuleName"
ModuleDocstring: C string containing the module doc string
"""
module_start = '#include "Python.h"'
member_include = '#include "structmember.h"'
module_doc = """\
PyDoc_STRVAR(%(ModuleName)s_doc,
%(ModuleDocstring)s);
"""
methoddef_start = """\
static struct PyMethodDef %(MethodDefName)s[] = {"""
methoddef_def = """\
{"%(PythonName)s", (PyCFunction)%(CName)s, %(MethType)s},"""
methoddef_def_doc = """\
{"%(PythonName)s", (PyCFunction)%(CName)s, %(MethType)s,
%(DocstringVar)s},"""
methoddef_end = """\
{NULL, NULL}
};
"""
memberdef_start = """\
#define OFF(X) offsetof(%(StructName)s, X)
static struct PyMemberDef %(MemberDefName)s[] = {"""
memberdef_def_doc = """\
{"%(PythonName)s", %(Type)s, OFF(%(CName)s), %(Flags)s,
%(Docstring)s},"""
memberdef_def = """\
{"%(PythonName)s", %(Type)s, OFF(%(CName)s), %(Flags)s},"""
memberdef_end = """\
{NULL}
};
#undef OFF
"""
dealloc_func = """static void
%(name)s(PyObject *ob)
{
}
"""
docstring = """\
PyDoc_STRVAR(%(DocstringVar)s,
%(Docstring)s);
"""
funcdef_start = """\
static PyObject *
%(name)s(%(args)s)
{"""
funcdef_end = """\
}
"""
varargs = """\
if (!PyArg_ParseTuple(args, \"%(ArgParse)s:%(PythonName)s\",
%(ArgTargets)s))
return NULL;"""
module_init_start = """\
PyMODINIT_FUNC
init%(ModuleName)s(void)
{
PyObject *mod;
mod = Py_InitModule3("%(ModuleName)s", %(MethodDefName)s,
%(ModuleName)s_doc);
if (mod == NULL)
return;
"""
type_init_type = " %(CTypeName)s.ob_type = &PyType_Type;"
module_add_type = """\
if (!PyObject_SetAttrString(mod, "%(TypeName)s",
(PyObject *)&%(CTypeName)s))
return;
"""
type_struct_start = """\
static PyTypeObject %(CTypeName)s = {
PyObject_HEAD_INIT(0)"""
type_struct_end = """\
};
"""
--- NEW FILE: util.py ---
def cstring(s, width=70):
"""Return C string representation of a Python string.
width specifies the maximum width of any line of the C string.
"""
L = []
for l in s.split("\n"):
if len(l) < width:
L.append(r'"%s\n"' % l)
return "\n".join(L)
def unindent(s, skipfirst=True):
"""Return an unindented version of a docstring.
Removes indentation on lines following the first one, using the
leading whitespace of the first indented line that is not blank
to determine the indentation.
"""
lines = s.split("\n")
if skipfirst:
first = lines.pop(0)
L = [first]
else:
L = []
indent = None
for l in lines:
ls = l.strip()
if ls:
indent = len(l) - len(ls)
break
L += [l[indent:] for l in lines]
return "\n".join(L)
_______________________________________________
Stackless-checkins mailing list
Stackless-checkins at stackless.com
http://www.stackless.com/mailman/listinfo/stackless-checkins
- Previous message: [Stackless-checkins] CVS: slpdev/src/2.2/src/Tools/framer README.txt, NONE, 1.1 TODO.txt, NONE, 1.1 example.py, NONE, 1.1
- Next message: [Stackless-checkins] CVS: slpdev/src/2.2/src/Tools/scripts byext.py, NONE, 1.1 combinerefs.py, NONE, 1.1 db2pickle.py, NONE, 1.1 diff.py, NONE, 1.1 gprof2html.py, NONE, 1.1 hotshotmain.py, NONE, 1.1 idle, NONE, 1.1 pickle2db.py, NONE, 1.1 setup.py, NONE, 1.1 texcheck.py, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Stackless-checkins
mailing list