Merge pull request #7387 from cool-RR/2020-06-11-raise-from

Fix exception causes all over the codebase
This commit is contained in:
Ran Benita 2020-06-21 22:42:18 +03:00 committed by GitHub
commit 83891d9022
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 38 additions and 34 deletions

View File

@ -233,6 +233,7 @@ Pulkit Goyal
Punyashloka Biswal
Quentin Pradet
Ralf Schmitt
Ram Rachum
Ralph Giles
Ran Benita
Raphael Castaneda

View File

@ -0,0 +1 @@
Fixed exception causes all over the codebase, i.e. use `raise new_exception from old_exception` when wrapping an exception.

View File

@ -215,7 +215,7 @@ class Source:
newex.offset = ex.offset
newex.lineno = ex.lineno
newex.text = ex.text
raise newex
raise newex from ex
else:
if flag & ast.PyCF_ONLY_AST:
assert isinstance(co, ast.AST)

View File

@ -1189,8 +1189,8 @@ class Config:
def _getini(self, name: str) -> Any:
try:
description, type, default = self._parser._inidict[name]
except KeyError:
raise ValueError("unknown configuration value: {!r}".format(name))
except KeyError as e:
raise ValueError("unknown configuration value: {!r}".format(name)) from e
override_value = self._get_override_ini_value(name)
if override_value is None:
try:
@ -1286,14 +1286,14 @@ class Config:
if val is None and skip:
raise AttributeError(name)
return val
except AttributeError:
except AttributeError as e:
if default is not notset:
return default
if skip:
import pytest
pytest.skip("no {!r} option found".format(name))
raise ValueError("no option named {!r}".format(name))
raise ValueError("no option named {!r}".format(name)) from e
def getvalue(self, name, path=None):
""" (deprecated, use getoption()) """

View File

@ -265,9 +265,9 @@ class Argument:
else:
try:
self.dest = self._short_opts[0][1:]
except IndexError:
except IndexError as e:
self.dest = "???" # Needed for the error repr.
raise ArgumentError("need a long or short option", self)
raise ArgumentError("need a long or short option", self) from e
def names(self) -> List[str]:
return self._short_opts + self._long_opts

View File

@ -26,7 +26,7 @@ def _parse_ini_config(path: py.path.local) -> iniconfig.IniConfig:
try:
return iniconfig.IniConfig(path)
except iniconfig.ParseError as exc:
raise UsageError(str(exc))
raise UsageError(str(exc)) from exc
def load_config_dict_from_file(

View File

@ -28,10 +28,10 @@ def _validate_usepdb_cls(value: str) -> Tuple[str, str]:
"""Validate syntax of --pdbcls option."""
try:
modname, classname = value.split(":")
except ValueError:
except ValueError as e:
raise argparse.ArgumentTypeError(
"{!r} is not in the format 'modname:classname'".format(value)
)
) from e
return (modname, classname)
@ -130,7 +130,7 @@ class pytestPDB:
value = ":".join((modname, classname))
raise UsageError(
"--pdbcls: could not import {!r}: {}".format(value, exc)
)
) from exc
else:
import pdb

View File

@ -938,13 +938,13 @@ def _eval_scope_callable(
# Type ignored because there is no typing mechanism to specify
# keyword arguments, currently.
result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg] # noqa: F821
except Exception:
except Exception as e:
raise TypeError(
"Error evaluating {} while defining fixture '{}'.\n"
"Expected a function with the signature (*, fixture_name, config)".format(
scope_callable, fixture_name
)
)
) from e
if not isinstance(result, str):
fail(
"Expected {} to return a 'str' while defining fixture '{}', but it returned:\n"

View File

@ -487,13 +487,13 @@ def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[i
log_level = log_level.upper()
try:
return int(getattr(logging, log_level, log_level))
except ValueError:
except ValueError as e:
# Python logging does not recognise this as a logging level
raise pytest.UsageError(
"'{}' is not recognized as a logging level name for "
"'{}'. Please consider passing the "
"logging level num instead.".format(log_level, setting_name)
)
) from e
# run after terminalreporter/capturemanager are configured

View File

@ -73,7 +73,7 @@ def resolve(name: str) -> object:
if expected == used:
raise
else:
raise ImportError("import error in {}: {}".format(used, ex))
raise ImportError("import error in {}: {}".format(used, ex)) from ex
found = annotated_getattr(found, part, used)
return found
@ -81,12 +81,12 @@ def resolve(name: str) -> object:
def annotated_getattr(obj: object, name: str, ann: str) -> object:
try:
obj = getattr(obj, name)
except AttributeError:
except AttributeError as e:
raise AttributeError(
"{!r} object at {} has no attribute {!r}".format(
type(obj).__name__, ann, name
)
)
) from e
return obj

