Merge branch '1.7' into 4817_fix_URLs

This commit is contained in:
Takeshi KOMIYA 2018-04-09 01:56:12 +09:00 committed by GitHub
commit ca8e79a392
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 68 additions and 21 deletions

View File

@ -20,6 +20,9 @@ Bugs fixed
* #4790: autosummary: too wide two column tables in PDF builds
* #4795: Latex customization via ``_templates/longtable.tex_t`` is broken
* #4789: imgconverter: confused by convert.exe of Windows
* #4783: On windows, Sphinx crashed when drives of srcdir and outdir are
different
* #4812: autodoc ignores type annotated variables
* #4817: wrong URLs on warning messages
Testing

View File

@ -40,7 +40,7 @@ from sphinx.util import pycompat # noqa: F401
from sphinx.util.console import bold # type: ignore
from sphinx.util.docutils import is_html5_writer_available, directive_helper
from sphinx.util.i18n import find_catalog_source_files
from sphinx.util.osutil import ENOENT, ensuredir
from sphinx.util.osutil import ENOENT, ensuredir, relpath
from sphinx.util.tags import Tags
if False:
@ -342,7 +342,7 @@ class Sphinx(object):
if self.statuscode == 0 and self.builder.epilog:
logger.info('')
logger.info(self.builder.epilog % {
'outdir': path.relpath(self.outdir),
'outdir': relpath(self.outdir),
'project': self.config.project
})
except Exception as err:

View File

