Merge pull request #5175 from tk0miya/5161_html_crashes_on_copying

Fix html: crashes if copying static files are failed (refs: #5161)
This commit is contained in:
Takeshi KOMIYA 2018-07-16 14:51:38 +09:00 committed by GitHub
commit c777b920c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 64 deletions

View File

@ -44,6 +44,7 @@ Bugs fixed
sorting sorting
* #5139: autodoc: Enum argument missing if it shares value with another * #5139: autodoc: Enum argument missing if it shares value with another
* #4946: py domain: rtype field could not handle "None" as a type * #4946: py domain: rtype field could not handle "None" as a type
* #5161: html: crashes if copying static files are failed
Testing Testing
-------- --------

View File

@ -740,85 +740,93 @@ class StandaloneHTMLBuilder(Builder):
try: try:
copyfile(path.join(self.srcdir, src), copyfile(path.join(self.srcdir, src),
path.join(self.outdir, '_downloads', dest)) path.join(self.outdir, '_downloads', dest))
except Exception as err: except EnvironmentError as err:
logger.warning('cannot copy downloadable file %r: %s', logger.warning('cannot copy downloadable file %r: %s',
path.join(self.srcdir, src), err) path.join(self.srcdir, src), err)
def copy_static_files(self): def copy_static_files(self):
# type: () -> None # type: () -> None
# copy static files try:
logger.info(bold('copying static files... '), nonl=True) # copy static files
ensuredir(path.join(self.outdir, '_static')) logger.info(bold('copying static files... '), nonl=True)
# first, create pygments style file ensuredir(path.join(self.outdir, '_static'))
with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f: # first, create pygments style file
f.write(self.highlighter.get_stylesheet()) # type: ignore with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
# then, copy translations JavaScript file f.write(self.highlighter.get_stylesheet()) # type: ignore
if self.config.language is not None: # then, copy translations JavaScript file
jsfile = self._get_translations_js() if self.config.language is not None:
if jsfile: jsfile = self._get_translations_js()
copyfile(jsfile, path.join(self.outdir, '_static', if jsfile:
'translations.js')) copyfile(jsfile, path.join(self.outdir, '_static',
'translations.js'))
# copy non-minified stemmer JavaScript file # copy non-minified stemmer JavaScript file
if self.indexer is not None: if self.indexer is not None:
jsfile = self.indexer.get_js_stemmer_rawcode() jsfile = self.indexer.get_js_stemmer_rawcode()
if jsfile: if jsfile:
copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js')) copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js'))
ctx = self.globalcontext.copy() ctx = self.globalcontext.copy()
# add context items for search function used in searchtools.js_t # add context items for search function used in searchtools.js_t
if self.indexer is not None: if self.indexer is not None:
ctx.update(self.indexer.context_for_searchtool()) ctx.update(self.indexer.context_for_searchtool())
# then, copy over theme-supplied static files # then, copy over theme-supplied static files
if self.theme: if self.theme:
for theme_path in self.theme.get_theme_dirs()[::-1]: for theme_path in self.theme.get_theme_dirs()[::-1]:
entry = path.join(theme_path, 'static') entry = path.join(theme_path, 'static')
copy_asset(entry, path.join(self.outdir, '_static'), excluded=DOTFILES, copy_asset(entry, path.join(self.outdir, '_static'), excluded=DOTFILES,
context=ctx, renderer=self.templates)
# then, copy over all user-supplied static files
excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
for static_path in self.config.html_static_path:
entry = path.join(self.confdir, static_path)
if not path.exists(entry):
logger.warning('html_static_path entry %r does not exist', entry)
continue
copy_asset(entry, path.join(self.outdir, '_static'), excluded,
context=ctx, renderer=self.templates) context=ctx, renderer=self.templates)
# then, copy over all user-supplied static files # copy logo and favicon files if not already in static path
excluded = Matcher(self.config.exclude_patterns + ["**/.*"]) if self.config.html_logo:
for static_path in self.config.html_static_path: logobase = path.basename(self.config.html_logo)
entry = path.join(self.confdir, static_path) logotarget = path.join(self.outdir, '_static', logobase)
if not path.exists(entry): if not path.isfile(path.join(self.confdir, self.config.html_logo)):
logger.warning('html_static_path entry %r does not exist', entry) logger.warning('logo file %r does not exist', self.config.html_logo)
continue elif not path.isfile(logotarget):
copy_asset(entry, path.join(self.outdir, '_static'), excluded, copyfile(path.join(self.confdir, self.config.html_logo),
context=ctx, renderer=self.templates) logotarget)
# copy logo and favicon files if not already in static path if self.config.html_favicon:
if self.config.html_logo: iconbase = path.basename(self.config.html_favicon)
logobase = path.basename(self.config.html_logo) icontarget = path.join(self.outdir, '_static', iconbase)
logotarget = path.join(self.outdir, '_static', logobase) if not path.isfile(path.join(self.confdir, self.config.html_favicon)):
if not path.isfile(path.join(self.confdir, self.config.html_logo)): logger.warning('favicon file %r does not exist', self.config.html_favicon)
logger.warning('logo file %r does not exist', self.config.html_logo) elif not path.isfile(icontarget):
elif not path.isfile(logotarget): copyfile(path.join(self.confdir, self.config.html_favicon),
copyfile(path.join(self.confdir, self.config.html_logo), icontarget)
logotarget) logger.info('done')
if self.config.html_favicon: except EnvironmentError as err:
iconbase = path.basename(self.config.html_favicon) # TODO: In py3, EnvironmentError (and IOError) was merged into OSError.
icontarget = path.join(self.outdir, '_static', iconbase) # So it should be replaced by IOError on dropping py2 support
if not path.isfile(path.join(self.confdir, self.config.html_favicon)): logger.warning(__('cannot copy static file %r'), err)
logger.warning('favicon file %r does not exist', self.config.html_favicon)
elif not path.isfile(icontarget):
copyfile(path.join(self.confdir, self.config.html_favicon),
icontarget)
logger.info('done')
def copy_extra_files(self): def copy_extra_files(self):
# type: () -> None # type: () -> None
# copy html_extra_path files try:
logger.info(bold('copying extra files... '), nonl=True) # copy html_extra_path files
excluded = Matcher(self.config.exclude_patterns) logger.info(bold('copying extra files... '), nonl=True)
excluded = Matcher(self.config.exclude_patterns)
for extra_path in self.config.html_extra_path: for extra_path in self.config.html_extra_path:
entry = path.join(self.confdir, extra_path) entry = path.join(self.confdir, extra_path)
if not path.exists(entry): if not path.exists(entry):
logger.warning('html_extra_path entry %r does not exist', entry) logger.warning('html_extra_path entry %r does not exist', entry)
continue continue
copy_asset(entry, self.outdir, excluded) copy_asset(entry, self.outdir, excluded)
logger.info('done') logger.info('done')
except EnvironmentError as err:
logger.warning(__('cannot copy extra file %r'), err)
def write_buildinfo(self): def write_buildinfo(self):
# type: () -> None # type: () -> None