Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/click/exceptions.py: 39%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import annotations
3import collections.abc as cabc
4import typing as t
5from gettext import gettext as _
6from gettext import ngettext
8from ._compat import get_text_stderr
9from .utils import echo
10from .utils import format_filename
12if t.TYPE_CHECKING:
13 from .core import Command
14 from .core import Context
15 from .core import Parameter
18def _join_param_hints(param_hint: cabc.Sequence[str] | str | None) -> str | None:
19 if param_hint is not None and not isinstance(param_hint, str):
20 return " / ".join(repr(x) for x in param_hint)
22 return param_hint
25class ClickException(Exception):
26 """An exception that Click can handle and show to the user."""
28 #: The exit code for this exception.
29 exit_code = 1
31 def __init__(self, message: str) -> None:
32 super().__init__(message)
33 self.message = message
35 def format_message(self) -> str:
36 return self.message
38 def __str__(self) -> str:
39 return self.message
41 def show(self, file: t.IO[t.Any] | None = None) -> None:
42 if file is None:
43 file = get_text_stderr()
45 echo(_("Error: {message}").format(message=self.format_message()), file=file)
48class UsageError(ClickException):
49 """An internal exception that signals a usage error. This typically
50 aborts any further handling.
52 :param message: the error message to display.
53 :param ctx: optionally the context that caused this error. Click will
54 fill in the context automatically in some situations.
55 """
57 exit_code = 2
59 def __init__(self, message: str, ctx: Context | None = None) -> None:
60 super().__init__(message)
61 self.ctx = ctx
62 self.cmd: Command | None = self.ctx.command if self.ctx else None
64 def show(self, file: t.IO[t.Any] | None = None) -> None:
65 if file is None:
66 file = get_text_stderr()
67 color = None
68 hint = ""
69 if (
70 self.ctx is not None
71 and self.ctx.command.get_help_option(self.ctx) is not None
72 ):
73 hint = _("Try '{command} {option}' for help.").format(
74 command=self.ctx.command_path, option=self.ctx.help_option_names[0]
75 )
76 hint = f"{hint}\n"
77 if self.ctx is not None:
78 color = self.ctx.color
79 echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color)
80 echo(
81 _("Error: {message}").format(message=self.format_message()),
82 file=file,
83 color=color,
84 )
87class BadParameter(UsageError):
88 """An exception that formats out a standardized error message for a
89 bad parameter. This is useful when thrown from a callback or type as
90 Click will attach contextual information to it (for instance, which
91 parameter it is).
93 .. versionadded:: 2.0
95 :param param: the parameter object that caused this error. This can
96 be left out, and Click will attach this info itself
97 if possible.
98 :param param_hint: a string that shows up as parameter name. This
99 can be used as alternative to `param` in cases
100 where custom validation should happen. If it is
101 a string it's used as such, if it's a list then
102 each item is quoted and separated.
103 """
105 def __init__(
106 self,
107 message: str,
108 ctx: Context | None = None,
109 param: Parameter | None = None,
110 param_hint: str | None = None,
111 ) -> None:
112 super().__init__(message, ctx)
113 self.param = param
114 self.param_hint = param_hint
116 def format_message(self) -> str:
117 if self.param_hint is not None:
118 param_hint = self.param_hint
119 elif self.param is not None:
120 param_hint = self.param.get_error_hint(self.ctx) # type: ignore
121 else:
122 return _("Invalid value: {message}").format(message=self.message)
124 return _("Invalid value for {param_hint}: {message}").format(
125 param_hint=_join_param_hints(param_hint), message=self.message
126 )
129class MissingParameter(BadParameter):
130 """Raised if click required an option or argument but it was not
131 provided when invoking the script.
133 .. versionadded:: 4.0
135 :param param_type: a string that indicates the type of the parameter.
136 The default is to inherit the parameter type from
137 the given `param`. Valid values are ``'parameter'``,
138 ``'option'`` or ``'argument'``.
139 """
141 def __init__(
142 self,
143 message: str | None = None,
144 ctx: Context | None = None,
145 param: Parameter | None = None,
146 param_hint: str | None = None,
147 param_type: str | None = None,
148 ) -> None:
149 super().__init__(message or "", ctx, param, param_hint)
150 self.param_type = param_type
152 def format_message(self) -> str:
153 if self.param_hint is not None:
154 param_hint: str | None = self.param_hint
155 elif self.param is not None:
156 param_hint = self.param.get_error_hint(self.ctx) # type: ignore
157 else:
158 param_hint = None
160 param_hint = _join_param_hints(param_hint)
161 param_hint = f" {param_hint}" if param_hint else ""
163 param_type = self.param_type
164 if param_type is None and self.param is not None:
165 param_type = self.param.param_type_name
167 msg = self.message
168 if self.param is not None:
169 msg_extra = self.param.type.get_missing_message(self.param)
170 if msg_extra:
171 if msg:
172 msg += f". {msg_extra}"
173 else:
174 msg = msg_extra
176 msg = f" {msg}" if msg else ""
178 # Translate param_type for known types.
179 if param_type == "argument":
180 missing = _("Missing argument")
181 elif param_type == "option":
182 missing = _("Missing option")
183 elif param_type == "parameter":
184 missing = _("Missing parameter")
185 else:
186 missing = _("Missing {param_type}").format(param_type=param_type)
188 return f"{missing}{param_hint}.{msg}"
190 def __str__(self) -> str:
191 if not self.message:
192 param_name = self.param.name if self.param else None
193 return _("Missing parameter: {param_name}").format(param_name=param_name)
194 else:
195 return self.message
198class NoSuchOption(UsageError):
199 """Raised if click attempted to handle an option that does not
200 exist.
202 .. versionadded:: 4.0
203 """
205 def __init__(
206 self,
207 option_name: str,
208 message: str | None = None,
209 possibilities: cabc.Sequence[str] | None = None,
210 ctx: Context | None = None,
211 ) -> None:
212 if message is None:
213 message = _("No such option: {name}").format(name=option_name)
215 super().__init__(message, ctx)
216 self.option_name = option_name
217 self.possibilities = possibilities
219 def format_message(self) -> str:
220 if not self.possibilities:
221 return self.message
223 possibility_str = ", ".join(sorted(self.possibilities))
224 suggest = ngettext(
225 "Did you mean {possibility}?",
226 "(Possible options: {possibilities})",
227 len(self.possibilities),
228 ).format(possibility=possibility_str, possibilities=possibility_str)
229 return f"{self.message} {suggest}"
232class BadOptionUsage(UsageError):
233 """Raised if an option is generally supplied but the use of the option
234 was incorrect. This is for instance raised if the number of arguments
235 for an option is not correct.
237 .. versionadded:: 4.0
239 :param option_name: the name of the option being used incorrectly.
240 """
242 def __init__(
243 self, option_name: str, message: str, ctx: Context | None = None
244 ) -> None:
245 super().__init__(message, ctx)
246 self.option_name = option_name
249class BadArgumentUsage(UsageError):
250 """Raised if an argument is generally supplied but the use of the argument
251 was incorrect. This is for instance raised if the number of values
252 for an argument is not correct.
254 .. versionadded:: 6.0
255 """
258class FileError(ClickException):
259 """Raised if a file cannot be opened."""
261 def __init__(self, filename: str, hint: str | None = None) -> None:
262 if hint is None:
263 hint = _("unknown error")
265 super().__init__(hint)
266 self.ui_filename: str = format_filename(filename)
267 self.filename = filename
269 def format_message(self) -> str:
270 return _("Could not open file {filename!r}: {message}").format(
271 filename=self.ui_filename, message=self.message
272 )
275class Abort(RuntimeError):
276 """An internal signalling exception that signals Click to abort."""
279class Exit(RuntimeError):
280 """An exception that indicates that the application should exit with some
281 status code.
283 :param code: the status code to exit with.
284 """
286 __slots__ = ("exit_code",)
288 def __init__(self, code: int = 0) -> None:
289 self.exit_code: int = code