Merge pull request #4807 from tk0miya/4783_relpath

Fix #4783: Sphinx crashed when drives of srcdir and outdir are different
This commit is contained in:
Takeshi KOMIYA 2018-04-08 23:35:59 +09:00 committed by GitHub
commit 7e1707000f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 25 additions and 16 deletions

View File

@ -20,6 +20,8 @@ Bugs fixed
* #4790: autosummary: too wide two column tables in PDF builds * #4790: autosummary: too wide two column tables in PDF builds
* #4795: Latex customization via ``_templates/longtable.tex_t`` is broken * #4795: Latex customization via ``_templates/longtable.tex_t`` is broken
* #4789: imgconverter: confused by convert.exe of Windows * #4789: imgconverter: confused by convert.exe of Windows
* #4783: On windows, Sphinx crashed when drives of srcdir and outdir are
different
Testing 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.console import bold # type: ignore
from sphinx.util.docutils import is_html5_writer_available, directive_helper from sphinx.util.docutils import is_html5_writer_available, directive_helper
from sphinx.util.i18n import find_catalog_source_files 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 from sphinx.util.tags import Tags
if False: if False:
@ -342,7 +342,7 @@ class Sphinx(object):
if self.statuscode == 0 and self.builder.epilog: if self.statuscode == 0 and self.builder.epilog:
logger.info('') logger.info('')
logger.info(self.builder.epilog % { logger.info(self.builder.epilog % {
'outdir': path.relpath(self.outdir), 'outdir': relpath(self.outdir),
'project': self.config.project 'project': self.config.project
}) })
except Exception as err: 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 import i18n, logging, status_iterator
from sphinx.util.console import bold # type: ignore from sphinx.util.console import bold # type: ignore
from sphinx.util.i18n import find_catalog 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, \ from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
parallel_available parallel_available
@ -237,7 +237,7 @@ class Builder(object):
def cat2relpath(cat): def cat2relpath(cat):
# type: (CatalogInfo) -> unicode # 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) logger.info(bold('building [mo]: ') + message)
for catalog in status_iterator(catalogs, 'writing output... ', "darkgreen", 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.console import bold # type: ignore
from sphinx.util.i18n import find_catalog from sphinx.util.i18n import find_catalog
from sphinx.util.nodes import extract_messages, traverse_translatable_index 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 from sphinx.util.tags import Tags
if False: if False:
@ -284,8 +284,7 @@ class MessageCatalogBuilder(I18nBuilder):
if self.config.gettext_location: if self.config.gettext_location:
# generate "#: file1:line1\n#: file2:line2 ..." # generate "#: file1:line1\n#: file2:line2 ..."
output.write("#: %s\n" % "\n#: ".join( # type: ignore output.write("#: %s\n" % "\n#: ".join( # type: ignore
"%s:%s" % (canon_path( "%s:%s" % (canon_path(relpath(source, self.outdir)), line)
safe_relpath(source, self.outdir)), line)
for source, line, _ in positions)) for source, line, _ in positions))
if self.config.gettext_uuid: if self.config.gettext_uuid:
# generate "# uuid1\n# uuid2\n ..." # generate "# uuid1\n# uuid2\n ..."

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

View File

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

View File

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

View File

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

View File

@ -205,14 +205,21 @@ def ustrftime(format, *args):
return r.encode().decode('unicode-escape') return r.encode().decode('unicode-escape')
def safe_relpath(path, start=None): def relpath(path, start=os.curdir):
# type: (unicode, unicode) -> unicode # 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: try:
return os.path.relpath(path, start) return os.path.relpath(path, start)
except ValueError: except ValueError:
return path return path
safe_relpath = relpath # for compatibility
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() # type: unicode fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() # type: unicode