import six


def collect_ancestor_classes(cls, terminal_cls=None, module=None):
    """
    Collects all the classes in the inheritance hierarchy of the given class, 
    including the class itself.
     
    If module is an object or list, we only return classes that are in one 
    of the given module/modules.This will exclude base classes that come 
    from external libraries.
    
    If terminal_cls is encountered in the hierarchy, we stop ascending 
    the tree.
    """
    if terminal_cls is None:
        terminal_cls = []
    elif not isinstance(terminal_cls, (list, set, tuple)):
        terminal_cls = [terminal_cls]
    
    if module is not None:
        if not isinstance(module, (list, set, tuple)):
            module = [module]
        module_strings = []
        for m in module:
            if isinstance(m, six.string_types):
                module_strings.append(m)
            else:
                module_strings.append(m.__name__)
        module = module_strings
    
    ancestors = []
    if (module is None or cls.__module__ in module) and cls not in terminal_cls:
        ancestors.append(cls)
        for base in cls.__bases__:
            ancestors.extend(collect_ancestor_classes(base, terminal_cls, module))
    
    return ancestors