Merge pull request #4097 from stephenfin/argparse-integration

Fix #3259: Argparse integration
This commit is contained in:
Takayuki SHIMIZUKAWA
2017-10-21 18:58:55 +09:00
committed by GitHub
10 changed files with 388 additions and 438 deletions

View File

@@ -3,7 +3,7 @@
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = python ../sphinx-build.py
SPHINXBUILD = python ../sphinx/cmd/build.py
SPHINXPROJ = sphinx
SOURCEDIR = .
BUILDDIR = _build

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Sphinx - Python documentation toolchain
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys
if __name__ == '__main__':
from sphinx.ext.apidoc import main
sys.exit(main(sys.argv[1:]))

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Sphinx - Python documentation toolchain
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys
if __name__ == '__main__':
from sphinx.ext.autosummary.generate import main
sys.exit(main(sys.argv[1:]))

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Sphinx - Python documentation toolchain
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys
if __name__ == '__main__':
from sphinx import main
sys.exit(main(sys.argv[1:]))

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Sphinx - Python documentation toolchain
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys
if __name__ == '__main__':
from sphinx.cmd.quickstart import main
sys.exit(main(sys.argv[1:]))

View File

@@ -11,13 +11,13 @@
from __future__ import print_function
from __future__ import absolute_import
import re
import argparse
import os
import re
import sys
import optparse
import time
from os import path
from io import open
from os import path
# try to import readline, unix specific enhancement
try:
@@ -509,23 +509,6 @@ where "builder" is one of the supported builders, e.g. html, latex or linkcheck.
''')
def usage(argv, msg=None):
# type: (List[unicode], unicode) -> None
if msg:
print(msg, file=sys.stderr)
print(file=sys.stderr)
USAGE = """\
Sphinx v%s
Usage: %%prog [options] [projectdir]
""" % __display_version__
EPILOG = """\
For more information, visit <http://sphinx-doc.org/>.
"""
def valid_dir(d):
# type: (Dict) -> bool
dir = d['path']
@@ -556,18 +539,86 @@ def valid_dir(d):
return True
class MyFormatter(optparse.IndentedHelpFormatter):
def format_usage(self, usage): # type: ignore
# type: (str) -> str
return usage
def get_parser():
# type: () -> argparse.ArgumentParser
parser = argparse.ArgumentParser(
usage='%(prog)s [OPTIONS] <PROJECT_DIR>',
epilog="For more information, visit <http://sphinx-doc.org/>.",
description="""
Generate required files for a Sphinx project.
def format_help(self, formatter):
result = []
if self.description:
result.append(self.format_description(formatter))
if self.option_list:
result.append(self.format_option_help(formatter))
return "\n".join(result)
sphinx-quickstart is an interactive tool that asks some questions about your
project and then generates a complete documentation directory and sample
Makefile to be used with sphinx-build.
""")
parser.add_argument('-q', '--quiet', action='store_true', dest='quiet',
default=False,
help='quiet mode')
parser.add_argument('--version', action='version', dest='show_version',
version='%%(prog)s %s' % __display_version__)
parser.add_argument('path', metavar='PROJECT_DIR', default='.',
help='output path')
group = parser.add_argument_group('Structure options')
group.add_argument('--sep', action='store_true',
help='if specified, separate source and build dirs')
group.add_argument('--dot', metavar='DOT',
help='replacement for dot in _templates etc.')
group = parser.add_argument_group('Project basic options')
group.add_argument('-p', '--project', metavar='PROJECT', dest='project',
help='project name')
group.add_argument('-a', '--author', metavar='AUTHOR', dest='author',
help='author names')
group.add_argument('-v', metavar='VERSION', dest='version', default='',
help='version of project')
group.add_argument('-r', '--release', metavar='RELEASE', dest='release',
help='release of project')
group.add_argument('-l', '--language', metavar='LANGUAGE', dest='language',
help='document language')
group.add_argument('--suffix', metavar='SUFFIX',
help='source file suffix')
group.add_argument('--master', metavar='MASTER',
help='master document name')
group.add_argument('--epub', action='store_true', default=False,
help='use epub')
group = parser.add_argument_group('Extension options')
for ext in EXTENSIONS:
group.add_argument('--ext-' + ext, action='store_true',
dest='ext_' + ext, default=False,
help='enable %s extension' % ext)
group.add_argument('--extensions', metavar='EXTENSIONS', dest='extensions',
action='append', help='enable extensions')
# TODO(stephenfin): Consider using mutually exclusive groups here
group = parser.add_argument_group('Makefile and Batchfile creation')
group.add_argument('--makefile', action='store_true', default=False,
help='create makefile')
group.add_argument('--no-makefile', action='store_true', default=False,
help='not create makefile')
group.add_argument('--batchfile', action='store_true', default=False,
help='create batchfile')
group.add_argument('--no-batchfile', action='store_true', default=False,
help='not create batchfile')
group.add_argument('-M', '--no-use-make-mode', action='store_false',
dest='make_mode', default=False,
help='not use make-mode for Makefile/make.bat')
group.add_argument('-m', '--use-make-mode', action='store_true',
dest='make_mode', default=True,
help='use make-mode for Makefile/make.bat')
group = parser.add_argument_group('Project templating')
group.add_argument('-t', '--templatedir', metavar='TEMPLATEDIR',
dest='templatedir',
help='template directory for template files')
group.add_argument('-d', metavar='NAME=VALUE', action='append',
dest='variables',
help='define a template variable')
return parser
def main(argv=sys.argv[1:]):
@@ -575,81 +626,14 @@ def main(argv=sys.argv[1:]):
if not color_terminal():
nocolor()
parser = optparse.OptionParser(USAGE, epilog=EPILOG,
version='Sphinx v%s' % __display_version__,
formatter=MyFormatter())
parser.add_option('-q', '--quiet', action='store_true', dest='quiet',
default=False,
help='quiet mode')
group = parser.add_option_group('Structure options')
group.add_option('--sep', action='store_true', dest='sep',
help='if specified, separate source and build dirs')
group.add_option('--dot', metavar='DOT', dest='dot',
help='replacement for dot in _templates etc.')
group = parser.add_option_group('Project basic options')
group.add_option('-p', '--project', metavar='PROJECT', dest='project',
help='project name')
group.add_option('-a', '--author', metavar='AUTHOR', dest='author',
help='author names')
group.add_option('-v', metavar='VERSION', dest='version',
help='version of project')
group.add_option('-r', '--release', metavar='RELEASE', dest='release',
help='release of project')
group.add_option('-l', '--language', metavar='LANGUAGE', dest='language',
help='document language')
group.add_option('--suffix', metavar='SUFFIX', dest='suffix',
help='source file suffix')
group.add_option('--master', metavar='MASTER', dest='master',
help='master document name')
group.add_option('--epub', action='store_true', dest='epub',
default=False,
help='use epub')
group = parser.add_option_group('Extension options')
for ext in EXTENSIONS:
group.add_option('--ext-' + ext, action='store_true',
dest='ext_' + ext, default=False,
help='enable %s extension' % ext)
group.add_option('--extensions', metavar='EXTENSIONS', dest='extensions',
action='append', help='enable extensions')
group = parser.add_option_group('Makefile and Batchfile creation')
group.add_option('--makefile', action='store_true', dest='makefile',
default=False,
help='create makefile')
group.add_option('--no-makefile', action='store_true', dest='no_makefile',
default=False,
help='not create makefile')
group.add_option('--batchfile', action='store_true', dest='batchfile',
default=False,
help='create batchfile')
group.add_option('--no-batchfile', action='store_true', dest='no_batchfile',
default=False,
help='not create batchfile')
group.add_option('-M', '--no-use-make-mode', action='store_false', dest='make_mode',
help='not use make-mode for Makefile/make.bat')
group.add_option('-m', '--use-make-mode', action='store_true', dest='make_mode',
default=True,
help='use make-mode for Makefile/make.bat')
group = parser.add_option_group('Project templating')
group.add_option('-t', '--templatedir', metavar='TEMPLATEDIR', dest='templatedir',
help='template directory for template files')
group.add_option('-d', metavar='NAME=VALUE', action='append', dest='variables',
help='define a template variable')
# parse options
parser = get_parser()
try:
opts, args = parser.parse_args(argv)
args = parser.parse_args(argv)
except SystemExit as err:
return err.code
if len(args) > 0:
opts.ensure_value('path', args[0])
d = vars(opts)
d = vars(args)
# delete None or False value
d = dict((k, v) for k, v in d.items() if not (v is None or v is False))
@@ -707,7 +691,7 @@ def main(argv=sys.argv[1:]):
except ValueError:
print('Invalid template variable: %s' % variable)
generate(d, templatedir=opts.templatedir)
generate(d, templatedir=args.templatedir)
return 0

View File

@@ -10,14 +10,13 @@
"""
from __future__ import print_function
import argparse
import sys
import optparse
import traceback
from os import path
from six import text_type, binary_type
from docutils.utils import SystemMessage
from six import text_type, binary_type
from sphinx import __display_version__
from sphinx.errors import SphinxError
@@ -33,39 +32,9 @@ if False:
from typing import Any, IO, List, Union # NOQA
USAGE = """\
Sphinx v%s
Usage: %%prog [options] sourcedir outdir [filenames...]
Filename arguments:
without -a and without filenames, write new and changed files.
with -a, write all files.
with filenames, write these.
""" % __display_version__
EPILOG = """\
For more information, visit <http://sphinx-doc.org/>.
"""
class MyFormatter(optparse.IndentedHelpFormatter):
def format_usage(self, usage):
# type: (Any) -> Any
return usage
def format_help(self, formatter):
# type: (Any) -> unicode
result = [] # type: List[unicode]
if self.description: # type: ignore
result.append(self.format_description(formatter))
if self.option_list: # type: ignore
result.append(self.format_option_help(formatter)) # type: ignore
return "\n".join(result)
def handle_exception(app, opts, exception, stderr=sys.stderr):
def handle_exception(app, args, exception, stderr=sys.stderr):
# type: (Sphinx, Any, Union[Exception, KeyboardInterrupt], IO) -> None
if opts.pdb:
if args.pdb:
import pdb
print(red('Exception occurred while building, starting debugger:'),
file=stderr)
@@ -73,7 +42,7 @@ def handle_exception(app, opts, exception, stderr=sys.stderr):
pdb.post_mortem(sys.exc_info()[2])
else:
print(file=stderr)
if opts.verbosity or opts.traceback:
if args.verbosity or args.traceback:
traceback.print_exc(None, stderr)
print(file=stderr)
if isinstance(exception, KeyboardInterrupt):
@@ -114,104 +83,130 @@ def handle_exception(app, opts, exception, stderr=sys.stderr):
file=stderr)
def get_parser():
# type: () -> argparse.ArgumentParser
parser = argparse.ArgumentParser(
usage='usage: %(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]',
epilog='For more information, visit <http://sphinx-doc.org/>.',
description="""
Generate documentation from source files.
sphinx-build generates documentation from the files in SOURCEDIR and places it
in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration
settings. The 'sphinx-quickstart' tool may be used to generate template files,
including 'conf.py'
sphinx-build can create documentation in different formats. A format is
selected by specifying the builder name on the command line; it defaults to
HTML. Builders can also perform other tasks related to documentation
processing.
By default, everything that is outdated is built. Output only for selected
files can be built by specifying individual filenames.
""")
parser.add_argument('--version', action='version', dest='show_version',
version='%%(prog)s %s' % __display_version__)
parser.add_argument('sourcedir',
help='path to documentation source files')
parser.add_argument('outputdir',
help='path to output directory')
parser.add_argument('filenames', nargs='*',
help='a list of specific files to rebuild. Ignored '
'if -a is specified')
group = parser.add_argument_group('general options')
group.add_argument('-b', metavar='BUILDER', dest='builder',
default='html',
help='builder to use (default: html)')
group.add_argument('-a', action='store_true', dest='force_all',
help='write all files (default: only write new and '
'changed files)')
group.add_argument('-E', action='store_true', dest='freshenv',
help='don\'t use a saved environment, always read '
'all files')
group.add_argument('-d', metavar='PATH', dest='doctreedir',
help='path for the cached environment and doctree '
'files (default: OUTPUTDIR/.doctrees)')
group.add_argument('-j', metavar='N', default=1, type=int, dest='jobs',
help='build in parallel with N processes where '
'possible')
group = parser.add_argument_group('build configuration options')
group.add_argument('-c', metavar='PATH', dest='confdir',
help='path where configuration file (conf.py) is '
'located (default: same as SOURCEDIR)')
group.add_argument('-C', action='store_true', dest='noconfig',
help='use no config file at all, only -D options')
group.add_argument('-D', metavar='setting=value', action='append',
dest='define', default=[],
help='override a setting in configuration file')
group.add_argument('-A', metavar='name=value', action='append',
dest='htmldefine', default=[],
help='pass a value into HTML templates')
group.add_argument('-t', metavar='TAG', action='append',
dest='tags', default=[],
help='define tag: include "only" blocks with TAG')
group.add_argument('-n', action='store_true', dest='nitpicky',
help='nit-picky mode, warn about all missing '
'references')
group = parser.add_argument_group('console output options')
group.add_argument('-v', action='count', dest='verbosity', default=0,
help='increase verbosity (can be repeated)')
group.add_argument('-q', action='store_true', dest='quiet',
help='no output on stdout, just warnings on stderr')
group.add_argument('-Q', action='store_true', dest='really_quiet',
help='no output at all, not even warnings')
group.add_argument('--color', action='store_const', const='yes',
default='auto',
help='do emit colored output (default: auto-detect)')
group.add_argument('-N', '--no-color', dest='color', action='store_const',
const='no',
help='do not emit colored output (default: '
'auto-detect)')
group.add_argument('-w', metavar='FILE', dest='warnfile',
help='write warnings (and errors) to given file')
group.add_argument('-W', action='store_true', dest='warningiserror',
help='turn warnings into errors')
group.add_argument('-T', action='store_true', dest='traceback',
help='show full traceback on exception')
group.add_argument('-P', action='store_true', dest='pdb',
help='run Pdb on exception')
return parser
def main(argv=sys.argv[1:]): # type: ignore
# type: (List[unicode]) -> int
parser = optparse.OptionParser(USAGE, epilog=EPILOG, formatter=MyFormatter())
parser.add_option('--version', action='store_true', dest='version',
help='show version information and exit')
group = parser.add_option_group('General options')
group.add_option('-b', metavar='BUILDER', dest='builder', default='html',
help='builder to use; default is html')
group.add_option('-a', action='store_true', dest='force_all',
help='write all files; default is to only write new and '
'changed files')
group.add_option('-E', action='store_true', dest='freshenv',
help='don\'t use a saved environment, always read '
'all files')
group.add_option('-d', metavar='PATH', default=None, dest='doctreedir',
help='path for the cached environment and doctree files '
'(default: outdir/.doctrees)')
group.add_option('-j', metavar='N', default=1, type='int', dest='jobs',
help='build in parallel with N processes where possible')
# this option never gets through to this point (it is intercepted earlier)
# group.add_option('-M', metavar='BUILDER', dest='make_mode',
# help='"make" mode -- as used by Makefile, like '
# '"sphinx-build -M html"')
group = parser.add_option_group('Build configuration options')
group.add_option('-c', metavar='PATH', dest='confdir',
help='path where configuration file (conf.py) is located '
'(default: same as sourcedir)')
group.add_option('-C', action='store_true', dest='noconfig',
help='use no config file at all, only -D options')
group.add_option('-D', metavar='setting=value', action='append',
dest='define', default=[],
help='override a setting in configuration file')
group.add_option('-A', metavar='name=value', action='append',
dest='htmldefine', default=[],
help='pass a value into HTML templates')
group.add_option('-t', metavar='TAG', action='append',
dest='tags', default=[],
help='define tag: include "only" blocks with TAG')
group.add_option('-n', action='store_true', dest='nitpicky',
help='nit-picky mode, warn about all missing references')
group = parser.add_option_group('Console output options')
group.add_option('-v', action='count', dest='verbosity', default=0,
help='increase verbosity (can be repeated)')
group.add_option('-q', action='store_true', dest='quiet',
help='no output on stdout, just warnings on stderr')
group.add_option('-Q', action='store_true', dest='really_quiet',
help='no output at all, not even warnings')
group.add_option('--color', dest='color',
action='store_const', const='yes', default='auto',
help='Do emit colored output (default: auto-detect)')
group.add_option('-N', '--no-color', dest='color',
action='store_const', const='no',
help='Do not emit colored output (default: auto-detect)')
group.add_option('-w', metavar='FILE', dest='warnfile',
help='write warnings (and errors) to given file')
group.add_option('-W', action='store_true', dest='warningiserror',
help='turn warnings into errors')
group.add_option('-T', action='store_true', dest='traceback',
help='show full traceback on exception')
group.add_option('-P', action='store_true', dest='pdb',
help='run Pdb on exception')
parser = get_parser()
# parse options
try:
opts, args = parser.parse_args(argv)
args = parser.parse_args(argv)
except SystemExit as err:
return err.code
# handle basic options
if opts.version:
print('Sphinx (sphinx-build) %s' % __display_version__)
return 0
# get paths (first and second positional argument)
try:
srcdir = abspath(args[0])
confdir = abspath(opts.confdir or srcdir)
if opts.noconfig:
srcdir = abspath(args.sourcedir)
confdir = abspath(args.confdir or srcdir)
if args.noconfig:
confdir = None
if not path.isdir(srcdir):
print('Error: Cannot find source directory `%s\'.' % srcdir,
file=sys.stderr)
return 1
if not opts.noconfig and not path.isfile(path.join(confdir, 'conf.py')):
if not args.noconfig and not path.isfile(path.join(confdir, 'conf.py')):
print('Error: Config directory doesn\'t contain a conf.py file.',
file=sys.stderr)
return 1
outdir = abspath(args[1])
outdir = abspath(args.outputdir)
if srcdir == outdir:
print('Error: source directory and destination directory are same.',
file=sys.stderr)
return 1
except IndexError:
parser.print_help()
return 1
except UnicodeError:
print(
'Error: Multibyte filename not supported on this filesystem '
@@ -219,7 +214,7 @@ def main(argv=sys.argv[1:]): # type: ignore
return 1
# handle remaining filename arguments
filenames = args[2:]
filenames = args.filenames
errored = False
for filename in filenames:
if not path.isfile(filename):
@@ -235,35 +230,35 @@ def main(argv=sys.argv[1:]): # type: ignore
except Exception:
likely_encoding = None
if opts.force_all and filenames:
if args.force_all and filenames:
print('Error: Cannot combine -a option and filenames.', file=sys.stderr)
return 1
if opts.color == 'no' or (opts.color == 'auto' and not color_terminal()):
if args.color == 'no' or (args.color == 'auto' and not color_terminal()):
nocolor()
doctreedir = abspath(opts.doctreedir or path.join(outdir, '.doctrees'))
doctreedir = abspath(args.doctreedir or path.join(outdir, '.doctrees'))
status = sys.stdout
warning = sys.stderr
error = sys.stderr
if opts.quiet:
if args.quiet:
status = None
if opts.really_quiet:
if args.really_quiet:
status = warning = None
if warning and opts.warnfile:
if warning and args.warnfile:
try:
warnfp = open(opts.warnfile, 'w')
warnfp = open(args.warnfile, 'w')
except Exception as exc:
print('Error: Cannot open warning file %r: %s' %
(opts.warnfile, exc), file=sys.stderr)
(args.warnfile, exc), file=sys.stderr)
sys.exit(1)
warning = Tee(warning, warnfp) # type: ignore
error = warning
confoverrides = {}
for val in opts.define:
for val in args.define:
try:
key, val = val.split('=', 1)
except ValueError:
@@ -277,7 +272,7 @@ def main(argv=sys.argv[1:]): # type: ignore
pass
confoverrides[key] = val
for val in opts.htmldefine:
for val in args.htmldefine:
try:
key, val = val.split('=')
except ValueError:
@@ -294,17 +289,17 @@ def main(argv=sys.argv[1:]): # type: ignore
pass
confoverrides['html_context.%s' % key] = val
if opts.nitpicky:
if args.nitpicky:
confoverrides['nitpicky'] = True
app = None
try:
with patch_docutils(), docutils_namespace():
app = Sphinx(srcdir, confdir, outdir, doctreedir, opts.builder,
confoverrides, status, warning, opts.freshenv,
opts.warningiserror, opts.tags, opts.verbosity, opts.jobs)
app.build(opts.force_all, filenames)
app = Sphinx(srcdir, confdir, outdir, doctreedir, args.builder,
confoverrides, status, warning, args.freshenv,
args.warningiserror, args.tags, args.verbosity, args.jobs)
app.build(args.force_all, filenames)
return app.statuscode
except (Exception, KeyboardInterrupt) as exc:
handle_exception(app, opts, exc, error)
handle_exception(app, args, exc, error)
return 1

View File

@@ -17,9 +17,9 @@
from __future__ import print_function
import argparse
import os
import sys
import optparse
from os import path
from six import binary_type
from fnmatch import fnmatch
@@ -265,12 +265,6 @@ def recurse_tree(rootpath, excludes, opts):
return toplevels
def normalize_excludes(rootpath, excludes):
# type: (unicode, List[unicode]) -> List[unicode]
"""Normalize the excluded directory list."""
return [path.abspath(exclude) for exclude in excludes]
def is_excluded(root, excludes):
# type: (unicode, List[unicode]) -> bool
"""Check if the directory is in the exclude list.
@@ -284,106 +278,116 @@ def is_excluded(root, excludes):
return False
def main(argv=sys.argv[1:]):
# type: (List[str]) -> int
"""Parse and check the command line arguments."""
parser = optparse.OptionParser(
usage="""\
usage: %prog [options] -o <output_path> <module_path> [exclude_pattern, ...]
def get_parser():
# type: () -> argparse.ArgumentParser
parser = argparse.ArgumentParser(
usage='usage: %(prog)s [OPTIONS] -o <OUTPUT_PATH> <MODULE_PATH> '
'[EXCLUDE_PATTERN, ...]',
epilog='For more information, visit <http://sphinx-doc.org/>.',
description="""
Look recursively in <MODULE_PATH> for Python modules and packages and create
one reST file with automodule directives per package in the <OUTPUT_PATH>.
Look recursively in <module_path> for Python modules and packages and create
one reST file with automodule directives per package in the <output_path>.
The <exclude_pattern>s can be file and/or directory patterns that will be
The <EXCLUDE_PATTERN>s can be file and/or directory patterns that will be
excluded from generation.
Note: By default this script will not overwrite already created files.""")
parser.add_option('-o', '--output-dir', action='store', dest='destdir',
help='Directory to place all output', default='')
parser.add_option('-d', '--maxdepth', action='store', dest='maxdepth',
help='Maximum depth of submodules to show in the TOC '
'(default: 4)', type='int', default=4)
parser.add_option('-f', '--force', action='store_true', dest='force',
help='Overwrite existing files')
parser.add_option('-l', '--follow-links', action='store_true',
dest='followlinks', default=False,
help='Follow symbolic links. Powerful when combined '
'with collective.recipe.omelette.')
parser.add_option('-n', '--dry-run', action='store_true', dest='dryrun',
help='Run the script without creating files')
parser.add_option('-e', '--separate', action='store_true',
dest='separatemodules',
help='Put documentation for each module on its own page')
parser.add_option('-P', '--private', action='store_true',
dest='includeprivate',
help='Include "_private" modules')
parser.add_option('-T', '--no-toc', action='store_true', dest='notoc',
help='Don\'t create a table of contents file')
parser.add_option('-E', '--no-headings', action='store_true',
dest='noheadings',
help='Don\'t create headings for the module/package '
'packages (e.g. when the docstrings already contain '
'them)')
parser.add_option('-M', '--module-first', action='store_true',
dest='modulefirst',
help='Put module documentation before submodule '
'documentation')
parser.add_option('--implicit-namespaces', action='store_true',
dest='implicit_namespaces',
help='Interpret module paths according to PEP-0420 '
'implicit namespaces specification')
parser.add_option('-s', '--suffix', action='store', dest='suffix',
help='file suffix (default: rst)', default='rst')
parser.add_option('-F', '--full', action='store_true', dest='full',
help='Generate a full project with sphinx-quickstart')
parser.add_option('-a', '--append-syspath', action='store_true',
dest='append_syspath',
help='Append module_path to sys.path, used when --full is given')
parser.add_option('-H', '--doc-project', action='store', dest='header',
help='Project name (default: root module name)')
parser.add_option('-A', '--doc-author', action='store', dest='author',
type='str',
help='Project author(s), used when --full is given')
parser.add_option('-V', '--doc-version', action='store', dest='version',
help='Project version, used when --full is given')
parser.add_option('-R', '--doc-release', action='store', dest='release',
help='Project release, used when --full is given, '
'defaults to --doc-version')
parser.add_option('--version', action='store_true', dest='show_version',
help='Show version information and exit')
group = parser.add_option_group('Extension options')
parser.add_argument('--version', action='version', dest='show_version',
version='%%(prog)s %s' % __display_version__)
parser.add_argument('module_path',
help='path to module to document')
parser.add_argument('exclude_pattern', nargs='*',
help='fnmatch-style file and/or directory patterns '
'to exclude from generation')
parser.add_argument('-o', '--output-dir', action='store', dest='destdir',
required=True,
help='directory to place all output')
parser.add_argument('-d', '--maxdepth', action='store', dest='maxdepth',
type=int, default=4,
help='maximum depth of submodules to show in the TOC '
'(default: 4)')
parser.add_argument('-f', '--force', action='store_true', dest='force',
help='overwrite existing files')
parser.add_argument('-l', '--follow-links', action='store_true',
dest='followlinks', default=False,
help='follow symbolic links. Powerful when combined '
'with collective.recipe.omelette.')
parser.add_argument('-n', '--dry-run', action='store_true', dest='dryrun',
help='run the script without creating files')
parser.add_argument('-e', '--separate', action='store_true',
dest='separatemodules',
help='put documentation for each module on its own page')
parser.add_argument('-P', '--private', action='store_true',
dest='includeprivate',
help='include "_private" modules')
parser.add_argument('-T', '--no-toc', action='store_true', dest='notoc',
help="don't create a table of contents file")
parser.add_argument('-E', '--no-headings', action='store_true',
dest='noheadings',
help="don't create headings for the module/package "
"packages (e.g. when the docstrings already "
"contain them)")
parser.add_argument('-M', '--module-first', action='store_true',
dest='modulefirst',
help='put module documentation before submodule '
'documentation')
parser.add_argument('--implicit-namespaces', action='store_true',
dest='implicit_namespaces',
help='interpret module paths according to PEP-0420 '
'implicit namespaces specification')
parser.add_argument('-s', '--suffix', action='store', dest='suffix',
default='rst',
help='file suffix (default: rst)')
parser.add_argument('-F', '--full', action='store_true', dest='full',
help='generate a full project with sphinx-quickstart')
parser.add_argument('-a', '--append-syspath', action='store_true',
dest='append_syspath',
help='append module_path to sys.path, used when --full is given')
parser.add_argument('-H', '--doc-project', action='store', dest='header',
help='project name (default: root module name)')
parser.add_argument('-A', '--doc-author', action='store', dest='author',
help='project author(s), used when --full is given')
parser.add_argument('-V', '--doc-version', action='store', dest='version',
help='project version, used when --full is given')
parser.add_argument('-R', '--doc-release', action='store', dest='release',
help='project release, used when --full is given, '
'defaults to --doc-version')
group = parser.add_argument_group('extension options')
for ext in EXTENSIONS:
group.add_option('--ext-' + ext, action='store_true',
dest='ext_' + ext, default=False,
help='enable %s extension' % ext)
group.add_argument('--ext-' + ext, action='store_true',
dest='ext_' + ext, default=False,
help='enable %s extension' % ext)
(opts, args) = parser.parse_args(argv)
return parser
if opts.show_version:
print('Sphinx (sphinx-apidoc) %s' % __display_version__)
return 0
if not args:
parser.error('A package path is required.')
def main(argv=sys.argv[1:]):
# type: (List[str]) -> int
"""Parse and check the command line arguments."""
parser = get_parser()
args = parser.parse_args(argv)
rootpath, excludes = args[0], args[1:]
if not opts.destdir:
parser.error('An output directory is required.')
if opts.header is None:
opts.header = path.abspath(rootpath).split(path.sep)[-1]
if opts.suffix.startswith('.'):
opts.suffix = opts.suffix[1:]
rootpath = path.abspath(args.module_path)
# normalize opts
if args.header is None:
args.header = rootpath.split(path.sep)[-1]
if args.suffix.startswith('.'):
args.suffix = args.suffix[1:]
if not path.isdir(rootpath):
print('%s is not a directory.' % rootpath, file=sys.stderr)
sys.exit(1)
if not path.isdir(opts.destdir):
if not opts.dryrun:
os.makedirs(opts.destdir)
rootpath = path.abspath(rootpath)
excludes = normalize_excludes(rootpath, excludes)
modules = recurse_tree(rootpath, excludes, opts)
if opts.full:
if not path.isdir(args.destdir) and not args.dryrun:
os.makedirs(args.destdir)
excludes = [path.abspath(exclude) for exclude in args.exclude_pattern]
modules = recurse_tree(rootpath, excludes, args)
if args.full:
from sphinx.cmd import quickstart as qs
modules.sort()
prev_module = '' # type: unicode
@@ -394,14 +398,14 @@ Note: By default this script will not overwrite already created files.""")
prev_module = module
text += ' %s\n' % module
d = dict(
path = opts.destdir,
path = args.destdir,
sep = False,
dot = '_',
project = opts.header,
author = opts.author or 'Author',
version = opts.version or '',
release = opts.release or opts.version or '',
suffix = '.' + opts.suffix,
project = args.header,
author = args.author or 'Author',
version = args.version or '',
release = args.release or args.version or '',
suffix = '.' + args.suffix,
master = 'index',
epub = True,
ext_autodoc = True,
@@ -409,29 +413,30 @@ Note: By default this script will not overwrite already created files.""")
ext_todo = True,
makefile = True,
batchfile = True,
mastertocmaxdepth = opts.maxdepth,
mastertocmaxdepth = args.maxdepth,
mastertoctree = text,
language = 'en',
module_path = rootpath,
append_syspath = opts.append_syspath,
append_syspath = args.append_syspath,
)
enabled_exts = {'ext_' + ext: getattr(opts, 'ext_' + ext)
for ext in EXTENSIONS if getattr(opts, 'ext_' + ext)}
enabled_exts = {'ext_' + ext: getattr(args, 'ext_' + ext)
for ext in EXTENSIONS if getattr(args, 'ext_' + ext)}
d.update(enabled_exts)
if isinstance(opts.header, binary_type):
if isinstance(args.header, binary_type):
d['project'] = d['project'].decode('utf-8')
if isinstance(opts.author, binary_type):
if isinstance(args.author, binary_type):
d['author'] = d['author'].decode('utf-8')
if isinstance(opts.version, binary_type):
if isinstance(args.version, binary_type):
d['version'] = d['version'].decode('utf-8')
if isinstance(opts.release, binary_type):
if isinstance(args.release, binary_type):
d['release'] = d['release'].decode('utf-8')
if not opts.dryrun:
qs.generate(d, silent=True, overwrite=opts.force)
elif not opts.notoc:
create_modules_toc_file(modules, opts)
if not args.dryrun:
qs.generate(d, silent=True, overwrite=args.force)
elif not args.notoc:
create_modules_toc_file(modules, args)
return 0

View File

@@ -19,16 +19,17 @@
"""
from __future__ import print_function
import argparse
import codecs
import os
import pydoc
import re
import sys
import pydoc
import optparse
import codecs
from jinja2 import FileSystemLoader, TemplateNotFound
from jinja2.sandbox import SandboxedEnvironment
from sphinx import __display_version__
from sphinx import package_dir
from sphinx.ext.autosummary import import_by_name, get_documenter
from sphinx.jinja2glue import BuiltinTemplateLoader
@@ -59,33 +60,6 @@ if False:
from sphinx.environment import BuildEnvironment # NOQA
def main(argv=sys.argv[1:]):
# type: (List[str]) -> None
usage = """%prog [OPTIONS] SOURCEFILE ..."""
p = optparse.OptionParser(usage.strip())
p.add_option("-o", "--output-dir", action="store", type="string",
dest="output_dir", default=None,
help="Directory to place all output in")
p.add_option("-s", "--suffix", action="store", type="string",
dest="suffix", default="rst",
help="Default suffix for files (default: %default)")
p.add_option("-t", "--templates", action="store", type="string",
dest="templates", default=None,
help="Custom template directory (default: %default)")
p.add_option("-i", "--imported-members", action="store_true",
dest="imported_members", default=False,
help="Document imported members (default: %default)")
options, args = p.parse_args(argv)
if len(args) < 1:
p.error('no input files given')
generate_autosummary_docs(args, options.output_dir,
"." + options.suffix,
template_dir=options.templates,
imported_members=options.imported_members)
def _simple_info(msg):
# type: (unicode) -> None
print(msg)
@@ -373,5 +347,57 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
return documented
def get_parser():
# type: () -> argparse.ArgumentParser
parser = argparse.ArgumentParser(
usage='%(prog)s [OPTIONS] <SOURCE_FILE>...',
epilog='For more information, visit <http://sphinx-doc.org/>.',
description="""
Generate ReStructuredText using autosummary directives.
sphinx-autogen is a frontend to sphinx.ext.autosummary.generate. It generates
the reStructuredText files from the autosummary directives contained in the
given input files.
The format of the autosummary directive is documented in the
``sphinx.ext.autosummary`` Python module and can be read using::
pydoc sphinx.ext.autosummary
""")
parser.add_argument('--version', action='version', dest='show_version',
version='%%(prog)s %s' % __display_version__)
parser.add_argument('source_file', nargs='+',
help='source files to generate rST files for')
parser.add_argument('-o', '--output-dir', action='store',
dest='output_dir',
help='directory to place all output in')
parser.add_argument('-s', '--suffix', action='store', dest='suffix',
default='rst',
help='default suffix for files (default: '
'%(default)s)')
parser.add_argument('-t', '--templates', action='store', dest='templates',
default=None,
help='custom template directory (default: '
'%(default)s)')
parser.add_argument('-i', '--imported-members', action='store_true',
dest='imported_members', default=False,
help='document imported members (default: '
'%(default)s)')
return parser
def main(argv=sys.argv[1:]):
# type: (List[str]) -> None
args = get_parser().parse_args(argv)
generate_autosummary_docs(args.source_file, args.output_dir,
'.' + args.suffix,
template_dir=args.templates,
imported_members=args.imported_members)
if __name__ == '__main__':
main()

View File

@@ -152,10 +152,10 @@ def test_trailing_underscore(make_app, apidoc):
@pytest.mark.apidoc(
coderoot='test-root',
options=[
'--doc-project', u'プロジェクト名'.encode('utf-8'),
'--doc-author', u'著者名'.encode('utf-8'),
'--doc-version', u'バージョン'.encode('utf-8'),
'--doc-release', u'リリース'.encode('utf-8'),
'--doc-project', u'プロジェクト名',
'--doc-author', u'著者名',
'--doc-version', u'バージョン',
'--doc-release', u'リリース',
],
)
def test_multibyte_parameters(make_app, apidoc):