# 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 exporters
from Exporter import Exporter
from declarations import *
from settings import *
from policies import *
from SingleCodeUnit import SingleCodeUnit
from EnumExporter import EnumExporter
from utils import makeid, enumerate
import copy
import exporterutils
import re

#==============================================================================
# ClassExporter
#==============================================================================
class ClassExporter(Exporter):
    'Generates boost.python code to export a class declaration'
 
    def __init__(self, info, parser_tail=None):
        Exporter.__init__(self, info, parser_tail)
        # sections of code
        self.sections = {}
        # template: each item in the list is an item into the class_<...> 
        # section.
        self.sections['template'] = []  
        # constructor: each item in the list is a parameter to the class_ 
        # constructor, like class_<C>(...)
        self.sections['constructor'] = []
        # inside: everything within the class_<> statement        
        self.sections['inside'] = []        
        # scope: items outside the class statement but within its scope.
        # scope* s = new scope(class<>());
        # ...
        # delete s;
        self.sections['scope'] = []
        # declarations: outside the BOOST_PYTHON_MODULE macro
        self.sections['declaration'] = []
        self.sections['declaration-outside'] = []
        self.sections['include'] = []
        # a list of Constructor instances
        self.constructors = []
        # a list of code units, generated by nested declarations
        self.nested_codeunits = []


    def ScopeName(self):
        return makeid(self.class_.FullName()) + '_scope'


    def Name(self):
        return self.info.name


    def SetDeclarations(self, declarations):
        Exporter.SetDeclarations(self, declarations)
        if self.declarations:
            decl = self.GetDeclaration(self.info.name)
            if isinstance(decl, Typedef):
                self.class_ = self.GetDeclaration(decl.type.name)
                if not self.info.rename:
                    self.info.rename = decl.name
            else:
                self.class_ = decl
            self.class_ = copy.deepcopy(self.class_)
        else:
            self.class_ = None
        
        
    def ClassBases(self):
        all_bases = []       
        for level in self.class_.hierarchy:
            for base in level:
                all_bases.append(base)
        return [self.GetDeclaration(x.name) for x in all_bases] 

    
    def Order(self):
        '''Return the TOTAL number of bases that this class has, including the
        bases' bases.  Do this because base classes must be instantialized
        before the derived classes in the module definition.  
        '''
        num_bases = len(self.ClassBases())
        return num_bases, self.class_.FullName()
        
    
    def Export(self, codeunit, exported_names):
        self.InheritMethods(exported_names)
        self.MakeNonVirtual()
        if not self.info.exclude:
            self.ExportBasics()
            self.ExportBases(exported_names)
            self.ExportConstructors()
            self.ExportVariables()
            self.ExportVirtualMethods(codeunit)
            self.ExportMethods()
            self.ExportOperators()
            self.ExportNestedClasses(exported_names)
            self.ExportNestedEnums(exported_names)
            self.ExportSmartPointer()
            self.ExportOpaquePointerPolicies()
            self.ExportAddedCode()
            self.Write(codeunit)
            exported_names[self.Name()] = 1


    def InheritMethods(self, exported_names):
        '''Go up in the class hierarchy looking for classes that were not
        exported yet, and then add their public members to this classes
        members, as if they were members of this class. This allows the user to
        just export one type and automatically get all the members from the
        base classes.
        '''
        valid_members = (Method, ClassVariable, NestedClass, ClassEnumeration)
        fullnames = [x.FullName() for x in self.class_]
        pointers = [x.PointerDeclaration(True) for x in self.class_ if isinstance(x, Method)]
        fullnames = dict([(x, None) for x in fullnames])
        pointers = dict([(x, None) for x in pointers])
        for level in self.class_.hierarchy:
            level_exported = False
            for base in level:
                base = self.GetDeclaration(base.name)
                if base.FullName() not in exported_names:
                    for member in base:
                        if type(member) in valid_members:
                            member_copy = copy.deepcopy(member)   
                            member_copy.class_ = self.class_.FullName()
                            if isinstance(member_copy, Method):
                                pointer = member_copy.PointerDeclaration(True)
                                if pointer not in pointers:
                                    self.class_.AddMember(member)
                                    pointers[pointer] = None
                            elif member_copy.FullName() not in fullnames:
                                self.class_.AddMember(member)        
                else:
                    level_exported = True
            if level_exported:
                break
        def IsValid(member):
            return isinstance(member, valid_members) and member.visibility == Scope.public
        self.public_members = [x for x in self.class_ if IsValid(x)] 


    def Write(self, codeunit):
        indent = self.INDENT
        boost_ns = namespaces.python
        pyste_ns = namespaces.pyste
        code = ''
        # begin a scope for this class if needed
        nested_codeunits = self.nested_codeunits
        needs_scope = self.sections['scope'] or nested_codeunits
        if needs_scope:
            scope_name = self.ScopeName()
            code += indent + boost_ns + 'scope* %s = new %sscope(\n' %\
                (scope_name, boost_ns)
        # export the template section
        template_params = ', '.join(self.sections['template'])
        code += indent + boost_ns + 'class_< %s >' % template_params
        # export the constructor section
        constructor_params = ', '.join(self.sections['constructor'])
        code += '(%s)\n' % constructor_params
        # export the inside section
        in_indent = indent*2
        for line in self.sections['inside']:
            code += in_indent + line + '\n' 
        # write the scope section and end it
        if not needs_scope:
            code += indent + ';\n'
        else:
            code += indent + ');\n'
            for line in self.sections['scope']:
                code += indent + line + '\n'
            # write the contents of the nested classes
            for nested_unit in nested_codeunits:
                code += '\n' + nested_unit.Section('module')
            # close the scope
            code += indent + 'delete %s;\n' % scope_name
            
        # write the code to the module section in the codeunit        
        codeunit.Write('module', code + '\n')
        
        # write the declarations to the codeunit        
        declarations = '\n'.join(self.sections['declaration'])
        for nested_unit in nested_codeunits:
            declarations += nested_unit.Section('declaration')
        if declarations:
            codeunit.Write('declaration', declarations + '\n')
        declarations_outside = '\n'.join(self.sections['declaration-outside'])
        if declarations_outside:
            codeunit.Write('declaration-outside', declarations_outside + '\n')

        # write the includes to the codeunit
        includes = '\n'.join(self.sections['include'])
        for nested_unit in nested_codeunits:
            includes += nested_unit.Section('include')
        if includes:
            codeunit.Write('include', includes)


    def Add(self, section, item):
        'Add the item into the corresponding section'
        self.sections[section].append(item)

        
    def ExportBasics(self):
        '''Export the name of the class and its class_ statement.'''
        class_name = self.class_.FullName()
        self.Add('template', class_name)
        name = self.info.rename or self.class_.name
        self.Add('constructor', '"%s"' % name)
        
        
    def ExportBases(self, exported_names):
        'Expose the bases of the class into the template section'        
        hierarchy = self.class_.hierarchy
        exported = []
        for level in hierarchy:
            for base in level:
                if base.visibility == Scope.public and base.name in exported_names:
                    exported.append(base.name)
            if exported:
                break
        if exported:
            code = namespaces.python + 'bases< %s > ' %  (', '.join(exported))
            self.Add('template', code)         


    def ExportConstructors(self):
        '''Exports all the public contructors of the class, plus indicates if the 
        class is noncopyable.
        '''
        py_ns = namespaces.python
        indent = self.INDENT
        
        def init_code(cons):
            'return the init<>() code for the given contructor'
            param_list = [p.FullName() for p in cons.parameters]
            min_params_list = param_list[:cons.minArgs]
            max_params_list = param_list[cons.minArgs:]
            min_params = ', '.join(min_params_list)
            max_params = ', '.join(max_params_list)
            init = py_ns + 'init< '
            init += min_params
            if max_params:
                if min_params:
                    init += ', '
                init += py_ns + ('optional< %s >' % max_params)
            init += ' >()'    
            return init
        
        constructors = [x for x in self.public_members if isinstance(x, Constructor)]
        # don't export copy constructors if the class is abstract
        # we could remove all constructors, but this will have the effect of
        # inserting no_init in the declaration, which would not allow
        # even subclasses to be instantiated.
        self.constructors = constructors[:]
        if self.class_.abstract:
            for cons in constructors:
                if cons.IsCopy():
                    constructors.remove(cons)
                    break
            
        if not constructors:
            # declare no_init
            self.Add('constructor', py_ns + 'no_init') 
        else:
            # write the constructor with less parameters to the constructor section
            smaller = None
            for cons in constructors:
                if smaller is None or len(cons.parameters) < len(smaller.parameters):
                    smaller = cons
            assert smaller is not None
            self.Add('constructor', init_code(smaller))
            constructors.remove(smaller)
            # write the rest to the inside section, using def()
            for cons in constructors:
                code = '.def(%s)' % init_code(cons) 
                self.Add('inside', code)

        # check if the class is copyable
        if not self.class_.HasCopyConstructor() or self.class_.abstract:
            self.Add('template', namespaces.boost + 'noncopyable')
            
        
    def ExportVariables(self):
        'Export the variables of the class, both static and simple variables'
        vars = [x for x in self.public_members if isinstance(x, Variable)]
        for var in vars:
            if self.info[var.name].exclude: 
                continue
            name = self.info[var.name].rename or var.name
            fullname = var.FullName() 
            if var.type.const:
                def_ = '.def_readonly'
            else:
                def_ = '.def_readwrite'
            code = '%s("%s", &%s)' % (def_, name, fullname)
            self.Add('inside', code)

    
    def OverloadName(self, method):
        'Returns the name of the overloads struct for the given method'
        name = makeid(method.FullName())
        overloads = '_overloads_%i_%i' % (method.minArgs, method.maxArgs)    
        return name + overloads

    
    def GetAddedMethods(self):
        added_methods = self.info.__added__
        result = []
        if added_methods:
            for name, rename in added_methods:
                decl = self.GetDeclaration(name)
                self.info[name].rename = rename
                result.append(decl)
        return result

                
    def ExportMethods(self):
        '''Export all the non-virtual methods of this class, plus any function
        that is to be exported as a method'''
            
        declared = {}
        def DeclareOverloads(m):
            'Declares the macro for the generation of the overloads'
            if (isinstance(m, Method) and m.static) or type(m) == Function:
                func = m.FullName()
                macro = 'BOOST_PYTHON_FUNCTION_OVERLOADS'
            else:
                func = m.name
                macro = 'BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS' 
            code = '%s(%s, %s, %i, %i)\n' % (macro, self.OverloadName(m), func, m.minArgs, m.maxArgs)
            if code not in declared:
                declared[code] = True
                self.Add('declaration', code)


        def Pointer(m):
            'returns the correct pointer declaration for the method m'
            # check if this method has a wrapper set for him
            wrapper = self.info[m.name].wrapper
            if wrapper:
                return '&' + wrapper.FullName()
            else:
                return m.PointerDeclaration() 

        def IsExportable(m):
            'Returns true if the given method is exportable by this routine'
            ignore = (Constructor, ClassOperator, Destructor)
            return isinstance(m, Function) and not isinstance(m, ignore) and not m.virtual        
        
        methods = [x for x in self.public_members if IsExportable(x)]        
        methods.extend(self.GetAddedMethods())
        
        staticmethods = {}
        
        for method in methods:
            method_info = self.info[method.name]
            
            # skip this method if it was excluded by the user
            if method_info.exclude:
                continue 

            # rename the method if the user requested
            name = method_info.rename or method.name
            
            # warn the user if this method needs a policy and doesn't have one
            method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
            
            # check for policies
            policy = method_info.policy or ''
            if policy:
                policy = ', %s%s()' % (namespaces.python, policy.Code())
            # check for overloads
            overload = ''
            if method.minArgs != method.maxArgs and not method_info.wrapper: 
                # add the overloads for this method
                DeclareOverloads(method)
                overload_name = self.OverloadName(method)
                overload = ', %s%s()' % (namespaces.pyste, overload_name)
        
            # build the .def string to export the method
            pointer = Pointer(method)
            code = '.def("%s", %s' % (name, pointer)
            code += policy
            code += overload
            code += ')'
            self.Add('inside', code)
            # static method
            if isinstance(method, Method) and method.static:
                staticmethods[name] = 1
            # add wrapper code if this method has one
            wrapper = method_info.wrapper
            if wrapper and wrapper.code:
                self.Add('declaration', wrapper.code)
        
        # export staticmethod statements
        for name in staticmethods:
            code = '.staticmethod("%s")' % name
            self.Add('inside', code) 


                
    def MakeNonVirtual(self):
        '''Make all methods that the user indicated to no_override no more virtual, delegating their
        export to the ExportMethods routine'''
        for member in self.class_:
            if type(member) == Method and member.virtual:
                member.virtual = not self.info[member.name].no_override 


    def ExportVirtualMethods(self, codeunit):        
        # check if this class has any virtual methods
        has_virtual_methods = False
        for member in self.class_:
            if type(member) == Method and member.virtual:
                has_virtual_methods = True
                break

        holder = self.info.holder
        if has_virtual_methods:
            generator = _VirtualWrapperGenerator(self.class_, self.ClassBases(), self.info, codeunit)
            if holder:
                self.Add('template', holder(generator.FullName()))
            else:
                self.Add('template', generator.FullName())
            for definition in generator.GenerateDefinitions():
                self.Add('inside', definition)
            self.Add('declaration', generator.GenerateVirtualWrapper(self.INDENT))
        else:
            if holder:
                self.Add('template', holder(self.class_.FullName()))

    # operators natively supported by boost
    BOOST_SUPPORTED_OPERATORS = '+ - * / % ^ & ! ~ | < > == != <= >= << >> && || += -= '\
        '*= /= %= ^= &= |= <<= >>='.split()
    # create a map for faster lookup
    BOOST_SUPPORTED_OPERATORS = dict(zip(BOOST_SUPPORTED_OPERATORS, range(len(BOOST_SUPPORTED_OPERATORS))))

    # a dict of operators that are not directly supported by boost, but can be exposed
    # simply as a function with a special name
    BOOST_RENAME_OPERATORS = {
        '()' : '__call__',
    }

    # converters which have a special name in python
    # it's a map of a regular expression of the converter's result to the
    # appropriate python name
    SPECIAL_CONVERTERS = {
        re.compile(r'(const)?\s*double$') : '__float__',
        re.compile(r'(const)?\s*float$') : '__float__',
        re.compile(r'(const)?\s*int$') : '__int__',
        re.compile(r'(const)?\s*long$') : '__long__',
        re.compile(r'(const)?\s*char\s*\*?$') : '__str__',
        re.compile(r'(const)?.*::basic_string<.*>\s*(\*|\&)?$') : '__str__',
    }
        
    
    def ExportOperators(self):
        'Export all member operators and free operators related to this class'
        
        def GetFreeOperators():
            'Get all the free (global) operators related to this class'
            operators = []
            for decl in self.declarations:
                if isinstance(decl, Operator):
                    # check if one of the params is this class
                    for param in decl.parameters:
                        if param.name == self.class_.FullName():
                            operators.append(decl)
                            break
            return operators

        def GetOperand(param):
            'Returns the operand of this parameter (either "self", or "other<type>")'
            if param.name == self.class_.FullName():
                return namespaces.python + 'self'
            else:
                return namespaces.python + ('other< %s >()' % param.name)


        def HandleSpecialOperator(operator):
            # gatter information about the operator and its parameters
            result_name = operator.result.name                        
            param1_name = ''
            if operator.parameters:
                param1_name = operator.parameters[0].name
                
            # check for str
            ostream = 'basic_ostream'
            is_str = result_name.find(ostream) != -1 and param1_name.find(ostream) != -1
            if is_str:
                namespace = namespaces.python + 'self_ns::'
                self_ = namespaces.python + 'self'
                return '.def(%sstr(%s))' % (namespace, self_)

            # is not a special operator
            return None
                

        
        frees = GetFreeOperators()
        members = [x for x in self.public_members if type(x) == ClassOperator]
        all_operators = frees + members
        operators = [x for x in all_operators if not self.info['operator'][x.name].exclude]
        
        for operator in operators:
            # gatter information about the operator, for use later
            wrapper = self.info['operator'][operator.name].wrapper
            if wrapper:
                pointer = '&' + wrapper.FullName()
                if wrapper.code:
                    self.Add('declaration-outside', wrapper.code)
            else:
                pointer = operator.PointerDeclaration()                 
            rename = self.info['operator'][operator.name].rename

            # check if this operator will be exported as a method
            export_as_method = wrapper or rename or operator.name in self.BOOST_RENAME_OPERATORS
            
            # check if this operator has a special representation in boost
            special_code = HandleSpecialOperator(operator)
            has_special_representation = special_code is not None
            
            if export_as_method:
                # export this operator as a normal method, renaming or using the given wrapper
                if not rename:
                    if wrapper:
                        rename = wrapper.name
                    else:
                        rename = self.BOOST_RENAME_OPERATORS[operator.name]
                policy = ''
                policy_obj = self.info['operator'][operator.name].policy
                if policy_obj:
                    policy = ', %s()' % policy_obj.Code() 
                self.Add('inside', '.def("%s", %s%s)' % (rename, pointer, policy))
            
            elif has_special_representation:
                self.Add('inside', special_code)
                
            elif operator.name in self.BOOST_SUPPORTED_OPERATORS:
                # export this operator using boost's facilities
                op = operator
                is_unary = isinstance(op, Operator) and len(op.parameters) == 1 or\
                           isinstance(op, ClassOperator) and len(op.parameters) == 0
                if is_unary:
                    self.Add('inside', '.def( %s%sself )' % \
                        (operator.name, namespaces.python))
                else:
                    # binary operator
                    if len(operator.parameters) == 2:
                        left_operand = GetOperand(operator.parameters[0])
                        right_operand = GetOperand(operator.parameters[1])
                    else:
                        left_operand = namespaces.python + 'self'
                        right_operand = GetOperand(operator.parameters[0])
                    self.Add('inside', '.def( %s %s %s )' % \
                        (left_operand, operator.name, right_operand))

        # export the converters.
        # export them as simple functions with a pre-determined name

        converters = [x for x in self.public_members if type(x) == ConverterOperator]
                
        def ConverterMethodName(converter):
            result_fullname = converter.result.FullName()
            result_name = converter.result.name
            for regex, method_name in self.SPECIAL_CONVERTERS.items():
                if regex.match(result_fullname):
                    return method_name
            else:
                # extract the last name from the full name
                result_name = makeid(result_name)
                return 'to_' + result_name
            
        for converter in converters:
            info = self.info['operator'][converter.result.FullName()]
            # check if this operator should be excluded
            if info.exclude:
                continue
            
            special_code = HandleSpecialOperator(converter)
            if info.rename or not special_code:
                # export as method
                name = info.rename or ConverterMethodName(converter)
                pointer = converter.PointerDeclaration()
                policy_code = ''
                if info.policy:
                    policy_code = ', %s()' % info.policy.Code()
                self.Add('inside', '.def("%s", %s%s)' % (name, pointer, policy_code))
                    
            elif special_code:
                self.Add('inside', special_code)



    def ExportNestedClasses(self, exported_names):
        nested_classes = [x for x in self.public_members if isinstance(x, NestedClass)]
        for nested_class in nested_classes:
            nested_info = self.info[nested_class.name]
            nested_info.include = self.info.include
            nested_info.name = nested_class.FullName()
            exporter = self.__class__(nested_info)
            exporter.SetDeclarations(self.declarations)
            codeunit = SingleCodeUnit(None, None)
            exporter.Export(codeunit, exported_names)
            self.nested_codeunits.append(codeunit)


    def ExportNestedEnums(self, exported_names):
        nested_enums = [x for x in self.public_members if isinstance(x, ClassEnumeration)]
        for enum in nested_enums:
            enum_info = self.info[enum.name]
            enum_info.include = self.info.include
            enum_info.name = enum.FullName()
            exporter = EnumExporter(enum_info)
            exporter.SetDeclarations(self.declarations)
            codeunit = SingleCodeUnit(None, None)
            exporter.Export(codeunit, exported_names)
            self.nested_codeunits.append(codeunit)


    def ExportSmartPointer(self):
        smart_ptr = self.info.smart_ptr
        if smart_ptr:
            class_name = self.class_.FullName()
            smart_ptr = smart_ptr % class_name
            self.Add('scope', '%sregister_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
            

    def ExportOpaquePointerPolicies(self):
        # check all methods for 'return_opaque_pointer' policies
        methods = [x for x in self.public_members if isinstance(x, Method)]
        for method in methods:
            return_opaque_policy = return_value_policy(return_opaque_pointer)
            if self.info[method.name].policy == return_opaque_policy:
                macro = exporterutils.EspecializeTypeID(method.result.name) 
                if macro:
                    self.Add('declaration-outside', macro)

    def ExportAddedCode(self):
        if self.info.__code__:
            for code in self.info.__code__:
                self.Add('inside', code)
 

#==============================================================================
# Virtual Wrapper utils
#==============================================================================

def _ParamsInfo(m, count=None):
    if count is None:
        count = len(m.parameters)
    param_names = ['p%i' % i for i in range(count)]
    param_types = [x.FullName() for x in m.parameters[:count]]
    params = ['%s %s' % (t, n) for t, n in zip(param_types, param_names)]
    #for i, p in enumerate(m.parameters[:count]):
    #    if p.default is not None:
    #        #params[i] += '=%s' % p.default
    #        params[i] += '=%s' % (p.name + '()')
    params = ', '.join(params) 
    return params, param_names, param_types

            
class _VirtualWrapperGenerator(object):
    'Generates code to export the virtual methods of the given class'

    def __init__(self, class_, bases, info, codeunit):
        self.class_ = copy.deepcopy(class_)
        self.bases = bases[:]
        self.info = info
        self.wrapper_name = makeid(class_.FullName()) + '_Wrapper'
        self.virtual_methods = None
        self._method_count = {}
        self.codeunit = codeunit
        self.GenerateVirtualMethods()


    SELF = 'py_self'

    
    def DefaultImplementationNames(self, method):
        '''Returns a list of default implementations for this method, one for each
        number of default arguments. Always returns at least one name, and return from 
        the one with most arguments to the one with the least.
        '''
        base_name = 'default_' + method.name 
        minArgs = method.minArgs
        maxArgs = method.maxArgs
        if minArgs == maxArgs:
            return [base_name]
        else:
            return [base_name + ('_%i' % i) for i in range(minArgs, maxArgs+1)]                


    def Declaration(self, method, indent):
        '''Returns a string with the declarations of the virtual wrapper and
        its default implementations. This string must be put inside the Wrapper
        body.        
        '''
        pyste = namespaces.pyste
        python = namespaces.python
        rename = self.info[method.name].rename or method.name
        result = method.result.FullName()
        return_str = 'return '
        if result == 'void':
            return_str = ''
        params, param_names, param_types = _ParamsInfo(method)
        constantness = ''
        if method.const:
            constantness = ' const'
        
        # call_method callback
        decl  = indent + '%s %s(%s)%s%s {\n' % (result, method.name, params, constantness, method.Exceptions())
        param_names_str = ', '.join(param_names)
        if param_names_str:
            param_names_str = ', ' + param_names_str
        
        self_str = self.SELF
        
        decl += indent*2 + '%(return_str)s%(python)scall_method< %(result)s >'  \
                           '(%(self_str)s, "%(rename)s"%(param_names_str)s);\n' % locals()
        decl += indent + '}\n'

        # default implementations (with overloading)
        def DefaultImpl(method, param_names):
            'Return the body of a default implementation wrapper'
            indent2 = indent * 2
            wrapper = self.info[method.name].wrapper
            if not wrapper:
                # return the default implementation of the class
                return indent2 + '%s%s(%s);\n' % \
                    (return_str, method.FullName(), ', '.join(param_names)) 
            else:
                if wrapper.code:
                    self.codeunit.Write('declaration-outside', wrapper.code) 
                # return a call for the wrapper
                params = ', '.join(['this'] + param_names)
                return indent2 + '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
                
        if not method.abstract and method.visibility != Scope.private:
            minArgs = method.minArgs
            maxArgs = method.maxArgs
            impl_names = self.DefaultImplementationNames(method)
            for impl_name, argNum in zip(impl_names, range(minArgs, maxArgs+1)): 
                params, param_names, param_types = _ParamsInfo(method, argNum)            
                decl += '\n'
                decl += indent + '%s %s(%s)%s {\n' % (result, impl_name, params, constantness)
                decl += DefaultImpl(method, param_names)
                decl += indent + '}\n'                
        return decl
            

    def MethodDefinition(self, method):
        '''Returns a list of lines, which should be put inside the class_
        statement to export this method.'''
        # dont define abstract methods
        pyste = namespaces.pyste
        rename = self.info[method.name].rename or method.name
        default_names = self.DefaultImplementationNames(method)
        class_name = self.class_.FullName()
        wrapper_name = pyste + self.wrapper_name
        result = method.result.FullName()
        is_method_unique = method.is_unique
        constantness = ''
        if method.const:
            constantness = ' const'
        
        # create a list of default-impl pointers
        minArgs = method.minArgs
        maxArgs = method.maxArgs 
        if method.abstract:
            default_pointers = []
        elif is_method_unique:
            default_pointers = ['&%s::%s' % (wrapper_name, x) for x in default_names]
        else:
            default_pointers = []
            for impl_name, argNum in zip(default_names, range(minArgs, maxArgs+1)):
                param_list = [x.FullName() for x in method.parameters[:argNum]]
                params = ', '.join(param_list)             
                signature = '%s (%s::*)(%s)%s' % (result, wrapper_name, params, constantness)
                default_pointer = '(%s)&%s::%s' % (signature, wrapper_name, impl_name)
                default_pointers.append(default_pointer)
            
        # get the pointer of the method
        pointer = method.PointerDeclaration()
        if method.abstract:
            pointer = namespaces.python + ('pure_virtual(%s)' % pointer)

        # warn the user if this method needs a policy and doesn't have one
        method_info = self.info[method.name]
        method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)

        # Add policy to overloaded methods also
        policy = method_info.policy or '' 
        if policy:
            policy = ', %s%s()' % (namespaces.python, policy.Code())

        # generate the defs
        definitions = []
        # basic def
        if default_pointers:
            definitions.append('.def("%s", %s, %s%s)' % (rename, pointer, default_pointers[-1], policy))
            for default_pointer in default_pointers[:-1]:
                definitions.append('.def("%s", %s%s)' % (rename, default_pointer, policy))
        else:
            definitions.append('.def("%s", %s%s)' % (rename, pointer, policy))
        return definitions

    
    def FullName(self):
        return namespaces.pyste + self.wrapper_name


    def GenerateVirtualMethods(self):
        '''To correctly export all virtual methods, we must also make wrappers
        for the virtual methods of the bases of this class, as if the methods
        were from this class itself.
        This method creates the instance variable self.virtual_methods.
        '''        
        def IsVirtual(m):
            if type(m) is Method:
                pure_virtual = m.abstract and m.virtual
                virtual = m.virtual and m.visibility != Scope.private
                return virtual or pure_virtual
            else:
                return False
                
        # extract the virtual methods, avoiding duplications. The duplication
        # must take in account the full signature without the class name, so 
        # that inherited members are correctly excluded if the subclass overrides
        # them.
        def MethodSig(method):
            if method.const:
                const = ' const'
            else:
                const = ''
            if method.result:
                result = method.result.FullName()
            else:
                result = ''
            params = ', '.join([x.FullName() for x in method.parameters]) 
            return '%s %s(%s)%s%s' % (
                result, method.name, params, const, method.Exceptions())  

        already_added = {}
        self.virtual_methods = []
        for member in self.class_:
            if IsVirtual(member):
                already_added[MethodSig(member)] = None
                self.virtual_methods.append(member)

        for base in self.bases:
            base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
            for base_method in base_methods:
                self.class_.AddMember(base_method)
                
        all_methods = [x for x in self.class_ if IsVirtual(x)]
        
        for member in all_methods:
            sig = MethodSig(member)
            if IsVirtual(member) and not sig in already_added:
                self.virtual_methods.append(member)
                already_added[sig] = 0
            
    
    def Constructors(self):
        return self.class_.Constructors(publics_only=True)
    
        
    def GenerateDefinitions(self):
        defs = []
        for method in self.virtual_methods:
            exclude = self.info[method.name].exclude
            # generate definitions only for public methods and non-abstract methods
            if method.visibility == Scope.public and not exclude:
                defs.extend(self.MethodDefinition(method))
        return defs

        
    def GenerateVirtualWrapper(self, indent):
        'Return the wrapper for this class'
        
        # generate the class code
        class_name = self.class_.FullName()
        code = 'struct %s: %s\n' % (self.wrapper_name, class_name)
        code += '{\n'
        # generate constructors (with the overloads for each one)
        for cons in self.Constructors(): # only public constructors
            minArgs = cons.minArgs
            maxArgs = cons.maxArgs
            # from the min number of arguments to the max number, generate
            # all version of the given constructor
            cons_code = ''
            for argNum in range(minArgs, maxArgs+1):
                params, param_names, param_types = _ParamsInfo(cons, argNum)
                if params:
                    params = ', ' + params
                cons_code += indent + '%s(PyObject* %s_%s):\n' % \
                    (self.wrapper_name, self.SELF, params)
                cons_code += indent*2 + '%s(%s), %s(%s_) {}\n\n' % \
                    (class_name, ', '.join(param_names), self.SELF, self.SELF)
            code += cons_code
        # generate the body
        body = []
        for method in self.virtual_methods:
            if not self.info[method.name].exclude:
                body.append(self.Declaration(method, indent))            
        body = '\n'.join(body) 
        code += body + '\n'
        # add the self member
        code += indent + 'PyObject* %s;\n' % self.SELF
        code += '};\n'
        return code 
