forked from tox-dev/tox
-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
exception.py
108 lines (76 loc) · 3.35 KB
/
exception.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import os
import signal
import sys
if sys.version_info >= (3, 3):
from shlex import quote as shlex_quote
else:
from pipes import quote as shlex_quote
def exit_code_str(exception_name, command, exit_code):
"""String representation for an InvocationError, with exit code
NOTE: this might also be used by plugin tests (tox-venv at the time of writing),
so some coordination is needed if this is ever moved or a different solution for this hack
is found.
NOTE: this is a separate function because pytest-mock `spy` does not work on Exceptions
We can use neither a class method nor a static because of https://bugs.python.org/issue23078.
Even a normal method failed with "TypeError: descriptor '__getattribute__' requires a
'BaseException' object but received a 'type'".
"""
str_ = "{} for command {}".format(exception_name, command)
if exit_code is not None:
if exit_code < 0 or (os.name == "posix" and exit_code > 128):
signals = {
number: name for name, number in vars(signal).items() if name.startswith("SIG")
}
if exit_code < 0:
# Signal reported via subprocess.Popen.
sig_name = signals.get(-exit_code)
str_ += " (exited with code {:d} ({}))".format(exit_code, sig_name)
else:
str_ += " (exited with code {:d})".format(exit_code)
number = exit_code - 128
name = signals.get(number)
if name:
str_ += (
")\nNote: this might indicate a fatal error signal "
"({:d} - 128 = {:d}: {})".format(exit_code, number, name)
)
str_ += " (exited with code {:d})".format(exit_code)
return str_
class Error(Exception):
def __str__(self):
return "{}: {}".format(self.__class__.__name__, self.args[0])
class MissingSubstitution(Error):
FLAG = "TOX_MISSING_SUBSTITUTION"
"""placeholder for debugging configurations"""
def __init__(self, name):
self.name = name
super(Error, self).__init__(name)
class ConfigError(Error):
"""Error in tox configuration."""
class SubstitutionStackError(ConfigError, ValueError):
"""Error in tox configuration recursive substitution."""
class UnsupportedInterpreter(Error):
"""Signals an unsupported Interpreter."""
class InterpreterNotFound(Error):
"""Signals that an interpreter could not be found."""
class InvocationError(Error):
"""An error while invoking a script."""
def __init__(self, command, exit_code=None, out=None):
super(Error, self).__init__(command, exit_code)
self.command = command
self.exit_code = exit_code
self.out = out
def __str__(self):
return exit_code_str(self.__class__.__name__, self.command, self.exit_code)
class MissingDirectory(Error):
"""A directory did not exist."""
class MissingDependency(Error):
"""A dependency could not be found or determined."""
class MissingRequirement(Error):
"""A requirement defined in :config:`require` is not met."""
def __init__(self, config):
self.config = config
def __str__(self):
return " ".join(shlex_quote(i) for i in self.config.requires)
class BadRequirement(Error):
"""A requirement defined in :config:`require` cannot be parsed."""