Files
pycapnp/bootstrap/setup.py
2013-06-25 22:43:26 -07:00

261 lines
8.7 KiB
Python

#!/usr/bin/env python
from distutils.core import setup
from Cython.Build import cythonize
from jinja2 import Environment, FileSystemLoader
import os
curr_dir = os.path.abspath(os.path.dirname(__file__))
env = Environment(loader=FileSystemLoader(curr_dir))
nodes = {
'Node' : {'body' : 'struct',
'members' : {
'id' : {'type' : 'UInt64'},
'displayName' : {'type' : 'Text'},
'scopeId' : {'type' : 'UInt64'},
'nestedNodes' : {'type' : 'List[Node.NestedNode]'},
'NestedNode' : {'body' : 'struct', 'is_not_field' : True,
'members' : {
'name' : {'type' : 'Text'},
'id' : {'type' : 'UInt64'},
}},
'annotations' : {'type' : 'List[Annotation]'},
'body' : {'body' : 'union',
'members' : {
'fileNode' : {'type' : 'FileNode'},
'structNode' : {'type' : 'StructNode'},
'enumNode' : {'type' : 'EnumNode'},
'interfaceNode' : {'type' : 'InterfaceNode'},
'constNode' : {'type' : 'ConstNode'},
'annotationNode' : {'type' : 'AnnotationNode'},
}},
}},
'Type' : {'body' : 'struct',
'members' : {
'body' : {'body' : 'union',
'members' : {
'voidType' : {'type' : 'Void'},
'boolType' : {'type' : 'Void'},
'int8Type' : {'type' : 'Void'},
'int16Type' : {'type' : 'Void'},
'int32Type' : {'type' : 'Void'},
'int64Type' : {'type' : 'Void'},
'uint8Type' : {'type' : 'Void'},
'uint16Type' : {'type' : 'Void'},
'uint32Type' : {'type' : 'Void'},
'uint64Type' : {'type' : 'Void'},
'float32Type' : {'type' : 'Void'},
'float64Type' : {'type' : 'Void'},
'textType' : {'type' : 'Void'},
'dataType' : {'type' : 'Void'},
'listType' : {'type' : 'Type'},
'enumType' : {'type' : 'UInt64'},
'structType' : {'type' : 'UInt64'},
'interfaceType' : {'type' : 'UInt64'},
'objectType' : {'type' : 'Void'},
}},
}},
'Value' : {'body' : 'struct',
'members' : {
'body' : {'body' : 'union',
'members' : {
'voidValue' : {'type' : 'Void'},
'boolValue' : {'type' : 'Bool'},
'int8Value' : {'type' : 'Int8'},
'int16Value' : {'type' : 'Int16'},
'int32Value' : {'type' : 'Int32'},
'int64Value' : {'type' : 'Int64'},
'uint8Value' : {'type' : 'UInt8'},
'uint16Value' : {'type' : 'UInt16'},
'uint32Value' : {'type' : 'UInt32'},
'uint64Value' : {'type' : 'UInt64'},
'float32Value' : {'type' : 'Float32'},
'float64Value' : {'type' : 'Float64'},
'textValue' : {'type' : 'Text'},
'dataValue' : {'type' : 'Data'},
'listValue' : {'type' : 'Object'},
'enumValue' : {'type' : 'UInt16'},
'structValue' : {'type' : 'Object'},
'interfaceValue' : {'type' : 'Void'},
'objectValue' : {'type' : 'Object'},
}},
}},
'Annotation' : {'body' : 'struct',
'members' : {
'id' : {'type' : 'UInt64'},
'value' : {'type' : 'Value'},
}},
'FileNode' : {'body' : 'struct',
'members' : {
'imports' : {'type' : 'List[FileNode.Import]'},
'Import' : {'body' : 'struct', 'is_not_field' : True,
'members' : {
'id' : {'type' : 'UInt64'},
'name' : {'type' : 'Text'},
}},
}},
'ElementSize' : {'body' : 'enum',
'members' : {
'empty' : {},
'bit' : {},
'byte' : {},
'twoBytes' : {},
'fourBytes' : {},
'eightBytes' : {},
'pointer' : {},
'inlineComposite' : {},
}},
'StructNode' : {'body' : 'struct',
'members' : {
'dataSectionWordSize' : {'type' : 'UInt16'},
'pointerSectionSize' : {'type' : 'UInt16'},
# 'preferredListEncoding' : {'type' : 'ElementSize'},
'members' : {'type' : 'List[StructNode.Member]'},
'Member' : {'body' : 'struct', 'is_not_field' : True,
'members' : {
'name' : {'type' : 'Text'},
'ordinal' : {'type' : 'UInt16'},
'codeOrder' : {'type' : 'UInt16'},
'annotations' : {'type' : 'List[Annotation]'},
'body' : {'body' : 'union',
'members' : {
'fieldMember' : {'type' : 'StructNode.Field'},
'unionMember' : {'type' : 'StructNode.Union'},
}},
}},
'Field' : {'body' : 'struct', 'is_not_field' : True,
'members' : {
'offset' : {'type' : 'UInt32'},
'type' : {'type' : 'Type'},
'defaultValue' : {'type' : 'Value'},
}},
'Union' : {'body' : 'struct', 'is_not_field' : True,
'members' : {
'discriminantOffset' : {'type' : 'UInt32'},
'members' : {'type' : 'List[StructNode.Member]'},
}},
}},
'EnumNode' : {'body' : 'struct',
'members' : {
'enumerants' : {'type' : 'List[EnumNode.Enumerant]'},
'Enumerant' : {'body' : 'struct', 'is_not_field' : True,
'members' : {
'name' : {'type' : 'Text'},
'codeOrder' : {'type' : 'UInt16'},
'annotations' : {'type' : 'List[Annotation]'},
}},
}},
'InterfaceNode' : {'body' : 'struct',
'members' : {
'methods' : {'type' : 'List[InterfaceNode.Method]'},
'Method' : {'body' : 'struct', 'is_not_field' : True,
'members' : {
'name' : {'type' : 'Text'},
'codeOrder' : {'type' : 'UInt16'},
'params' : {'type' : 'List[InterfaceNode.Method.Param]'},
'Param' : {'body' : 'struct', 'is_not_field' : True,
'members' : {
'name' : {'type' : 'Text'},
'type' : {'type' : 'Type'},
'defaultValue' : {'type' : 'Value'},
'annotations' : {'type' : 'List[Annotation]'},
}},
'requiredParamCount' : {'type' : 'UInt16'},
'returnType' : {'type' : 'Type'},
'annotations' : {'type' : 'List[Annotation]'},
}},
}},
'ConstNode' : {'body' : 'struct',
'members' : {
'type' : {'type' : 'Type'},
'value' : {'type' : 'Value'},
}},
'AnnotationNode' : {'body' : 'struct',
'members' : {
'type' : {'type' : 'Type'},
'targetsFile' : {'type' : 'Bool'},
'targetsConst' : {'type' : 'Bool'},
'targetsEnum' : {'type' : 'Bool'},
'targetsEnumerant' : {'type' : 'Bool'},
'targetsStruct' : {'type' : 'Bool'},
'targetsField' : {'type' : 'Bool'},
'targetsUnion' : {'type' : 'Bool'},
'targetsInterface' : {'type' : 'Bool'},
'targetsMethod' : {'type' : 'Bool'},
'targetsParam' : {'type' : 'Bool'},
'targetsAnnotation' : {'type' : 'Bool'},
}},
'CodeGeneratorRequest' : {'body' : 'struct',
'members' : {
'nodes' : {'type' : 'List[Node]'},
'requestedFiles' : {'type' : 'List[UInt64]'},
}},
}
primitive_types = set(('Bool','Int8','Int16','Int32','Int64','UInt8','UInt16','UInt32','UInt64','Float32','Float64'))
built_in_types = set(('Bool','Int8','Int16','Int32','Int64','UInt8','UInt16','UInt32','UInt64','Float32','Float64', 'Text', 'Data', 'Void', 'Object'))
list_types = {}
enum_types = []
union_types = []
def capitalize(s):
if len(s) < 2:
return s
return s[0].upper() + s[1:]
def upper_and_under(s):
if len(s) < 2:
return s
ret = [s[0]]
for letter in s[1:]:
if letter.isupper():
ret.append('_')
ret.append(letter)
return ''.join(ret).upper()
def fixNodes(n):
def fixNode(node_dict, full_name):
nested = {}
node_dict['full_name'] = full_name
node_dict['full_name_cython'] = '_' + full_name.replace('.', '_')
for member, member_dict in node_dict['members'].items():
member_dict['full_type'] = member_dict.get('type')
if 'body' in member_dict:
nested[member] = fixNode(member_dict, full_name+'.'+capitalize(member))
if member_dict['body'] == 'enum':
enum_types.append(nested[member])
elif member_dict['body'] == 'union':
union_types.append(nested[member])
if 'is_not_field' in member_dict:
del node_dict['members'][member]
else:
node_dict['members'][member] = {'type' : full_name+'.'+capitalize(member)}
node_dict['members'][member]['full_type'] = node_dict['members'][member].get('type')
elif member_dict.get('type', '').startswith('List'):
elem_type = member_dict['type'][member_dict['type'].find('[')+1:member_dict['type'].find(']')]
elem_type_name = elem_type if elem_type in built_in_types else capitalize((full_name+'.'+elem_type))
elem_type_cython = elem_type if elem_type in built_in_types else 'C_' + capitalize((full_name+'.'+elem_type))
list_types['List[%s]' % elem_type_name] = {'elem_type' : elem_type, 'elem_type_cython' : elem_type_cython}
member_dict['type'] = 'List[%s]' % elem_type_name
elif '.' in member_dict.get('type', ''):
member_dict['type'] = '.'.join(member_dict['type'].split('.')[1:])
node_dict['nestedNodes'] = nested
return node_dict
for node, node_dict in n.items():
res=fixNode(node_dict, capitalize(node))
if node_dict['body'] == 'enum':
enum_types.append(res)
elif node_dict['body'] == 'union':
union_types.append(res)
return n
env.filters['capitalize'] = capitalize
env.filters['upper_and_under'] = upper_and_under
nodes = fixNodes(nodes)
tmpl = env.get_template('capnp.tmpl.pxd')
open(os.path.join(curr_dir, 'capnp_schema.pxd'), 'w').write(tmpl.render(nodes=nodes, namespace='::capnp::schema', built_in_types=built_in_types, enum_types=enum_types, union_types=union_types))
tmpl = env.get_template('capnp.tmpl.pyx')
open(os.path.join(curr_dir, 'schema.capnp.cpp.pyx'), 'w').write(tmpl.render(nodes=nodes, namespace='::capnp::schema', primitive_types=primitive_types, built_in_types=built_in_types, list_types=list_types, enum_types=enum_types, union_types=union_types))
setup(
name = "capnp",
ext_modules = cythonize('schema.capnp.cpp.pyx'),
)