Fix exception causes all over the codebase

This commit is contained in:
Ram Rachum 2020-06-14 00:46:19 +03:00
parent 0fc97a0b56
commit 53c1dff91c
28 changed files with 114 additions and 105 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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':

View File

@ -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 ------------------------------

View File

@ -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]]:

View File

@ -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) -------------------------------------------

View File

@ -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

View File

@ -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]:

View File

@ -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']:

View File

@ -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))

View File

@ -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."""

View File

@ -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 = {}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]:

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -64,8 +64,8 @@ def compile_latex_document(app, filename='python.tex'):
'-output-directory=%s' % app.config.latex_engine,
filename]
subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
except OSError: # most likely the latex executable was not found
raise pytest.skip.Exception
except OSError as exc: # most likely the latex executable was not found
raise pytest.skip.Exception from exc
except CalledProcessError as exc:
print(exc.stdout)
print(exc.stderr)
@ -1545,7 +1545,7 @@ def test_texescape_for_unicode_supported_engine(app, status, warning):
assert 'superscript: ⁰, ¹' in result
assert 'subscript: ₀, ₁' in result
@pytest.mark.sphinx('latex', testroot='basic',
confoverrides={'latex_elements': {'extrapackages': r'\usepackage{foo}'}})
def test_latex_elements_extrapackages(app, status, warning):

View File

@ -58,8 +58,8 @@ def test_texinfo(app, status, warning):
try:
args = ['makeinfo', '--no-split', 'sphinxtests.texi']
subprocess.run(args, stdout=PIPE, stderr=PIPE, cwd=app.outdir, check=True)
except OSError:
raise pytest.skip.Exception # most likely makeinfo was not found
except OSError as exc:
raise pytest.skip.Exception from exc # most likely makeinfo was not found
except CalledProcessError as exc:
print(exc.stdout)
print(exc.stderr)