View File

@ -551,8 +551,10 @@ class Module(nodes.File, PyCollector):
importmode = self.config.getoption("--import-mode")
try:
mod = import_path(self.fspath, mode=importmode)
except SyntaxError:
raise self.CollectError(ExceptionInfo.from_current().getrepr(style="short"))
except SyntaxError as e:
raise self.CollectError(
ExceptionInfo.from_current().getrepr(style="short")
) from e
except ImportPathMismatchError as e:
raise self.CollectError(
"import file mismatch:\n"
@ -562,8 +564,8 @@ class Module(nodes.File, PyCollector):
" %s\n"
"HINT: remove __pycache__ / .pyc files and/or use a "
"unique basename for your test file modules" % e.args
)
except ImportError:
) from e
except ImportError as e:
exc_info = ExceptionInfo.from_current()
if self.config.getoption("verbose") < 2:
exc_info.traceback = exc_info.traceback.filter(filter_traceback)
@ -578,7 +580,7 @@ class Module(nodes.File, PyCollector):
"Hint: make sure your test modules/packages have valid Python names.\n"
"Traceback:\n"
"{traceback}".format(fspath=self.fspath, traceback=formatted_tb)
)
) from e
except _pytest.runner.Skipped as e:
if e.allow_module_level:
raise
@ -587,7 +589,7 @@ class Module(nodes.File, PyCollector):
"To decorate a test function, use the @pytest.mark.skip "
"or @pytest.mark.skipif decorators instead, and to skip a "
"module use `pytestmark = pytest.mark.{skip,skipif}."
)
) from e
self.config.pluginmanager.consider_module(mod)
return mod
@ -836,8 +838,8 @@ class CallSpec2:
def getparam(self, name: str) -> object:
try:
return self.params[name]
except KeyError:
raise ValueError(name)
except KeyError as e:
raise ValueError(name) from e
@property
def id(self) -> str:
@ -1074,8 +1076,8 @@ class Metafunc:
except TypeError:
try:
iter(ids)
except TypeError:
raise TypeError("ids must be a callable or an iterable")
except TypeError as e:
raise TypeError("ids must be a callable or an iterable") from e
num_ids = len(parameters)
# num_ids == 0 is a special case: https://github.com/pytest-dev/pytest/issues/1849

View File

@ -48,8 +48,8 @@ def _parse_filter(
lineno = int(lineno_)
if lineno < 0:
raise ValueError
except (ValueError, OverflowError):
raise warnings._OptionError("invalid lineno {!r}".format(lineno_))
except (ValueError, OverflowError) as e:
raise warnings._OptionError("invalid lineno {!r}".format(lineno_)) from e
else:
lineno = 0
return (action, message, category, module, lineno)

View File

@ -1778,5 +1778,5 @@ def test_conftest_import_error_repr(tmpdir):
):
try:
raise RuntimeError("some error")
except Exception:
raise ConftestImportFailure(path, sys.exc_info())
except Exception as e:
raise ConftestImportFailure(path, sys.exc_info()) from e

View File

@ -534,8 +534,8 @@ def test_outcomeexception_passes_except_Exception() -> None:
with pytest.raises(outcomes.OutcomeException):
try:
raise outcomes.OutcomeException("test")
except Exception:
raise NotImplementedError()
except Exception as e:
raise NotImplementedError from e
def test_pytest_exit() -> None: