summaryrefslogtreecommitdiff
path: root/sphinx/cmdline.py
diff options
context:
space:
mode:
authorStephen Finucane <stephen@that.guru>2017-09-28 20:00:57 +0100
committerStephen Finucane <stephen@that.guru>2017-10-09 16:28:39 +0100
commitb778cfe2999930d812c5e6f16142dc5d2311996d (patch)
tree6b1e11903963ced9daef03d7652883a736bb8af5 /sphinx/cmdline.py
parentc68381bd6597f50e085b96d7f69a982db8baabda (diff)
downloadsphinx-git-b778cfe2999930d812c5e6f16142dc5d2311996d.tar.gz
sphinx-build: Convert to argparse
Once again, not much different to the previous conversions. We make best use of the argparse module, allowing us to remove some funky workarounds. Signed-off-by: Stephen Finucane <stephen@that.guru>
Diffstat (limited to 'sphinx/cmdline.py')
-rw-r--r--sphinx/cmdline.py230
1 files changed, 101 insertions, 129 deletions
diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py
index 54e4dcb78..30bef6674 100644
--- a/sphinx/cmdline.py
+++ b/sphinx/cmdline.py
@@ -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):
@@ -116,102 +85,105 @@ def handle_exception(app, opts, exception, stderr=sys.stderr):
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 = argparse.ArgumentParser(
+ usage='usage: %(prog)s [OPTIONS] SOURCEDIR OUTDIR [FILENAMES...]',
+ epilog='For more information, visit <http://sphinx-doc.org/>.')
+
+ 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: outdir/.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')
# 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 +191,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 +207,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 +249,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 +266,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