Source code for oncilla.buildApi

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
**buildApi.py**

**Platform:**
	Windows, Linux, Mac Os X.

**Description:**
	Builds Sphinx documentation Api files.

**Others:**

"""

#**********************************************************************************************************************
#***	Future imports.
#**********************************************************************************************************************
from __future__ import unicode_literals

#**********************************************************************************************************************
#***	Encoding manipulations.
#**********************************************************************************************************************
import sys

def _setEncoding():
	"""
	Sets the Application encoding.
	"""

	reload(sys)
	sys.setdefaultencoding("utf-8")

_setEncoding()

#**********************************************************************************************************************
#***	External imports.
#**********************************************************************************************************************
import argparse
import os
import shutil

if sys.version_info[:2] <= (2, 6):
	from ordereddict import OrderedDict
else:
	from collections import OrderedDict

#**********************************************************************************************************************
#***	Internal imports.
#**********************************************************************************************************************
import foundations.common
import foundations.decorators
import foundations.exceptions
import foundations.strings
import foundations.verbose
import foundations.walkers
from foundations.io import File

# Oncilla: Statement commented by auto-documentation process: sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "libraries"))
# Oncilla: Statement commented by auto-documentation process: import python.pyclbr as moduleBrowser

#**********************************************************************************************************************
#***	Module attributes.
#**********************************************************************************************************************
__author__ = "Thomas Mansencal"
__copyright__ = "Copyright (C) 2008 - 2014 - Thomas Mansencal"
__license__ = "GPL V3.0 - http://www.gnu.org/licenses/"
__maintainer__ = "Thomas Mansencal"
__email__ = "thomas.mansencal@gmail.com"
__status__ = "Production"

__all__ = ["LOGGER",
		   "FILES_EXTENSION",
		   "TOCTREE_TEMPLATE_BEGIN",
		   "TOCTREE_TEMPLATE_END",
		   "SANITIZER",
		   "importSanitizer",
		   "buildApi",
		   "getCommandLineArguments",
		   "main"]

LOGGER = foundations.verbose.installLogger()

FILES_EXTENSION = ".rst"

TOCTREE_TEMPLATE_BEGIN = ["Api\n",
						  "====\n",
						  "\n",
						  "Modules Summary:\n",
						  "\n",
						  ".. toctree::\n",
						  "   :maxdepth: 1\n",
						  "\n"]

TOCTREE_TEMPLATE_END = []

SANITIZER = os.path.join(os.path.dirname(__file__), "defaultSanitizer.py")

foundations.verbose.getLoggingConsoleHandler()
foundations.verbose.setVerbosityLevel(3)

#**********************************************************************************************************************
#***	Module classes and definitions.
#**********************************************************************************************************************
[docs]def importSanitizer(sanitizer): """ Imports the sanitizer python module. :param sanitizer: Sanitizer python module file. :type sanitizer: unicode :return: Module. :rtype: object """ directory = os.path.dirname(sanitizer) not directory in sys.path and sys.path.append(directory) namespace = __import__(foundations.strings.getSplitextBasename(sanitizer)) if hasattr(namespace, "bleach"): return namespace else: raise foundations.exceptions.ProgrammingError( "{0} | '{1}' is not a valid sanitizer module file!".format(sanitizer))
[docs]def buildApi(packages, input, output, sanitizer, excludedModules=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 excludedModules: Excluded modules. :type excludedModules: list :return: Definition success. :rtype: bool """ LOGGER.info("{0} | Building Sphinx documentation API!".format(buildApi.__name__)) sanitizer = importSanitizer(sanitizer) if os.path.exists(input): shutil.rmtree(input) os.makedirs(input) excludedModules = [] if excludedModules is None else excludedModules packagesModules = {"apiModules": [], "testsModules": []} for package in packages: package = __import__(package) path = foundations.common.getFirstItem(package.__path__) packageDirectory = os.path.dirname(path) for file in sorted( list(foundations.walkers.filesWalker(packageDirectory, filtersIn=("{0}.*\.ui$".format(path),)))): LOGGER.info("{0} | Ui file: '{1}'".format(buildApi.__name__, file)) targetDirectory = os.path.dirname(file).replace(packageDirectory, "") directory = "{0}{1}".format(input, targetDirectory) if not foundations.common.pathExists(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.filesWalker(packageDirectory, filtersIn=("{0}.*\.py$".format(path),), filtersOut=excludedModules))): LOGGER.info("{0} | Python file: '{1}'".format(buildApi.__name__, file)) module = "{0}.{1}".format((".".join(os.path.dirname(file).replace(packageDirectory, "").split("/"))), foundations.strings.getSplitextBasename(file)).strip(".") LOGGER.info("{0} | Module name: '{1}'".format(buildApi.__name__, module)) directory = os.path.dirname(os.path.join(input, module.replace(".", "/"))) if not foundations.common.pathExists(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 rstFilePath = "{0}{1}".format(module, FILES_EXTENSION) LOGGER.info("{0} | Building API file: '{1}'".format(buildApi.__name__, rstFilePath)) rstFile = File(os.path.join(output, rstFilePath)) header = ["_`{0}`\n".format(module), "==={0}\n".format("=" * len(module)), "\n", ".. automodule:: {0}\n".format(module), "\n"] rstFile.content.extend(header) functions = OrderedDict() classes = OrderedDict() moduleAttributes = OrderedDict() for member, object in moduleBrowser._readmodule(module, [source, ]).iteritems(): if object.__class__ == moduleBrowser.Function: if not member.startswith("_"): functions[member] = [".. autofunction:: {0}\n".format(member)] elif object.__class__ == moduleBrowser.Class: classes[member] = [".. autoclass:: {0}\n".format(member), " :show-inheritance:\n", " :members:\n"] elif object.__class__ == moduleBrowser.Global: if not member.startswith("_"): moduleAttributes[member] = [".. attribute:: {0}.{1}\n".format(module, member)] moduleAttributes and rstFile.content.append("Module Attributes\n-----------------\n\n") for moduleAttribute in moduleAttributes.itervalues(): rstFile.content.extend(moduleAttribute) rstFile.content.append("\n") functions and rstFile.content.append("Functions\n---------\n\n") for function in functions.itervalues(): rstFile.content.extend(function) rstFile.content.append("\n") classes and rstFile.content.append("Classes\n-------\n\n") for class_ in classes.itervalues(): rstFile.content.extend(class_) rstFile.content.append("\n") rstFile.write() modules.append(module) packagesModules["apiModules"].extend([module for module in modules if not "tests" in module]) packagesModules["testsModules"].extend([module for module in modules if "tests" in module]) apiFile = File("{0}{1}".format(output, FILES_EXTENSION)) apiFile.content.extend(TOCTREE_TEMPLATE_BEGIN) for module in packagesModules["apiModules"]: apiFile.content.append(" {0} <{1}>\n".format(module, "api/{0}".format(module))) for module in packagesModules["testsModules"]: apiFile.content.append(" {0} <{1}>\n".format(module, "api/{0}".format(module))) apiFile.content.extend(TOCTREE_TEMPLATE_END) apiFile.write() return True
[docs]def getCommandLineArguments(): """ Retrieves command line arguments. :return: Namespace. :rtype: Namespace """ parser = argparse.ArgumentParser(add_help=False) parser.add_argument("-h", "--help", action="help", help="'Displays this help message and exit.'") parser.add_argument("-p", "--packages", dest="packages", nargs="+", help="'Packages to include in the API.'") parser.add_argument("-i", "--input", type=unicode, dest="input", help="'Input modules directory.'") parser.add_argument("-o", "--output", type=unicode, dest="output", help="'Output reStructuredText files directory.'") parser.add_argument("-s", "--sanitizer", type=unicode, dest="sanitizer", help="'Sanitizer python module'") parser.add_argument("-x", "--excludedModules", dest="excludedModules", nargs="*", help="'Excluded modules.'") if len(sys.argv) == 1: parser.print_help() sys.exit(1) return parser.parse_args() # Oncilla: Statement commented by auto-documentation process: # Oncilla: Statement commented by auto-documentation process: @foundations.decorators.systemExit
[docs]def main(): """ Starts the Application. :return: Definition success. :rtype: bool """ args = getCommandLineArguments() args.sanitizer = args.sanitizer if foundations.common.pathExists(args.sanitizer) else SANITIZER args.excludedModules = args.excludedModules if all(args.excludedModules) else [] return buildApi(args.packages, args.input, args.output, args.sanitizer, args.excludedModules) # Oncilla: Statement commented by auto-documentation process: # Oncilla: Statement commented by auto-documentation process: if __name__ == "__main__": # Oncilla: Statement commented by auto-documentation process: main() # Oncilla: Statement commented by auto-documentation process: