Merge pull request #7387 from cool-RR/2020-06-11-raise-from
Fix exception causes all over the codebase
This commit is contained in:
commit
83891d9022
1
AUTHORS
1
AUTHORS
|
@ -233,6 +233,7 @@ Pulkit Goyal
|
||||||
Punyashloka Biswal
|
Punyashloka Biswal
|
||||||
Quentin Pradet
|
Quentin Pradet
|
||||||
Ralf Schmitt
|
Ralf Schmitt
|
||||||
|
Ram Rachum
|
||||||
Ralph Giles
|
Ralph Giles
|
||||||
Ran Benita
|
Ran Benita
|
||||||
Raphael Castaneda
|
Raphael Castaneda
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fixed exception causes all over the codebase, i.e. use `raise new_exception from old_exception` when wrapping an exception.
|
|
@ -215,7 +215,7 @@ class Source:
|
||||||
newex.offset = ex.offset
|
newex.offset = ex.offset
|
||||||
newex.lineno = ex.lineno
|
newex.lineno = ex.lineno
|
||||||
newex.text = ex.text
|
newex.text = ex.text
|
||||||
raise newex
|
raise newex from ex
|
||||||
else:
|
else:
|
||||||
if flag & ast.PyCF_ONLY_AST:
|
if flag & ast.PyCF_ONLY_AST:
|
||||||
assert isinstance(co, ast.AST)
|
assert isinstance(co, ast.AST)
|
||||||
|
|
|
@ -1189,8 +1189,8 @@ class Config:
|
||||||
def _getini(self, name: str) -> Any:
|
def _getini(self, name: str) -> Any:
|
||||||
try:
|
try:
|
||||||
description, type, default = self._parser._inidict[name]
|
description, type, default = self._parser._inidict[name]
|
||||||
except KeyError:
|
except KeyError as e:
|
||||||
raise ValueError("unknown configuration value: {!r}".format(name))
|
raise ValueError("unknown configuration value: {!r}".format(name)) from e
|
||||||
override_value = self._get_override_ini_value(name)
|
override_value = self._get_override_ini_value(name)
|
||||||
if override_value is None:
|
if override_value is None:
|
||||||
try:
|
try:
|
||||||
|
@ -1286,14 +1286,14 @@ class Config:
|
||||||
if val is None and skip:
|
if val is None and skip:
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
return val
|
return val
|
||||||
except AttributeError:
|
except AttributeError as e:
|
||||||
if default is not notset:
|
if default is not notset:
|
||||||
return default
|
return default
|
||||||
if skip:
|
if skip:
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
pytest.skip("no {!r} option found".format(name))
|
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):
|
def getvalue(self, name, path=None):
|
||||||
""" (deprecated, use getoption()) """
|
""" (deprecated, use getoption()) """
|
||||||
|
|
|
@ -265,9 +265,9 @@ class Argument:
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self.dest = self._short_opts[0][1:]
|
self.dest = self._short_opts[0][1:]
|
||||||
except IndexError:
|
except IndexError as e:
|
||||||
self.dest = "???" # Needed for the error repr.
|
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]:
|
def names(self) -> List[str]:
|
||||||
return self._short_opts + self._long_opts
|
return self._short_opts + self._long_opts
|
||||||
|
|
|
@ -26,7 +26,7 @@ def _parse_ini_config(path: py.path.local) -> iniconfig.IniConfig:
|
||||||
try:
|
try:
|
||||||
return iniconfig.IniConfig(path)
|
return iniconfig.IniConfig(path)
|
||||||
except iniconfig.ParseError as exc:
|
except iniconfig.ParseError as exc:
|
||||||
raise UsageError(str(exc))
|
raise UsageError(str(exc)) from exc
|
||||||
|
|
||||||
|
|
||||||
def load_config_dict_from_file(
|
def load_config_dict_from_file(
|
||||||
|
|
|
@ -28,10 +28,10 @@ def _validate_usepdb_cls(value: str) -> Tuple[str, str]:
|
||||||
"""Validate syntax of --pdbcls option."""
|
"""Validate syntax of --pdbcls option."""
|
||||||
try:
|
try:
|
||||||
modname, classname = value.split(":")
|
modname, classname = value.split(":")
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
raise argparse.ArgumentTypeError(
|
raise argparse.ArgumentTypeError(
|
||||||
"{!r} is not in the format 'modname:classname'".format(value)
|
"{!r} is not in the format 'modname:classname'".format(value)
|
||||||
)
|
) from e
|
||||||
return (modname, classname)
|
return (modname, classname)
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ class pytestPDB:
|
||||||
value = ":".join((modname, classname))
|
value = ":".join((modname, classname))
|
||||||
raise UsageError(
|
raise UsageError(
|
||||||
"--pdbcls: could not import {!r}: {}".format(value, exc)
|
"--pdbcls: could not import {!r}: {}".format(value, exc)
|
||||||
)
|
) from exc
|
||||||
else:
|
else:
|
||||||
import pdb
|
import pdb
|
||||||
|
|
||||||
|
|
|
@ -938,13 +938,13 @@ def _eval_scope_callable(
|
||||||
# Type ignored because there is no typing mechanism to specify
|
# Type ignored because there is no typing mechanism to specify
|
||||||
# keyword arguments, currently.
|
# keyword arguments, currently.
|
||||||
result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg] # noqa: F821
|
result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg] # noqa: F821
|
||||||
except Exception:
|
except Exception as e:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"Error evaluating {} while defining fixture '{}'.\n"
|
"Error evaluating {} while defining fixture '{}'.\n"
|
||||||
"Expected a function with the signature (*, fixture_name, config)".format(
|
"Expected a function with the signature (*, fixture_name, config)".format(
|
||||||
scope_callable, fixture_name
|
scope_callable, fixture_name
|
||||||
)
|
)
|
||||||
)
|
) from e
|
||||||
if not isinstance(result, str):
|
if not isinstance(result, str):
|
||||||
fail(
|
fail(
|
||||||
"Expected {} to return a 'str' while defining fixture '{}', but it returned:\n"
|
"Expected {} to return a 'str' while defining fixture '{}', but it returned:\n"
|
||||||
|
|
|
@ -487,13 +487,13 @@ def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[i
|
||||||
log_level = log_level.upper()
|
log_level = log_level.upper()
|
||||||
try:
|
try:
|
||||||
return int(getattr(logging, log_level, log_level))
|
return int(getattr(logging, log_level, log_level))
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
# Python logging does not recognise this as a logging level
|
# Python logging does not recognise this as a logging level
|
||||||
raise pytest.UsageError(
|
raise pytest.UsageError(
|
||||||
"'{}' is not recognized as a logging level name for "
|
"'{}' is not recognized as a logging level name for "
|
||||||
"'{}'. Please consider passing the "
|
"'{}'. Please consider passing the "
|
||||||
"logging level num instead.".format(log_level, setting_name)
|
"logging level num instead.".format(log_level, setting_name)
|
||||||
)
|
) from e
|
||||||
|
|
||||||
|
|
||||||
# run after terminalreporter/capturemanager are configured
|
# run after terminalreporter/capturemanager are configured
|
||||||
|
|
|
@ -73,7 +73,7 @@ def resolve(name: str) -> object:
|
||||||
if expected == used:
|
if expected == used:
|
||||||
raise
|
raise
|
||||||
else:
|
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)
|
found = annotated_getattr(found, part, used)
|
||||||
return found
|
return found
|
||||||
|
|
||||||
|
@ -81,12 +81,12 @@ def resolve(name: str) -> object:
|
||||||
def annotated_getattr(obj: object, name: str, ann: str) -> object:
|
def annotated_getattr(obj: object, name: str, ann: str) -> object:
|
||||||
try:
|
try:
|
||||||
obj = getattr(obj, name)
|
obj = getattr(obj, name)
|
||||||
except AttributeError:
|
except AttributeError as e:
|
||||||
raise AttributeError(
|
raise AttributeError(
|
||||||
"{!r} object at {} has no attribute {!r}".format(
|
"{!r} object at {} has no attribute {!r}".format(
|
||||||
type(obj).__name__, ann, name
|
type(obj).__name__, ann, name
|
||||||
)
|
)
|
||||||
)
|
) from e
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -551,8 +551,10 @@ class Module(nodes.File, PyCollector):
|
||||||
importmode = self.config.getoption("--import-mode")
|
importmode = self.config.getoption("--import-mode")
|
||||||
try:
|
try:
|
||||||
mod = import_path(self.fspath, mode=importmode)
|
mod = import_path(self.fspath, mode=importmode)
|
||||||
except SyntaxError:
|
except SyntaxError as e:
|
||||||
raise self.CollectError(ExceptionInfo.from_current().getrepr(style="short"))
|
raise self.CollectError(
|
||||||
|
ExceptionInfo.from_current().getrepr(style="short")
|
||||||
|
) from e
|
||||||
except ImportPathMismatchError as e:
|
except ImportPathMismatchError as e:
|
||||||
raise self.CollectError(
|
raise self.CollectError(
|
||||||
"import file mismatch:\n"
|
"import file mismatch:\n"
|
||||||
|
@ -562,8 +564,8 @@ class Module(nodes.File, PyCollector):
|
||||||
" %s\n"
|
" %s\n"
|
||||||
"HINT: remove __pycache__ / .pyc files and/or use a "
|
"HINT: remove __pycache__ / .pyc files and/or use a "
|
||||||
"unique basename for your test file modules" % e.args
|
"unique basename for your test file modules" % e.args
|
||||||
)
|
) from e
|
||||||
except ImportError:
|
except ImportError as e:
|
||||||
exc_info = ExceptionInfo.from_current()
|
exc_info = ExceptionInfo.from_current()
|
||||||
if self.config.getoption("verbose") < 2:
|
if self.config.getoption("verbose") < 2:
|
||||||
exc_info.traceback = exc_info.traceback.filter(filter_traceback)
|
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"
|
"Hint: make sure your test modules/packages have valid Python names.\n"
|
||||||
"Traceback:\n"
|
"Traceback:\n"
|
||||||
"{traceback}".format(fspath=self.fspath, traceback=formatted_tb)
|
"{traceback}".format(fspath=self.fspath, traceback=formatted_tb)
|
||||||
)
|
) from e
|
||||||
except _pytest.runner.Skipped as e:
|
except _pytest.runner.Skipped as e:
|
||||||
if e.allow_module_level:
|
if e.allow_module_level:
|
||||||
raise
|
raise
|
||||||
|
@ -587,7 +589,7 @@ class Module(nodes.File, PyCollector):
|
||||||
"To decorate a test function, use the @pytest.mark.skip "
|
"To decorate a test function, use the @pytest.mark.skip "
|
||||||
"or @pytest.mark.skipif decorators instead, and to skip a "
|
"or @pytest.mark.skipif decorators instead, and to skip a "
|
||||||
"module use `pytestmark = pytest.mark.{skip,skipif}."
|
"module use `pytestmark = pytest.mark.{skip,skipif}."
|
||||||
)
|
) from e
|
||||||
self.config.pluginmanager.consider_module(mod)
|
self.config.pluginmanager.consider_module(mod)
|
||||||
return mod
|
return mod
|
||||||
|
|
||||||
|
@ -836,8 +838,8 @@ class CallSpec2:
|
||||||
def getparam(self, name: str) -> object:
|
def getparam(self, name: str) -> object:
|
||||||
try:
|
try:
|
||||||
return self.params[name]
|
return self.params[name]
|
||||||
except KeyError:
|
except KeyError as e:
|
||||||
raise ValueError(name)
|
raise ValueError(name) from e
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self) -> str:
|
def id(self) -> str:
|
||||||
|
@ -1074,8 +1076,8 @@ class Metafunc:
|
||||||
except TypeError:
|
except TypeError:
|
||||||
try:
|
try:
|
||||||
iter(ids)
|
iter(ids)
|
||||||
except TypeError:
|
except TypeError as e:
|
||||||
raise TypeError("ids must be a callable or an iterable")
|
raise TypeError("ids must be a callable or an iterable") from e
|
||||||
num_ids = len(parameters)
|
num_ids = len(parameters)
|
||||||
|
|
||||||
# num_ids == 0 is a special case: https://github.com/pytest-dev/pytest/issues/1849
|
# num_ids == 0 is a special case: https://github.com/pytest-dev/pytest/issues/1849
|
||||||
|
|
|
@ -48,8 +48,8 @@ def _parse_filter(
|
||||||
lineno = int(lineno_)
|
lineno = int(lineno_)
|
||||||
if lineno < 0:
|
if lineno < 0:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except (ValueError, OverflowError):
|
except (ValueError, OverflowError) as e:
|
||||||
raise warnings._OptionError("invalid lineno {!r}".format(lineno_))
|
raise warnings._OptionError("invalid lineno {!r}".format(lineno_)) from e
|
||||||
else:
|
else:
|
||||||
lineno = 0
|
lineno = 0
|
||||||
return (action, message, category, module, lineno)
|
return (action, message, category, module, lineno)
|
||||||
|
|
|
@ -1778,5 +1778,5 @@ def test_conftest_import_error_repr(tmpdir):
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
raise RuntimeError("some error")
|
raise RuntimeError("some error")
|
||||||
except Exception:
|
except Exception as e:
|
||||||
raise ConftestImportFailure(path, sys.exc_info())
|
raise ConftestImportFailure(path, sys.exc_info()) from e
|
||||||
|
|
|
@ -534,8 +534,8 @@ def test_outcomeexception_passes_except_Exception() -> None:
|
||||||
with pytest.raises(outcomes.OutcomeException):
|
with pytest.raises(outcomes.OutcomeException):
|
||||||
try:
|
try:
|
||||||
raise outcomes.OutcomeException("test")
|
raise outcomes.OutcomeException("test")
|
||||||
except Exception:
|
except Exception as e:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError from e
|
||||||
|
|
||||||
|
|
||||||
def test_pytest_exit() -> None:
|
def test_pytest_exit() -> None:
|
||||||
|
|
Loading…
Reference in New Issue