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