Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sphinx-doc/sphinx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/sphinx
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx')
-rw-r--r--sphinx/builders/gettext.py2
-rw-r--r--sphinx/builders/html/__init__.py4
-rw-r--r--sphinx/builders/latex/theming.py8
-rw-r--r--sphinx/config.py14
-rw-r--r--sphinx/domains/c.py13
-rw-r--r--sphinx/domains/cpp.py27
-rw-r--r--sphinx/domains/std.py4
-rw-r--r--sphinx/environment/__init__.py7
-rw-r--r--sphinx/ext/autodoc/importer.py4
-rw-r--r--sphinx/ext/autosummary/__init__.py2
-rw-r--r--sphinx/ext/graphviz.py8
-rw-r--r--sphinx/ext/imgconverter.py2
-rw-r--r--sphinx/ext/imgmath.py16
-rw-r--r--sphinx/ext/intersphinx.py2
-rw-r--r--sphinx/pycode/__init__.py10
-rw-r--r--sphinx/registry.py21
-rw-r--r--sphinx/search/ja.py4
-rw-r--r--sphinx/setup_command.py2
-rw-r--r--sphinx/theming.py16
-rw-r--r--sphinx/transforms/post_transforms/__init__.py4
-rw-r--r--sphinx/util/__init__.py14
-rw-r--r--sphinx/util/i18n.py2
-rw-r--r--sphinx/util/inspect.py8
-rw-r--r--sphinx/util/osutil.py4
-rw-r--r--sphinx/util/pycompat.py7
-rw-r--r--sphinx/writers/texinfo.py4
26 files changed, 109 insertions, 100 deletions
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index 65f112510..8e30762e9 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -278,7 +278,7 @@ class MessageCatalogBuilder(I18nBuilder):
origin = MsgOrigin(template, line)
self.catalogs['sphinx'].add(msg, origin)
except Exception as exc:
- raise ThemeError('%s: %r' % (template, exc))
+ raise ThemeError('%s: %r' % (template, exc)) from exc
def build(self, docnames: Iterable[str], summary: str = None, method: str = 'update') -> None: # NOQA
self._extract_from_template()
diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py
index 5340c93f9..99d7aa13b 100644
--- a/sphinx/builders/html/__init__.py
+++ b/sphinx/builders/html/__init__.py
@@ -140,7 +140,7 @@ class BuildInfo:
build_info.tags_hash = lines[3].split()[1].strip()
return build_info
except Exception as exc:
- raise ValueError(__('build info file is broken: %r') % exc)
+ raise ValueError(__('build info file is broken: %r') % exc) from exc
def __init__(self, config: Config = None, tags: Tags = None, config_categories: List[str] = []) -> None: # NOQA
self.config_hash = ''
@@ -1015,7 +1015,7 @@ class StandaloneHTMLBuilder(Builder):
return
except Exception as exc:
raise ThemeError(__("An error happened in rendering the page %s.\nReason: %r") %
- (pagename, exc))
+ (pagename, exc)) from exc
if not outfilename:
outfilename = self.get_outfilename(pagename)
diff --git a/sphinx/builders/latex/theming.py b/sphinx/builders/latex/theming.py
index da6a7fa04..130bded4a 100644
--- a/sphinx/builders/latex/theming.py
+++ b/sphinx/builders/latex/theming.py
@@ -87,10 +87,12 @@ class UserTheme(Theme):
try:
value = self.config.get('theme', key)
setattr(self, key, value)
- except configparser.NoSectionError:
- raise ThemeError(__('%r doesn\'t have "theme" setting') % filename)
+ except configparser.NoSectionError as exc:
+ raise ThemeError(__('%r doesn\'t have "theme" setting') %
+ filename) from exc
except configparser.NoOptionError as exc:
- raise ThemeError(__('%r doesn\'t have "%s" setting') % (filename, exc.args[0]))
+ raise ThemeError(__('%r doesn\'t have "%s" setting') %
+ (filename, exc.args[0])) from exc
for key in self.OPTIONAL_CONFIG_KEYS:
try:
diff --git a/sphinx/config.py b/sphinx/config.py
index 92c203dfd..353268e38 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -196,9 +196,9 @@ class Config:
elif isinstance(defvalue, int):
try:
return int(value)
- except ValueError:
+ except ValueError as exc:
raise ValueError(__('invalid number %r for config value %r, ignoring') %
- (value, name))
+ (value, name)) from exc
elif hasattr(defvalue, '__call__'):
return value
elif defvalue is not None and not isinstance(defvalue, str):
@@ -319,17 +319,17 @@ def eval_config_file(filename: str, tags: Tags) -> Dict[str, Any]:
execfile_(filename, namespace)
except SyntaxError as err:
msg = __("There is a syntax error in your configuration file: %s\n")
- raise ConfigError(msg % err)
- except SystemExit:
+ raise ConfigError(msg % err) from err
+ except SystemExit as exc:
msg = __("The configuration file (or one of the modules it imports) "
"called sys.exit()")
- raise ConfigError(msg)
+ raise ConfigError(msg) from exc
except ConfigError:
# pass through ConfigError from conf.py as is. It will be shown in console.
raise
- except Exception:
+ except Exception as exc:
msg = __("There is a programmable error in your configuration file:\n\n%s")
- raise ConfigError(msg % traceback.format_exc())
+ raise ConfigError(msg % traceback.format_exc()) from exc
return namespace
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index 36a8f1f65..b4cf32a99 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -2300,7 +2300,8 @@ class DefinitionParser(BaseParser):
errs = []
errs.append((exCast, "If type cast expression"))
errs.append((exUnary, "If unary expression"))
- raise self._make_multi_error(errs, "Error in cast expression.")
+ raise self._make_multi_error(errs,
+ "Error in cast expression.") from exUnary
else:
return self._parse_unary_expression()
@@ -2767,7 +2768,7 @@ class DefinitionParser(BaseParser):
msg += " (e.g., 'void (*f(int arg))(double)')"
prevErrors.append((exNoPtrParen, msg))
header = "Error in declarator"
- raise self._make_multi_error(prevErrors, header)
+ raise self._make_multi_error(prevErrors, header) from exNoPtrParen
pos = self.pos
try:
return self._parse_declarator_name_suffix(named, paramMode, typed)
@@ -2775,7 +2776,7 @@ class DefinitionParser(BaseParser):
self.pos = pos
prevErrors.append((e, "If declarator-id"))
header = "Error in declarator or parameters"
- raise self._make_multi_error(prevErrors, header)
+ raise self._make_multi_error(prevErrors, header) from e
def _parse_initializer(self, outer: str = None, allowFallback: bool = True
) -> ASTInitializer:
@@ -2843,7 +2844,7 @@ class DefinitionParser(BaseParser):
if True:
header = "Type must be either just a name or a "
header += "typedef-like declaration."
- raise self._make_multi_error(prevErrors, header)
+ raise self._make_multi_error(prevErrors, header) from exTyped
else:
# For testing purposes.
# do it again to get the proper traceback (how do you
@@ -2994,7 +2995,7 @@ class DefinitionParser(BaseParser):
errs = []
errs.append((exExpr, "If expression"))
errs.append((exType, "If type"))
- raise self._make_multi_error(errs, header)
+ raise self._make_multi_error(errs, header) from exType
return res
@@ -3132,7 +3133,7 @@ class CObject(ObjectDescription):
name = _make_phony_error_name()
symbol = parentSymbol.add_name(name)
self.env.temp_data['c:last_symbol'] = symbol
- raise ValueError
+ raise ValueError from e
try:
symbol = parentSymbol.add_declaration(ast, docname=self.env.docname)
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index 1783db491..c202786e8 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -4882,7 +4882,7 @@ class DefinitionParser(BaseParser):
raise self._make_multi_error([
(eFold, "If fold expression"),
(eExpr, "If parenthesized expression")
- ], "Error in fold expression or parenthesized expression.")
+ ], "Error in fold expression or parenthesized expression.") from eExpr
return ASTParenExpr(res)
# now it definitely is a fold expression
if self.skip_string(')'):
@@ -5066,7 +5066,7 @@ class DefinitionParser(BaseParser):
errors = []
errors.append((eType, "If type"))
errors.append((eExpr, "If expression"))
- raise self._make_multi_error(errors, header)
+ raise self._make_multi_error(errors, header) from eExpr
else: # a primary expression or a type
pos = self.pos
try:
@@ -5093,7 +5093,7 @@ class DefinitionParser(BaseParser):
errors = []
errors.append((eOuter, "If primary expression"))
errors.append((eInner, "If type"))
- raise self._make_multi_error(errors, header)
+ raise self._make_multi_error(errors, header) from eInner
# and now parse postfixes
postFixes = [] # type: List[ASTPostfixOp]
@@ -5253,7 +5253,8 @@ class DefinitionParser(BaseParser):
errs = []
errs.append((exCast, "If type cast expression"))
errs.append((exUnary, "If unary expression"))
- raise self._make_multi_error(errs, "Error in cast expression.")
+ raise self._make_multi_error(errs,
+ "Error in cast expression.") from exUnary
else:
return self._parse_unary_expression()
@@ -5504,7 +5505,7 @@ class DefinitionParser(BaseParser):
self.pos = pos
prevErrors.append((e, "If non-type argument"))
header = "Error in parsing template argument list."
- raise self._make_multi_error(prevErrors, header)
+ raise self._make_multi_error(prevErrors, header) from e
if parsedEnd:
assert not parsedComma
break
@@ -5949,7 +5950,7 @@ class DefinitionParser(BaseParser):
self.pos = pos
prevErrors.append((exNoPtrParen, "If parenthesis in noptr-declarator"))
header = "Error in declarator"
- raise self._make_multi_error(prevErrors, header)
+ raise self._make_multi_error(prevErrors, header) from exNoPtrParen
if typed: # pointer to member
pos = self.pos
try:
@@ -5988,7 +5989,7 @@ class DefinitionParser(BaseParser):
self.pos = pos
prevErrors.append((e, "If declarator-id"))
header = "Error in declarator or parameters-and-qualifiers"
- raise self._make_multi_error(prevErrors, header)
+ raise self._make_multi_error(prevErrors, header) from e
def _parse_initializer(self, outer: str = None, allowFallback: bool = True
) -> ASTInitializer:
@@ -6096,7 +6097,7 @@ class DefinitionParser(BaseParser):
header = "Error when parsing function declaration."
else:
assert False
- raise self._make_multi_error(prevErrors, header)
+ raise self._make_multi_error(prevErrors, header) from exTyped
else:
# For testing purposes.
# do it again to get the proper traceback (how do you
@@ -6163,7 +6164,7 @@ class DefinitionParser(BaseParser):
errs.append((eType, "If default template argument is a type"))
msg = "Error in non-type template parameter"
msg += " or constrained template parameter."
- raise self._make_multi_error(errs, msg)
+ raise self._make_multi_error(errs, msg) from eType
def _parse_type_using(self) -> ASTTypeUsing:
name = self._parse_nested_name()
@@ -6510,7 +6511,7 @@ class DefinitionParser(BaseParser):
self.pos = pos
prevErrors.append((e, "If type alias or template alias"))
header = "Error in type declaration."
- raise self._make_multi_error(prevErrors, header)
+ raise self._make_multi_error(prevErrors, header) from e
elif objectType == 'concept':
declaration = self._parse_concept()
elif objectType == 'member':
@@ -6576,7 +6577,7 @@ class DefinitionParser(BaseParser):
errs.append((e1, "If shorthand ref"))
errs.append((e2, "If full function ref"))
msg = "Error in cross-reference."
- raise self._make_multi_error(errs, msg)
+ raise self._make_multi_error(errs, msg) from e2
def parse_expression(self) -> Union[ASTExpression, ASTType]:
pos = self.pos
@@ -6597,7 +6598,7 @@ class DefinitionParser(BaseParser):
errs = []
errs.append((exExpr, "If expression"))
errs.append((exType, "If type"))
- raise self._make_multi_error(errs, header)
+ raise self._make_multi_error(errs, header) from exType
def _make_phony_error_name() -> ASTNestedName:
@@ -6790,7 +6791,7 @@ class CPPObject(ObjectDescription):
name = _make_phony_error_name()
symbol = parentSymbol.add_name(name)
self.env.temp_data['cpp:last_symbol'] = symbol
- raise ValueError
+ raise ValueError from e
try:
symbol = parentSymbol.add_declaration(ast, docname=self.env.docname)
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index fbbed3a6b..016f84ebc 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -1061,10 +1061,10 @@ class StandardDomain(Domain):
try:
figure_id = target_node['ids'][0]
return env.toc_fignumbers[docname][figtype][figure_id]
- except (KeyError, IndexError):
+ except (KeyError, IndexError) as exc:
# target_node is found, but fignumber is not assigned.
# Maybe it is defined in orphaned document.
- raise ValueError
+ raise ValueError from exc
def get_full_qualified_name(self, node: Element) -> str:
if node.get('reftype') == 'option':
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index 6584ac6d8..1e58542bb 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -393,7 +393,8 @@ class BuildEnvironment:
if catalog.domain == domain:
self.dependencies[docname].add(catalog.mo_path)
except OSError as exc:
- raise DocumentError(__('Failed to scan documents in %s: %r') % (self.srcdir, exc))
+ raise DocumentError(__('Failed to scan documents in %s: %r') %
+ (self.srcdir, exc)) from exc
def get_outdated_files(self, config_changed: bool) -> Tuple[Set[str], Set[str], Set[str]]:
"""Return (added, changed, removed) sets."""
@@ -511,8 +512,8 @@ class BuildEnvironment:
"""
try:
return self.domains[domainname]
- except KeyError:
- raise ExtensionError(__('Domain %r is not registered') % domainname)
+ except KeyError as exc:
+ raise ExtensionError(__('Domain %r is not registered') % domainname) from exc
# --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py
index cdccf710d..e5e84eda3 100644
--- a/sphinx/ext/autodoc/importer.py
+++ b/sphinx/ext/autodoc/importer.py
@@ -33,7 +33,7 @@ def import_module(modname: str, warningiserror: bool = False) -> Any:
except BaseException as exc:
# Importing modules may cause any side effects, including
# SystemExit, so we need to catch all errors.
- raise ImportError(exc, traceback.format_exc())
+ raise ImportError(exc, traceback.format_exc()) from exc
def import_object(modname: str, objpath: List[str], objtype: str = '',
@@ -98,7 +98,7 @@ def import_object(modname: str, objpath: List[str], objtype: str = '',
errmsg += '; the following exception was raised:\n%s' % traceback.format_exc()
logger.debug(errmsg)
- raise ImportError(errmsg)
+ raise ImportError(errmsg) from exc
def get_module_members(module: Any) -> List[Tuple[str, Any]]:
diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py
index 162b6868c..58e192bda 100644
--- a/sphinx/ext/autosummary/__init__.py
+++ b/sphinx/ext/autosummary/__init__.py
@@ -647,7 +647,7 @@ def _import_by_name(name: str) -> Tuple[Any, Any, str]:
else:
return sys.modules[modname], None, modname
except (ValueError, ImportError, AttributeError, KeyError) as e:
- raise ImportError(*e.args)
+ raise ImportError(*e.args) from e
# -- :autolink: (smart default role) -------------------------------------------
diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py
index c21868a6f..4a8dd0a4d 100644
--- a/sphinx/ext/graphviz.py
+++ b/sphinx/ext/graphviz.py
@@ -256,7 +256,7 @@ def render_dot(self: SphinxTranslator, code: str, options: Dict,
return None, None
except CalledProcessError as exc:
raise GraphvizError(__('dot exited with error:\n[stderr]\n%r\n'
- '[stdout]\n%r') % (exc.stderr, exc.stdout))
+ '[stdout]\n%r') % (exc.stderr, exc.stdout)) from exc
def render_dot_html(self: HTMLTranslator, node: graphviz, code: str, options: Dict,
@@ -270,7 +270,7 @@ def render_dot_html(self: HTMLTranslator, node: graphviz, code: str, options: Di
fname, outfn = render_dot(self, code, options, format, prefix)
except GraphvizError as exc:
logger.warning(__('dot code %r: %s'), code, exc)
- raise nodes.SkipNode
+ raise nodes.SkipNode from exc
classes = [imgcls, 'graphviz'] + node.get('classes', [])
imgcls = ' '.join(filter(None, classes))
@@ -321,7 +321,7 @@ def render_dot_latex(self: LaTeXTranslator, node: graphviz, code: str,
fname, outfn = render_dot(self, code, options, 'pdf', prefix)
except GraphvizError as exc:
logger.warning(__('dot code %r: %s'), code, exc)
- raise nodes.SkipNode
+ raise nodes.SkipNode from exc
is_inline = self.is_inline(node)
@@ -358,7 +358,7 @@ def render_dot_texinfo(self: TexinfoTranslator, node: graphviz, code: str,
fname, outfn = render_dot(self, code, options, 'png', prefix)
except GraphvizError as exc:
logger.warning(__('dot code %r: %s'), code, exc)
- raise nodes.SkipNode
+ raise nodes.SkipNode from exc
if fname is not None:
self.body.append('@image{%s,,,[graphviz],png}\n' % fname[:-4])
raise nodes.SkipNode
diff --git a/sphinx/ext/imgconverter.py b/sphinx/ext/imgconverter.py
index bf4b9b9d1..dd13a9879 100644
--- a/sphinx/ext/imgconverter.py
+++ b/sphinx/ext/imgconverter.py
@@ -70,7 +70,7 @@ class ImagemagickConverter(ImageConverter):
except CalledProcessError as exc:
raise ExtensionError(__('convert exited with error:\n'
'[stderr]\n%r\n[stdout]\n%r') %
- (exc.stderr, exc.stdout))
+ (exc.stderr, exc.stdout)) from exc
def setup(app: Sphinx) -> Dict[str, Any]:
diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py
index 2050e470e..d11c5d7c5 100644
--- a/sphinx/ext/imgmath.py
+++ b/sphinx/ext/imgmath.py
@@ -165,13 +165,13 @@ def compile_math(latex: str, builder: Builder) -> str:
try:
subprocess.run(command, stdout=PIPE, stderr=PIPE, cwd=tempdir, check=True)
return path.join(tempdir, 'math.dvi')
- except OSError:
+ except OSError as exc:
logger.warning(__('LaTeX command %r cannot be run (needed for math '
'display), check the imgmath_latex setting'),
builder.config.imgmath_latex)
- raise InvokeError
+ raise InvokeError from exc
except CalledProcessError as exc:
- raise MathExtError('latex exited with error', exc.stderr, exc.stdout)
+ raise MathExtError('latex exited with error', exc.stderr, exc.stdout) from exc
def convert_dvi_to_image(command: List[str], name: str) -> Tuple[bytes, bytes]:
@@ -179,13 +179,13 @@ def convert_dvi_to_image(command: List[str], name: str) -> Tuple[bytes, bytes]:
try:
ret = subprocess.run(command, stdout=PIPE, stderr=PIPE, check=True)
return ret.stdout, ret.stderr
- except OSError:
+ except OSError as exc:
logger.warning(__('%s command %r cannot be run (needed for math '
'display), check the imgmath_%s setting'),
name, command[0], name)
- raise InvokeError
+ raise InvokeError from exc
except CalledProcessError as exc:
- raise MathExtError('%s exited with error' % name, exc.stderr, exc.stdout)
+ raise MathExtError('%s exited with error' % name, exc.stderr, exc.stdout) from exc
def convert_dvi_to_png(dvipath: str, builder: Builder) -> Tuple[str, int]:
@@ -326,7 +326,7 @@ def html_visit_math(self: HTMLTranslator, node: nodes.math) -> None:
backrefs=[], source=node.astext())
sm.walkabout(self)
logger.warning(__('display latex %r: %s'), node.astext(), msg)
- raise nodes.SkipNode
+ raise nodes.SkipNode from exc
if fname is None:
# something failed -- use text-only as a bad substitute
self.body.append('<span class="math">%s</span>' %
@@ -352,7 +352,7 @@ def html_visit_displaymath(self: HTMLTranslator, node: nodes.math_block) -> None
backrefs=[], source=node.astext())
sm.walkabout(self)
logger.warning(__('inline latex %r: %s'), node.astext(), msg)
- raise nodes.SkipNode
+ raise nodes.SkipNode from exc
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append('<p>')
if node['number']:
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
index 02f605bac..a6c4ef694 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -179,7 +179,7 @@ def fetch_inventory(app: Sphinx, uri: str, inv: Any) -> Any:
join = path.join if localuri else posixpath.join
invdata = InventoryFile.load(f, uri, join)
except ValueError as exc:
- raise ValueError('unknown or unsupported inventory version: %r' % exc)
+ raise ValueError('unknown or unsupported inventory version: %r' % exc) from exc
except Exception as err:
err.args = ('intersphinx inventory %r not readable due to %s: %s',
inv, err.__class__.__name__, str(err))
diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py
index 963680a54..29e53178f 100644
--- a/sphinx/pycode/__init__.py
+++ b/sphinx/pycode/__init__.py
@@ -37,7 +37,7 @@ class ModuleAnalyzer:
try:
mod = import_module(modname)
except Exception as err:
- raise PycodeError('error importing %r' % modname, err)
+ raise PycodeError('error importing %r' % modname, err) from err
loader = getattr(mod, '__loader__', None)
filename = getattr(mod, '__file__', None)
if loader and getattr(loader, 'get_source', None):
@@ -54,7 +54,7 @@ class ModuleAnalyzer:
try:
filename = loader.get_filename(modname)
except ImportError as err:
- raise PycodeError('error getting filename for %r' % modname, err)
+ raise PycodeError('error getting filename for %r' % modname, err) from err
if filename is None:
# all methods for getting filename failed, so raise...
raise PycodeError('no source found for module %r' % modname)
@@ -92,7 +92,7 @@ class ModuleAnalyzer:
if '.egg' + path.sep in filename:
obj = cls.cache['file', filename] = cls.for_egg(filename, modname)
else:
- raise PycodeError('error opening %r' % filename, err)
+ raise PycodeError('error opening %r' % filename, err) from err
return obj
@classmethod
@@ -104,7 +104,7 @@ class ModuleAnalyzer:
code = egg.read(relpath).decode()
return cls.for_string(code, modname, filename)
except Exception as exc:
- raise PycodeError('error opening %r' % filename, exc)
+ raise PycodeError('error opening %r' % filename, exc) from exc
@classmethod
def for_module(cls, modname: str) -> "ModuleAnalyzer":
@@ -169,7 +169,7 @@ class ModuleAnalyzer:
self.tags = parser.definitions
self.tagorder = parser.deforders
except Exception as exc:
- raise PycodeError('parsing %r failed: %r' % (self.srcname, exc))
+ raise PycodeError('parsing %r failed: %r' % (self.srcname, exc)) from exc
def find_attr_docs(self) -> Dict[Tuple[str, str], List[str]]:
"""Find class and module-level attributes and their documentation."""
diff --git a/sphinx/registry.py b/sphinx/registry.py
index cad74559c..0aec0a9fd 100644
--- a/sphinx/registry.py
+++ b/sphinx/registry.py
@@ -139,9 +139,9 @@ class SphinxComponentRegistry:
entry_points = iter_entry_points('sphinx.builders', name)
try:
entry_point = next(entry_points)
- except StopIteration:
+ except StopIteration as exc:
raise SphinxError(__('Builder name %s not registered or available'
- ' through entry point') % name)
+ ' through entry point') % name) from exc
self.load_extension(app, entry_point.module_name)
@@ -273,8 +273,8 @@ class SphinxComponentRegistry:
def get_source_parser(self, filetype: str) -> "Type[Parser]":
try:
return self.source_parsers[filetype]
- except KeyError:
- raise SphinxError(__('Source parser for %s not registered') % filetype)
+ except KeyError as exc:
+ raise SphinxError(__('Source parser for %s not registered') % filetype) from exc
def get_source_parsers(self) -> Dict[str, "Type[Parser]"]:
return self.source_parsers
@@ -311,9 +311,11 @@ class SphinxComponentRegistry:
try:
visit, depart = handlers # unpack once for assertion
translation_handlers[node.__name__] = (visit, depart)
- except ValueError:
- raise ExtensionError(__('kwargs for add_node() must be a (visit, depart) '
- 'function tuple: %r=%r') % (builder_name, handlers))
+ except ValueError as exc:
+ raise ExtensionError(
+ __('kwargs for add_node() must be a (visit, depart) '
+ 'function tuple: %r=%r') % (builder_name, handlers)
+ ) from exc
def get_translator_class(self, builder: Builder) -> "Type[nodes.NodeVisitor]":
return self.translators.get(builder.name,
@@ -407,7 +409,8 @@ class SphinxComponentRegistry:
mod = import_module(extname)
except ImportError as err:
logger.verbose(__('Original exception:\n') + traceback.format_exc())
- raise ExtensionError(__('Could not import extension %s') % extname, err)
+ raise ExtensionError(__('Could not import extension %s') % extname,
+ err) from err
setup = getattr(mod, 'setup', None)
if setup is None:
@@ -423,7 +426,7 @@ class SphinxComponentRegistry:
__('The %s extension used by this project needs at least '
'Sphinx v%s; it therefore cannot be built with this '
'version.') % (extname, err)
- )
+ ) from err
if metadata is None:
metadata = {}
diff --git a/sphinx/search/ja.py b/sphinx/search/ja.py
index d1f444be1..c1e72b8f8 100644
--- a/sphinx/search/ja.py
+++ b/sphinx/search/ja.py
@@ -528,9 +528,9 @@ class SearchJapanese(SearchLanguage):
dotted_path = options.get('type', 'sphinx.search.ja.DefaultSplitter')
try:
self.splitter = import_object(dotted_path)(options)
- except ExtensionError:
+ except ExtensionError as exc:
raise ExtensionError("Splitter module %r can't be imported" %
- dotted_path)
+ dotted_path) from exc
def split(self, input: str) -> List[str]:
return self.splitter.split(input)
diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py
index 2c0076304..24beab856 100644
--- a/sphinx/setup_command.py
+++ b/sphinx/setup_command.py
@@ -198,7 +198,7 @@ class BuildDoc(Command):
except Exception as exc:
handle_exception(app, self, exc, sys.stderr)
if not self.pdb:
- raise SystemExit(1)
+ raise SystemExit(1) from exc
if not self.link_index:
continue
diff --git a/sphinx/theming.py b/sphinx/theming.py
index 13a895393..087ee7f24 100644
--- a/sphinx/theming.py
+++ b/sphinx/theming.py
@@ -74,17 +74,17 @@ class Theme:
try:
inherit = self.config.get('theme', 'inherit')
- except configparser.NoSectionError:
- raise ThemeError(__('theme %r doesn\'t have "theme" setting') % name)
- except configparser.NoOptionError:
- raise ThemeError(__('theme %r doesn\'t have "inherit" setting') % name)
+ except configparser.NoSectionError as exc:
+ raise ThemeError(__('theme %r doesn\'t have "theme" setting') % name) from exc
+ except configparser.NoOptionError as exc:
+ raise ThemeError(__('theme %r doesn\'t have "inherit" setting') % name) from exc
if inherit != 'none':
try:
self.base = factory.create(inherit)
- except ThemeError:
+ except ThemeError as exc:
raise ThemeError(__('no theme named %r found, inherited by %r') %
- (inherit, name))
+ (inherit, name)) from exc
def get_theme_dirs(self) -> List[str]:
"""Return a list of theme directories, beginning with this theme's,
@@ -101,13 +101,13 @@ class Theme:
"""
try:
return self.config.get(section, name)
- except (configparser.NoOptionError, configparser.NoSectionError):
+ except (configparser.NoOptionError, configparser.NoSectionError) as exc:
if self.base:
return self.base.get_config(section, name, default)
if default is NODEFAULT:
raise ThemeError(__('setting %s.%s occurs in none of the '
- 'searched theme configs') % (section, name))
+ 'searched theme configs') % (section, name)) from exc
else:
return default
diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py
index 4499e3376..7dc14af52 100644
--- a/sphinx/transforms/post_transforms/__init__.py
+++ b/sphinx/transforms/post_transforms/__init__.py
@@ -82,8 +82,8 @@ class ReferencesResolver(SphinxPostTransform):
# let the domain try to resolve the reference
try:
domain = self.env.domains[node['refdomain']]
- except KeyError:
- raise NoUri(target, typ)
+ except KeyError as exc:
+ raise NoUri(target, typ) from exc
newnode = domain.resolve_xref(self.env, refdoc, self.app.builder,
typ, target, node, contnode)
# really hardwired reference types
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index ca9bb028d..3bf049f98 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -285,21 +285,21 @@ def get_module_source(modname: str) -> Tuple[str, str]:
try:
mod = import_module(modname)
except Exception as err:
- raise PycodeError('error importing %r' % modname, err)
+ raise PycodeError('error importing %r' % modname, err) from err
filename = getattr(mod, '__file__', None)
loader = getattr(mod, '__loader__', None)
if loader and getattr(loader, 'get_filename', None):
try:
filename = loader.get_filename(modname)
except Exception as err:
- raise PycodeError('error getting filename for %r' % filename, err)
+ raise PycodeError('error getting filename for %r' % filename, err) from err
if filename is None and loader:
try:
filename = loader.get_source(modname)
if filename:
return 'string', filename
except Exception as err:
- raise PycodeError('error getting source for %r' % modname, err)
+ raise PycodeError('error getting source for %r' % modname, err) from err
if filename is None:
raise PycodeError('no source found for module %r' % modname)
filename = path.normpath(path.abspath(filename))
@@ -456,8 +456,8 @@ def parselinenos(spec: str, total: int) -> List[int]:
items.extend(range(start - 1, end))
else:
raise ValueError
- except Exception:
- raise ValueError('invalid line number spec: %r' % spec)
+ except Exception as exc:
+ raise ValueError('invalid line number spec: %r' % spec) from exc
return items
@@ -596,9 +596,9 @@ def import_object(objname: str, source: str = None) -> Any:
except (AttributeError, ImportError) as exc:
if source:
raise ExtensionError('Could not import %s (needed for %s)' %
- (objname, source), exc)
+ (objname, source), exc) from exc
else:
- raise ExtensionError('Could not import %s' % objname, exc)
+ raise ExtensionError('Could not import %s' % objname, exc) from exc
def split_full_qualified_name(name: str) -> Tuple[str, str]:
diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py
index 1cb75637c..499f2316f 100644
--- a/sphinx/util/i18n.py
+++ b/sphinx/util/i18n.py
@@ -312,7 +312,7 @@ def get_image_filename_for_language(filename: str, env: "BuildEnvironment") -> s
try:
return filename_format.format(**d)
except KeyError as exc:
- raise SphinxError('Invalid figure_language_filename: %r' % exc)
+ raise SphinxError('Invalid figure_language_filename: %r' % exc) from exc
def search_image_for_language(filename: str, env: "BuildEnvironment") -> str:
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index d4928c847..3077f9eb2 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -321,7 +321,7 @@ def safe_getattr(obj: Any, name: str, *defargs: Any) -> Any:
"""A getattr() that turns all exceptions into AttributeErrors."""
try:
return getattr(obj, name, *defargs)
- except Exception:
+ except Exception as exc:
# sometimes accessing a property raises an exception (e.g.
# NotImplementedError), so let's try to read the attribute directly
try:
@@ -336,7 +336,7 @@ def safe_getattr(obj: Any, name: str, *defargs: Any) -> Any:
if defargs:
return defargs[0]
- raise AttributeError(name)
+ raise AttributeError(name) from exc
def safe_getmembers(object: Any, predicate: Callable[[str], bool] = None,
@@ -385,8 +385,8 @@ def object_description(object: Any) -> str:
for x in sorted_values)
try:
s = repr(object)
- except Exception:
- raise ValueError
+ except Exception as exc:
+ raise ValueError from exc
# Strip non-deterministic memory addresses such as
# ``<__main__.A at 0x7f68cb685710>``
s = memory_address_re.sub('', s)
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
index 23f5b0137..0390b038d 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -168,10 +168,10 @@ def abspath(pathdir: str) -> str:
if isinstance(pathdir, bytes):
try:
pathdir = pathdir.decode(fs_encoding)
- except UnicodeDecodeError:
+ except UnicodeDecodeError as exc:
raise UnicodeDecodeError('multibyte filename not supported on '
'this filesystem encoding '
- '(%r)' % fs_encoding)
+ '(%r)' % fs_encoding) from exc
return pathdir
diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py
index 664387cac..2173fce14 100644
--- a/sphinx/util/pycompat.py
+++ b/sphinx/util/pycompat.py
@@ -34,11 +34,11 @@ def convert_with_2to3(filepath: str) -> str:
try:
from lib2to3.refactor import RefactoringTool, get_fixers_from_package
from lib2to3.pgen2.parse import ParseError
- except ImportError:
+ except ImportError as exc:
# python 3.9.0a6+ emits PendingDeprecationWarning for lib2to3.
# Additionally, removal of the module is still discussed at PEP-594.
# To support future python, this catches ImportError for lib2to3.
- raise SyntaxError
+ raise SyntaxError from exc
fixers = get_fixers_from_package('lib2to3.fixes')
refactoring_tool = RefactoringTool(fixers)
@@ -49,7 +49,8 @@ def convert_with_2to3(filepath: str) -> str:
# do not propagate lib2to3 exceptions
lineno, offset = err.context[1]
# try to match ParseError details with SyntaxError details
- raise SyntaxError(err.msg, (filepath, lineno, offset, err.value))
+
+ raise SyntaxError(err.msg, (filepath, lineno, offset, err.value)) from err
return str(tree)
diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py
index 9c30244e9..b77bf4352 100644
--- a/sphinx/writers/texinfo.py
+++ b/sphinx/writers/texinfo.py
@@ -853,8 +853,8 @@ class TexinfoTranslator(SphinxTranslator):
num = node.astext().strip()
try:
footnode, used = self.footnotestack[-1][num]
- except (KeyError, IndexError):
- raise nodes.SkipNode
+ except (KeyError, IndexError) as exc:
+ raise nodes.SkipNode from exc
# footnotes are repeated for each reference
footnode.walkabout(self) # type: ignore
raise nodes.SkipChildren