Source code for autodoc

# ../autodoc.py

"""This module provides a class to create documentation automatically."""

# =============================================================================
# >> IMPORTS
# =============================================================================
# Python
import sys

from path import Path

# =============================================================================
# >> ALL DECLARATION
# =============================================================================
__all__ = ('SphinxError',
           'SphinxProject',
           )


# =============================================================================
# >> CLASSES
# =============================================================================
[docs]class SphinxError(Exception): """Exception raised when creating, building, or generating Sphinx docs."""
[docs]class SphinxProject(object): """Representation of a Sphinx project."""
[docs] def __init__(self, package_dir, project_dir): """Initialize the Sphinx project object. :param str package_dir: The path to the package to document. :param str project_dir: The path to the Sphinx project or where it should be saved. """ self._package_dir = Path(package_dir) self._project_dir = Path(project_dir) self.validate_package()
@property def project_dir(self): """Return the project directory. :rtype: Path """ return self._project_dir @property def project_source_dir(self): """Return the project source directory. :rtype: Path """ return self.project_dir / 'source' @property def project_build_dir(self): """Return the project build directory. :rtype: Path """ return self.project_dir / 'build' @property def package_dir(self): """Return the package directory as a Path object. :rtype: Path """ return self._package_dir
[docs] def project_exists(self): """Return True if the Sphinx project exists. :rtype: bool """ return self.project_dir.isdir()
[docs] def package_exists(self): """Return True if the package exists. :rtype: bool """ return self.package_dir.isdir()
[docs] def create(self, author, project_name=None, version='1'): """Create a new Sphinx project. :param str author: Name of the package author. :param str project_name: Name of the project that is displayed in the documentation. If None, it will be the name of the package. :param str version: Project/package version. :raise ValueError: Raised if the project already exists. :raise ValueError: Raised if the package does not exist. :raise SphinxError: Raised if an error occured during the creation. """ if self.project_exists(): raise ValueError('The project already exists.') self.validate_package() self.project_dir.mkdir() from sphinx.quickstart import main argv = [ '', # Will be skipped. '-q', # Don't start the interactive mode ] if project_name is None: project_name = self.package_dir.namebase argv.append('-p {0}'.format(project_name)) argv.append('-a {0}'.format(author)) argv.append('-v {0}'.format(version)) argv.extend([ str(self.project_dir), '--sep', # Separate source and build directory '--ext-autodoc', # Enable autodoc '--no-makefile', '--no-batchfile' ]) # Hacky, but required, because sphinx is reading sys.argv even if you # pass a list to main() old_argv = sys.argv sys.argv = argv try: main(sys.argv) except: raise SphinxError finally: sys.argv = old_argv
[docs] def generate_project_files(self, sub_dir=''): """Generate the project files (`*.rst` files). :param str sub_dir: A sub-directory of the :attr:`project_source_dir` where the module documentation will be generated in. :raise ValueError: Raised if the project and/or package does not exist. :raise SphinxError: Raised if an error occured during the generation. """ self.validate_project_and_package() from sphinx.apidoc import main argv = [ '', # Will be skipped. '-e', # Separate pages/files for every module '-o', str(self.project_source_dir / sub_dir), str(self.package_dir), # Package to document ] # Hacky, but required, because sphinx is reading sys.argv even if you # pass a list to main() old_argv = sys.argv sys.argv = argv try: main(sys.argv) except: raise SphinxError finally: sys.argv = old_argv
[docs] def build(self, clean=False): """Build the Sphinx project. :param bool clean: If True a clean build will be created. :raise ValueError: Raised if the project and/or package does not exist. :raise SphinxError: Raised if an error occured during the build. """ self.validate_project_and_package() if clean: self.project_build_dir.rmtree_p() add_to_path = self.package_dir not in sys.path if add_to_path: sys.path.append(str(self.package_dir.parent)) from sphinx import main argv = [ '', # Will be skipped. str(self.project_source_dir), str(self.project_build_dir), ] # Hacky, but required, because sphinx is reading sys.argv even if you # pass a list to main() old_argv = sys.argv sys.argv = argv try: main(sys.argv) except SystemExit as e: if e.code != 0: raise SphinxError finally: sys.argv = old_argv if add_to_path: sys.path.remove(str(self.package_dir.parent))
[docs] def quickstart(self, author, project_name=None, version='1'): """A wrapper for creating, generating, and building documentation. :param str author: Author of the project. :param str project_name: Name of the project. :param str version: Version of the project. """ if not self.project_exists(): self.create(author, project_name, version) self.generate_project_files() self.build()
[docs] def validate_project_and_package(self): """Validate the project and package. :raise ValueError: Raised if the project or package does not exist. """ self.validate_project() self.validate_package()
[docs] def validate_project(self): """Validate the project. :raise ValueError: Raised if the project does not exist. """ if not self.project_exists(): raise ValueError( 'Create the project before generating project files.')
[docs] def validate_package(self): """Validate the package. :raise ValueError: Raised if the package does not exist. """ if not self.package_exists(): raise ValueError('The package does not exist.')