diff options
Diffstat (limited to 'sphinx/cmd/quickstart.py')
-rw-r--r-- | sphinx/cmd/quickstart.py | 104 |
1 files changed, 40 insertions, 64 deletions
diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py index 5494423e4..d3e41aa54 100644 --- a/sphinx/cmd/quickstart.py +++ b/sphinx/cmd/quickstart.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ sphinx.cmd.quickstart ~~~~~~~~~~~~~~~~~~~~~ @@ -8,8 +7,6 @@ :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ -from __future__ import absolute_import -from __future__ import print_function import argparse import locale @@ -17,9 +14,10 @@ import os import re import sys import time +import warnings from collections import OrderedDict -from io import open from os import path +from urllib.parse import quote # try to import readline, unix specific enhancement try: @@ -34,12 +32,10 @@ except ImportError: USE_LIBEDIT = False from docutils.utils import column_width -from six import PY2, PY3, text_type, binary_type -from six.moves import input -from six.moves.urllib.parse import quote as urlquote import sphinx.locale from sphinx import __display_version__, package_dir +from sphinx.deprecation import RemovedInSphinx40Warning from sphinx.locale import __ from sphinx.util import texescape from sphinx.util.console import ( # type: ignore @@ -52,7 +48,7 @@ if False: # For type annotation from typing import Any, Callable, Dict, List, Pattern, Union # NOQA -TERM_ENCODING = getattr(sys.stdin, 'encoding', None) +TERM_ENCODING = getattr(sys.stdin, 'encoding', None) # RemovedInSphinx40Warning EXTENSIONS = OrderedDict([ ('autodoc', __('automatically insert docstrings from modules')), @@ -91,7 +87,7 @@ else: # function to get input from terminal -- overridden by the test suite def term_input(prompt): - # type: (unicode) -> unicode + # type: (str) -> str if sys.platform == 'win32': # Important: On windows, readline is not enabled by default. In these # environment, escape sequences have been broken. To avoid the @@ -107,29 +103,29 @@ class ValidationError(Exception): def is_path(x): - # type: (unicode) -> unicode + # type: (str) -> str x = path.expanduser(x) - if path.exists(x) and not path.isdir(x): + if not path.isdir(x): raise ValidationError(__("Please enter a valid path name.")) return x def allow_empty(x): - # type: (unicode) -> unicode + # type: (str) -> str return x def nonempty(x): - # type: (unicode) -> unicode + # type: (str) -> str if not x: raise ValidationError(__("Please enter some text.")) return x def choice(*l): - # type: (unicode) -> Callable[[unicode], unicode] + # type: (str) -> Callable[[str], str] def val(x): - # type: (unicode) -> unicode + # type: (str) -> str if x not in l: raise ValidationError(__('Please enter one of %s.') % ', '.join(l)) return x @@ -137,14 +133,14 @@ def choice(*l): def boolean(x): - # type: (unicode) -> bool + # type: (str) -> bool if x.upper() not in ('Y', 'YES', 'N', 'NO'): raise ValidationError(__("Please enter either 'y' or 'n'.")) return x.upper() in ('Y', 'YES') def suffix(x): - # type: (unicode) -> unicode + # type: (str) -> str if not (x[0:1] == '.' and len(x) > 1): raise ValidationError(__("Please enter a file suffix, " "e.g. '.rst' or '.txt'.")) @@ -152,13 +148,16 @@ def suffix(x): def ok(x): - # type: (unicode) -> unicode + # type: (str) -> str return x def term_decode(text): - # type: (Union[bytes,unicode]) -> unicode - if isinstance(text, text_type): + # type: (Union[bytes,str]) -> str + warnings.warn('term_decode() is deprecated.', + RemovedInSphinx40Warning, stacklevel=2) + + if isinstance(text, str): return text # Use the known encoding, if possible @@ -173,32 +172,18 @@ def term_decode(text): 'and terminal encoding unknown -- assuming ' 'UTF-8 or Latin-1.'))) try: - return text.decode('utf-8') + return text.decode() except UnicodeDecodeError: return text.decode('latin1') def do_prompt(text, default=None, validator=nonempty): - # type: (unicode, unicode, Callable[[unicode], Any]) -> Union[unicode, bool] + # type: (str, str, Callable[[str], Any]) -> Union[str, bool] while True: if default is not None: - prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) # type: unicode + prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) else: prompt = PROMPT_PREFIX + text + ': ' - if PY2: - # for Python 2.x, try to get a Unicode string out of it - if prompt.encode('ascii', 'replace').decode('ascii', 'replace') \ - != prompt: - if TERM_ENCODING: - prompt = prompt.encode(TERM_ENCODING) - else: - print(turquoise(__('* Note: non-ASCII default value provided ' - 'and terminal encoding unknown -- assuming ' - 'UTF-8 or Latin-1.'))) - try: - prompt = prompt.encode('utf-8') - except UnicodeEncodeError: - prompt = prompt.encode('latin1') if USE_LIBEDIT: # Note: libedit has a problem for combination of ``input()`` and escape # sequence (see #5335). To avoid the problem, all prompts are not colored @@ -209,7 +194,6 @@ def do_prompt(text, default=None, validator=nonempty): x = term_input(prompt).strip() if default and not x: x = default - x = term_decode(x) try: x = validator(x) except ValidationError as err: @@ -220,27 +204,26 @@ def do_prompt(text, default=None, validator=nonempty): def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")): - # type: (unicode, Pattern) -> unicode + # type: (str, Pattern) -> str # remove Unicode literal prefixes - if PY3: - return rex.sub('\\1', source) - else: - return source + warnings.warn('convert_python_source() is deprecated.', + RemovedInSphinx40Warning) + return rex.sub('\\1', source) class QuickstartRenderer(SphinxRenderer): def __init__(self, templatedir): - # type: (unicode) -> None + # type: (str) -> None self.templatedir = templatedir or '' - super(QuickstartRenderer, self).__init__() + super().__init__() def render(self, template_name, context): - # type: (unicode, Dict) -> unicode + # type: (str, Dict) -> str user_template = path.join(self.templatedir, path.basename(template_name)) if self.templatedir and path.exists(user_template): return self.render_from_file(user_template, context) else: - return super(QuickstartRenderer, self).render(template_name, context) + return super().render(template_name, context) def ask_user(d): @@ -388,7 +371,7 @@ directly.''')) def generate(d, overwrite=True, silent=False, templatedir=None): - # type: (Dict, bool, bool, unicode) -> None + # type: (Dict, bool, bool, str) -> None """Generate project based on values in *d*.""" template = QuickstartRenderer(templatedir=templatedir) @@ -399,18 +382,17 @@ def generate(d, overwrite=True, silent=False, templatedir=None): if 'mastertocmaxdepth' not in d: d['mastertocmaxdepth'] = 2 - d['PY3'] = PY3 + d['PY3'] = True d['project_fn'] = make_filename(d['project']) - d['project_url'] = urlquote(d['project'].encode('idna')) + d['project_url'] = quote(d['project'].encode('idna')) d['project_manpage'] = d['project_fn'].lower() d['now'] = time.asctime() d['project_underline'] = column_width(d['project']) * '=' d.setdefault('extensions', []) d['copyright'] = time.strftime('%Y') + ', ' + d['author'] - d['author_texescaped'] = text_type(d['author']).\ - translate(texescape.tex_escape_map) + d['author_texescaped'] = d['author'].translate(texescape.tex_escape_map) d['project_doc'] = d['project'] + ' Documentation' - d['project_doc_texescaped'] = text_type(d['project'] + ' Documentation').\ + d['project_doc_texescaped'] = (d['project'] + ' Documentation').\ translate(texescape.tex_escape_map) # escape backslashes and single quotes in strings that are put into @@ -420,8 +402,7 @@ def generate(d, overwrite=True, silent=False, templatedir=None): 'version', 'release', 'master'): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") - if not path.isdir(d['path']): - ensuredir(d['path']) + ensuredir(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] @@ -441,7 +422,7 @@ def generate(d, overwrite=True, silent=False, templatedir=None): ensuredir(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): - # type: (unicode, unicode, unicode) -> None + # type: (str, str, str) -> None if overwrite or not path.isfile(fpath): if 'quiet' not in d: print(__('Creating file %s.') % fpath) @@ -455,7 +436,7 @@ def generate(d, overwrite=True, silent=False, templatedir=None): if not conf_path or not path.isfile(conf_path): conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t') with open(conf_path) as f: - conf_text = convert_python_source(f.read()) + conf_text = f.read() write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d)) @@ -474,13 +455,13 @@ def generate(d, overwrite=True, silent=False, templatedir=None): d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d['path'], 'Makefile'), - template.render(makefile_template, d), u'\n') + template.render(makefile_template, d), '\n') if d['batchfile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' write_file(path.join(d['path'], 'make.bat'), - template.render(batchfile_template, d), u'\r\n') + template.render(batchfile_template, d), '\r\n') if silent: return @@ -659,11 +640,6 @@ def main(argv=sys.argv[1:]): print('[Interrupted.]') return 130 # 128 + SIGINT - # decode values in d if value is a Python string literal - for key, value in d.items(): - if isinstance(value, binary_type): - d[key] = term_decode(value) - # handle use of CSV-style extension values d.setdefault('extensions', []) for ext in d['extensions'][:]: |