1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""
Code to build the documentation in the setup.py
To use this code, run::
python setup.py build_sphinx
"""
# Standard library imports
import sys
import os
from os.path import join as pjoin
import zipfile
import warnings
import shutil
from distutils.cmd import Command
from distutils.command.clean import clean
# Sphinx import.
from sphinx.setup_command import BuildDoc
_info_fname = pjoin('nipype', 'info.py')
INFO_VARS = {}
exec(open(_info_fname, 'rt').read(), {}, INFO_VARS)
DOC_BUILD_DIR = os.path.join('doc', '_build', 'html')
DOC_DOCTREES_DIR = os.path.join('doc', '_build', 'doctrees')
################################################################################
# Distutils Command class for installing nipype to a temporary location.
class TempInstall(Command):
temp_install_dir = os.path.join('build', 'install')
def run(self):
""" build and install nipype in a temporary location. """
install = self.distribution.get_command_obj('install')
install.install_scripts = self.temp_install_dir
install.install_base = self.temp_install_dir
install.install_platlib = self.temp_install_dir
install.install_purelib = self.temp_install_dir
install.install_data = self.temp_install_dir
install.install_lib = self.temp_install_dir
install.install_headers = self.temp_install_dir
install.run()
# Horrible trick to reload nipype with our temporary instal
for key in sys.modules.keys():
if key.startswith('nipype'):
sys.modules.pop(key, None)
sys.path.append(os.path.abspath(self.temp_install_dir))
# Pop the cwd
sys.path.pop(0)
import nipype
def initialize_options(self):
pass
def finalize_options(self):
pass
################################################################################
# Distutils Command class for API generation
class APIDocs(TempInstall):
description = \
"""generate API docs """
user_options = [
('None', None, 'this command has no options'),
]
def run(self):
# First build the project and install it to a temporary location.
TempInstall.run(self)
os.chdir('doc')
try:
# We are running the API-building script via an
# system call, but overriding the import path.
toolsdir = os.path.abspath(pjoin('..', 'tools'))
for docbuilder in ['build_interface_docs.py']:
build_templates = pjoin(toolsdir, docbuilder)
cmd = """%s -c 'import sys; sys.path.append("%s"); sys.path.append("%s"); execfile("%s", dict(__name__="__main__"))'""" \
% (sys.executable,
toolsdir,
self.temp_install_dir,
build_templates)
os.system(cmd)
finally:
os.chdir('..')
################################################################################
# Code to copy the sphinx-generated html docs in the distribution.
def relative_path(filename):
""" Return the relative path to the file, assuming the file is
in the DOC_BUILD_DIR directory.
"""
length = len(os.path.abspath(DOC_BUILD_DIR)) + 1
return os.path.abspath(filename)[length:]
################################################################################
# Distutils Command class build the docs
class MyBuildDoc(BuildDoc):
""" Sub-class the standard sphinx documentation building system, to
add logics for API generation and matplotlib's plot directive.
"""
def run(self):
self.run_command('api_docs')
# We need to be in the doc directory for to plot_directive
# and API generation to work
"""
os.chdir('doc')
try:
BuildDoc.run(self)
finally:
os.chdir('..')
"""
# It put's the build in a doc/doc/_build directory with the
# above?!?! I'm leaving the code above here but commented out
# in case I'm missing something?
BuildDoc.run(self)
self.zip_docs()
def zip_docs(self):
if not os.path.exists(DOC_BUILD_DIR):
raise OSError, 'Doc directory does not exist.'
target_file = os.path.join('doc', 'documentation.zip')
# ZIP_DEFLATED actually compresses the archive. However, there
# will be a RuntimeError if zlib is not installed, so we check
# for it. ZIP_STORED produces an uncompressed zip, but does not
# require zlib.
try:
zf = zipfile.ZipFile(target_file, 'w',
compression=zipfile.ZIP_DEFLATED)
except RuntimeError:
warnings.warn('zlib not installed, storing the docs '
'without compression')
zf = zipfile.ZipFile(target_file, 'w',
compression=zipfile.ZIP_STORED)
for root, dirs, files in os.walk(DOC_BUILD_DIR):
relative = relative_path(root)
if not relative.startswith('.doctrees'):
for f in files:
zf.write(os.path.join(root, f),
os.path.join(relative, 'html_docs', f))
zf.close()
def finalize_options(self):
""" Override the default for the documentation build
directory.
"""
self.build_dir = os.path.join(*DOC_BUILD_DIR.split(os.sep)[:-1])
BuildDoc.finalize_options(self)
################################################################################
# Distutils Command class to clean
class Clean(clean):
def run(self):
clean.run(self)
api_path = os.path.join('doc', 'api', 'generated')
if os.path.exists(api_path):
print "Removing %s" % api_path
shutil.rmtree(api_path)
interface_path = os.path.join('doc', 'interfaces', 'generated')
if os.path.exists(interface_path):
print "Removing %s" % interface_path
shutil.rmtree(interface_path)
if os.path.exists(DOC_BUILD_DIR):
print "Removing %s" % DOC_BUILD_DIR
shutil.rmtree(DOC_BUILD_DIR)
if os.path.exists(DOC_DOCTREES_DIR):
print "Removing %s" % DOC_DOCTREES_DIR
shutil.rmtree(DOC_DOCTREES_DIR)
# The command classes for distutils, used by the setup.py
cmdclass = {'build_sphinx': MyBuildDoc,
'api_docs': APIDocs,
'clean': Clean,
}
|