Imports all the sub-modules of a package, a useful technique for developing
    plugins.  By default, this method will walk the directory structure looking
    for submodules and packages.  You can also specify a __toc__ attribute
    on the package to define the sub-modules that you want to import.
    
    :param      package_or_toc  | <package> || <str> filename
                ignore          | [<str>, ..] || None
                recurse         | <bool>
                silent          | <bool>
    
    :usage      |>>> import projex
                |>>> import projex.docgen
                |>>> projex.importmodules(projex.docgen)
                |[<projex.docgen.commands>, <projex.docgen.default_config>, ..]
    
    :return     [<module> || <package>, ..]

def importmodules(package_or_toc, ignore=None, recurse=False, silent=None):
    """
    Imports all the sub-modules of a package, a useful technique for developing
    plugins.  By default, this method will walk the directory structure looking
    for submodules and packages.  You can also specify a __toc__ attribute
    on the package to define the sub-modules that you want to import.
    
    :param      package_or_toc  | <package> || <str> filename
                ignore          | [<str>, ..] || None
                recurse         | <bool>
                silent          | <bool>
    
    :usage      |>>> import projex
                |>>> import projex.docgen
                |>>> projex.importmodules(projex.docgen)
                |[<projex.docgen.commands>, <projex.docgen.default_config>, ..]
    
    :return     [<module> || <package>, ..]
    """
    if package_or_toc in __IMPORTED:
        return

    __IMPORTED.add(package_or_toc)

    if silent is None:
        silent = os.environ.get('PROJEX_LOG_IMPORTS', 'False').lower() != 'true'

    toc = []
    output = []
    if ignore is None:
        ignore = []

    # import from a set toc file
    if type(package_or_toc) in (str, unicode):
        # import a toc file
        if os.path.isfile(package_or_toc):
            f = open(package_or_toc, 'r')
            toc = f.readlines()
            f.close()

        # import from a directory
        elif os.path.isdir(package_or_toc):
            toc, paths = findmodules(package_or_toc, recurse=recurse)
            for path in paths:
                if path in sys.path:
                    sys.path.remove(path)

                sys.path.insert(0, path)

        # import a module by string
        else:
            use_sub_modules = False
            if package_or_toc.endswith('.*'):
                use_sub_modules = True
                package_or_toc = package_or_toc[:-2]

            try:
                __import__(package_or_toc)
                module = sys.modules[package_or_toc]
            except ImportError as err:
                if not silent:
                    logger.error('Unable to import module: %s', package_or_toc)
                    logger.debug(traceback.print_exc())
                return []
            except KeyError:
                if not silent:
                    logger.error('Unable to find module: %s', package_or_toc)
                return []

            if use_sub_modules:
                base = os.path.dirname(module.__file__)
                for path in os.listdir(base):
                    if path.endswith('.py') and path != '__init__.py':
                        importmodules(package_or_toc + '.' + path.replace('.py', ''))
                    elif os.path.isdir(os.path.join(base, path)):
                        importmodules(package_or_toc + '.' + path)
            else:
                return importmodules(module)

    # import from a given package
    else:
        toc = getattr(package_or_toc, '__toc__', [])

        if not toc:
            toc = []
            recurse = getattr(package_or_toc, '__recurse__', False)
            try:
                paths = package_or_toc.__path__
            except AttributeError:
                try:
                    paths = [os.path.dirname(package_or_toc.__file__)]
                except AttributeError:
                    paths = []

            for path in paths:
                data = findmodules(path, recurse=recurse)
                toc += data[0]
                for sub_path in data[1]:
                    if sub_path in sys.path:
                        sys.path.remove(sub_path)

                    sys.path.insert(0, sub_path)

            setattr(package_or_toc, '__toc__', toc)

    # import using standard means (successful for when dealing with 
    for modname in sorted(toc):
        # check against a callable ignore method
        if callable(ignore) and ignore(modname):
            continue

        elif type(modname) in (list, tuple) and modname not in ignore:
            continue

        # ignore preset options
        if modname.endswith('__init__'):
            continue
        elif modname.endswith('__plugins__'):
            continue

        try:
            output.append(sys.modules[modname])
            continue
        except KeyError:
            pass

        if not silent:
            logger.debug('Importing: %s' % modname)
        try:
            mod = importlib.import_module(modname)
            sys.modules[modname] = mod
            output.append(mod)
        except ImportError, err:
            if not silent:
                logger.error('Error importing module: %s', modname)
                logger.debug(traceback.print_exc())

    return output