Merge pull request #6535 from tk0miya/refactor_type_annotation_cmd

Migrate to py3 style type annotation: sphinx.cmd
This commit is contained in:
Takeshi KOMIYA 2019-06-30 15:17:19 +09:00 committed by GitHub
commit 05949f8347
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 85 deletions

View File

@ -14,6 +14,7 @@ import multiprocessing
import os import os
import sys import sys
import traceback import traceback
from typing import Any, IO, List
from docutils.utils import SystemMessage from docutils.utils import SystemMessage
@ -26,13 +27,8 @@ from sphinx.util import Tee, format_exception_cut_frames, save_traceback
from sphinx.util.console import red, nocolor, color_terminal, terminal_safe # type: ignore from sphinx.util.console import red, nocolor, color_terminal, terminal_safe # type: ignore
from sphinx.util.docutils import docutils_namespace, patch_docutils from sphinx.util.docutils import docutils_namespace, patch_docutils
if False:
# For type annotation
from typing import Any, IO, List, Union # NOQA
def handle_exception(app: Sphinx, args: Any, exception: BaseException, stderr: IO = sys.stderr) -> None: # NOQA
def handle_exception(app, args, exception, stderr=sys.stderr):
# type: (Sphinx, Any, Union[Exception, KeyboardInterrupt], IO) -> None
if args.pdb: if args.pdb:
import pdb import pdb
print(red(__('Exception occurred while building, starting debugger:')), print(red(__('Exception occurred while building, starting debugger:')),
@ -82,8 +78,7 @@ def handle_exception(app, args, exception, stderr=sys.stderr):
file=stderr) file=stderr)
def jobs_argument(value): def jobs_argument(value: str) -> int:
# type: (str) -> int
""" """
Special type to handle 'auto' flags passed to 'sphinx-build' via -j flag. Can Special type to handle 'auto' flags passed to 'sphinx-build' via -j flag. Can
be expanded to handle other special scaling requests, such as setting job count be expanded to handle other special scaling requests, such as setting job count
@ -99,8 +94,7 @@ def jobs_argument(value):
return jobs return jobs
def get_parser(): def get_parser() -> argparse.ArgumentParser:
# type: () -> argparse.ArgumentParser
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
usage='%(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]', usage='%(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]',
epilog=__('For more information, visit <http://sphinx-doc.org/>.'), epilog=__('For more information, visit <http://sphinx-doc.org/>.'),
@ -195,15 +189,13 @@ files can be built by specifying individual filenames.
return parser return parser
def make_main(argv=sys.argv[1:]): def make_main(argv: List[str] = sys.argv[1:]) -> int:
# type: (List[str]) -> int
"""Sphinx build "make mode" entry.""" """Sphinx build "make mode" entry."""
from sphinx.cmd import make_mode from sphinx.cmd import make_mode
return make_mode.run_make_mode(argv[1:]) return make_mode.run_make_mode(argv[1:])
def build_main(argv=sys.argv[1:]): def build_main(argv: List[str] = sys.argv[1:]) -> int:
# type: (List[str]) -> int
"""Sphinx build "main" command-line entry.""" """Sphinx build "main" command-line entry."""
parser = get_parser() parser = get_parser()
@ -288,8 +280,7 @@ def build_main(argv=sys.argv[1:]):
return 2 return 2
def main(argv=sys.argv[1:]): def main(argv: List[str] = sys.argv[1:]) -> int:
# type: (List[str]) -> int
sphinx.locale.setlocale(locale.LC_ALL, '') sphinx.locale.setlocale(locale.LC_ALL, '')
sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx') sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx')

View File

