class Function(ForwardWrapperBase):
    """
    Class that generates a wrapper to a C function.
    """

    def __init__(self, function_name, return_value, parameters, docstring=None, unblock_threads=None,
                 template_parameters=(), custom_name=None, deprecated=False, foreign_cpp_namespace=None,
                 throw=()):
        """
        :param function_name: name of the C function
        :param return_value: the function return value
        :type return_value: L{ReturnValue}
        :param parameters: the function parameters
        :type parameters: list of L{Parameter}

        :param custom_name: an alternative name to give to this
           function at python-side; if omitted, the name of the
           function in the python module will be the same name as the
           function in C++ (minus namespace).

        :param deprecated: deprecation state for this API:
          - False: Not deprecated
          - True: Deprecated
          - "message": Deprecated, and deprecation warning contains the given message

        :param foreign_cpp_namespace: if set, the function is assumed
          to belong to the given C++ namespace, regardless of the C++
          namespace of the python module it will be added to.

        :param throw: list of C++ exceptions that the function may throw
        :type throw: list of L{CppException}
        """
        self.stack_where_defined = traceback.extract_stack()

        if unblock_threads is None:
            unblock_threads = settings.unblock_threads

        ## backward compatibility check
        if isinstance(return_value, string_types) and isinstance(function_name, ReturnValue):
            warnings.warn("Function has changed API; see the API documentation (but trying to correct...)",
                          DeprecationWarning, stacklevel=2)
            function_name, return_value = return_value, function_name

        if return_value is None:
            return_value = ReturnValue.new('void')

        return_value = utils.eval_retval(return_value, self)
        parameters = [utils.eval_param(param, self) for param in parameters]

        super(Function, self).__init__(
            return_value, parameters,
            parse_error_return="return NULL;",
            error_return="return NULL;",
            unblock_threads=unblock_threads)
        self.deprecated = deprecated
        self.foreign_cpp_namespace = foreign_cpp_namespace
        self._module = None
        function_name = utils.ascii(function_name)
        self.function_name = function_name
        self.wrapper_base_name = None
        self.wrapper_actual_name = None
        self.docstring = docstring
        self.self_parameter_pystruct = None
        self.template_parameters = template_parameters
        self.custom_name = custom_name
        for t in throw:
            assert isinstance(t, CppException)
        self.throw = list(throw)
        self.custodians_and_wards = [] # list of (custodian, ward, postcall)
        from pybindgen import cppclass
        cppclass.scan_custodians_and_wards(self)

    def get_custom_name(self):
        if self.mangled_name != utils.get_mangled_name(self.function_name, self.template_parameters):
            return self.mangled_name
        else:
            return None

    def set_custom_name(self, custom_name):
        if custom_name is None:
            self.mangled_name = utils.get_mangled_name(self.function_name, self.template_parameters)
        else:
            self.mangled_name = custom_name
    custom_name = property(get_custom_name, set_custom_name)

    def clone(self):
        """Creates a semi-deep copy of this function wrapper.  The returned
        function wrapper clone contains copies of all parameters, so
        they can be modified at will.
        """
        func = Function(self.function_name,
                        self.return_value,
                        [copy(param) for param in self.parameters],
                        docstring=self.docstring,
                        custom_name=self.custom_name)
        func._module = self._module
        func.wrapper_base_name = self.wrapper_base_name
        func.wrapper_actual_name = self.wrapper_actual_name
        func.throw = list(self.throw)
        func.custodians_and_wards = list(self.custodians_and_wards)

        return func

    def add_custodian_and_ward(self, custodian, ward, postcall=None):
        """Add a custodian/ward relationship to the function wrapper

        A custodian/ward relationship is one where one object
        (custodian) keeps a references to another object (ward), thus
        keeping it alive.  When the custodian is destroyed, the
        reference to the ward is released, allowing the ward to be
        freed if no other reference to it is being kept by the user
        code.  Please note that custodian/ward manages the lifecycle
        of Python wrappers, not the C/C++ objects referenced by the
        wrappers.  In most cases, the wrapper owns the C/C++ object,
        and so the lifecycle of the C/C++ object is also managed by
        this.  However, there are cases when a Python wrapper does not
        own the underlying C/C++ object, only references it.

        The custodian and ward objects are indicated by an integer
        with the following meaning:
          - C{-1}: the return value of the function
          - value > 0: the nth parameter of the function, starting at 1

        :parameter custodian: number of the object that assumes the role of custodian
        :parameter ward: number of the object that assumes the role of ward

        :parameter postcall: if True, the relationship is added after
             the C function call, if False it is added before the
             call.  If not given, the value False is assumed if the
             return value is not involved, else postcall=True is used.
        """
        if custodian == -1 or ward == -1:
            if postcall is None:
                postcall = True
            if not postcall:
                raise TypeConfigurationError("custodian/ward policy must be postcall "
                                             "when a return value is involved")
        else:
            if postcall is None:
                postcall = False
        self.custodians_and_wards.append((custodian, ward, postcall))

    def get_module(self):
        """Get the Module object this function belongs to"""
        return self._module
    def set_module(self, module):
        """Set the Module object this function belongs to"""
        self._module = module
        self.wrapper_base_name = "_wrap_%s_%s" % (
            module.prefix, self.mangled_name)
    module = property(get_module, set_module)

    def generate_call(self):
        "virtual method implementation; do not call"
        if self.foreign_cpp_namespace:
            namespace = self.foreign_cpp_namespace + '::'
        elif self._module.cpp_namespace_prefix:
            namespace = self._module.cpp_namespace_prefix + '::'
        else:
            namespace = ''

        if self.template_parameters:
            template_params = '< %s >' % ', '.join(self.template_parameters)
        else:
            template_params = ''

        if self.throw:
            self.before_call.write_code('try\n{')
            self.before_call.indent()

        if self.return_value.ctype == 'void':
            self.before_call.write_code(
                '%s%s%s(%s);' % (namespace, self.function_name, template_params,
                                 ", ".join(self.call_params)))
        else:
            if self.return_value.REQUIRES_ASSIGNMENT_CONSTRUCTOR:
                self.before_call.write_code(
                    '%s retval = %s%s%s(%s);' % (self.return_value.ctype,
                                                 namespace, self.function_name, template_params,
                                                 ", ".join(self.call_params)))
            else:
                self.before_call.write_code(
                    'retval = %s%s%s(%s);' % (namespace, self.function_name, template_params,
                                              ", ".join(self.call_params)))

        if self.throw:
            for exc in self.throw:
                self.before_call.unindent()
                self.before_call.write_code('} catch (%s const &exc) {' % exc.full_name)
                self.before_call.indent()
                self.before_call.write_cleanup()
                exc.write_convert_to_python(self.before_call, 'exc')
                self.before_call.write_code('return NULL;')
            self.before_call.unindent()
            self.before_call.write_code('}')

    def _before_call_hook(self):
        "hook that post-processes parameters and check for custodian=<n> CppClass parameters"
        from . import cppclass
        cppclass.implement_parameter_custodians_precall(self)

    def _before_return_hook(self):
        "hook that post-processes parameters and check for custodian=<n> CppClass parameters"
        from . import cppclass
        cppclass.implement_parameter_custodians_postcall(self)

    def generate(self, code_sink, wrapper_name=None, extra_wrapper_params=()):
        """
        Generates the wrapper code

        :param code_sink: a CodeSink instance that will receive the generated code
        :param wrapper_name: name of wrapper function
        """

        if self.throw: # Bug #780945
            self.return_value.REQUIRES_ASSIGNMENT_CONSTRUCTOR = False
            self.reset_code_generation_state()

        if wrapper_name is None:
            self.wrapper_actual_name = self.wrapper_base_name
        else:
            self.wrapper_actual_name = wrapper_name
        tmp_sink = codesink.MemoryCodeSink()
        self.generate_body(tmp_sink)

        flags = self.get_py_method_def_flags()
        self.wrapper_args = []
        if 'METH_VARARGS' in flags:
            if self.self_parameter_pystruct is None:
                self_param = 'PyObject * PYBINDGEN_UNUSED(dummy)'
            else:
                self_param = '%s *self' % self.self_parameter_pystruct
            self.wrapper_args.append(self_param)
            self.wrapper_args.append("PyObject *args")
            if 'METH_KEYWORDS' in flags:
                self.wrapper_args.append("PyObject *kwargs")
            else:
                self.wrapper_args.append("PyObject *PYBINDGEN_UNUSED(_kwargs)")
        else:
                self.wrapper_args.append("PyObject *PYBINDGEN_UNUSED(_args)")
                self.wrapper_args.append("PyObject *PYBINDGEN_UNUSED(_kwargs)")
        self.wrapper_args.extend(extra_wrapper_params)
        self.wrapper_return = "PyObject *"
        self.write_open_wrapper(code_sink)
        tmp_sink.flush_to(code_sink)
        self.write_close_wrapper(code_sink)


    def generate_declaration(self, code_sink, extra_wrapper_parameters=()):
        ## We need to fake generate the code (and throw away the
        ## result) only in order to obtain correct method signature.
        self.reset_code_generation_state()
        self.generate(codesink.NullCodeSink(), extra_wrapper_params=extra_wrapper_parameters)
        assert isinstance(self.wrapper_return, string_types)
        assert isinstance(self.wrapper_actual_name, string_types)
        assert isinstance(self.wrapper_args, list)
        code_sink.writeln('%s %s(%s);' % (self.wrapper_return, self.wrapper_actual_name, ', '.join(self.wrapper_args)))
        self.reset_code_generation_state()

    def get_py_method_def(self, name):
        """
        Returns an array element to use in a PyMethodDef table.
        Should only be called after code generation.

        :param name: python function/method name
        """
        flags = self.get_py_method_def_flags()
        assert isinstance(self.wrapper_return, string_types)
        assert isinstance(self.wrapper_actual_name, string_types)
        assert isinstance(self.wrapper_args, list)

        if self.docstring is None:
            self.docstring = self.generate_docstring(name)

        return "{(char *) \"%s\", (PyCFunction) %s, %s, %s }," % \
               (name, self.wrapper_actual_name, '|'.join(sorted(flags)),
                (self.docstring is None and "NULL" or ('"'+self.docstring+'"')))

    def generate_docstring(self, name):
        parameters = self.parameters
        signature = "{0}({1})".format(name, ", ".join([p.name for p in parameters]))
        params = "\\n".join(["type: {0}: {1}".format(p.name, p.ctype)
                             for p in parameters])
        string = signature + "\\n\\n" + params
        return string class OverloadedFunction(overloading.OverloadedWrapper):
    """Adds support for overloaded functions"""
    RETURN_TYPE = 'PyObject *'
    ERROR_RETURN = 'return NULL;' class CustomFunctionWrapper(Function):
    """
    Adds a custom function wrapper.  The custom wrapper must be
    prepared to support overloading, i.e. it must have an additional
    "PyObject \\*\\*return_exception" parameter, and raised exceptions
    must be returned by this parameter.
    """

    NEEDS_OVERLOADING_INTERFACE = True

    def __init__(self, function_name, wrapper_name, wrapper_body=None,
                 flags=('METH_VARARGS', 'METH_KEYWORDS'), docstring=None):
        """
        :param function_name: name for function, Python side
        :param wrapper_name: name of the C wrapper function
        :param wrapper_body: if not None, the function wrapper is generated containing this parameter value as function body
        """
        super(CustomFunctionWrapper, self).__init__(function_name, ReturnValue.new('void'), [], docstring=docstring)
        self.wrapper_base_name = wrapper_name
        self.wrapper_actual_name = wrapper_name
        self.meth_flags = list(flags)
        self.wrapper_body = wrapper_body
        self.wrapper_args = ["PyObject *args", "PyObject *kwargs", "PyObject **return_exception"]
        self.wrapper_return = "PyObject *"


    def generate(self, code_sink, dummy_wrapper_name=None, extra_wrapper_params=()):
        assert extra_wrapper_params == ["PyObject **return_exception"]
        if self.wrapper_body is not None:
            code_sink.writeln(self.wrapper_body)
        else:
            self.generate_declaration(code_sink, extra_wrapper_parameters=extra_wrapper_params)

        #return "PyObject * %s (PyObject *args, PyObject *kwargs, PyObject **return_exception)" % self.wrapper_actual_name

    def generate_call(self, *args, **kwargs):
        pass class CodeBlock(object):
    '''An intelligent code block that keeps track of cleanup actions.
    This object is to be used by TypeHandlers when generating code.'''

    class CleanupHandle(object):
        """Handle for some cleanup code"""
        __slots__ = ['code_block', 'position']
        def __init__(self, code_block, position):
            """Create a handle given code_block and position"""
            self.code_block = code_block
            self.position = position

        def __cmp__(self, other):
            comp = cmp(self.code_block, other.code_block)
            if comp:
                return comp
            return cmp(self.position, other.position)

        def cancel(self):
            """Cancel the cleanup code"""
            self.code_block.remove_cleanup_code(self)

        def get_position(self):
            "returns the cleanup code relative position"
            return self.position


    def __init__(self, error_return, declarations, predecessor=None):
        '''
        CodeBlock constructor

        >>> block = CodeBlock("return NULL;", DeclarationsScope())
        >>> block.write_code("foo();")
        >>> cleanup1 = block.add_cleanup_code("clean1();")
        >>> cleanup2 = block.add_cleanup_code("clean2();")
        >>> cleanup3 = block.add_cleanup_code("clean3();")
        >>> cleanup2.cancel()
        >>> block.write_error_check("error()", "error_clean()")
        >>> block.write_code("bar();")
        >>> block.write_cleanup()
        >>> print block.sink.flush().rstrip()
        foo();
        if (error()) {
            error_clean()
            clean3();
            clean1();
            return NULL;
        }
        bar();
        clean3();
        clean1();

        :param error_return: code that is generated on error conditions
                           (detected by write_error_check()); normally
                           it returns from the wrapper function,
                           e.g. return NULL;
        :param predecessor: optional predecessor code block; a
                          predecessor is used to search for additional
                          cleanup actions.
        '''
        assert isinstance(declarations, DeclarationsScope)
        assert predecessor is None or isinstance(predecessor, CodeBlock)
        self.sink = codesink.MemoryCodeSink()
        self.predecessor = predecessor
        self._cleanup_actions = {}
        self._last_cleanup_position = 0
        self.error_return = error_return
        self.declarations = declarations

    def clear(self):
        self._cleanup_actions = {}
        self._last_cleanup_position = 0
        self.sink = codesink.MemoryCodeSink()

    def declare_variable(self, type_, name, initializer=None, array=None):
        """
        Calls declare_variable() on the associated DeclarationsScope object.
        """
        if ':' in name:
            raise ValueError("invalid variable name: %s " % name)
        return self.declarations.declare_variable(type_, name, initializer, array)

    def write_code(self, code):
        '''Write out some simple code'''
        self.sink.writeln(code)

    def indent(self, level=4):
        '''Add a certain ammount of indentation to all lines written
        from now on and until unindent() is called'''
        self.sink.indent(level)

    def unindent(self):
        '''Revert indentation level to the value before last indent() call'''
        self.sink.unindent()

    def add_cleanup_code(self, cleanup_code):
        '''Add a chunk of code used to cleanup previously allocated resources

        Returns a handle used to cancel the cleanup code
        '''
        self._last_cleanup_position += 1
        handle = self.CleanupHandle(self, self._last_cleanup_position)
        self._cleanup_actions[handle.get_position()] = cleanup_code
        return handle

    def remove_cleanup_code(self, handle):
        '''Remove cleanup code previously added with add_cleanup_code()
        '''
        assert isinstance(handle, self.CleanupHandle)
        del self._cleanup_actions[handle.get_position()]

    def get_cleanup_code(self):
        '''return a new list with all cleanup actions, including the
        ones from predecessor code blocks; Note: cleanup actions are
        executed in reverse order than when they were added.'''
        cleanup = []
        items = list(self._cleanup_actions.items())
        items.sort()
        for dummy, code in items:
            cleanup.append(code)
        cleanup.reverse()
        if self.predecessor is not None:
            cleanup.extend(self.predecessor.get_cleanup_code())
        return cleanup

    def write_error_check(self, failure_expression, failure_cleanup=None):
        '''Add a chunk of code that checks for a possible error

        :param failure_expression: C boolean expression that is true when
                              an error occurred
        :param failure_cleanup: optional extra cleanup code to write only
                           for the the case when failure_expression is
                           true; this extra cleanup code comes before
                           all other cleanup code previously registered.
        '''
        self.sink.writeln("if (%s) {" % (failure_expression,))
        self.sink.indent()
        if failure_cleanup is not None:
            self.sink.writeln(failure_cleanup)
        self.write_error_return()
        self.sink.unindent()
        self.sink.writeln("}")

    def write_cleanup(self):
        """Write the current cleanup code."""
        for cleanup_action in self.get_cleanup_code():
            self.sink.writeln(cleanup_action)

    def write_error_return(self):
        '''Add a chunk of code that cleans up and returns an error.
        '''
        self.write_cleanup()
        self.sink.writeln(self.error_return) class DeclarationsScope(object):
    """Manages variable declarations in a given scope."""

    def __init__(self, parent_scope=None):
        """
        Constructor

        >>> scope = DeclarationsScope()
        >>> scope.declare_variable('int', 'foo')
        'foo'
        >>> scope.declare_variable('char*', 'bar')
        'bar'
        >>> scope.declare_variable('int', 'foo')
        'foo2'
        >>> scope.declare_variable('int', 'foo', '1')
        'foo3'
        >>> scope.declare_variable('const char *', 'kwargs', '{"hello", NULL}', '[]')
        'kwargs'
        >>> print scope.get_code_sink().flush().rstrip()
        int foo;
        char *bar;
        int foo2;
        int foo3 = 1;
        const char *kwargs[] = {"hello", NULL};

        :param parent_scope: optional 'parent scope'; if given,
                        declarations in this scope will avoid clashing
                        with names in the parent scope, and vice
                        versa.
        """
        self._declarations = codesink.MemoryCodeSink()
        ## name -> number of variables with that name prefix
        if parent_scope is None:
            self.declared_variables = {}
        else:
            assert isinstance(parent_scope, DeclarationsScope)
            self.declared_variables = parent_scope.declared_variables

    def clear(self):
        self._declarations = codesink.MemoryCodeSink()
        self.declared_variables.clear()

    def declare_variable(self, type_, name, initializer=None, array=None):
        """Add code to declare a variable. Returns the actual variable
        name used (uses 'name' as base, with a number in case of conflict.)

        :param type_: C type name of the variable
        :param name: base name of the variable; actual name used can be
                slightly different in case of name conflict.
        :param initializer: optional, value to initialize the variable with
        :param array: optional, array size specifiction, e.g. '[]', or '[100]'
        """
        try:
            num = self.declared_variables[name]
        except KeyError:
            num = 0
        num += 1
        self.declared_variables[name] = num
        if num == 1:
            varname = name
        else:
            varname = "%s%i" % (name, num)
        decl = join_ctype_and_name(type_, varname)
        if array is not None:
            decl += array
        if initializer is not None:
            decl += ' = ' + initializer
        self._declarations.writeln(decl + ';')
        return varname

    def reserve_variable(self, name):
        """Reserve a variable name, to be used later.

        :param name: base name of the variable; actual name used can be
                slightly different in case of name conflict.
        """
        try:
            num = self.declared_variables[name]
        except KeyError:
            num = 0
        num += 1
        self.declared_variables[name] = num
        if num == 1:
            varname = name
        else:
            varname = "%s%i" % (name, num)
        return varname

    def get_code_sink(self):
        """Returns the internal MemoryCodeSink that holds all declararions."""
        return self._declarations class ReturnValue(_ReturnValue):
    __metaclass__ = ReturnValueMeta class TypeHandler(object):
    SUPPORTS_TRANSFORMATIONS = False

    def __init__(self, ctype, is_const=False):
        if ctype is None:
            self.ctype = None
            self.untransformed_ctype = None
            self.type_traits = None
        else:
            if isinstance(ctype, ctypeparser.TypeTraits):
                self.type_traits = ctype
                if is_const:
                    warnings.warn("is_const is deprecated, put a 'const' in the C type instead.", DeprecationWarning)
                    if self.type_traits.type_is_pointer or self.type_traits.type_is_reference:
                        self.type_traits.make_target_const()
                    else:
                        self.type_traits.make_const()
            elif isinstance(ctype, string_types):
                if is_const:
                    warnings.warn("is_const is deprecated, put a 'const' in the C type instead.", DeprecationWarning)
                    self.type_traits = ctypeparser.TypeTraits('const %s' % ctype)
                else:
                    self.type_traits = ctypeparser.TypeTraits(ctype)
            else:
                raise TypeError
            self.ctype = str(self.type_traits.ctype)
        self.untransformed_ctype = self.ctype
        self.transformation = NullTypeTransformation()

    def _get_ctype_no_const(self):
        return str(self.type_traits.ctype_no_const)
    ctype_no_const = property(_get_ctype_no_const)

    def set_tranformation(self, transformation, untransformed_ctype):
        warnings.warn("Typo: set_tranformation -> set_transformation", DeprecationWarning, stacklevel=2)
        return self.set_transformation(transformation, untransformed_ctype)

    def set_transformation(self, transformation, untransformed_ctype):
        "Set the type transformation to use in this type handler"

        assert isinstance(transformation, TypeTransformation)
        assert untransformed_ctype != self.ctype
        assert isinstance(self.transformation, NullTypeTransformation)
        assert self.SUPPORTS_TRANSFORMATIONS

        self.transformation = transformation
        self.untransformed_ctype = untransformed_ctype class MemoryCodeSink(CodeSink):
    """A code sink that keeps the code in memory,
    and can later flush the code to another code sink"""
    def __init__(self):
        "Constructor"
        CodeSink.__init__(self)
        self.lines = []

    def writeln(self, line=''):
        """Write one or more lines of code"""
        self.lines.extend(self._format_code(line))

    def flush_to(self, sink):
        """Flushes code to another code sink
        :param sink: another CodeSink instance
        """
        assert isinstance(sink, CodeSink)
        for line in self.lines:
            sink.writeln(line.rstrip())
        self.lines = []

    def flush(self):
        "Flushes the code and returns the formatted output as a return value string"
        l = []
        for line in self.lines:
            l.extend(self._format_code(line))
        self.lines = []
        return "\n".join(l) + '\n' class CodeSink(object):
    """Abstract base class for code sinks"""
    def __init__(self):
        r'''Constructor

        >>> sink = MemoryCodeSink()
        >>> sink.writeln("foo();")
        >>> sink.writeln("if (true) {")
        >>> sink.indent()
        >>> sink.writeln("bar();")
        >>> sink.unindent()
        >>> sink.writeln("zbr();")
        >>> print sink.flush().rstrip()
        foo();
        if (true) {
            bar();
        zbr();

        >>> sink = MemoryCodeSink()
        >>> sink.writeln("foo();")
        >>> sink.writeln()
        >>> sink.writeln("bar();")
        >>> print len(sink.flush().split("\n"))
        4
        '''
        self.indent_level = 0 # current indent level
        self.indent_stack = [] # previous indent levels
        if DEBUG:
            self._last_unindent_stack = None # for debugging

    def _format_code(self, code):
        """Utility method for subclasses to use for formatting code
        (splits lines and indents them)"""
        assert isinstance(code, string_types)
        l = []
        for line in code.split('\n'):
            l.append(' '*self.indent_level + line)
        return l

    def writeln(self, line=''):
        """Write one or more lines of code"""
        raise NotImplementedError

    def indent(self, level=4):
        '''Add a certain ammount of indentation to all lines written
        from now on and until unindent() is called'''
        self.indent_stack.append(self.indent_level)
        self.indent_level += level

    def unindent(self):
        '''Revert indentation level to the value before last indent() call'''
        if DEBUG:
            try:
                self.indent_level = self.indent_stack.pop()
            except IndexError:
                if self._last_unindent_stack is not None:
                    for line in traceback.format_list(self._last_unindent_stack):
                        sys.stderr.write(line)
                raise
            self._last_unindent_stack = traceback.extract_stack()
        else:
            self.indent_level = self.indent_stack.pop() class FileCodeSink(CodeSink):
    """A code sink that writes to a file-like object"""
    def __init__(self, file_):
        """
        :param file_: a file like object
        """
        CodeSink.__init__(self)
        self.file = file_

    def __repr__(self):
        return "<pybindgen.typehandlers.codesink.FileCodeSink %r>" % (self.file.name,)

    def writeln(self, line=''):
        """Write one or more lines of code"""
        self.file.write('\n'.join(self._format_code(line)))
        self.file.write('\n')

    def __lt__(self, other):
        if isinstance(other, FileCodeSink):
            return self.file.name < other.file.name class NullCodeSink(CodeSink):
    """A code sink that discards all content.  Useful to 'test' if code
    generation would work without actually generating anything."""

    def __init__(self):
        "Constructor"
        CodeSink.__init__(self)

    def writeln(self, line=''):
        """Write one or more lines of code"""
        pass

    def flush_to(self, sink):
        """Flushes code to another code sink
        :param sink: another CodeSink instance
        """
        raise TypeError("Cannot flush a NullCodeSink; it has no content!")

    def flush(self):
        "Flushes the code and returns the formatted output as a return value string"
        raise TypeError("Cannot flush a NullCodeSink; it has no content!") class CppClass(object):
    """
    A CppClass object takes care of generating the code for wrapping a C++ class
    """

    def __init__(self, name, parent=None, incref_method=None, decref_method=None,
                 automatic_type_narrowing=None, allow_subclassing=None,
                 is_singleton=False, outer_class=None,
                 peekref_method=None,
                 template_parameters=(), custom_template_class_name=None,
                 incomplete_type=False, free_function=None,
                 incref_function=None, decref_function=None,
                 python_name=None, memory_policy=None,
                 foreign_cpp_namespace=None,
                 docstring=None,
                 custom_name=None,
                 import_from_module=None,
                 destructor_visibility='public'
                 ):
        """
        :param name: class name

        :param parent: optional parent class wrapper, or list of
                       parents.  Valid values are None, a CppClass
                       instance, or a list of CppClass instances.

        :param incref_method: (deprecated in favour of memory_policy) if the class supports reference counting, the
                         name of the method that increments the
                         reference count (may be inherited from parent
                         if not given)
        :param decref_method: (deprecated in favour of memory_policy) if the class supports reference counting, the
                         name of the method that decrements the
                         reference count (may be inherited from parent
                         if not given)
        :param automatic_type_narrowing: if True, automatic return type
                                    narrowing will be done on objects
                                    of this class and its descendants
                                    when returned by pointer from a
                                    function or method.
        :param allow_subclassing: if True, generated class wrappers will
                             allow subclassing in Python.
        :param is_singleton: if True, the class is considered a singleton,
                        and so the python wrapper will never call the
                        C++ class destructor to free the value.
        :param peekref_method: (deprecated in favour of memory_policy) if the class supports reference counting, the
                          name of the method that returns the current reference count.
        :param free_function: (deprecated in favour of memory_policy) name of C function used to deallocate class instances
        :param incref_function: (deprecated in favour of memory_policy) same as incref_method, but as a function instead of method
        :param decref_function: (deprecated in favour of memory_policy) same as decref_method, but as a function instead of method

        :param python_name: name of the class as it will appear from
             Python side.  This parameter is DEPRECATED in favour of
             custom_name.

        :param memory_policy: memory management policy; if None, it
            inherits from the parent class.  Only root classes can have a
            memory policy defined.
        :type memory_policy: L{MemoryPolicy}

        :param foreign_cpp_namespace: if set, the class is assumed to
            belong to the given C++ namespace, regardless of the C++
            namespace of the python module it will be added to.  For
            instance, this can be useful to wrap std classes, like
            std::ofstream, without having to create an extra python
            submodule.

        :param docstring: None or a string containing the docstring
            that will be generated for the class

        :param custom_name: an alternative name to give to this class
            at python-side; if omitted, the name of the class in the
            python module will be the same name as the class in C++
            (minus namespace).

        :param import_from_module: if not None, the type is imported
                    from a foreign Python module with the given name.
        """
        assert outer_class is None or isinstance(outer_class, CppClass)
        self.incomplete_type = incomplete_type
        self.outer_class = outer_class
        self._module = None
        self.name = name
        self.docstring = docstring
        self.mangled_name = None
        self.mangled_full_name = None
        self.template_parameters = template_parameters
        self.container_traits = None
        self.import_from_module = import_from_module
        assert destructor_visibility in ['public', 'private', 'protected']
        self.destructor_visibility = destructor_visibility

        self.custom_name = custom_name
        if custom_template_class_name:
            warnings.warn("Use the custom_name parameter.",
                          DeprecationWarning, stacklevel=2)
            self.custom_name = custom_template_class_name
        if python_name:
            warnings.warn("Use the custom_name parameter.",
                          DeprecationWarning, stacklevel=2)
            self.custom_name = python_name

        self.is_singleton = is_singleton
        self.foreign_cpp_namespace = foreign_cpp_namespace
        self.full_name = None # full name with C++ namespaces attached and template parameters
        self.methods = collections.OrderedDict() # name => OverloadedMethod
        self._dummy_methods = [] # methods that have parameter/retval binding problems
        self.nonpublic_methods = []
        self.constructors = [] # (name, wrapper) pairs
        self.pytype = PyTypeObject()
        self.slots = self.pytype.slots
        self.helper_class = None
        self.instance_creation_function = None
        self.post_instance_creation_function = None
        ## set to True when we become aware generating the helper
        ## class is not going to be possible
        self.helper_class_disabled = False
        self.cannot_be_constructed = '' # reason
        self.has_trivial_constructor = False
        self.has_copy_constructor = False
        self.has_output_stream_operator = False
        self._have_pure_virtual_methods = None
        self._wrapper_registry = None
        self.binary_comparison_operators = set()
        self.binary_numeric_operators = dict()
        self.inplace_numeric_operators = dict()
        self.unary_numeric_operators = dict()
        self.valid_sequence_methods = {"__len__"       : "sq_length",
                                       "__add__"       : "sq_concat",
                                       "__mul__"       : "sq_repeat",
                                       "__getitem__"   : "sq_item",
                                       "__getslice__"  : "sq_slice",
                                       "__setitem__"   : "sq_ass_item",
                                       "__setslice__"  : "sq_ass_slice",
                                       "__contains__"  : "sq_contains",
                                       "__iadd__"      : "sq_inplace_concat",
                                       "__imul__"      : "sq_inplace_repeat"}

        ## list of CppClasses from which a value of this class can be
        ## implicitly generated; corresponds to a
        ## operator ThisClass(); in the other class.
        self.implicitly_converts_from = []

        ## list of hook functions to call just prior to helper class
        ## code generation.
        self.helper_class_hooks = []

        self._pystruct = None #"***GIVE ME A NAME***"
        self.metaclass_name = "***GIVE ME A NAME***"
        self.pytypestruct = "***GIVE ME A NAME***"

        self.instance_attributes = PyGetSetDef("%s__getsets" % self._pystruct)
        self.static_attributes = PyGetSetDef("%s__getsets" % self.metaclass_name)

        if isinstance(parent, list):
            self.bases = list(parent)
            self.parent = self.bases[0]
        elif isinstance(parent, CppClass):
            self.parent = parent
            self.bases = [parent]
        elif parent is None:
            self.parent = None
            self.bases = []
        else:
            raise TypeError("'parent' must be None, CppClass instance, or a list of CppClass instances")

        if free_function:
            warnings.warn("Use FreeFunctionPolicy and memory_policy parameter.", DeprecationWarning)
            assert memory_policy is None
            memory_policy = FreeFunctionPolicy(free_function)
        elif incref_method:
            warnings.warn("Use ReferenceCountingMethodsPolicy and memory_policy parameter.", DeprecationWarning)
            assert memory_policy is None
            memory_policy = ReferenceCountingMethodsPolicy(incref_method, decref_method, peekref_method)
        elif incref_function:
            warnings.warn("Use ReferenceCountingFunctionsPolicy and memory_policy parameter.", DeprecationWarning)
            assert memory_policy is None
            memory_policy = ReferenceCountingFunctionsPolicy(incref_function, decref_function)

        if not self.bases:
            assert memory_policy is None or isinstance(memory_policy, MemoryPolicy)
            self.memory_policy = memory_policy
        else:
            for base in self.bases:
                if base.memory_policy is not None:
                    self.memory_policy = base.memory_policy
                    assert memory_policy is None, \
                        "changing memory policy from parent (%s) to child (%s) class not permitted" \
                        % (base.name, self.name)
                    break
            else:
                self.memory_policy = memory_policy

        if automatic_type_narrowing is None:
            if not self.bases:
                self.automatic_type_narrowing = settings.automatic_type_narrowing
            else:
                self.automatic_type_narrowing = self.parent.automatic_type_narrowing
        else:
            self.automatic_type_narrowing = automatic_type_narrowing

        if allow_subclassing is None:
            if self.parent is None:
                self.allow_subclassing = settings.allow_subclassing
            else:
                self.allow_subclassing = self.parent.allow_subclassing
        else:
            if any([p.allow_subclassing for p in self.bases]) and not allow_subclassing:
                raise ValueError("Cannot disable subclassing if a parent class allows it")
            else:
                self.allow_subclassing = allow_subclassing

        if self.destructor_visibility not in ['public', 'protected']:
            self.allow_subclassing = False

        self.typeid_map_name = None

        if name != 'dummy':
            ## register type handlers

            class ThisClassParameter(CppClassParameter):
                """Register this C++ class as pass-by-value parameter"""
                CTYPES = []
                cpp_class = self
            self.ThisClassParameter = ThisClassParameter
            try:
                param_type_matcher.register(name, self.ThisClassParameter)
            except ValueError:
                pass


            class ThisClassRefParameter(CppClassRefParameter):
                """Register this C++ class as pass-by-reference parameter"""
                CTYPES = []
                cpp_class = self
            self.ThisClassRefParameter = ThisClassRefParameter
            try:
                param_type_matcher.register(name+'&', self.ThisClassRefParameter)
            except ValueError:
                pass

            class ThisClassReturn(CppClassReturnValue):
                """Register this C++ class as value return"""
                CTYPES = []
                cpp_class = self
            self.ThisClassReturn = ThisClassReturn
            self.ThisClassRefReturn = ThisClassReturn
            try:
                return_type_matcher.register(name, self.ThisClassReturn)
                return_type_matcher.register(name, self.ThisClassRefReturn)
            except ValueError:
                pass

            if self.memory_policy is not None:
                self.memory_policy.register_ptr_parameter_and_return(self, name)
            else: # Regular pointer
                class ThisClassPtrParameter(CppClassPtrParameter):
                    """Register this C++ class as pass-by-pointer parameter"""
                    CTYPES = []
                    cpp_class = self
                self.ThisClassPtrParameter = ThisClassPtrParameter
                try:
                    param_type_matcher.register(name+'*', self.ThisClassPtrParameter)
                except ValueError:
                    pass

                class ThisClassPtrReturn(CppClassPtrReturnValue):
                    """Register this C++ class as pointer return"""
                    CTYPES = []
                    cpp_class = self
                self.ThisClassPtrReturn = ThisClassPtrReturn
                try:
                    return_type_matcher.register(name+'*', self.ThisClassPtrReturn)
                except ValueError:
                    pass


            class ThisClassRefReturn(CppClassRefReturnValue):
                """Register this C++ class as reference return"""
                CTYPES = []
                cpp_class = self
            self.ThisClassRefReturn = ThisClassRefReturn
            try:
                return_type_matcher.register(name+'&', self.ThisClassRefReturn)
            except ValueError:
                pass

    def __repr__(self):
        return "<pybindgen.CppClass %r>" % self.full_name

    def add_container_traits(self, *args, **kwargs):
        assert self.container_traits is None
        self.container_traits = CppClassContainerTraits(self, *args, **kwargs)

    def add_binary_comparison_operator(self, operator):
        """
        Add support for a C++ binary comparison operator, such as == or <.

        The binary operator is assumed to operate with both operands
        of the type of the class, either by reference or by value.

        :param operator: string indicating the name of the operator to
            support, e.g. '=='
        """
        operator = utils.ascii(operator)
        if not isinstance(operator, string_types):
            raise TypeError("expected operator name as string")
        if operator not in ['==', '!=', '<', '<=', '>', '>=']:
            raise ValueError("The operator %r is invalid or not yet supported by PyBindGen" % (operator,))
        self.binary_comparison_operators.add(operator)

    def add_binary_numeric_operator(self, operator, result_cppclass=None,
                                    left_cppclass=None, right=None):
        """
        Add support for a C++ binary numeric operator, such as +, -, \\*, or /.

        :param operator: string indicating the name of the operator to
           support, e.g. '=='

        :param result_cppclass: the CppClass object of the result type, assumed to be this class if omitted
        :param left_cppclass: the CppClass object of the left operand type, assumed to be this class if omitted

        :param right: the type of the right parameter. Can be a
          CppClass, Parameter, or param spec. Assumed to be this class
          if omitted
        """
        operator = utils.ascii(operator)
        if not isinstance(operator, string_types):
            raise TypeError("expected operator name as string")
        if operator not in ['+', '-', '*', '/']:
            raise ValueError("The operator %r is invalid or not yet supported by PyBindGen" % (operator,))
        try:
            l = self.binary_numeric_operators[operator]
        except KeyError:
            l = []
            self.binary_numeric_operators[operator] = l
        if result_cppclass is None:
            result_cppclass = self
        if left_cppclass is None:
            left_cppclass = self

        if right is None:
            right = self
        elif isinstance(right, CppClass):
            pass
        else:
            if isinstance(right, string_types):
                right = utils.param(right, 'right')
            try:
                right = utils.eval_param(right, None)
            except utils.SkipWrapper:
                return

        op = (result_cppclass, left_cppclass, right)
        if op not in l:
            l.append(op)


    def add_inplace_numeric_operator(self, operator, right=None):
        """
        Add support for a C++ inplace numeric operator, such as +=, -=, \\*=, or /=.

        :param operator: string indicating the name of the operator to
           support, e.g. '+='

        :param right: the type of the right parameter. Can be a
          CppClass, Parameter, or param spec. Assumed to be this class
          if omitted
        """
        operator = utils.ascii(operator)
        if not isinstance(operator, string_types):
            raise TypeError("expected operator name as string")
        if operator not in ['+=', '-=', '*=', '/=']:
            raise ValueError("The operator %r is invalid or not yet supported by PyBindGen" % (operator,))
        try:
            l = self.inplace_numeric_operators[operator]
        except KeyError:
            l = []
            self.inplace_numeric_operators[operator] = l
        if right is None:
            right = self
        else:
            if isinstance(right, string_types):
                right = utils.param(right, 'right')
            try:
                right = utils.eval_param(right, None)
            except utils.SkipWrapper:
                return
        if right not in l:
            l.append((self, self, right))

    def add_unary_numeric_operator(self, operator, result_cppclass=None, left_cppclass=None):
        """
        Add support for a C++ unary numeric operators, currently only -.

        :param operator: string indicating the name of the operator to
          support, e.g. '-'

        :param result_cppclass: the CppClass object of the result type, assumed to be this class if omitted
        :param left_cppclass: the CppClass object of the left operand type, assumed to be this class if omitted
        """
        operator = utils.ascii(operator)
        if not isinstance(operator, string_types):
            raise TypeError("expected operator name as string")
        if operator not in ['-']:
            raise ValueError("The operator %r is invalid or not yet supported by PyBindGen" % (operator,))
        try:
            l = self.unary_numeric_operators[operator]
        except KeyError:
            l = []
            self.unary_numeric_operators[operator] = l
        if result_cppclass is None:
            result_cppclass = self
        if left_cppclass is None:
            left_cppclass = self
        op = (result_cppclass, left_cppclass)
        if op not in l:
            l.append(op)

    def add_class(self, *args, **kwargs):
        """
        Add a nested class.  See L{CppClass} for information about accepted parameters.
        """
        assert 'outer_class' not in kwargs
        kwargs['outer_class'] = self
        return self.module.add_class(*args, **kwargs)


    def add_enum(self, *args, **kwargs):
        """
        Add a nested enum.  See L{Enum} for information about accepted parameters.
        """
        assert 'outer_class' not in kwargs
        kwargs['outer_class'] = self
        return self.module.add_enum(*args, **kwargs)


    def get_mro(self):
        """
        Get the method resolution order (MRO) of this class.

        :return: an iterator that gives CppClass objects, from leaf to root class
        """
        to_visit = [self]
        visited = set()
        while to_visit:
            cls = to_visit.pop(0)
            visited.add(cls)
            yield cls
            for base in cls.bases:
                if base not in visited:
                    to_visit.append(base)

    def get_all_methods(self):
        """Returns an iterator to iterate over all methods of the class"""
        for overload in self.methods.values():
            for method in overload.wrappers:
                yield method
        for method in self.nonpublic_methods:
            yield method

    def get_have_pure_virtual_methods(self):
        """
        Returns True if the class has pure virtual methods with no
        implementation (which would mean the type is not instantiable
        directly, only through a helper class).
        """
        if self._have_pure_virtual_methods is not None:
            return self._have_pure_virtual_methods
        mro = list(self.get_mro())
        mro_reversed = list(mro)
        mro_reversed.reverse()

        self._have_pure_virtual_methods = False
        for pos, cls in enumerate(mro_reversed):
            for method in list(cls.get_all_methods()) + cls._dummy_methods:
                if not isinstance(method, CppMethod):
                    continue

                if method.is_pure_virtual:
                    ## found a pure virtual method; now go see in the
                    ## child classes, check if any of them implements
                    ## this pure virtual method.
                    implemented = False
                    for child_cls in mro_reversed[pos+1:]:
                        for child_method in list(child_cls.get_all_methods()) + child_cls._dummy_methods:
                            if not isinstance(child_method, CppMethod):
                                continue
                            if not child_method.is_virtual:
                                continue
                            if not child_method.matches_signature(method):
                                continue
                            if not child_method.is_pure_virtual:
                                implemented = True
                            break
                        if implemented:
                            break
                    if not implemented:
                        self._have_pure_virtual_methods = True

        return self._have_pure_virtual_methods

    have_pure_virtual_methods = property(get_have_pure_virtual_methods)


    def is_subclass(self, other):
        """Return True if this CppClass instance represents a class that is a
        subclass of another class represented by the CppClasss object \\`other\\'."""
        if not isinstance(other, CppClass):
            raise TypeError
        return other in self.get_mro()

    def add_helper_class_hook(self, hook):
        """
        Add a hook function to be called just prior to a helper class
        being generated.  The hook function applies to this class and
        all subclasses.  The hook function is called like this::
          hook_function(helper_class)
        """
        if not isinstance(hook, collectionsCallable):
            raise TypeError("hook function must be callable")
        self.helper_class_hooks.append(hook)

    def _get_all_helper_class_hooks(self):
        """
        Returns a list of all helper class hook functions, including
        the ones registered with parent classes.  Parent hooks will
        appear first in the list.
        """
        l = []
        for cls in self.get_mro():
            l = cls.helper_class_hooks + l
        return l

    def set_instance_creation_function(self, instance_creation_function):
        """Set a custom function to be called to create instances of this
        class and its subclasses.

        :param instance_creation_function: instance creation function; see
                                      default_instance_creation_function()
                                      for signature and example.
        """
        self.instance_creation_function = instance_creation_function

    def set_post_instance_creation_function(self, post_instance_creation_function):
        """Set a custom function to be called to add code after an
        instance is created (usually by the "instance creation
        function") and registered with the Python runtime.

        :param post_instance_creation_function: post instance creation function
        """
        self.post_instance_creation_function = post_instance_creation_function

    def get_instance_creation_function(self):
        for cls in self.get_mro():
            if cls.instance_creation_function is not None:
                return cls.instance_creation_function
        if cls.memory_policy is not None:
            return cls.memory_policy.get_instance_creation_function()
        return default_instance_creation_function

    def get_post_instance_creation_function(self):
        for cls in self.get_mro():
            if cls.post_instance_creation_function is not None:
                return cls.post_instance_creation_function
        return None

    def write_create_instance(self, code_block, lvalue, parameters, construct_type_name=None):
        instance_creation_func = self.get_instance_creation_function()
        if construct_type_name is None:
            construct_type_name = self.get_construct_name()
        instance_creation_func(self, code_block, lvalue, parameters, construct_type_name)

    def write_post_instance_creation_code(self, code_block, lvalue, parameters, construct_type_name=None):
        post_instance_creation_func = self.get_post_instance_creation_function()
        if post_instance_creation_func is None:
            return
        if construct_type_name is None:
            construct_type_name = self.get_construct_name()
        post_instance_creation_func(self, code_block, lvalue, parameters, construct_type_name)

    def get_pystruct(self):
        if self._pystruct is None:
            raise ValueError
        return self._pystruct
    pystruct = property(get_pystruct)

    def get_construct_name(self):
        """Get a name usable for new %s construction, or raise
        CodeGenerationError if none found"""
        if self.cannot_be_constructed:
            raise CodeGenerationError("%s cannot be constructed (%s)" % (self.full_name, self.cannot_be_constructed))
        if self.have_pure_virtual_methods:
            raise CodeGenerationError("%s cannot be constructed (class has pure virtual methods)" % self.full_name)
        else:
            return self.full_name


    def implicitly_converts_to(self, other):
        """
        Declares that values of this class can be implicitly converted
        to another class; corresponds to a operator AnotherClass();
        special method.
        """
        assert isinstance(other, CppClass)
        other.implicitly_converts_from.append(self)

    def get_all_implicit_conversions(self):
        """
        Gets a new list of all other classes whose value can be implicitly
        converted to a value of this class.

        >>> Foo = CppClass("Foo")
        >>> Bar = CppClass("Bar")
        >>> Zbr = CppClass("Zbr")
        >>> Bar.implicitly_converts_to(Foo)
        >>> Zbr.implicitly_converts_to(Bar)
        >>> l = Foo.get_all_implicit_conversions()
        >>> l.sort(lambda cls1, cls2: cmp(cls1.name, cls2.name))
        >>> [cls.name for cls in l]
        ['Bar']
        """
        return list(self.implicitly_converts_from)
#         classes = []
#         to_visit = list(self.implicitly_converts_from)
#         while to_visit:
#             source = to_visit.pop(0)
#             if source in classes or source is self:
#                 continue
#             classes.append(source)
#             to_visit.extend(source.implicitly_converts_from)
#         return classes

    def _update_names(self):

        prefix = settings.name_prefix.capitalize()

        if self.outer_class is None:
            if self.foreign_cpp_namespace:
                self.full_name = self.foreign_cpp_namespace + '::' + self.name
            else:
                if self._module.cpp_namespace_prefix:
                    if self._module.cpp_namespace_prefix == '::':
                        self.full_name = '::' + self.name
                    else:
                        self.full_name = self._module.cpp_namespace_prefix + '::' + self.name
                else:
                    self.full_name = self.name
        else:
            assert not self.foreign_cpp_namespace
            self.full_name = '::'.join([self.outer_class.full_name, self.name])

        def make_upper(s):
            if s and s[0].islower():
                return s[0].upper()+s[1:]
            else:
                return s

        def mangle(name):
            return mangle_name(name)

        def flatten(name):
            "make a name like::This look LikeThis"
            return ''.join([make_upper(mangle(s)) for s in name.split('::')])

        self.mangled_name = flatten(self.name)
        self.mangled_full_name = flatten(self.full_name)

        if self.template_parameters:
            self.full_name += "< %s >" % (', '.join(self.template_parameters))
            mangled_template_params = '__' + '_'.join([flatten(s) for s in self.template_parameters])
            self.mangled_name += mangled_template_params
            self.mangled_full_name += mangled_template_params

        self._pystruct = "Py%s%s" % (prefix, self.mangled_full_name)
        self.metaclass_name = "%sMeta" % self.mangled_full_name
        self.pytypestruct = "Py%s%s_Type" % (prefix,  self.mangled_full_name)

        self.instance_attributes.cname = "%s__getsets" % self._pystruct
        self.static_attributes.cname = "%s__getsets" % self.metaclass_name

        ## re-register the class type handlers, now with class full name
        self.register_alias(self.full_name)

        if self.get_type_narrowing_root() is self:
            self.typeid_map_name = "%s__typeid_map" % self.pystruct
        else:
            self.typeid_map_name = None

    def register_alias(self, alias):
        """Re-register the class with another base name, in addition to any
        registrations that might have already been done."""

        self.module.register_type(None, alias, self)

        self.ThisClassParameter.CTYPES.append(alias)
        try:
            param_type_matcher.register(alias, self.ThisClassParameter)
        except ValueError: pass

        self.ThisClassRefParameter.CTYPES.append(alias+'&')
        try:
            param_type_matcher.register(alias+'&', self.ThisClassRefParameter)
        except ValueError: pass

        self.ThisClassReturn.CTYPES.append(alias)
        try:
            return_type_matcher.register(alias, self.ThisClassReturn)
        except ValueError: pass

        if self.memory_policy is not None:
            self.memory_policy.register_ptr_alias_parameter_and_return(self, alias)
        else:
            self.ThisClassPtrParameter.CTYPES.append(alias+'*')
            try:
                param_type_matcher.register(alias+'*', self.ThisClassPtrParameter)
            except ValueError: pass

            self.ThisClassPtrReturn.CTYPES.append(alias+'*')
            try:
                return_type_matcher.register(alias+'*', self.ThisClassPtrReturn)
            except ValueError: pass

        self.ThisClassRefReturn.CTYPES.append(alias)
        try:
            return_type_matcher.register(alias+'&', self.ThisClassRefReturn)
        except ValueError: pass


    def get_module(self):
        """Get the Module object this class belongs to"""
        return self._module

    def set_module(self, module):
        """Set the Module object this class belongs to"""
        self._module = module
        self._update_names()

    module = property(get_module, set_module)


    def inherit_default_constructors(self):
        """inherit the default constructors from the parentclass according to C++
        language rules"""
        for base in self.bases:
            for cons in base.constructors:
                if len(cons.parameters) == 0:
                    self.add_constructor([], visibility=cons.visibility)
                elif (len(cons.parameters) == 1
                      and isinstance(cons.parameters[0], self.parent.ThisClassRefParameter)):
                    self.add_constructor([self.ThisClassRefParameter(
                        self.full_name + "&",
                        "obj",
                        cons.parameters[0].direction)],
                        visibility=cons.visibility)

    def get_helper_class(self):
        """gets the "helper class" for this class wrapper, creating it if necessary"""
        for cls in self.get_mro():
            if cls.helper_class_disabled:
                return None
        if not self.allow_subclassing:
            return None
        if self.helper_class is None:
            if not self.is_singleton:
                self.helper_class = CppHelperClass(self)
                self.module.add_include('<typeinfo>')
        return self.helper_class

    def get_type_narrowing_root(self):
        """Find the root CppClass along the subtree of all parent classes that
        have automatic_type_narrowing=True Note: multiple inheritance
        not implemented"""
        if not self.automatic_type_narrowing:
            return None
        root = self
        while (root.parent is not None
               and root.parent.automatic_type_narrowing):
            root = root.parent
        return root

    def _register_typeid(self, module):
        """register this class with the typeid map root class"""
        root = self.get_type_narrowing_root()
        module.after_init.write_code("%s.register_wrapper(typeid(%s), &%s);"
                                     % (root.typeid_map_name, self.full_name, self.pytypestruct))

    def _generate_typeid_map(self, code_sink, module):
        """generate the typeid map and fill it with values"""
        try:
            module.declare_one_time_definition("TypeIDMap")
        except KeyError:
            pass
        else:
            code_sink.writeln('''

#include <map>
#include <string>
#include <typeinfo>
#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__clang__)
# include <cxxabi.h>
#endif

#define PBG_TYPEMAP_DEBUG 0

namespace pybindgen {

class TypeMap
{
   std::map<std::string, PyTypeObject *> m_map;

public:

   TypeMap() {}

   void register_wrapper(const std::type_info &cpp_type_info, PyTypeObject *python_wrapper)
   {

#if PBG_TYPEMAP_DEBUG
   std::cerr << "register_wrapper(this=" << this << ", type_name=" << cpp_type_info.name()
             << ", python_wrapper=" << python_wrapper->tp_name << ")" << std::endl;
#endif

       m_map[std::string(cpp_type_info.name())] = python_wrapper;
   }

''')

            if settings.gcc_rtti_abi_complete:
                code_sink.writeln('''
   PyTypeObject * lookup_wrapper(const std::type_info &cpp_type_info, PyTypeObject *fallback_wrapper)
   {

#if PBG_TYPEMAP_DEBUG
   std::cerr << "lookup_wrapper(this=" << this << ", type_name=" << cpp_type_info.name() << ")" << std::endl;
#endif

       PyTypeObject *python_wrapper = m_map[cpp_type_info.name()];
       if (python_wrapper)
           return python_wrapper;
       else {
#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__clang__)

           // Get closest (in the single inheritance tree provided by cxxabi.h)
           // registered python wrapper.
           const abi::__si_class_type_info *_typeinfo =
               dynamic_cast<const abi::__si_class_type_info*> (&cpp_type_info);
#if PBG_TYPEMAP_DEBUG
          std::cerr << "  -> looking at C++ type " << _typeinfo->name() << std::endl;
#endif
           while (_typeinfo && (python_wrapper = m_map[std::string(_typeinfo->name())]) == 0) {
               _typeinfo = dynamic_cast<const abi::__si_class_type_info*> (_typeinfo->__base_type);
#if PBG_TYPEMAP_DEBUG
               std::cerr << "  -> looking at C++ type " << _typeinfo->name() << std::endl;
#endif
           }

#if PBG_TYPEMAP_DEBUG
          if (python_wrapper) {
              std::cerr << "  -> found match " << std::endl;
          } else {
              std::cerr << "  -> return fallback wrapper" << std::endl;
          }
#endif

           return python_wrapper? python_wrapper : fallback_wrapper;

#else // non gcc 3+ compilers can only match against explicitly registered classes, not hidden subclasses
           return fallback_wrapper;
#endif
       }
   }
};

}
''')
            else:
                code_sink.writeln('''
   PyTypeObject * lookup_wrapper(const std::type_info &cpp_type_info, PyTypeObject *fallback_wrapper)
   {

#if PBG_TYPEMAP_DEBUG
   std::cerr << "lookup_wrapper(this=" << this << ", type_name=" << cpp_type_info.name() << ")" << std::endl;
#endif

       PyTypeObject *python_wrapper = m_map[cpp_type_info.name()];
       return python_wrapper? python_wrapper : fallback_wrapper;
   }
};

}
''')


        if self.import_from_module:
            code_sink.writeln("\nextern pybindgen::TypeMap *_%s;\n" % self.typeid_map_name)
            code_sink.writeln("#define %s (*_%s)\n" % (self.typeid_map_name, self.typeid_map_name))
        else:
            code_sink.writeln("\nextern pybindgen::TypeMap %s;\n" % self.typeid_map_name)

    def _add_method_obj(self, method):
        """
        Add a method object to the class.  For internal use.

        :param method: a L{CppMethod} or L{Function} instance that can generate the method wrapper
        """
        if isinstance(method, CppMethod):
            name = method.mangled_name
        elif isinstance(method, function.Function):
            name = method.custom_name
            assert isinstance(method.parameters[0], CppClassParameterBase)
            assert method.parameters[0].cpp_class is self, \
                "expected first parameter to be of class %s, but it is of class %s" % \
                (self.full_name, method.parameters[0].cpp_class.full_name)
            method.parameters[0].take_value_from_python_self = True
            method.module = self.module
            method.is_virtual = False
            method.is_pure_virtual = False
            method.self_parameter_pystruct = self.pystruct
            method.visibility = 'public'
            method.force_parse = method.PARSE_TUPLE_AND_KEYWORDS
        else:
            raise TypeError

        method.class_ = self

        if method.visibility == 'protected' and not method.is_virtual:
            helper_class = self.get_helper_class()
            if helper_class is not None:
                parent_caller = CppVirtualMethodParentCaller(method)
                parent_caller.helper_class = helper_class
                parent_caller.main_wrapper = method
                helper_class.add_virtual_parent_caller(parent_caller)
        elif method.visibility == 'public':
            if name == '__call__': # needs special handling
                method.force_parse = method.PARSE_TUPLE_AND_KEYWORDS

            try:
                overload = self.methods[name]
            except KeyError:
                overload = CppOverloadedMethod(name)
                overload.pystruct = self.pystruct
                self.methods[name] = overload

            ## add it....
            try:
                utils.call_with_error_handling(overload.add, (method,), {}, method)
            except utils.SkipWrapper:
                return


            # Grr! I hate C++.  Overloading + inheritance = disaster!
            # So I ended up coding something which C++ does not in
            # fact support, but I feel bad to just throw away my good
            # code due to a C++ fault, so I am leaving here the code
            # disabled.  Maybe some future C++ version will come along
            # and fix this problem, who knows :P
            if 0:
                # due to a limitation of the pybindgen overloading
                # strategy, we need to re-wrap for this class all
                # methods with the same name and different signature
                # from parent classes.
                overload._compute_all_wrappers()
                if isinstance(method, CppMethod):
                    mro = self.get_mro()
                    next(mro) # skip 'self'
                    for cls in mro:
                        try:
                            parent_overload = cls.methods[name]
                        except KeyError:
                            continue
                        parent_overload._compute_all_wrappers()
                        for parent_method in parent_overload.all_wrappers:
                            already_exists = False
                            for existing_method in overload.all_wrappers:
                                if existing_method.matches_signature(parent_method):
                                    already_exists = True
                                    break
                            if not already_exists:
                                new_method = parent_method.clone()
                                new_method.class_ = self
                                overload.add(new_method)

        else:
            self.nonpublic_methods.append(method)
        if method.is_virtual:
            self._have_pure_virtual_methods = None
            helper_class = self.get_helper_class()
            if helper_class is not None:
                helper_class.add_virtual_method(method)

    def add_method(self, *args, **kwargs):
        """
        Add a method to the class. See the documentation for
        L{CppMethod.__init__} for information on accepted parameters.
        """

        ## <compat>
        if len(args) >= 1 and isinstance(args[0], CppMethod):
            meth = args[0]
            warnings.warn("add_method has changed API; see the API documentation",
                          DeprecationWarning, stacklevel=2)
            if len(args) == 2:
                meth.custom_name = args[1]
            elif 'name' in kwargs:
                assert len(args) == 1
                meth.custom_name = kwargs['name']
            else:
                assert len(args) == 1
                assert len(kwargs) == 0
        elif len(args) >= 1 and isinstance(args[0], function.Function):
            meth = args[0]
            warnings.warn("add_method has changed API; see the API documentation",
                          DeprecationWarning, stacklevel=2)
            if len(args) == 2:
                meth.custom_name = args[1]
            elif 'name' in kwargs:
                assert len(args) == 1
                meth.custom_name = kwargs['name']
            else:
                assert len(args) == 1
                assert len(kwargs) == 0
        ## </compat>

        else:
            try:
                meth = CppMethod(*args, **kwargs)
            except utils.SkipWrapper:
                if kwargs.get('is_virtual', False):
                    ## if the method was supposed to be virtual, this
                    ## is a very important fact that needs to be
                    ## recorded in the class, even if the method is
                    ## not wrapped.
                    method = CppDummyMethod(*args, **kwargs)
                    method.class_ = self
                    self._dummy_methods.append(method)
                    self._have_pure_virtual_methods = None
                    helper_class = self.get_helper_class()
                    if helper_class is not None:
                        helper_class.add_virtual_method(method)
                        if helper_class.cannot_be_constructed:
                            self.helper_class = None
                            self.helper_class_disabled = True

                return None
        self._add_method_obj(meth)
        return meth

    def add_function_as_method(self, *args, **kwargs):
        """
        Add a function as method of the class. See the documentation for
        L{Function.__init__} for information on accepted parameters.
        TODO: explain the implicit first function parameter
        """
        try:
            meth = function.Function(*args, **kwargs)
        except utils.SkipWrapper:
            return None
        self._add_method_obj(meth)
        return meth

    def add_custom_method_wrapper(self, *args, **kwargs):
        """
        Adds a custom method wrapper. See L{CustomCppMethodWrapper} for more information.
        """
        try:
            meth = CustomCppMethodWrapper(*args, **kwargs)
        except utils.SkipWrapper:
            return None
        self._add_method_obj(meth)
        return meth

    def set_helper_class_disabled(self, flag=True):
        self.helper_class_disabled = flag
        if flag:
            self.helper_class = None

    def set_cannot_be_constructed(self, reason):
        assert isinstance(reason, string_types)
        self.cannot_be_constructed = reason

    def _add_constructor_obj(self, wrapper):
        """
        Add a constructor to the class.

        :param wrapper: a CppConstructor instance
        """
        assert isinstance(wrapper, CppConstructor)
        wrapper.set_class(self)
        self.constructors.append(wrapper)
        if not wrapper.parameters:
            self.has_trivial_constructor = True # FIXME: I don't remember what is this used for anymore, maybe remove
        if len(wrapper.parameters) == 1 and isinstance(wrapper.parameters[0], (CppClassRefParameter, CppClassParameter)) \
                and wrapper.parameters[0].cpp_class is self and wrapper.visibility == 'public':
            self.has_copy_constructor = True

    def add_output_stream_operator(self):
        """
        Add str() support based on C++ output stream operator.

        Calling this method enables wrapping of an assumed to be defined operator function::

             std::ostream & operator << (std::ostream &, MyClass const &);

        The wrapper will be registered as an str() python operator,
        and will call the C++ operator function to convert the value
        to a string.
        """
        self.has_output_stream_operator = True
        self.module.add_include("<ostream>")
        self.module.add_include("<sstream>")

    def add_constructor(self, *args, **kwargs):
        """
        Add a constructor to the class. See the documentation for
        L{CppConstructor.__init__} for information on accepted parameters.
        """

        ## <compat>
        if len(args) == 1 and isinstance(args[0], CppConstructor):
            warnings.warn("add_constructor has changed API; see the API documentation",
                          DeprecationWarning, stacklevel=2)
            constructor = args[0]
        elif len(args) == 1 and isinstance(args[0], function.Function):
            warnings.warn("add_constructor has changed API; see the API documentation",
                          DeprecationWarning, stacklevel=2)
            func = args[0]
            constructor = CppFunctionAsConstructor(func.function_name, func.parameters)
            constructor.module = self.module
        ## </compat>
        else:
            try:
                constructor = CppConstructor(*args, **kwargs)
            except utils.SkipWrapper:
                return None
        self._add_constructor_obj(constructor)
        return constructor

    def add_copy_constructor(self):
        """
        Utility method to add a 'copy constructor' method to this class.
        """
        try:
            constructor = CppConstructor([self.ThisClassRefParameter("const %s &" % self.full_name,
                                                                     'ctor_arg')])
        except utils.SkipWrapper:
            return None
        self._add_constructor_obj(constructor)
        return constructor

    def add_function_as_constructor(self, *args, **kwargs):
        """
        Wrap a function that behaves as a constructor to the class. See the documentation for
        L{CppFunctionAsConstructor.__init__} for information on accepted parameters.
        """
        try:
            constructor = CppFunctionAsConstructor(*args, **kwargs)
        except utils.SkipWrapper:
            return None
        self._add_constructor_obj(constructor)
        return constructor

    def add_static_attribute(self, name, value_type, is_const=False):
        """
        :param value_type: a ReturnValue object
        :param name: attribute name (i.e. the name of the class member variable)
        :param is_const: True if the attribute is const, i.e. cannot be modified
        """

        ## backward compatibility check
        if isinstance(value_type, string_types) and isinstance(name, ReturnValue):
            warnings.warn("add_static_attribute has changed API; see the API documentation (but trying to correct...)",
                          DeprecationWarning, stacklevel=2)
            value_type, name = name, value_type

        try:
            value_type = utils.eval_retval(value_type, None)
        except utils.SkipWrapper:
            return

        assert isinstance(value_type, ReturnValue)
        getter = CppStaticAttributeGetter(value_type, self, name)
        getter.stack_where_defined = traceback.extract_stack()
        if is_const:
            setter = None
        else:
            setter = CppStaticAttributeSetter(value_type, self, name)
            setter.stack_where_defined = traceback.extract_stack()
        self.static_attributes.add_attribute(name, getter, setter)

    def add_custom_instance_attribute(self, name, value_type, getter, is_const=False, setter=None, custom_name=None,
                                      getter_template_parameters=[],
                                      setter_template_parameters=[]):
        """
        :param value_type: a ReturnValue object
        :param name: attribute name (i.e. the name of the class member variable)
        :param is_const: True if the attribute is const, i.e. cannot be modified
        :param getter: None, or name of a method of this class used to get the value
        :param setter: None, or name of a method of this class used to set the value
        :param getter_template_parameters: optional list of template parameters for getter function
        :param setter_template_parameters: optional list of template parameters for setter function
        """

        ## backward compatibility check
        if isinstance(value_type, string_types) and isinstance(name, ReturnValue):
            warnings.warn("add_custom_instance_attribute has changed API; see the API documentation (but trying to correct...)",
                          DeprecationWarning, stacklevel=2)
            value_type, name = name, value_type

        try:
            value_type = utils.eval_retval(value_type, None)
        except utils.SkipWrapper:
            return

        assert isinstance(value_type, ReturnValue)
        getter_wrapper = CppCustomInstanceAttributeGetter(value_type, self, name, getter=getter,
                                                          template_parameters = getter_template_parameters)
        getter_wrapper.stack_where_defined = traceback.extract_stack()
        if is_const:
            setter_wrapper = None
            assert setter is None
        else:
            setter_wrapper = CppCustomInstanceAttributeSetter(value_type, self, name, setter=setter,
                                                              template_parameters = setter_template_parameters)
            setter_wrapper.stack_where_defined = traceback.extract_stack()
        self.instance_attributes.add_attribute(name, getter_wrapper, setter_wrapper, custom_name)

    def add_instance_attribute(self, name, value_type, is_const=False,
                               getter=None, setter=None, custom_name=None):
        """
        :param value_type: a ReturnValue object
        :param name: attribute name (i.e. the name of the class member variable)
        :param is_const: True if the attribute is const, i.e. cannot be modified
        :param getter: None, or name of a method of this class used to get the value
        :param setter: None, or name of a method of this class used to set the value
        """

        ## backward compatibility check
        if isinstance(value_type, string_types) and isinstance(name, ReturnValue):
            warnings.warn("add_static_attribute has changed API; see the API documentation (but trying to correct...)",
                          DeprecationWarning, stacklevel=2)
            value_type, name = name, value_type

        try:
            value_type = utils.eval_retval(value_type, None)
        except utils.SkipWrapper:
            return

        assert isinstance(value_type, ReturnValue)
        getter_wrapper = CppInstanceAttributeGetter(value_type, self, name, getter=getter)
        getter_wrapper.stack_where_defined = traceback.extract_stack()
        if is_const:
            setter_wrapper = None
            assert setter is None
        else:
            setter_wrapper = CppInstanceAttributeSetter(value_type, self, name, setter=setter)
            setter_wrapper.stack_where_defined = traceback.extract_stack()
        self.instance_attributes.add_attribute(name, getter_wrapper, setter_wrapper, custom_name)


    def _inherit_helper_class_parent_virtuals(self):
        """
        Given a class containing a helper class, add all virtual
        methods from the all parent classes of this class.
        """
        mro = self.get_mro()
        next(mro) # skip 'self'
        for cls in mro:
            for method in cls.get_all_methods():
                if not method.is_virtual:
                    continue
                method = method.clone()
                self.helper_class.add_virtual_method(method)

    def _get_wrapper_registry(self):
        # there is one wrapper registry object per root class only,
        # which is used for all subclasses.
        if self.parent is None:
            if self._wrapper_registry is None:
                self._wrapper_registry = settings.wrapper_registry(self.pystruct)
            return self._wrapper_registry
        else:
            return self.parent._get_wrapper_registry()
    wrapper_registry = property(_get_wrapper_registry)

    def generate_forward_declarations(self, code_sink, module):
        """
        Generates forward declarations for the instance and type
        structures.
        """

        if self.memory_policy is not None:
            pointer_type = self.memory_policy.get_pointer_type(self.full_name)
        else:
            pointer_type = self.full_name + " *"

        if self.allow_subclassing:
            code_sink.writeln('''
typedef struct {
    PyObject_HEAD
    %sobj;
    PyObject *inst_dict;
    PyBindGenWrapperFlags flags:8;
} %s;
    ''' % (pointer_type, self.pystruct))

        else:

            code_sink.writeln('''
typedef struct {
    PyObject_HEAD
    %sobj;
    PyBindGenWrapperFlags flags:8;
} %s;
    ''' % (pointer_type, self.pystruct))

        code_sink.writeln()

        if self.import_from_module:
            code_sink.writeln('extern PyTypeObject *_%s;' % (self.pytypestruct,))
            code_sink.writeln('#define %s (*_%s)' % (self.pytypestruct, self.pytypestruct))
        else:
            code_sink.writeln('extern PyTypeObject %s;' % (self.pytypestruct,))
            if not self.static_attributes.empty():
                code_sink.writeln('extern PyTypeObject Py%s_Type;' % (self.metaclass_name,))

        code_sink.writeln()

        if self.helper_class is not None:
            self._inherit_helper_class_parent_virtuals()
            for hook in self._get_all_helper_class_hooks():
                hook(self.helper_class)
            self.helper_class.generate_forward_declarations(code_sink)
            if self.helper_class.cannot_be_constructed:
                self.helper_class = None
                self.helper_class_disabled = True
        if self.have_pure_virtual_methods and self.helper_class is None:
            self.cannot_be_constructed = "have pure virtual methods but no helper class"

        if self.typeid_map_name is not None:
            self._generate_typeid_map(code_sink, module)

        if self.container_traits is not None:
            self.container_traits.generate_forward_declarations(code_sink, module)

        if self.parent is None:
            self.wrapper_registry.generate_forward_declarations(code_sink, module, self.import_from_module)

    def get_python_name(self):
        if self.template_parameters:
            if self.custom_name is None:
                class_python_name = self.mangled_name
            else:
                class_python_name = self.custom_name
        else:
            if self.custom_name is None:
                class_python_name = self.name
            else:
                class_python_name = self.custom_name
        return class_python_name

    def _generate_import_from_module(self, code_sink, module):
        if module.parent is None:
            error_retcode = "MOD_ERROR"
        else:
            error_retcode = "NULL"

        # TODO: skip this step if the requested typestructure is never used
        if ' named ' in self.import_from_module:
            module_name, type_name = self.import_from_module.split(" named ")
        else:
            module_name, type_name = self.import_from_module, self.name
        code_sink.writeln("PyTypeObject *_%s;" % self.pytypestruct)
        module.after_init.write_code("/* Import the %r class from module %r */" % (self.full_name, self.import_from_module))
        module.after_init.write_code("{"); module.after_init.indent()
        module.after_init.write_code("PyObject *module = PyImport_ImportModule((char*) \"%s\");" % module_name)
        module.after_init.write_code(
            "if (module == NULL) {\n"
            "    return %s;\n"
            "}" % (error_retcode,))

        module.after_init.write_code("_%s = (PyTypeObject*) PyObject_GetAttrString(module, (char*) \"%s\");\n"
                                     % (self.pytypestruct, self.get_python_name()))
        module.after_init.write_code("if (PyErr_Occurred()) PyErr_Clear();")

        if self.typeid_map_name is not None:
            code_sink.writeln("pybindgen::TypeMap *_%s;" % self.typeid_map_name)
            module.after_init.write_code("/* Import the %r class type map from module %r */" % (self.full_name, self.import_from_module))
            module.after_init.write_code("PyObject *_cobj = PyObject_GetAttrString(module, (char*) \"_%s\");"
                                         % (self.typeid_map_name))
            module.after_init.write_code("if (_cobj == NULL) {\n"
                                         "    _%s = new pybindgen::TypeMap;\n"
                                         "    PyErr_Clear();\n"
                                         "} else {\n"
                                         "    _%s = reinterpret_cast<pybindgen::TypeMap*> (PyCObject_AsVoidPtr (_cobj));\n"
                                         "    Py_DECREF(_cobj);\n"
                                         "}"
                                         % (self.typeid_map_name, self.typeid_map_name))

        if self.parent is None:
            self.wrapper_registry.generate_import(code_sink, module.after_init, "module")

        module.after_init.unindent(); module.after_init.write_code("}")

        if self.helper_class is not None:
            self.helper_class.generate(code_sink)


    def generate(self, code_sink, module):
        """Generates the class to a code sink"""

        if self.import_from_module:
            self._generate_import_from_module(code_sink, module)
            return # .......................... RETURN

        if self.typeid_map_name is not None:
            code_sink.writeln("\npybindgen::TypeMap %s;\n" % self.typeid_map_name)
            module.after_init.write_code("PyModule_AddObject(m, (char *) \"_%s\", PyCObject_FromVoidPtr(&%s, NULL));"
                                         % (self.typeid_map_name, self.typeid_map_name))

        if self.automatic_type_narrowing:
            self._register_typeid(module)

        if self.parent is None:
            self.wrapper_registry.generate(code_sink, module)

        if self.helper_class is not None:
            parent_caller_methods = self.helper_class.generate(code_sink)
        else:
            parent_caller_methods = []

        ## generate getsets
        instance_getsets = self.instance_attributes.generate(code_sink)
        self.slots.setdefault("tp_getset", instance_getsets)
        static_getsets = self.static_attributes.generate(code_sink)

        ## --- register the class type in the module ---
        module.after_init.write_code("/* Register the '%s' class */" % self.full_name)

        ## generate a metaclass if needed
        if static_getsets == '0':
            metaclass = None
        else:
            if self.parent is None:
                parent_typestruct = 'PyBaseObject_Type'
            else:
                parent_typestruct = self.parent.pytypestruct
            metaclass = PyMetaclass(self.metaclass_name,
                                    "Py_TYPE(&%s)" % parent_typestruct,
                                    self.static_attributes)
            metaclass.generate(code_sink, module)

        if self.parent is not None:
            assert isinstance(self.parent, CppClass)
            module.after_init.write_code('%s.tp_base = &%s;' %
                                         (self.pytypestruct, self.parent.pytypestruct))
            if len(self.bases) > 1:
                module.after_init.write_code('%s.tp_bases = PyTuple_New(%i);' % (self.pytypestruct, len(self.bases),))
                for basenum, base in enumerate(self.bases):
                    module.after_init.write_code('    Py_INCREF((PyObject *) &%s);' % (base.pytypestruct,))
                    module.after_init.write_code('    PyTuple_SET_ITEM(%s.tp_bases, %i, (PyObject *) &%s);'
                                                 % (self.pytypestruct, basenum, base.pytypestruct))

        if metaclass is not None:
            module.after_init.write_code('Py_TYPE(&%s) = &%s;' %
                                         (self.pytypestruct, metaclass.pytypestruct))

        module.after_init.write_error_check('PyType_Ready(&%s)'
                                          % (self.pytypestruct,))

        class_python_name = self.get_python_name()

        if self.outer_class is None:
            module.after_init.write_code(
                'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
                class_python_name, self.pytypestruct))
        else:
            module.after_init.write_code(
                'PyDict_SetItemString((PyObject*) %s.tp_dict, (char *) \"%s\", (PyObject *) &%s);' % (
                self.outer_class.pytypestruct, class_python_name, self.pytypestruct))

        have_constructor = self._generate_constructor(code_sink)

        self._generate_methods(code_sink, parent_caller_methods)

        if self.allow_subclassing:
            self._generate_gc_methods(code_sink)

        self._generate_destructor(code_sink, have_constructor)

        if self.has_output_stream_operator:
            self._generate_str(code_sink)

        #self._generate_tp_hash(code_sink)
        #self._generate_tp_compare(code_sink)

        #if self.slots.get("tp_hash", "NULL") == "NULL":
        #    self.slots["tp_hash"] = self._generate_tp_hash(code_sink)

        if self.slots.get("tp_richcompare", "NULL") == "NULL" and self.binary_comparison_operators:
            self.slots["tp_richcompare"] = self._generate_tp_richcompare(code_sink)

        if self.binary_numeric_operators or self.inplace_numeric_operators:
            self.slots["tp_as_number"] = self._generate_number_methods(code_sink)

        if self.have_sequence_methods():
            self.slots["tp_as_sequence"] = self._generate_sequence_methods(code_sink)

        if self.container_traits is not None:
            self.container_traits.generate(code_sink, module)

        self._generate_type_structure(code_sink, self.docstring)

    def _generate_number_methods(self, code_sink):
        number_methods_var_name = "%s__py_number_methods" % (self.mangled_full_name,)

        pynumbermethods = PyNumberMethods()
        pynumbermethods.slots['variable'] = number_methods_var_name

        # iterate over all types and request generation of the
        # convertion functions for that type (so that those functions
        # are not generated in the middle of one of the wrappers we
        # are about to generate)
        root_module = self.module.get_root()
        for dummy_op_symbol, op_types in self.binary_numeric_operators.items():
            for (retval, left, right) in op_types:
                get_c_to_python_converter(retval, root_module, code_sink)
                get_python_to_c_converter(left, root_module, code_sink)
                get_python_to_c_converter(right, root_module, code_sink)

        for dummy_op_symbol, op_types in self.inplace_numeric_operators.items():
            for (retval, left, right) in op_types:
                get_python_to_c_converter(left, root_module, code_sink)
                get_python_to_c_converter(right, root_module, code_sink)
                get_c_to_python_converter(retval, root_module, code_sink)

        for dummy_op_symbol, op_types in self.unary_numeric_operators.items():
            for (retval, left) in op_types:
                get_c_to_python_converter(retval, root_module, code_sink)
                get_python_to_c_converter(left, root_module, code_sink)

        def try_wrap_operator(op_symbol, slot_name):
            if op_symbol in self.binary_numeric_operators:
                op_types = self.binary_numeric_operators[op_symbol]
            elif op_symbol in self.inplace_numeric_operators:
                op_types = self.inplace_numeric_operators[op_symbol]
            else:
                return

            wrapper_name = "%s__%s" % (self.mangled_full_name, slot_name)
            pynumbermethods.slots[slot_name] = wrapper_name
            code_sink.writeln(("static PyObject*\n"
                               "%s (PyObject *py_left, PyObject *py_right)\n"
                               "{") % wrapper_name)
            code_sink.indent()
            for (retval, left, right) in op_types:
                retval_converter, retval_name = get_c_to_python_converter(retval, root_module, code_sink)
                left_converter, left_name = get_python_to_c_converter(left, root_module, code_sink)
                right_converter, right_name = get_python_to_c_converter(right, root_module, code_sink)

                code_sink.writeln("{")
                code_sink.indent()

                code_sink.writeln("%s left;" % left_name)
                code_sink.writeln("%s right;" % right_name)

                code_sink.writeln("if (%s(py_left, &left) && %s(py_right, &right)) {" % (left_converter, right_converter))
                code_sink.indent()
                code_sink.writeln("%s result = (left %s right);" % (retval_name, op_symbol))
                code_sink.writeln("return %s(&result);" % retval_converter)
                code_sink.unindent()
                code_sink.writeln("}")
                code_sink.writeln("PyErr_Clear();")

                code_sink.unindent()
                code_sink.writeln("}")

            code_sink.writeln("Py_INCREF(Py_NotImplemented);")
            code_sink.writeln("return Py_NotImplemented;")
            code_sink.unindent()
            code_sink.writeln("}")

        def try_wrap_unary_operator(op_symbol, slot_name):
            if op_symbol in self.unary_numeric_operators:
                op_types = self.unary_numeric_operators[op_symbol]
            else:
                return

            wrapper_name = "%s__%s" % (self.mangled_full_name, slot_name)
            pynumbermethods.slots[slot_name] = wrapper_name
            code_sink.writeln(("static PyObject*\n"
                               "%s (PyObject *py_self)\n"
                               "{") % wrapper_name)
            code_sink.indent()
            for (retval, left) in op_types:
                retval_converter, retval_name = get_c_to_python_converter(retval, root_module, code_sink)
                left_converter, left_name = get_python_to_c_converter(left, root_module, code_sink)

                code_sink.writeln("{")
                code_sink.indent()

                code_sink.writeln("%s self;" % left_name)

                code_sink.writeln("if (%s(py_self, &self)) {" % (left_converter))
                code_sink.indent()
                code_sink.writeln("%s result = %s(self);" % (retval_name, op_symbol))
                code_sink.writeln("return %s(&result);" % retval_converter)
                code_sink.unindent()
                code_sink.writeln("}")
                code_sink.writeln("PyErr_Clear();")

                code_sink.unindent()
                code_sink.writeln("}")

            code_sink.writeln("Py_INCREF(Py_NotImplemented);")
            code_sink.writeln("return Py_NotImplemented;")
            code_sink.unindent()
            code_sink.writeln("}")

        try_wrap_operator('+', 'nb_add')
        try_wrap_operator('-', 'nb_subtract')
        try_wrap_operator('*', 'nb_multiply')
        try_wrap_operator('/', 'nb_divide')

        try_wrap_operator('+=', 'nb_inplace_add')
        try_wrap_operator('-=', 'nb_inplace_subtract')
        try_wrap_operator('*=', 'nb_inplace_multiply')
        try_wrap_operator('/=', 'nb_inplace_divide')

        try_wrap_unary_operator('-', 'nb_negative')

        pynumbermethods.generate(code_sink)
        return '&' + number_methods_var_name

    def _generate_sequence_methods(self, code_sink):
        sequence_methods_var_name = "%s__py_sequence_methods" % (self.mangled_full_name,)

        pysequencemethods = PySequenceMethods()
        pysequencemethods.slots['variable'] = sequence_methods_var_name

        root_module = self.module.get_root()
        self_converter = root_module.generate_python_to_c_type_converter(self.ThisClassReturn(self.full_name), code_sink)

        def try_wrap_sequence_method(py_name, slot_name):
            if py_name in self.methods:
                numwraps = len(self.methods[py_name].wrappers)
                some_wrapper_is_function = max([isinstance(x, function.Function) for x in self.methods[py_name].wrappers])
                meth_wrapper_actual_name = self.methods[py_name].wrapper_actual_name
                wrapper_name = "%s__%s" % (self.mangled_full_name, slot_name)
                pysequencemethods.slots[slot_name] = wrapper_name
                if py_name == "__len__" and (numwraps > 1 or some_wrapper_is_function):
                    template = pysequencemethods.FUNCTION_TEMPLATES[slot_name + "_ARGS"]
                else:
                    template = pysequencemethods.FUNCTION_TEMPLATES[slot_name]
                code_sink.writeln(template % {'wrapper_name'   : wrapper_name,
                                              'py_struct'      : self._pystruct,
                                              'method_name'    : meth_wrapper_actual_name})
                return

        for py_name in self.valid_sequence_methods:
            slot_name = self.valid_sequence_methods[py_name]
            try_wrap_sequence_method(py_name, slot_name)

        pysequencemethods.generate(code_sink)
        return '&' + sequence_methods_var_name

    def have_sequence_methods(self):
        """Determine if this object has sequence methods registered."""
        for x in self.valid_sequence_methods:
            if x in self.methods:
                return True
        return False

    def _generate_type_structure(self, code_sink, docstring):
        """generate the type structure"""
        self.slots.setdefault("tp_basicsize",
                              "sizeof(%s)" % (self.pystruct,))
        tp_flags = set(['Py_TPFLAGS_DEFAULT'])
        if self.allow_subclassing:
            tp_flags.add("Py_TPFLAGS_HAVE_GC")
            tp_flags.add("Py_TPFLAGS_BASETYPE")
            self.slots.setdefault("tp_dictoffset",
                                  "offsetof(%s, inst_dict)" % self.pystruct)
        else:
            self.slots.setdefault("tp_dictoffset", "0")
        if self.binary_numeric_operators:
            tp_flags.add("Py_TPFLAGS_CHECKTYPES")
        self.slots.setdefault("tp_flags", '|'.join(sorted(tp_flags)))

        if docstring is None:
            docstring = self.generate_docstring()

        self.slots.setdefault("tp_doc", (docstring is None and 'NULL'
                                         or "\"%s\"" % (docstring,)))
        dict_ = self.slots
        dict_.setdefault("typestruct", self.pytypestruct)

        if self.outer_class is None:
            mod_path = self._module.get_module_path()
            mod_path.append(self.mangled_name)
            dict_.setdefault("tp_name", '.'.join(mod_path))
        else:
            dict_.setdefault("tp_name", '%s.%s' % (self.outer_class.slots['tp_name'], self.name))

        ## tp_call support
        try:
            call_method = self.methods['__call__']
        except KeyError:
            pass
        else:
            if call_method.wrapper_actual_name:
                dict_.setdefault("tp_call", call_method.wrapper_actual_name)

        self.pytype.generate(code_sink)

    def generate_docstring(self):
        name = self.get_python_name()
        return "\\n".join(sorted([c.generate_docstring(name) for c in self.constructors],
                                 key=len, reverse=True))

    def _generate_constructor(self, code_sink):
        """generate the constructor, if any"""
        have_constructor = True
        if self.constructors and ((not self.cannot_be_constructed) or self.helper_class is not None
                                  and not self.helper_class.cannot_be_constructed):
            code_sink.writeln()
            overload = CppOverloadedConstructor(None)
            self.constructors_overload = overload
            overload.pystruct = self.pystruct
            for constructor in self.constructors:
                try:
                    overload.add(constructor)
                except CodegenErrorBase:
                    continue
            if overload.wrappers:
                try:
                    overload.generate(code_sink)
                except utils.SkipWrapper:
                    constructor = None
                    have_constructor = False
                else:
                    constructor = overload.wrapper_actual_name
                    code_sink.writeln()
            else:
                constructor = None
                have_constructor = False
        else:
            ## In C++, and unlike Python, constructors with
            ## parameters are not automatically inheritted by
            ## subclasses.  We must generate a 'no constructor'
            ## tp_init to prevent this type from inheriting a
            ## tp_init that will allocate an instance of the
            ## parent class instead of this class.
            code_sink.writeln()
            wrapper = CppNoConstructor(self.cannot_be_constructed)
            wrapper.generate(code_sink, self)
            constructor = wrapper.wrapper_actual_name
            have_constructor = False
            code_sink.writeln()

        self.slots.setdefault("tp_init", (constructor is None and "NULL"
                                          or constructor))
        return have_constructor

    def _generate_copy_method(self, code_sink):
        construct_name = self.get_construct_name()
        copy_wrapper_name = '_wrap_%s__copy__' % self.pystruct
        code_sink.writeln('''
static PyObject*\n%s(%s *self, PyObject *PYBINDGEN_UNUSED(_args))
{
''' % (copy_wrapper_name, self.pystruct))
        code_sink.indent()

        declarations = DeclarationsScope()
        code_block = CodeBlock("return NULL;", declarations)

        py_copy = declarations.declare_variable("%s*" % self.pystruct, "py_copy")
        self.write_allocate_pystruct(code_block, py_copy)
        code_block.write_code("%s->obj = new %s(*self->obj);" % (py_copy, construct_name))
        if self.allow_subclassing:
            code_block.write_code("%s->inst_dict = NULL;" % py_copy)
        code_block.write_code("%s->flags = PYBINDGEN_WRAPPER_FLAG_NONE;" % py_copy)

        self.wrapper_registry.write_register_new_wrapper(code_block, py_copy, "%s->obj" % py_copy)

        code_block.write_code("return (PyObject*) %s;" % py_copy)

        declarations.get_code_sink().flush_to(code_sink)

        code_block.write_cleanup()
        code_block.sink.flush_to(code_sink)

        code_sink.unindent()
        code_sink.writeln("}")
        code_sink.writeln()
        return copy_wrapper_name

    def _generate_MI_parent_methods(self, code_sink):
        methods = {}
        mro = self.get_mro()
        next(mro)
        for base in mro:
            for method_name, parent_overload in base.methods.items():

                # skip methods registered via special type slots, not method table
                if method_name in (['__call__'] + list(self.valid_sequence_methods)):
                    continue

                try:
                    overload = methods[method_name]
                except KeyError:
                    overload = CppOverloadedMethod(method_name)
                    overload.pystruct = self.pystruct
                    methods[method_name] = overload

                for parent_wrapper in parent_overload.wrappers:

                    if parent_wrapper.visibility != 'public':
                        continue

                    # the method may have been re-defined as private in our class
                    private = False
                    for leaf_wrapper in self.nonpublic_methods:
                        if leaf_wrapper.matches_signature(parent_wrapper):
                            private = True
                            break
                    if private:
                        continue

                    # the method may have already been wrapped in our class
                    already_wrapped = False
                    try:
                        overload = self.methods[method_name]
                    except KeyError:
                        pass
                    else:
                        for leaf_wrapper in overload.wrappers:
                            if leaf_wrapper.matches_signature(parent_wrapper):
                                already_wrapped = True
                                break
                    if already_wrapped:
                        continue

                    wrapper = parent_wrapper.clone()
                    wrapper.original_class = base
                    wrapper.class_ = self
                    overload.add(wrapper)

        method_defs = []
        for method_name, overload in methods.items():
            if not overload.wrappers:
                continue

            classes = []
            for wrapper in overload.wrappers:
                if wrapper.original_class not in classes:
                    classes.append(wrapper.original_class)
            if len(classes) > 1:
                continue # overloading with multiple base classes is just too confusing

            try:
                utils.call_with_error_handling(overload.generate, (code_sink,), {}, overload)
            except utils.SkipWrapper:
                continue
            code_sink.writeln()
            method_defs.append(overload.get_py_method_def(method_name))
        return method_defs

    def _generate_methods(self, code_sink, parent_caller_methods):
        """generate the method wrappers"""
        method_defs = []
        for meth_name, overload in self.methods.items():
            code_sink.writeln()
            #overload.generate(code_sink)
            try:
                utils.call_with_error_handling(overload.generate, (code_sink,), {}, overload)
            except utils.SkipWrapper:
                continue
            # skip methods registered via special type slots, not method table
            if meth_name not in (['__call__'] + list(self.valid_sequence_methods)):
                method_defs.append(overload.get_py_method_def(meth_name))
            code_sink.writeln()
        method_defs.extend(parent_caller_methods)

        if len(self.bases) > 1: # https://bugs.launchpad.net/pybindgen/+bug/563786
            method_defs.extend(self._generate_MI_parent_methods(code_sink))

        if self.has_copy_constructor:
            try:
                copy_wrapper_name = utils.call_with_error_handling(self._generate_copy_method, (code_sink,), {}, self)
            except utils.SkipWrapper:
                pass
            else:
                method_defs.append('{(char *) "__copy__", (PyCFunction) %s, METH_NOARGS, NULL},' % copy_wrapper_name)

        ## generate the method table
        code_sink.writeln("static PyMethodDef %s_methods[] = {" % (self.pystruct,))
        code_sink.indent()
        for methdef in method_defs:
            code_sink.writeln(methdef)
        code_sink.writeln("{NULL, NULL, 0, NULL}")
        code_sink.unindent()
        code_sink.writeln("};")
        self.slots.setdefault("tp_methods", "%s_methods" % (self.pystruct,))

    def _get_delete_code(self):
        if self.is_singleton:
            delete_code = ''
        else:
            if self.memory_policy is not None:
                delete_code = self.memory_policy.get_delete_code(self)
            else:
                if self.incomplete_type:
                    raise CodeGenerationError("Cannot finish generating class %s: "
                                              "type is incomplete, but no free/unref_function defined"
                                              % self.full_name)
                if self.destructor_visibility == 'public':
                    delete_code = ("    %s *tmp = self->obj;\n"
                                   "    self->obj = NULL;\n"
                                   "    if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) {\n"
                                   "        delete tmp;\n"
                                   "    }" % (self.full_name,))
                else:
                    delete_code = ("    self->obj = NULL;\n")
        return delete_code

    def _generate_gc_methods(self, code_sink):
        """Generate tp_clear and tp_traverse"""

        ## --- tp_clear ---
        tp_clear_function_name = "%s__tp_clear" % (self.pystruct,)
        self.slots.setdefault("tp_clear", tp_clear_function_name )
        delete_code = self._get_delete_code()
        code_sink.writeln(r'''
static void
%s(%s *self)
{
    Py_CLEAR(self->inst_dict);
    %s
}
''' % (tp_clear_function_name, self.pystruct, delete_code))

        ## --- tp_traverse ---
        tp_traverse_function_name = "%s__tp_traverse" % (self.pystruct,)
        self.slots.setdefault("tp_traverse", tp_traverse_function_name )

        if self.helper_class is None:
            visit_self = ''
        else:
            if not isinstance(self.memory_policy, ReferenceCountingMethodsPolicy) or self.memory_policy.peekref_method is None:
                peekref_code = ''
            else:
                peekref_code = " && self->obj->%s() == 1" % self.memory_policy.peekref_method
            visit_self = '''
    if (self->obj && typeid(*self->obj).name() == typeid(%s).name() %s)
        Py_VISIT((PyObject *) self);
''' % (self.helper_class.name, peekref_code)

        code_sink.writeln(r'''
static int
%s(%s *self, visitproc visit, void *arg)
{
    Py_VISIT(self->inst_dict);
    %s
    return 0;
}
''' % (tp_traverse_function_name, self.pystruct, visit_self))

    def _generate_str(self, code_sink):
        """Generate a tp_str function and register it in the type"""

        tp_str_function_name = "_wrap_%s__tp_str" % (self.pystruct,)
        self.slots.setdefault("tp_str", tp_str_function_name )

        code_sink.writeln('''

static PyObject *
%s(%s *self)
{
    std::ostringstream oss;
    oss << *self->obj;
    return PyUnicode_FromString(oss.str ().c_str ());
}

''' % (tp_str_function_name, self.pystruct))

    def _generate_tp_hash(self, code_sink):
        """generates a tp_hash function, which returns a hash of the self->obj pointer"""

        tp_hash_function_name = "_wrap_%s__tp_hash" % (self.pystruct,)
        self.slots.setdefault("tp_hash", tp_hash_function_name )

        code_sink.writeln('''

static long
%s(%s *self)
{
    return (long) self->obj;
}

''' % (tp_hash_function_name, self.pystruct))
        return tp_hash_function_name

    def _generate_tp_compare(self, code_sink):
        """generates a tp_compare function, which compares the ->obj pointers"""

        tp_compare_function_name = "_wrap_%s__tp_compare" % (self.pystruct,)
        self.slots.setdefault("tp_compare", tp_compare_function_name )

        code_sink.writeln('''

static int
%s(%s *self, %s *other)
{
    if (self->obj == other->obj) return 0;
    if (self->obj > other->obj)  return -1;
    return 1;
}

''' % (tp_compare_function_name, self.pystruct, self.pystruct))


    def _generate_destructor(self, code_sink, have_constructor):
        """Generate a tp_dealloc function and register it in the type"""

        ## don't generate destructor if overridden by user
        if "tp_dealloc" in self.slots:
            return

        tp_dealloc_function_name = "_wrap_%s__tp_dealloc" % (self.pystruct,)
        code_sink.writeln(r'''
static void
%s(%s *self)
{''' % (tp_dealloc_function_name, self.pystruct))
        code_sink.indent()

        code_block = CodeBlock("PyErr_Print(); return;", DeclarationsScope())

        if self.memory_policy is not None:
            self.wrapper_registry.write_unregister_wrapper(code_block, 'self', self.memory_policy.get_pointer_to_void_name('self->obj'))
        else:
            self.wrapper_registry.write_unregister_wrapper(code_block, 'self', 'self->obj')

        if self.allow_subclassing:
            code_block.write_code("%s(self);" % self.slots["tp_clear"])
        else:
            code_block.write_code(self._get_delete_code())

        code_block.write_code('Py_TYPE(self)->tp_free((PyObject*)self);')

        code_block.write_cleanup()

        code_block.declarations.get_code_sink().flush_to(code_sink)
        code_block.sink.flush_to(code_sink)

        code_sink.unindent()
        code_sink.writeln('}\n')

        self.slots.setdefault("tp_dealloc", tp_dealloc_function_name )


    def _generate_tp_richcompare(self, code_sink):
        tp_richcompare_function_name = "_wrap_%s__tp_richcompare" % (self.pystruct,)

        code_sink.writeln("static PyObject*\n%s (%s *self, %s *other, int opid)"
                          % (tp_richcompare_function_name, self.pystruct, self.pystruct))
        code_sink.writeln("{")
        code_sink.indent()

        code_sink.writeln("""
if (!PyObject_IsInstance((PyObject*) other, (PyObject*) &%s)) {
    Py_INCREF(Py_NotImplemented);
    return Py_NotImplemented;
}""" % self.pytypestruct)

        code_sink.writeln("switch (opid)\n{")

        def wrap_operator(name, opid_code):
            code_sink.writeln("case %s:" % opid_code)
            code_sink.indent()
            if name in self.binary_comparison_operators:
                code_sink.writeln("if (*self->obj %(OP)s *other->obj) {\n"
                                  "    Py_INCREF(Py_True);\n"
                                  "    return Py_True;\n"
                                  "} else {\n"
                                  "    Py_INCREF(Py_False);\n"
                                  "    return Py_False;\n"
                                  "}" % dict(OP=name))
            else:
                code_sink.writeln("Py_INCREF(Py_NotImplemented);\n"
                                  "return Py_NotImplemented;")
            code_sink.unindent()

        wrap_operator('<', 'Py_LT')
        wrap_operator('<=', 'Py_LE')
        wrap_operator('==', 'Py_EQ')
        wrap_operator('!=', 'Py_NE')
        wrap_operator('>=', 'Py_GE')
        wrap_operator('>', 'Py_GT')

        code_sink.writeln("} /* closes switch (opid) */")

        code_sink.writeln("Py_INCREF(Py_NotImplemented);\n"
                          "return Py_NotImplemented;")

        code_sink.unindent()
        code_sink.writeln("}\n")

        return tp_richcompare_function_name

    def generate_typedef(self, module, alias):
        """
        Generates the appropriate Module code to register the class
        with a new name in that module (typedef alias).
        """
        module.after_init.write_code(
            'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
                alias, self.pytypestruct))

    def write_allocate_pystruct(self, code_block, lvalue, wrapper_type=None):
        """
        Generates code to allocate a python wrapper structure, using
        PyObject_New or PyObject_GC_New, plus some additional strcture
        initialization that may be needed.
        """
        if self.allow_subclassing:
            new_func = 'PyObject_GC_New'
        else:
            new_func = 'PyObject_New'
        if wrapper_type is None:
            wrapper_type = '&'+self.pytypestruct
        code_block.write_code("%s = %s(%s, %s);" %
                              (lvalue, new_func, self.pystruct, wrapper_type))
        if self.allow_subclassing:
            code_block.write_code(
                "%s->inst_dict = NULL;" % (lvalue,))
        if self.memory_policy is not None:
            code_block.write_code(self.memory_policy.get_pystruct_init_code(self, lvalue)) class Container(object):
    def __init__(self, name, value_type, container_type, outer_class=None, custom_name=None):
        """
        :param name: C++ type name of the container, e.g. std::vector<int> or MyIntList

        :param value_type: a ReturnValue of the element type: note,
            for mapping containers, value_type is a tuple with two
            ReturnValue's: (key, element).

        :param container_type: a string with the type of container,
            one of 'list', 'deque', 'queue', 'priority_queue',
            'vector', 'stack', 'set', 'multiset', 'hash_set',
            'hash_multiset', 'map', 'unordered_map'

        :param outer_class: if the type is defined inside a class, must be a reference to the outer class
        :type outer_class: None or L{CppClass}

        :param custom_name: alternative name to register with in the Python module

        """
        if '<' in name or '::' in name:
            self.name = utils.mangle_name(name)
            self.full_name = name
            self._full_name_is_definitive = True
        else:
            self._full_name_is_definitive = False
            self.full_name = None
            self.name = name
        self._module = None
        self.outer_class = outer_class
        self.mangled_name = None
        self.mangled_full_name = None
        self.container_traits = container_traits_list[container_type]
        self.custom_name = custom_name
        self._pystruct = None
        self.pytypestruct = "***GIVE ME A NAME***"
        self.pytype = PyTypeObject()

        self.iter_pytypestruct = "***GIVE ME A NAME***"
        self.iter_pytype = PyTypeObject()
        self._iter_pystruct = None

        if self.container_traits.is_mapping:
            (key_type, value_type) = value_type
            self.key_type = utils.eval_retval(key_type, self)
            self.value_type = utils.eval_retval(value_type, self)
        else:
            self.key_type = None
            self.value_type = utils.eval_retval(value_type, self)
        self.python_to_c_converter = None

        if name != 'dummy':
            ## register type handlers

            class ThisContainerParameter(ContainerParameter):
                """Register this C++ container as pass-by-value parameter"""
                CTYPES = []
                container_type = self
            self.ThisContainerParameter = ThisContainerParameter
            try:
                param_type_matcher.register(name, self.ThisContainerParameter)
            except ValueError:
                pass

            class ThisContainerRefParameter(ContainerRefParameter):
                """Register this C++ container as pass-by-value parameter"""
                CTYPES = []
                container_type = self
            self.ThisContainerRefParameter = ThisContainerRefParameter
            try:
                param_type_matcher.register(name + '&', self.ThisContainerRefParameter)
            except ValueError:
                pass

            class ThisContainerPtrParameter(ContainerPtrParameter):
                """Register this C++ container as pass-by-ptr parameter"""
                CTYPES = []
                container_type = self
            self.ThisContainerPtrParameter = ThisContainerPtrParameter
            try:
                param_type_matcher.register(name + '*', self.ThisContainerPtrParameter)
            except ValueError:
                pass

            class ThisContainerReturn(ContainerReturnValue):
                """Register this C++ container as value return"""
                CTYPES = []
                container_type = self
            self.ThisContainerReturn = ThisContainerReturn
            self.ThisContainerRefReturn = ThisContainerReturn
            try:
                return_type_matcher.register(name, self.ThisContainerReturn)
                return_type_matcher.register(name + '&', self.ThisContainerRefReturn)
            except ValueError:
                pass

    def __repr__(self):
        return "<pybindgen.Container %r>" % self.full_name

    def get_module(self):
        """Get the Module object this type belongs to"""
        return self._module

    def set_module(self, module):
        """Set the Module object this type belongs to"""
        self._module = module
        self._update_names()

    module = property(get_module, set_module)

    def get_pystruct(self):
        if self._pystruct is None:
            raise ValueError
        return self._pystruct
    pystruct = property(get_pystruct)

    def get_iter_pystruct(self):
        if self._iter_pystruct is None:
            raise ValueError
        return self._iter_pystruct
    iter_pystruct = property(get_iter_pystruct)

    def _update_names(self):

        prefix = settings.name_prefix.capitalize()

        if not self._full_name_is_definitive:
            if self.outer_class is None:
                if self._module.cpp_namespace_prefix:
                    if self._module.cpp_namespace_prefix == '::':
                        self.full_name = '::' + self.name
                    else:
                        self.full_name = self._module.cpp_namespace_prefix + '::' + self.name
                else:
                    self.full_name = self.name
            else:
                self.full_name = '::'.join([self.outer_class.full_name, self.name])

        def make_upper(s):
            if s and s[0].islower():
                return s[0].upper()+s[1:]
            else:
                return s

        def flatten(name):
            "make a name like::This look LikeThis"
            return ''.join([make_upper(utils.mangle_name(s)) for s in name.split('::')])

        self.mangled_name = flatten(self.name)
        self.mangled_full_name = utils.mangle_name(self.full_name)

        self._pystruct = "Py%s%s" % (prefix, self.mangled_full_name)
        self.pytypestruct = "Py%s%s_Type" % (prefix,  self.mangled_full_name)

        self._iter_pystruct = "Py%s%sIter" % (prefix, self.mangled_full_name)
        self.iter_pytypestruct = "Py%s%sIter_Type" % (prefix,  self.mangled_full_name)

        ## re-register the class type handlers, now with class full name
        self.register_alias(self.full_name)

        self.python_to_c_converter = self.module.get_root().get_python_to_c_type_converter_function_name(
            self.ThisContainerReturn(self.full_name))


    def register_alias(self, alias):
        """Re-register the class with another base name, in addition to any
        registrations that might have already been done."""

        self.module.register_type(None, alias, self)

        self.ThisContainerParameter.CTYPES.append(alias)
        try:
            param_type_matcher.register(alias, self.ThisContainerParameter)
        except ValueError: pass

        self.ThisContainerRefParameter.CTYPES.append(alias+'&')
        try:
            param_type_matcher.register(alias+'&', self.ThisContainerRefParameter)
        except ValueError: pass

        self.ThisContainerReturn.CTYPES.append(alias)
        try:
            return_type_matcher.register(alias, self.ThisContainerReturn)
        except ValueError: pass


    def generate_forward_declarations(self, code_sink, module):
        """
        Generates forward declarations for the instance and type
        structures.
        """

        # container pystruct
        code_sink.writeln('''
typedef struct {
    PyObject_HEAD
    %s *obj;
} %s;
    ''' % (self.full_name, self.pystruct))

        # container iterator pystruct
        code_sink.writeln('''
typedef struct {
    PyObject_HEAD
    %s *container;
    %s::iterator *iterator;
} %s;
    ''' % (self.pystruct, self.full_name, self.iter_pystruct))

        code_sink.writeln()
        code_sink.writeln('extern PyTypeObject %s;' % (self.pytypestruct,))
        code_sink.writeln('extern PyTypeObject %s;' % (self.iter_pytypestruct,))
        code_sink.writeln()

        this_type_converter = self.module.get_root().get_python_to_c_type_converter_function_name(
            self.ThisContainerReturn(self.full_name))
        self.module.get_root().declare_one_time_definition(this_type_converter)
        code_sink.writeln('int %(CONTAINER_CONVERTER_FUNC_NAME)s(PyObject *arg, %(CTYPE)s *container);'
                          % {'CTYPE': self.full_name,
                             'CONTAINER_CONVERTER_FUNC_NAME': this_type_converter,
                             })
        self.python_to_c_converter = this_type_converter

    def _get_python_name(self):
        if self.custom_name is None:
            class_python_name = self.mangled_name
        else:
            class_python_name = self.custom_name
        return class_python_name

    python_name = property(_get_python_name)

    def _get_python_full_name(self):
        if self.outer_class is None:
            mod_path = self._module.get_module_path()
            mod_path.append(self.python_name)
            return '.'.join(mod_path)
        else:
            return '%s.%s' % (self.outer_class.pytype.slots['tp_name'], self.python_name)

    python_full_name = property(_get_python_full_name)


    def generate(self, code_sink, module, docstring=None):
        """Generates the class to a code sink"""

        ## --- register the class type in the module ---
        module.after_init.write_code("/* Register the '%s' class */" % self.full_name)

        module.after_init.write_error_check('PyType_Ready(&%s)' % (self.pytypestruct,))
        module.after_init.write_error_check('PyType_Ready(&%s)' % (self.iter_pytypestruct,))

        class_python_name = self.python_name

        if self.outer_class is None:
            module.after_init.write_code(
                'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
                class_python_name, self.pytypestruct))
            module.after_init.write_code(
                'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
                class_python_name+'Iter', self.iter_pytypestruct))
        else:
            module.after_init.write_code(
                'PyDict_SetItemString((PyObject*) %s.tp_dict, (char *) \"%s\", (PyObject *) &%s);' % (
                self.outer_class.pytypestruct, class_python_name, self.pytypestruct))
            module.after_init.write_code(
                'PyDict_SetItemString((PyObject*) %s.tp_dict, (char *) \"%s\", (PyObject *) &%s);' % (
                self.outer_class.pytypestruct, class_python_name+'Iter', self.iter_pytypestruct))

        self._generate_gc_methods(code_sink)
        self._generate_destructor(code_sink)
        self._generate_iter_methods(code_sink)
        self._generate_container_constructor(code_sink)
        self._generate_type_structure(code_sink, docstring)

    def _generate_type_structure(self, code_sink, docstring):
        """generate the type structure"""

        self.pytype.slots.setdefault("tp_basicsize", "sizeof(%s)" % (self.pystruct,))
        self.pytype.slots.setdefault("tp_flags", "Py_TPFLAGS_DEFAULT")
        self.pytype.slots.setdefault("typestruct", self.pytypestruct)
        self.pytype.slots.setdefault("tp_name", self.python_full_name)
        self.pytype.generate(code_sink)

        self.iter_pytype.slots.setdefault("tp_basicsize", "sizeof(%s)" % (self.iter_pystruct,))
        self.iter_pytype.slots.setdefault("tp_flags", ("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC"))
        self.iter_pytype.slots.setdefault("typestruct", self.iter_pytypestruct)
        self.iter_pytype.slots.setdefault("tp_name", self.python_full_name + 'Iter')
        self.iter_pytype.generate(code_sink)

    def _get_iter_delete_code(self):
        delete_code = ("delete self->iterator;\n"
                       "    self->iterator = NULL;\n")
        return delete_code

    def _get_container_delete_code(self):
        delete_code = ("delete self->obj;\n"
                       "    self->obj = NULL;\n")
        return delete_code

    def _generate_gc_methods(self, code_sink):
        """Generate tp_clear and tp_traverse"""

        ## --- iterator tp_clear ---
        tp_clear_function_name = "%s__tp_clear" % (self.iter_pystruct,)
        self.iter_pytype.slots.setdefault("tp_clear", tp_clear_function_name )

        code_sink.writeln(r'''
static void
%s(%s *self)
{
    Py_CLEAR(self->container);
    %s
}
''' % (tp_clear_function_name, self.iter_pystruct, self._get_iter_delete_code()))

        ## --- iterator tp_traverse ---
        tp_traverse_function_name = "%s__tp_traverse" % (self.iter_pystruct,)
        self.iter_pytype.slots.setdefault("tp_traverse", tp_traverse_function_name )

        code_sink.writeln(r'''
static int
%s(%s *self, visitproc visit, void *arg)
{
    Py_VISIT((PyObject *) self->container);
    return 0;
}
''' % (tp_traverse_function_name, self.iter_pystruct))


    def _generate_destructor(self, code_sink):
        """Generate a tp_dealloc function and register it in the type"""

        # -- container --
        container_tp_dealloc_function_name = "_wrap_%s__tp_dealloc" % (self.pystruct,)
        code_sink.writeln(r'''
static void
%s(%s *self)
{
    %s
    Py_TYPE(self)->tp_free((PyObject*)self);
}
''' % (container_tp_dealloc_function_name, self.pystruct,
       self._get_container_delete_code()))

        self.pytype.slots.setdefault("tp_dealloc", container_tp_dealloc_function_name )


        # -- iterator --
        iter_tp_dealloc_function_name = "_wrap_%s__tp_dealloc" % (self.iter_pystruct,)
        code_sink.writeln(r'''
static void
%s(%s *self)
{
    Py_CLEAR(self->container);
    %s
    Py_TYPE(self)->tp_free((PyObject*)self);
}
''' % (iter_tp_dealloc_function_name, self.iter_pystruct, self._get_iter_delete_code()))

        self.iter_pytype.slots.setdefault("tp_dealloc", iter_tp_dealloc_function_name )


    def _generate_iter_methods(self, code_sink):

        container_tp_iter_function_name = "_wrap_%s__tp_iter" % (self.pystruct,)
        iterator_tp_iter_function_name = "_wrap_%s__tp_iter" % (self.iter_pystruct,)
        subst_vars = {
            'CONTAINER_ITER_FUNC': container_tp_iter_function_name,
            'ITERATOR_ITER_FUNC': iterator_tp_iter_function_name,
            'PYSTRUCT': self.pystruct,
            'ITER_PYSTRUCT': self.iter_pystruct,
            'ITER_PYTYPESTRUCT': self.iter_pytypestruct,
            'CTYPE': self.full_name,
            }
        # -- container --
        code_sink.writeln(r'''
static PyObject*
%(CONTAINER_ITER_FUNC)s(%(PYSTRUCT)s *self)
{
    %(ITER_PYSTRUCT)s *iter = PyObject_GC_New(%(ITER_PYSTRUCT)s, &%(ITER_PYTYPESTRUCT)s);
    Py_INCREF(self);
    iter->container = self;
    iter->iterator = new %(CTYPE)s::iterator(self->obj->begin());
    return (PyObject*) iter;
}
''' % subst_vars)

        self.pytype.slots.setdefault("tp_iter", container_tp_iter_function_name)


        # -- iterator --
        container_tp_iter_function_name = "_wrap_%s__tp_iter" % (self.pystruct,)
        code_sink.writeln(r'''
static PyObject*
%(ITERATOR_ITER_FUNC)s(%(ITER_PYSTRUCT)s *self)
{
    Py_INCREF(self);
    return (PyObject*) self;
}
''' % subst_vars)

        self.iter_pytype.slots.setdefault("tp_iter", iterator_tp_iter_function_name)

        # -- iterator tp_iternext
        iternext = IterNextWrapper(self)
        iternext.generate(code_sink)
        self.iter_pytype.slots.setdefault("tp_iternext", iternext.c_function_name)



    def _generate_container_constructor(self, code_sink):
        container_tp_init_function_name = "_wrap_%s__tp_init" % (self.pystruct,)
        item_python_to_c_converter = self.module.get_root().generate_python_to_c_type_converter(self.value_type, code_sink)
        if self.key_type is not None:
            key_python_to_c_converter = self.module.get_root().generate_python_to_c_type_converter(self.key_type, code_sink)
        this_type_converter = self.module.get_root().get_python_to_c_type_converter_function_name(
            self.ThisContainerReturn(self.full_name))
        subst_vars = {
            'FUNC': container_tp_init_function_name,
            'PYSTRUCT': self.pystruct,
            'PYTYPESTRUCT': self.pytypestruct,
            'CTYPE': self.full_name,
            'ITEM_CONVERTER': item_python_to_c_converter,
            'PYTHON_NAME': self.python_name,
            'ITEM_CTYPE': self.value_type.ctype,
            'CONTAINER_CONVERTER_FUNC_NAME': this_type_converter,
            'ADD_VALUE': self.container_traits.add_value_method,
            }

        if self.key_type is None:

            # generate mapping converter function

            code_sink.writeln(r'''
int %(CONTAINER_CONVERTER_FUNC_NAME)s(PyObject *arg, %(CTYPE)s *container)
{
    if (PyObject_IsInstance(arg, (PyObject*) &%(PYTYPESTRUCT)s)) {
        *container = *((%(PYSTRUCT)s*)arg)->obj;
    } else if (PyList_Check(arg)) {
        container->clear();
        Py_ssize_t size = PyList_Size(arg);
        for (Py_ssize_t i = 0; i < size; i++) {
            %(ITEM_CTYPE)s item;
            if (!%(ITEM_CONVERTER)s(PyList_GET_ITEM(arg, i), &item)) {
                return 0;
            }
            container->%(ADD_VALUE)s(item);
        }
    } else {
        PyErr_SetString(PyExc_TypeError, "parameter must be None, a %(PYTHON_NAME)s instance, or a list of %(ITEM_CTYPE)s");
        return 0;
    }
    return 1;
}
''' % subst_vars)

        else:

            # generate mapping converter function

            subst_vars.update({
                    'KEY_CONVERTER': key_python_to_c_converter,
                    'KEY_CTYPE': self.key_type.ctype,
                    })

            code_sink.writeln(r'''
int %(CONTAINER_CONVERTER_FUNC_NAME)s(PyObject *arg, %(CTYPE)s *container)
{
    if (PyObject_IsInstance(arg, (PyObject*) &%(PYTYPESTRUCT)s)) {
        *container = *((%(PYSTRUCT)s*)arg)->obj;
    } else if (PyList_Check(arg)) {
        container->clear();
        Py_ssize_t size = PyList_Size(arg);
        for (Py_ssize_t i = 0; i < size; i++) {
            PyObject *tup = PyList_GET_ITEM(arg, i);
            if (!PyTuple_Check(tup) || PyTuple_Size(tup) != 2) {
                PyErr_SetString(PyExc_TypeError, "items must be tuples with two elements");
                return 0;
            }
            std::pair< %(KEY_CTYPE)s, %(ITEM_CTYPE)s > item;
            if (!%(KEY_CONVERTER)s(PyTuple_GET_ITEM(tup, 0), &item.first)) {
                return 0;
            }
            if (!%(ITEM_CONVERTER)s(PyTuple_GET_ITEM(tup, 1), &item.second)) {
                return 0;
            }
            container->%(ADD_VALUE)s(item);
        }
    } else {
        PyErr_SetString(PyExc_TypeError, "parameter must be None, a %(PYTHON_NAME)s instance, or a list of %(ITEM_CTYPE)s");
        return 0;
    }
    return 1;
}
''' % subst_vars)
            # ---

        # constructor, calling the above converter function
        code_sink.writeln(r'''
static int
%(FUNC)s(%(PYSTRUCT)s *self, PyObject *args, PyObject *kwargs)
{
    const char *keywords[] = {"arg", NULL};
    PyObject *arg = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "|O", (char **) keywords, &arg)) {
        return -1;
    }

    self->obj = new %(CTYPE)s;

    if (arg == NULL)
        return 0;

    if (!%(CONTAINER_CONVERTER_FUNC_NAME)s(arg, self->obj)) {
        delete self->obj;
        self->obj = NULL;
        return -1;
    }
    return 0;
}
''' % subst_vars)

        self.pytype.slots.setdefault("tp_init", container_tp_init_function_name) PY3 = (sys.version_info[0] >= 3)
    def any(iterable):
def write_preamble(code_sink, min_python_version=None):
def mangle_name(name):
def get_mangled_name(base_name, template_args):
def call_with_error_handling(callback, args, kwargs, wrapper,
                             exceptions_to_handle=(TypeConfigurationError,
                                                   CodeGenerationError,
                                                   NotSupportedError)):
def ascii(value):
def param(*args, **kwargs):
def retval(*args, **kwargs):
def parse_param_spec(param_spec):
def parse_retval_spec(retval_spec):
def eval_param(param_value, wrapper=None):
def eval_retval(retval_value, wrapper=None):
class SkipWrapper(Exception):
from pybindgen.function import Function, OverloadedFunction, CustomFunctionWrapper
from pybindgen.typehandlers.base import CodeBlock, DeclarationsScope, ReturnValue, TypeHandler
from pybindgen.typehandlers.codesink import MemoryCodeSink, CodeSink, FileCodeSink, NullCodeSink
from pybindgen.cppclass import CppClass
from pybindgen.cppexception import CppException
from pybindgen.enum import Enum
from pybindgen.container import Container
from pybindgen.converter_functions import PythonToCConverter, CToPythonConverter
from pybindgen import utils
import warnings
import traceback
import collections
    def add_class(self, *args, **kwargs):
        """
        Add a class to the module. See the documentation for
        L{CppClass.__init__} for information on accepted parameters.
        """
        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], CppClass):
            cls = args[0]
            warnings.warn("add_class has changed API; see the API documentation",
                          DeprecationWarning, stacklevel=2)
        else:
            cls = CppClass(*args, **kwargs)
        self._add_class_obj(cls)
        return cls

    def add_struct(self, *args, **kwargs):
        """
        Add a struct to the module.

        In addition to the parameters accepted by
        L{CppClass.__init__}, this method accepts the following
        keyword parameters:

          - no_constructor (bool): if True, the structure will not
            have a constructor by default (if omitted, it will be
            considered to have a trivial constructor).

          - no_copy (bool): if True, the structure will not
            have a copy constructor by default (if omitted, it will be
            considered to have a simple copy constructor).

        """

        try:
            no_constructor = kwargs['no_constructor']
        except KeyError:
            no_constructor = False
        else:
            del kwargs['no_constructor']

        try:
            no_copy = kwargs['no_copy']
        except KeyError:
            no_copy = False
        else:
            del kwargs['no_copy']
        
        struct = CppClass(*args, **kwargs)
        struct.stack_where_defined = traceback.extract_stack()
        self._add_class_obj(struct)
        if not no_constructor:
            struct.add_constructor([])
        if not no_copy:
            struct.add_copy_constructor()
        return struct


    def add_cpp_namespace(self, name):
        """
        Add a nested module namespace corresponding to a C++
        namespace.  If the requested namespace was already added, the
        existing module is returned instead of creating a new one.

        :param name: name of C++ namespace (just the last component,
        not full scoped name); this also becomes the name of the
        submodule.

        :return: a L{SubModule} object that maps to this namespace.
        """
        name = utils.ascii(name)
        try:
            return self.get_submodule(name)
        except ValueError:
            module = SubModule(name, parent=self, cpp_namespace=name)
            module.stack_where_defined = traceback.extract_stack()
            return module

    def _add_enum_obj(self, enum):
        """
        Add an enumeration.
        """
        assert isinstance(enum, Enum)
        self.enums.append(enum)
        enum.module = self
        enum.section = self.current_section
        self.register_type(enum.name, enum.full_name, enum)

    def add_enum(self, *args, **kwargs):
        """
        Add an enumeration to the module. See the documentation for
        L{Enum.__init__} for information on accepted parameters.
        """
        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], Enum):
            enum = args[0]
            warnings.warn("add_enum has changed API; see the API documentation",
                          DeprecationWarning, stacklevel=2)
        else:
            enum = Enum(*args, **kwargs)
        enum.stack_where_defined = traceback.extract_stack()
        self._add_enum_obj(enum)
        return enum


    def _add_container_obj(self, container):
        """
        Add a container to the module.

        :param container: a L{Container} object
        """
        assert isinstance(container, Container)
        container.module = self
        container.section = self.current_section
        self.containers.append(container)
        self.register_type(container.name, container.full_name, container)

    def add_container(self, *args, **kwargs):
        """
        Add a container to the module. See the documentation for
        L{Container.__init__} for information on accepted parameters.
        """
        try:

            container = Container(*args, **kwargs)