#!/usr/bin/env python

import PyQt4
import inspect

modules = ["phonon", "Qsci", "QtAssistant", "QtCore", "QtDeclarative", "QtDesigner",
           "QtGui", "QtHelp", "QtMultimedia", "QtNetwork", "QtOpenGL", "QtScript",
           "QtScriptTools", "Qt", "QtSql", "QtSvg", "QtTest", "QtWebKit", "QtXmlPatterns",
           "QtXml"]

exclude = ["pyqtProperty", "pyqtSignal", "pyqtWrapperType", "wrappertype", "enumtype"]


class Metric(dict):
    _fields = "name", "modules", "classes", "methods", "functions"
    def __init__(self, *args, **kwargs):
        for f in Metric._fields:
            self.__dict__[f] = f == "name" and "" or 0
        for i in range(min(len(args), len(Metric._fields))):
            self.__dict__[Metric._fields[i]] = args[i]
        for k, v in kwargs.items():
            if k in Metric._fields:
                self.__dict__[k] = v
            else:
                raise KeyError, "%s is not a member of %s" % (k, self.__class__.__name__)

    def __repr__(self):
        return "%s(%s)" % (self.__class__.__name__,
                    ", ".join(["%s: %s" % (k, self.__dict__[k]) for k in Metric._fields]))

    def __add__(self, other):
        for f in Metric._fields[1:]:
            self.__dict__[f] = self.__dict__[f] + other.__dict__[f]
        return self


def inspector(obj, path, mm):
    if obj.__name__ in exclude:
        return
    path.append(obj.__name__)
    #print "inspect: %s" % ".".join(path)

    if inspect.ismodule(obj):
        mm.modules += 1
        for name, data in inspect.getmembers(obj, inspect.isclass):
            inspector(data, path, mm)

        for name, value in inspect.getmembers(obj, inspect.isbuiltin):
            print "function %s.%s" % (".".join(path), name)
            mm.functions += 1

    elif inspect.isclass(obj):
        print "class %s.%s" % (".".join(path), obj.__name__)
        mm.classes += 1
        try:
            for name, cls in inspect.getmembers(obj, inspect.isclass):
                inspector(cls, path, mm)

            for name, value in inspect.getmembers(obj, inspect.isbuiltin):
                print "method %s.%s" % (".".join(path), name)
                mm.methods += 1

        except AttributeError, e:
            print "failed: %s" % e
            pass

    #print "done: %s" % ".".join(path)
    path.pop()


def main():
    metric = Metric("PyQt4")
    for module in modules:
        #print "import: %s" % module
        try:
            module = __import__('PyQt4.%s' % module, globals(), locals(), [module])
        except ImportError, e:
            print e
            continue
        print "module: %s" % module.__name__
        mm = Metric(module.__name__)
        inspector(module, [], mm)
        print mm
        metric += mm
    print metric


if __name__ == "__main__":
    main()
