Builds the Sphinx documentation API.

    :param packages: Packages to include in the API.
    :type packages: list
    :param input: Input modules directory.
    :type input: unicode
    :param output: Output reStructuredText files directory.
    :type output: unicode
    :param sanitizer: Sanitizer python module.
    :type sanitizer: unicode
    :param excluded_modules: Excluded modules.
    :type excluded_modules: list
    :return: Definition success.
    :rtype: bool

def build_api(packages, input, output, sanitizer, excluded_modules=None):
    """
    Builds the Sphinx documentation API.

    :param packages: Packages to include in the API.
    :type packages: list
    :param input: Input modules directory.
    :type input: unicode
    :param output: Output reStructuredText files directory.
    :type output: unicode
    :param sanitizer: Sanitizer python module.
    :type sanitizer: unicode
    :param excluded_modules: Excluded modules.
    :type excluded_modules: list
    :return: Definition success.
    :rtype: bool
    """

    LOGGER.info("{0} | Building Sphinx documentation API!".format(build_api.__name__))

    sanitizer = import_sanitizer(sanitizer)

    if os.path.exists(input):
        shutil.rmtree(input)
        os.makedirs(input)

    excluded_modules = [] if excluded_modules is None else excluded_modules

    packages_modules = {"apiModules": [],
                        "testsModules": []}
    for package in packages:
        package = __import__(package)
        path = foundations.common.get_first_item(package.__path__)
        package_directory = os.path.dirname(path)

        for file in sorted(
                list(foundations.walkers.files_walker(package_directory, filters_in=("{0}.*\.ui$".format(path),)))):
            LOGGER.info("{0} | Ui file: '{1}'".format(build_api.__name__, file))
            target_directory = os.path.dirname(file).replace(package_directory, "")
            directory = "{0}{1}".format(input, target_directory)
            if not foundations.common.path_exists(directory):
                os.makedirs(directory)
            source = os.path.join(directory, os.path.basename(file))
            shutil.copyfile(file, source)

        modules = []
        for file in sorted(
                list(foundations.walkers.files_walker(package_directory, filters_in=("{0}.*\.py$".format(path),),
                                                      filters_out=excluded_modules))):
            LOGGER.info("{0} | Python file: '{1}'".format(build_api.__name__, file))
            module = "{0}.{1}".format((".".join(os.path.dirname(file).replace(package_directory, "").split("/"))),
                                      foundations.strings.get_splitext_basename(file)).strip(".")
            LOGGER.info("{0} | Module name: '{1}'".format(build_api.__name__, module))
            directory = os.path.dirname(os.path.join(input, module.replace(".", "/")))
            if not foundations.common.path_exists(directory):
                os.makedirs(directory)
            source = os.path.join(directory, os.path.basename(file))
            shutil.copyfile(file, source)

            sanitizer.bleach(source)

            if "__init__.py" in file:
                continue

            rst_file_path = "{0}{1}".format(module, FILES_EXTENSION)
            LOGGER.info("{0} | Building API file: '{1}'".format(build_api.__name__, rst_file_path))
            rst_file = File(os.path.join(output, rst_file_path))
            header = ["_`{0}`\n".format(module),
                      "==={0}\n".format("=" * len(module)),
                      "\n",
                      ".. automodule:: {0}\n".format(module),
                      "\n"]
            rst_file.content.extend(header)

            functions = OrderedDict()
            classes = OrderedDict()
            module_attributes = OrderedDict()
            for member, object in module_browser._readmodule(module, [source, ]).iteritems():
                if object.__class__ == module_browser.Function:
                    if not member.startswith("_"):
                        functions[member] = [".. autofunction:: {0}\n".format(member)]
                elif object.__class__ == module_browser.Class:
                    classes[member] = [".. autoclass:: {0}\n".format(member),
                                       "	:show-inheritance:\n",
                                       "	:members:\n"]
                elif object.__class__ == module_browser.Global:
                    if not member.startswith("_"):
                        module_attributes[member] = [".. attribute:: {0}.{1}\n".format(module, member)]

            module_attributes and rst_file.content.append("Module Attributes\n-----------------\n\n")
            for module_attribute in module_attributes.itervalues():
                rst_file.content.extend(module_attribute)
                rst_file.content.append("\n")

            functions and rst_file.content.append("Functions\n---------\n\n")
            for function in functions.itervalues():
                rst_file.content.extend(function)
                rst_file.content.append("\n")

            classes and rst_file.content.append("Classes\n-------\n\n")
            for class_ in classes.itervalues():
                rst_file.content.extend(class_)
                rst_file.content.append("\n")

            rst_file.write()
            modules.append(module)

        packages_modules["apiModules"].extend([module for module in modules if not "tests" in module])
        packages_modules["testsModules"].extend([module for module in modules if "tests" in module])

    api_file = File("{0}{1}".format(output, FILES_EXTENSION))
    api_file.content.extend(TOCTREE_TEMPLATE_BEGIN)
    for module in packages_modules["apiModules"]:
        api_file.content.append("   {0} <{1}>\n".format(module, "api/{0}".format(module)))
    for module in packages_modules["testsModules"]:
        api_file.content.append("   {0} <{1}>\n".format(module, "api/{0}".format(module)))
    api_file.content.extend(TOCTREE_TEMPLATE_END)
    api_file.write()

    return True