blob: 2a4f01eafe96f07da9f123adfeac40751b2a75b4 [file] [log] [blame]
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import os.path
import copy
import exporters
from ClassExporter import ClassExporter
from FunctionExporter import FunctionExporter
from EnumExporter import EnumExporter
from HeaderExporter import HeaderExporter
from VarExporter import VarExporter
from CodeExporter import CodeExporter
from exporterutils import FunctionWrapper
from utils import makeid
import warnings
#==============================================================================
# DeclarationInfo
#==============================================================================
class DeclarationInfo:
def __init__(self, otherInfo=None):
self.__infos = {}
self.__attributes = {}
if otherInfo is not None:
self.__infos = copy.deepcopy(otherInfo.__infos)
self.__attributes = copy.deepcopy(otherInfo.__attributes)
def __getitem__(self, name):
'Used to access sub-infos'
if name.startswith('__'):
raise AttributeError
default = DeclarationInfo()
default._Attribute('name', name)
return self.__infos.setdefault(name, default)
def __getattr__(self, name):
return self[name]
def _Attribute(self, name, value=None):
if value is None:
# get value
return self.__attributes.get(name)
else:
# set value
self.__attributes[name] = value
def AddExporter(self, exporter):
# this was causing a much serious bug, as reported by Niall Douglas:
# another solution must be found!
#if not exporters.importing:
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# FunctionInfo
#==============================================================================
class FunctionInfo(DeclarationInfo):
def __init__(self, name, include, tail=None, otherOption=None,
exporter_class = FunctionExporter):
DeclarationInfo.__init__(self, otherOption)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
# create a FunctionExporter
exporter = exporter_class(InfoWrapper(self), tail)
self.AddExporter(exporter)
#==============================================================================
# ClassInfo
#==============================================================================
class ClassInfo(DeclarationInfo):
def __init__(self, name, include, tail=None, otherInfo=None,
exporter_class = ClassExporter):
DeclarationInfo.__init__(self, otherInfo)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
# create a ClassExporter
exporter = exporter_class(InfoWrapper(self), tail)
self.AddExporter(exporter)
#==============================================================================
# templates
#==============================================================================
def GenerateName(name, type_list):
name = name.replace('::', '_')
names = [name] + type_list
return makeid('_'.join(names))
class ClassTemplateInfo(DeclarationInfo):
def __init__(self, name, include,
exporter_class = ClassExporter):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
self._exporter_class = exporter_class
def Instantiate(self, type_list, rename=None):
if not rename:
rename = GenerateName(self._Attribute('name'), type_list)
# generate code to instantiate the template
types = ', '.join(type_list)
tail = 'typedef %s< %s > %s;\n' % (self._Attribute('name'), types, rename)
tail += 'void __instantiate_%s()\n' % rename
tail += '{ sizeof(%s); }\n\n' % rename
# create a ClassInfo
class_ = ClassInfo(rename, self._Attribute('include'), tail, self,
exporter_class = self._exporter_class)
return class_
def __call__(self, types, rename=None):
if isinstance(types, str):
types = types.split()
return self.Instantiate(types, rename)
#==============================================================================
# EnumInfo
#==============================================================================
class EnumInfo(DeclarationInfo):
def __init__(self, name, include, exporter_class = EnumExporter):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
self._Attribute('export_values', False)
exporter = exporter_class(InfoWrapper(self))
self.AddExporter(exporter)
#==============================================================================
# HeaderInfo
#==============================================================================
class HeaderInfo(DeclarationInfo):
def __init__(self, include, exporter_class = HeaderExporter):
warnings.warn('AllFromHeader is not working in all cases in the current version.')
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = exporter_class(InfoWrapper(self))
self.AddExporter(exporter)
#==============================================================================
# VarInfo
#==============================================================================
class VarInfo(DeclarationInfo):
def __init__(self, name, include, exporter_class = VarExporter):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
exporter = exporter_class(InfoWrapper(self))
self.AddExporter(exporter)
#==============================================================================
# CodeInfo
#==============================================================================
class CodeInfo(DeclarationInfo):
def __init__(self, code, section, exporter_class = CodeExporter):
DeclarationInfo.__init__(self)
self._Attribute('code', code)
self._Attribute('section', section)
exporter = exporter_class(InfoWrapper(self))
self.AddExporter(exporter)
#==============================================================================
# InfoWrapper
#==============================================================================
class InfoWrapper:
'Provides a nicer interface for a info'
def __init__(self, info):
self.__dict__['_info'] = info # so __setattr__ is not called
def __getitem__(self, name):
return InfoWrapper(self._info[name])
def __getattr__(self, name):
return self._info._Attribute(name)
def __setattr__(self, name, value):
self._info._Attribute(name, value)
#==============================================================================
# Functions
#==============================================================================
def exclude(info):
info._Attribute('exclude', True)
def set_policy(info, policy):
info._Attribute('policy', policy)
def rename(info, name):
info._Attribute('rename', name)
def set_wrapper(info, wrapper):
if isinstance(wrapper, str):
wrapper = FunctionWrapper(wrapper)
info._Attribute('wrapper', wrapper)
def instantiate(template, types, rename=None):
if isinstance(types, str):
types = types.split()
return template.Instantiate(types, rename)
def use_shared_ptr(info):
info._Attribute('smart_ptr', 'boost::shared_ptr< %s >')
def use_auto_ptr(info):
info._Attribute('smart_ptr', 'std::auto_ptr< %s >')
def holder(info, function):
msg = "Expected a callable that accepts one string argument."
assert callable(function), msg
info._Attribute('holder', function)
def add_method(info, name, rename=None):
added = info._Attribute('__added__')
if added is None:
info._Attribute('__added__', [(name, rename)])
else:
added.append((name, rename))
def class_code(info, code):
added = info._Attribute('__code__')
if added is None:
info._Attribute('__code__', [code])
else:
added.append(code)
def final(info):
info._Attribute('no_override', True)
def export_values(info):
info._Attribute('export_values', True)