@ -19,7 +19,7 @@ from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.util import i18n, logging, status_iterator
from sphinx.util.console import bold # type: ignore
from sphinx.util.i18n import find_catalog
from sphinx.util.osutil import SEP, ensuredir, relative_uri
from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
parallel_available
@ -237,7 +237,7 @@ class Builder(object):
def cat2relpath(cat):
# type: (CatalogInfo) -> unicode
return path.relpath(cat.mo_path, self.env.srcdir).replace(path.sep, SEP)
return relpath(cat.mo_path, self.env.srcdir).replace(path.sep, SEP)
logger.info(bold('building [mo]: ') + message)
for catalog in status_iterator(catalogs, 'writing output... ', "darkgreen",

View File

@ -26,7 +26,7 @@ from sphinx.util import split_index_msg, logging, status_iterator
from sphinx.util.console import bold # type: ignore
from sphinx.util.i18n import find_catalog
from sphinx.util.nodes import extract_messages, traverse_translatable_index
from sphinx.util.osutil import safe_relpath, ensuredir, canon_path
from sphinx.util.osutil import relpath, ensuredir, canon_path
from sphinx.util.tags import Tags
if False:
@ -284,8 +284,7 @@ class MessageCatalogBuilder(I18nBuilder):
if self.config.gettext_location:
# generate "#: file1:line1\n#: file2:line2 ..."
output.write("#: %s\n" % "\n#: ".join( # type: ignore
"%s:%s" % (canon_path(
safe_relpath(source, self.outdir)), line)
"%s:%s" % (canon_path(relpath(source, self.outdir)), line)
for source, line, _ in positions))
if self.config.gettext_uuid:
# generate "# uuid1\n# uuid2\n ..."

View File

@ -23,7 +23,7 @@ from sphinx.util.nodes import explicit_title_re, set_source_info, \
if False:
# For type annotation
from typing import Any, Dict, List, Tuple # NOQA
from typing import Any, Dict, Generator, List, Tuple # NOQA
from sphinx.application import Sphinx # NOQA

View File

@ -38,7 +38,7 @@ from sphinx.util.docutils import sphinx_domains, WarningStream
from sphinx.util.i18n import find_catalog_files
from sphinx.util.matching import compile_matchers
from sphinx.util.nodes import is_translatable
from sphinx.util.osutil import SEP, ensuredir
from sphinx.util.osutil import SEP, ensuredir, relpath
from sphinx.util.parallel import ParallelTasks, parallel_available, make_chunks
from sphinx.util.websupport import is_commentable
@ -346,7 +346,7 @@ class BuildEnvironment(object):
*filename* should be absolute or relative to the source directory.
"""
if filename.startswith(self.srcdir):
filename = os.path.relpath(filename, self.srcdir)
filename = relpath(filename, self.srcdir)
for suffix in self.config.source_suffix:
if filename.endswith(suffix):
return filename[:-len(suffix)]

View File

@ -90,7 +90,7 @@ if False:
logger = logging.getLogger(__name__)
periods_re = re.compile('\.(?:\s+)')
periods_re = re.compile(r'\.(?:\s+)')
# -- autosummary_toc node ------------------------------------------------------

View File

@ -30,7 +30,7 @@ from sphinx.locale import _
from sphinx.util import force_decode, logging
from sphinx.util.console import bold # type: ignore
from sphinx.util.nodes import set_source_info
from sphinx.util.osutil import fs_encoding
from sphinx.util.osutil import fs_encoding, relpath
if False:
# For type annotation
@ -372,7 +372,7 @@ Doctest summary
"""Try to get the file which actually contains the doctest, not the
filename of the document it's included in."""
try:
filename = path.relpath(node.source, self.env.srcdir)\
filename = relpath(node.source, self.env.srcdir)\
.rsplit(':docstring of ', maxsplit=1)[0]
except Exception:
filename = self.env.doc2path(docname, base=None)

View File

@ -12,6 +12,7 @@ import ast
import inspect
import itertools
import re
import sys
import tokenize
from token import NAME, NEWLINE, INDENT, DEDENT, NUMBER, OP, STRING
from tokenize import COMMENT, NL
@ -27,6 +28,21 @@ indent_re = re.compile(u'^\\s*$')
emptyline_re = re.compile(u'^\\s*(#.*)?$')
if sys.version_info >= (3, 6):
ASSIGN_NODES = (ast.Assign, ast.AnnAssign)
else:
ASSIGN_NODES = (ast.Assign)
def get_assign_targets(node):
# type: (ast.AST) -> List[ast.expr]
"""Get list of targets from Assign and AnnAssign node."""
if isinstance(node, ast.Assign):
return node.targets
else:
return [node.target] # type: ignore
def get_lvar_names(node, self=None):
# type: (ast.AST, ast.expr) -> List[unicode]
"""Convert assignment-AST to variable names.
@ -284,7 +300,8 @@ class VariableCommentPicker(ast.NodeVisitor):
# type: (ast.Assign) -> None
"""Handles Assign node and pick up a variable comment."""
try:
varnames = sum([get_lvar_names(t, self=self.get_self()) for t in node.targets], [])
targets = get_assign_targets(node)
varnames = sum([get_lvar_names(t, self=self.get_self()) for t in targets], [])
current_line = self.get_line(node.lineno)
except TypeError:
return # this assignment is not new definition!
@ -320,12 +337,18 @@ class VariableCommentPicker(ast.NodeVisitor):
for varname in varnames:
self.add_entry(varname)
def visit_AnnAssign(self, node):
# type: (ast.AST) -> None
"""Handles AnnAssign node and pick up a variable comment."""
self.visit_Assign(node) # type: ignore
def visit_Expr(self, node):
# type: (ast.Expr) -> None
"""Handles Expr node and pick up a comment if string."""
if (isinstance(self.previous, ast.Assign) and isinstance(node.value, ast.Str)):
if (isinstance(self.previous, ASSIGN_NODES) and isinstance(node.value, ast.Str)):
try:
varnames = get_lvar_names(self.previous.targets[0], self.get_self())
targets = get_assign_targets(self.previous)
varnames = get_lvar_names(targets[0], self.get_self())
for varname in varnames:
if isinstance(node.value.s, text_type):
docstring = node.value.s

View File

@ -23,6 +23,7 @@ from sphinx.builders.latex import LaTeXBuilder
from sphinx.ext.autodoc import AutoDirective
from sphinx.pycode import ModuleAnalyzer
from sphinx.testing.path import path
from sphinx.util.osutil import relpath
if False:
from typing import List # NOQA
@ -184,7 +185,7 @@ def find_files(root, suffix=None):
dirpath = path(dirpath)
for f in [f for f in files if not suffix or f.endswith(suffix)]:
fpath = dirpath / f
yield os.path.relpath(fpath, root)
yield relpath(fpath, root)
def strip_escseq(text):

View File

@ -22,7 +22,7 @@ from babel.messages.pofile import read_po
from sphinx.errors import SphinxError
from sphinx.util import logging
from sphinx.util.osutil import SEP, walk
from sphinx.util.osutil import SEP, relpath, walk
logger = logging.getLogger(__name__)
@ -96,7 +96,7 @@ def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction):
domain = find_catalog(docname, compaction)
files = [gettext.find(domain, path.join(srcdir, dir_), [lang]) # type: ignore
for dir_ in locale_dirs]
files = [path.relpath(f, srcdir) for f in files if f] # type: ignore
files = [relpath(f, srcdir) for f in files if f] # type: ignore
return files # type: ignore
@ -137,7 +137,7 @@ def find_catalog_source_files(locale_dirs, locale, domains=None, gettext_compact
filenames = [f for f in filenames if f.endswith('.po')]
for filename in filenames:
base = path.splitext(filename)[0]
domain = path.relpath(path.join(dirpath, base), base_dir)
domain = relpath(path.join(dirpath, base), base_dir)
if gettext_compact and path.sep in domain:
domain = path.split(domain)[0]
domain = domain.replace(path.sep, SEP)

View File

@ -205,14 +205,21 @@ def ustrftime(format, *args):
return r.encode().decode('unicode-escape')
def safe_relpath(path, start=None):
def relpath(path, start=os.curdir):
# type: (unicode, unicode) -> unicode
"""Return a relative filepath to *path* either from the current directory or
from an optional *start* directory.
This is an alternative of ``os.path.relpath()``. This returns original path
if *path* and *start* are on different drives (for Windows platform).
"""
try:
return os.path.relpath(path, start)
except ValueError:
return path
safe_relpath = relpath # for compatibility
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() # type: unicode

View File

@ -9,6 +9,8 @@
:license: BSD, see LICENSE for details.
"""
import sys
import pytest
from six import PY2
@ -94,6 +96,18 @@ def test_comment_picker_location():
('Foo', 'attr3'): 'comment for attr3(3)'}
@pytest.mark.skipif(sys.version_info < (3, 6), reason='tests for py36+ syntax')
def test_annotated_assignment_py36():
source = ('a: str = "Sphinx" #: comment\n'
'b: int = 1\n'
'"""string on next line"""')
parser = Parser(source)
parser.parse()
assert parser.comments == {('', 'a'): 'comment',
('', 'b'): 'string on next line'}
assert parser.definitions == {}
def test_complex_assignment():
source = ('a = 1 + 1; b = a #: compound statement\n'
'c, d = (1, 1) #: unpack assignment\n'