'Return name and bases for all classes that are ancestors of
*classes*.
*parts* gives the number of dotted name parts that is removed from the
displayed node names.'

def _class_info(self, classes, show_builtins, private_bases, parts):

    all_classes = {}
    py_builtins = vars(builtins).values()
    def recurse(cls):
        if ((not show_builtins) and (cls in py_builtins)):
            return
        if ((not private_bases) and cls.__name__.startswith('_')):
            return
        nodename = self.class_name(cls, parts)
        fullname = self.class_name(cls, 0)
        tooltip = None
        try:
            if cls.__doc__:
                enc = ModuleAnalyzer.for_module(cls.__module__).encoding
                doc = cls.__doc__.strip().split('\n')[0]
                if (not isinstance(doc, text_type)):
                    doc = force_decode(doc, enc)
                if doc:
                    tooltip = ('"%s"' % doc.replace('"', '\\"'))
        except Exception:
            pass
        baselist = []
        all_classes[cls] = (nodename, fullname, baselist, tooltip)
        for base in cls.__bases__:
            if ((not show_builtins) and (base in py_builtins)):
                continue
            if ((not private_bases) and base.__name__.startswith('_')):
                continue
            baselist.append(self.class_name(base, parts))
            if (base not in all_classes):
                recurse(base)
    for cls in classes:
        recurse(cls)
    return list(all_classes.values())
