#! /usr/bin/env python

import inspect
import os
from abjad import abjad_configuration
from abjad.tools import iotools
from abjad.tools.abctools import AbjadObject
from abjad.tools.documentationtools import ClassCrawler
from abjad.tools.documentationtools import InheritanceGraph


def _shorten_class_name(abjad_class):
    parts = abjad_class.__module__.split('.')[2:]
    return '%s.%s' % (parts[0], parts[1])


def _find_inconsistencies():
    tools_path = os.path.abspath('.')
    abjad_classes = ClassCrawler(tools_path)()
    graph = InheritanceGraph(addresses=abjad_classes, root_addresses=[AbjadObject])
    bad_arcs = []
    for parent, children in graph.parent_children_mapping.iteritems():
        parent_attrs = inspect.classify_class_attrs(parent)
        parent_slots_def = [x for x in parent_attrs
            if x.name == '__slots__'][0].defining_class
        for child in children:
            child_attrs = inspect.classify_class_attrs(child)
            child_slots_def = [x for x in child_attrs
                if x.name == '__slots__'][0].defining_class
            if child_slots_def == child and parent_slots_def != parent:
                bad_arcs.append((parent, child))
    if bad_arcs:
        print '%d bad __slots__ relationships found:' % len(bad_arcs)
        for parent, child in sorted(bad_arcs, key=lambda x: (x[0].__module__, x[1].__module__)):
            print '\t%s -> %s' % (_shorten_class_name(parent), _shorten_class_name(child))
    else:
        print 'No bad __slots__ relationships found.'
    return graph


if __name__ == '__main__':
    iotools.clear_terminal()
    graph = _find_inconsistencies()
