Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close #8100: html: Show a better error message for html_static_files #8112

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -13,6 +13,9 @@ Deprecated
Features added
--------------

* #8100: html: Show a better error message for failures on copying
html_static_files

Bugs fixed
----------

Expand Down
13 changes: 11 additions & 2 deletions sphinx/builders/html/__init__.py
Expand Up @@ -751,18 +751,27 @@ def copy_stemmer_js(self) -> None:
copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js'))

def copy_theme_static_files(self, context: Dict) -> None:
def onerror(filename: str, error: Exception) -> None:
logger.warning(__('Failed to copy a file in html_static_file: %s: %r'),
filename, error)

if self.theme:
for entry in self.theme.get_theme_dirs()[::-1]:
copy_asset(path.join(entry, 'static'),
path.join(self.outdir, '_static'),
excluded=DOTFILES, context=context, renderer=self.templates)
excluded=DOTFILES, context=context,
renderer=self.templates, onerror=onerror)

def copy_html_static_files(self, context: Dict) -> None:
def onerror(filename: str, error: Exception) -> None:
logger.warning(__('Failed to copy a file in html_static_file: %s: %r'),
filename, error)

excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
for entry in self.config.html_static_path:
copy_asset(path.join(self.confdir, entry),
path.join(self.outdir, '_static'),
excluded, context=context, renderer=self.templates)
excluded, context=context, renderer=self.templates, onerror=onerror)

def copy_html_logo(self) -> None:
if self.config.html_logo:
Expand Down
18 changes: 13 additions & 5 deletions sphinx/util/fileutil.py
Expand Up @@ -10,7 +10,7 @@

import os
import posixpath
from typing import Dict
from typing import Callable, Dict

from docutils.utils import relative_path

Expand Down Expand Up @@ -56,7 +56,8 @@ def copy_asset_file(source: str, destination: str,


def copy_asset(source: str, destination: str, excluded: PathMatcher = lambda path: False,
context: Dict = None, renderer: "BaseRenderer" = None) -> None:
context: Dict = None, renderer: "BaseRenderer" = None,
onerror: Callable[[str, Exception], None] = None) -> None:
"""Copy asset files to destination recursively.

On copying, it expands the template variables if context argument is given and
Expand All @@ -67,6 +68,7 @@ def copy_asset(source: str, destination: str, excluded: PathMatcher = lambda pat
:param excluded: The matcher to determine the given path should be copied or not
:param context: The template variables. If not given, template files are simply copied
:param renderer: The template engine. If not given, SphinxRenderer is used by default
:param onerror: The error handler.
"""
if not os.path.exists(source):
return
Expand All @@ -90,6 +92,12 @@ def copy_asset(source: str, destination: str, excluded: PathMatcher = lambda pat

for filename in files:
if not excluded(posixpath.join(reldir, filename)):
copy_asset_file(posixpath.join(root, filename),
posixpath.join(destination, reldir),
context, renderer)
try:
copy_asset_file(posixpath.join(root, filename),
posixpath.join(destination, reldir),
context, renderer)
except Exception as exc:
if onerror:
onerror(posixpath.join(root, filename), exc)
else:
raise