@ -18,16 +18,13 @@ import os
import subprocess import subprocess
import sys import sys
from os import path from os import path
from typing import List
import sphinx import sphinx
from sphinx.cmd.build import build_main from sphinx.cmd.build import build_main
from sphinx.util.console import color_terminal, nocolor, bold, blue # type: ignore from sphinx.util.console import color_terminal, nocolor, bold, blue # type: ignore
from sphinx.util.osutil import cd, rmtree from sphinx.util.osutil import cd, rmtree
if False:
# For type annotation
from typing import List # NOQA
BUILDERS = [ BUILDERS = [
("", "html", "to make standalone HTML files"), ("", "html", "to make standalone HTML files"),
@ -58,20 +55,16 @@ BUILDERS = [
class Make: class Make:
def __init__(self, srcdir: str, builddir: str, opts: List[str]) -> None:
def __init__(self, srcdir, builddir, opts):
# type: (str, str, List[str]) -> None
self.srcdir = srcdir self.srcdir = srcdir
self.builddir = builddir self.builddir = builddir
self.opts = opts self.opts = opts
self.makecmd = os.environ.get('MAKE', 'make') # refer $MAKE to determine make command self.makecmd = os.environ.get('MAKE', 'make') # refer $MAKE to determine make command
def builddir_join(self, *comps): def builddir_join(self, *comps: str) -> str:
# type: (str) -> str
return path.join(self.builddir, *comps) return path.join(self.builddir, *comps)
def build_clean(self): def build_clean(self) -> int:
# type: () -> int
srcdir = path.abspath(self.srcdir) srcdir = path.abspath(self.srcdir)
builddir = path.abspath(self.builddir) builddir = path.abspath(self.builddir)
if not path.exists(self.builddir): if not path.exists(self.builddir):
@ -90,8 +83,7 @@ class Make:
rmtree(self.builddir_join(item)) rmtree(self.builddir_join(item))
return 0 return 0
def build_help(self): def build_help(self) -> None:
# type: () -> None
if not color_terminal(): if not color_terminal():
nocolor() nocolor()
@ -101,8 +93,7 @@ class Make:
if not osname or os.name == osname: if not osname or os.name == osname:
print(' %s %s' % (blue(bname.ljust(10)), description)) print(' %s %s' % (blue(bname.ljust(10)), description))
def build_latexpdf(self): def build_latexpdf(self) -> int:
# type: () -> int
if self.run_generic_build('latex') > 0: if self.run_generic_build('latex') > 0:
return 1 return 1
@ -117,8 +108,7 @@ class Make:
print('Error: Failed to run: %s' % makecmd) print('Error: Failed to run: %s' % makecmd)
return 1 return 1
def build_latexpdfja(self): def build_latexpdfja(self) -> int:
# type: () -> int
if self.run_generic_build('latex') > 0: if self.run_generic_build('latex') > 0:
return 1 return 1
@ -133,8 +123,7 @@ class Make:
print('Error: Failed to run: %s' % makecmd) print('Error: Failed to run: %s' % makecmd)
return 1 return 1
def build_info(self): def build_info(self) -> int:
# type: () -> int
if self.run_generic_build('texinfo') > 0: if self.run_generic_build('texinfo') > 0:
return 1 return 1
try: try:
@ -144,15 +133,13 @@ class Make:
print('Error: Failed to run: %s' % self.makecmd) print('Error: Failed to run: %s' % self.makecmd)
return 1 return 1
def build_gettext(self): def build_gettext(self) -> int:
# type: () -> int
dtdir = self.builddir_join('gettext', '.doctrees') dtdir = self.builddir_join('gettext', '.doctrees')
if self.run_generic_build('gettext', doctreedir=dtdir) > 0: if self.run_generic_build('gettext', doctreedir=dtdir) > 0:
return 1 return 1
return 0 return 0
def run_generic_build(self, builder, doctreedir=None): def run_generic_build(self, builder: str, doctreedir: str = None) -> int:
# type: (str, str) -> int
# compatibility with old Makefile # compatibility with old Makefile
papersize = os.getenv('PAPER', '') papersize = os.getenv('PAPER', '')
opts = self.opts opts = self.opts
@ -168,8 +155,7 @@ class Make:
return build_main(args + opts) return build_main(args + opts)
def run_make_mode(args): def run_make_mode(args: List[str]) -> int:
# type: (List[str]) -> int
if len(args) < 3: if len(args) < 3:
print('Error: at least 3 arguments (builder, source ' print('Error: at least 3 arguments (builder, source '
'dir, build dir) are required.', file=sys.stderr) 'dir, build dir) are required.', file=sys.stderr)

View File

@ -17,6 +17,7 @@ import time
import warnings import warnings
from collections import OrderedDict from collections import OrderedDict
from os import path from os import path
from typing import Any, Callable, Dict, List, Pattern, Union
# try to import readline, unix specific enhancement # try to import readline, unix specific enhancement
try: try:
@ -42,10 +43,6 @@ from sphinx.util.console import ( # type: ignore
from sphinx.util.osutil import ensuredir from sphinx.util.osutil import ensuredir
from sphinx.util.template import SphinxRenderer from sphinx.util.template import SphinxRenderer
if False:
# For type annotation
from typing import Any, Callable, Dict, List, Pattern, Union # NOQA
TERM_ENCODING = getattr(sys.stdin, 'encoding', None) # RemovedInSphinx40Warning TERM_ENCODING = getattr(sys.stdin, 'encoding', None) # RemovedInSphinx40Warning
EXTENSIONS = OrderedDict([ EXTENSIONS = OrderedDict([
@ -84,8 +81,7 @@ else:
# function to get input from terminal -- overridden by the test suite # function to get input from terminal -- overridden by the test suite
def term_input(prompt): def term_input(prompt: str) -> str:
# type: (str) -> str
if sys.platform == 'win32': if sys.platform == 'win32':
# Important: On windows, readline is not enabled by default. In these # Important: On windows, readline is not enabled by default. In these
# environment, escape sequences have been broken. To avoid the # environment, escape sequences have been broken. To avoid the
@ -100,58 +96,49 @@ class ValidationError(Exception):
"""Raised for validation errors.""" """Raised for validation errors."""
def is_path(x): def is_path(x: str) -> str:
# type: (str) -> str
x = path.expanduser(x) x = path.expanduser(x)
if not path.isdir(x): if not path.isdir(x):
raise ValidationError(__("Please enter a valid path name.")) raise ValidationError(__("Please enter a valid path name."))
return x return x
def allow_empty(x): def allow_empty(x: str) -> str:
# type: (str) -> str
return x return x
def nonempty(x): def nonempty(x: str) -> str:
# type: (str) -> str
if not x: if not x:
raise ValidationError(__("Please enter some text.")) raise ValidationError(__("Please enter some text."))
return x return x
def choice(*l): def choice(*l: str) -> Callable[[str], str]:
# type: (str) -> Callable[[str], str] def val(x: str) -> str:
def val(x):
# type: (str) -> str
if x not in l: if x not in l:
raise ValidationError(__('Please enter one of %s.') % ', '.join(l)) raise ValidationError(__('Please enter one of %s.') % ', '.join(l))
return x return x
return val return val
def boolean(x): def boolean(x: str) -> bool:
# type: (str) -> bool
if x.upper() not in ('Y', 'YES', 'N', 'NO'): if x.upper() not in ('Y', 'YES', 'N', 'NO'):
raise ValidationError(__("Please enter either 'y' or 'n'.")) raise ValidationError(__("Please enter either 'y' or 'n'."))
return x.upper() in ('Y', 'YES') return x.upper() in ('Y', 'YES')
def suffix(x): def suffix(x: str) -> str:
# type: (str) -> str
if not (x[0:1] == '.' and len(x) > 1): if not (x[0:1] == '.' and len(x) > 1):
raise ValidationError(__("Please enter a file suffix, " raise ValidationError(__("Please enter a file suffix, "
"e.g. '.rst' or '.txt'.")) "e.g. '.rst' or '.txt'."))
return x return x
def ok(x): def ok(x: str) -> str:
# type: (str) -> str
return x return x
def term_decode(text): def term_decode(text: Union[bytes, str]) -> str:
# type: (Union[bytes,str]) -> str
warnings.warn('term_decode() is deprecated.', warnings.warn('term_decode() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2) RemovedInSphinx40Warning, stacklevel=2)
@ -175,8 +162,7 @@ def term_decode(text):
return text.decode('latin1') return text.decode('latin1')
def do_prompt(text, default=None, validator=nonempty): def do_prompt(text: str, default: str = None, validator: Callable[[str], Any] = nonempty) -> Union[str, bool]: # NOQA
# type: (str, str, Callable[[str], Any]) -> Union[str, bool]
while True: while True:
if default is not None: if default is not None:
prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default)
@ -201,8 +187,7 @@ def do_prompt(text, default=None, validator=nonempty):
return x return x
def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")): def convert_python_source(source: str, rex: Pattern = re.compile(r"[uU]('.*?')")) -> str:
# type: (str, Pattern) -> str
# remove Unicode literal prefixes # remove Unicode literal prefixes
warnings.warn('convert_python_source() is deprecated.', warnings.warn('convert_python_source() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning)
@ -210,13 +195,11 @@ def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
class QuickstartRenderer(SphinxRenderer): class QuickstartRenderer(SphinxRenderer):
def __init__(self, templatedir): def __init__(self, templatedir: str) -> None:
# type: (str) -> None
self.templatedir = templatedir or '' self.templatedir = templatedir or ''
super().__init__() super().__init__()
def render(self, template_name, context): def render(self, template_name: str, context: Dict) -> str:
# type: (str, Dict) -> str
user_template = path.join(self.templatedir, path.basename(template_name)) user_template = path.join(self.templatedir, path.basename(template_name))
if self.templatedir and path.exists(user_template): if self.templatedir and path.exists(user_template):
return self.render_from_file(user_template, context) return self.render_from_file(user_template, context)
@ -224,8 +207,7 @@ class QuickstartRenderer(SphinxRenderer):
return super().render(template_name, context) return super().render(template_name, context)
def ask_user(d): def ask_user(d: Dict) -> None:
# type: (Dict) -> None
"""Ask the user for quickstart values missing from *d*. """Ask the user for quickstart values missing from *d*.
Values are: Values are:
@ -367,8 +349,8 @@ directly.'''))
print() print()
def generate(d, overwrite=True, silent=False, templatedir=None): def generate(d: Dict, overwrite: bool = True, silent: bool = False, templatedir: str = None
# type: (Dict, bool, bool, str) -> None ) -> None:
"""Generate project based on values in *d*.""" """Generate project based on values in *d*."""
template = QuickstartRenderer(templatedir=templatedir) template = QuickstartRenderer(templatedir=templatedir)
@ -401,8 +383,7 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
ensuredir(path.join(srcdir, d['dot'] + 'templates')) ensuredir(path.join(srcdir, d['dot'] + 'templates'))
ensuredir(path.join(srcdir, d['dot'] + 'static')) ensuredir(path.join(srcdir, d['dot'] + 'static'))
def write_file(fpath, content, newline=None): def write_file(fpath: str, content: str, newline: str = None) -> None:
# type: (str, str, str) -> None
if overwrite or not path.isfile(fpath): if overwrite or not path.isfile(fpath):
if 'quiet' not in d: if 'quiet' not in d:
print(__('Creating file %s.') % fpath) print(__('Creating file %s.') % fpath)
@ -460,8 +441,7 @@ where "builder" is one of the supported builders, e.g. html, latex or linkcheck.
''')) '''))
def valid_dir(d): def valid_dir(d: Dict) -> bool:
# type: (Dict) -> bool
dir = d['path'] dir = d['path']
if not path.exists(dir): if not path.exists(dir):
return True return True
@ -490,8 +470,7 @@ def valid_dir(d):
return True return True
def get_parser(): def get_parser() -> argparse.ArgumentParser:
# type: () -> argparse.ArgumentParser
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
usage='%(prog)s [OPTIONS] <PROJECT_DIR>', usage='%(prog)s [OPTIONS] <PROJECT_DIR>',
epilog=__("For more information, visit <http://sphinx-doc.org/>."), epilog=__("For more information, visit <http://sphinx-doc.org/>."),
@ -572,8 +551,7 @@ Makefile to be used with sphinx-build.
return parser return parser
def main(argv=sys.argv[1:]): def main(argv: List[str] = sys.argv[1:]) -> int:
# type: (List[str]) -> int
sphinx.locale.setlocale(locale.LC_ALL, '') sphinx.locale.setlocale(locale.LC_ALL, '')
sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx') sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx')