Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/click/exceptions.py: 40%
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 .globals import resolve_color_default
10from .utils import echo
11from .utils import format_filename
13if t.TYPE_CHECKING:
14 from .core import Command
15 from .core import Context
16 from .core import Parameter
19def _join_param_hints(param_hint: cabc.Sequence[str] | str | None) -> str | None:
20 if param_hint is not None and not isinstance(param_hint, str):
21 return " / ".join(repr(x) for x in param_hint)
23 return param_hint
26def _format_possibilities(possibilities: list[str]) -> str:
27 possibility_str = ", ".join(repr(p) for p in sorted(possibilities))
28 return ngettext(
29 "Did you mean {possibility}?",
30 "(Did you mean one of: {possibilities}?)",
31 len(possibilities),
32 ).format(possibility=possibility_str, possibilities=possibility_str)
35class ClickException(Exception):
36 """An exception that Click can handle and show to the user."""
38 #: The exit code for this exception.
39 exit_code = 1
41 def __init__(self, message: str) -> None:
42 super().__init__(message)
43 # The context will be removed by the time we print the message, so cache
44 # the color settings here to be used later on (in `show`)
45 self.show_color: bool | None = resolve_color_default()
46 self.message = message
48 def format_message(self) -> str:
49 return self.message
51 def __str__(self) -> str:
52 return self.message
54 def show(self, file: t.IO[t.Any] | None = None) -> None:
55 if file is None:
56 file = get_text_stderr()
58 echo(
59 _("Error: {message}").format(message=self.format_message()),
60 file=file,
61 color=self.show_color,
62 )
65class UsageError(ClickException):
66 """An internal exception that signals a usage error. This typically
67 aborts any further handling.
69 :param message: the error message to display.
70 :param ctx: optionally the context that caused this error. Click will
71 fill in the context automatically in some situations.
72 """
74 exit_code = 2
76 def __init__(self, message: str, ctx: Context | None = None) -> None:
77 super().__init__(message)
78 self.ctx = ctx
79 self.cmd: Command | None = self.ctx.command if self.ctx else None
81 def show(self, file: t.IO[t.Any] | None = None) -> None:
82 if file is None:
83 file = get_text_stderr()
84 color = None
85 hint = ""
86 if (
87 self.ctx is not None
88 and self.ctx.command.get_help_option(self.ctx) is not None
89 ):
90 help_names = self.ctx.command.get_help_option_names(self.ctx)
91 # Pick the longest name (like ``--help`` over ``-h``) for
92 # readability in error messages.
93 hint = _("Try '{command} {option}' for help.").format(
94 command=self.ctx.command_path,
95 option=max(help_names, key=len),
96 )
97 hint = f"{hint}\n"
98 if self.ctx is not None:
99 color = self.ctx.color
100 echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color)
101 echo(
102 _("Error: {message}").format(message=self.format_message()),
103 file=file,
104 color=color,
105 )
108class BadParameter(UsageError):
109 """An exception that formats out a standardized error message for a
110 bad parameter. This is useful when thrown from a callback or type as
111 Click will attach contextual information to it (for instance, which
112 parameter it is).
114 .. versionadded:: 2.0
116 :param param: the parameter object that caused this error. This can
117 be left out, and Click will attach this info itself
118 if possible.
119 :param param_hint: a string that shows up as parameter name. This
120 can be used as alternative to `param` in cases
121 where custom validation should happen. If it is
122 a string it's used as such, if it's a list then
123 each item is quoted and separated.
124 """
126 def __init__(
127 self,
128 message: str,
129 ctx: Context | None = None,
130 param: Parameter | None = None,
131 param_hint: cabc.Sequence[str] | str | None = None,
132 ) -> None:
133 super().__init__(message, ctx)
134 self.param = param
135 self.param_hint = param_hint
137 def format_message(self) -> str:
138 if self.param_hint is not None:
139 param_hint = self.param_hint
140 elif self.param is not None:
141 param_hint = self.param.get_error_hint(self.ctx)
142 else:
143 return _("Invalid value: {message}").format(message=self.message)
145 return _("Invalid value for {param_hint}: {message}").format(
146 param_hint=_join_param_hints(param_hint), message=self.message
147 )
150class MissingParameter(BadParameter):
151 """Raised if click required an option or argument but it was not
152 provided when invoking the script.
154 .. versionadded:: 4.0
156 :param param_type: a string that indicates the type of the parameter.
157 The default is to inherit the parameter type from
158 the given `param`. Valid values are ``'parameter'``,
159 ``'option'`` or ``'argument'``.
160 """
162 def __init__(
163 self,
164 message: str | None = None,
165 ctx: Context | None = None,
166 param: Parameter | None = None,
167 param_hint: cabc.Sequence[str] | str | None = None,
168 param_type: str | None = None,
169 ) -> None:
170 super().__init__(message or "", ctx, param, param_hint)
171 self.param_type = param_type
173 def format_message(self) -> str:
174 if self.param_hint is not None:
175 param_hint: cabc.Sequence[str] | str | None = self.param_hint
176 elif self.param is not None:
177 param_hint = self.param.get_error_hint(self.ctx)
178 else:
179 param_hint = None
181 param_hint = _join_param_hints(param_hint)
182 param_hint = f" {param_hint}" if param_hint else ""
184 param_type = self.param_type
185 if param_type is None and self.param is not None:
186 param_type = self.param.param_type_name
188 msg = self.message
189 if self.param is not None:
190 msg_extra = self.param.type.get_missing_message(
191 param=self.param, ctx=self.ctx
192 )
193 if msg_extra:
194 if msg:
195 msg += f". {msg_extra}"
196 else:
197 msg = msg_extra
199 msg = f" {msg}" if msg else ""
201 # Translate param_type for known types.
202 if param_type == "argument":
203 missing = _("Missing argument")
204 elif param_type == "option":
205 missing = _("Missing option")
206 elif param_type == "parameter":
207 missing = _("Missing parameter")
208 else:
209 missing = _("Missing {param_type}").format(param_type=param_type)
211 return f"{missing}{param_hint}.{msg}"
213 def __str__(self) -> str:
214 if not self.message:
215 param_name = self.param.name if self.param else None
216 return _("Missing parameter: {param_name}").format(param_name=param_name)
217 else:
218 return self.message
221class NoSuchOption(UsageError):
222 """Raised if Click attempted to handle an option that does not exist.
224 .. versionadded:: 4.0
225 """
227 def __init__(
228 self,
229 option_name: str,
230 message: str | None = None,
231 possibilities: cabc.Iterable[str] | None = None,
232 ctx: Context | None = None,
233 ) -> None:
234 if message is None:
235 message = _("No such option {name!r}.").format(name=option_name)
237 super().__init__(message, ctx)
238 self.option_name = option_name
239 self.possibilities: list[str] | None = None
240 if possibilities:
241 from difflib import get_close_matches
243 self.possibilities = get_close_matches(option_name, possibilities)
245 def format_message(self) -> str:
246 if not self.possibilities:
247 return self.message
248 return f"{self.message} {_format_possibilities(self.possibilities)}"
251class NoSuchCommand(UsageError):
252 """Raised if Click attempted to handle a command that does not exist."""
254 def __init__(
255 self,
256 command_name: str,
257 message: str | None = None,
258 possibilities: cabc.Iterable[str] | None = None,
259 ctx: Context | None = None,
260 ) -> None:
261 if message is None:
262 message = _("No such command {name!r}.").format(name=command_name)
264 super().__init__(message, ctx)
265 self.command_name = command_name
266 self.possibilities: list[str] | None = None
267 if possibilities:
268 from difflib import get_close_matches
270 self.possibilities = get_close_matches(command_name, possibilities)
272 def format_message(self) -> str:
273 if not self.possibilities:
274 return self.message
275 return f"{self.message} {_format_possibilities(self.possibilities)}"
278class BadOptionUsage(UsageError):
279 """Raised if an option is generally supplied but the use of the option
280 was incorrect. This is for instance raised if the number of arguments
281 for an option is not correct.
283 .. versionadded:: 4.0
285 :param option_name: the name of the option being used incorrectly.
286 """
288 def __init__(
289 self, option_name: str, message: str, ctx: Context | None = None
290 ) -> None:
291 super().__init__(message, ctx)
292 self.option_name = option_name
295class BadArgumentUsage(UsageError):
296 """Raised if an argument is generally supplied but the use of the argument
297 was incorrect. This is for instance raised if the number of values
298 for an argument is not correct.
300 .. versionadded:: 6.0
301 """
304class NoArgsIsHelpError(UsageError):
305 def __init__(self, ctx: Context) -> None:
306 self.ctx: Context
307 super().__init__(ctx.get_help(), ctx=ctx)
309 def show(self, file: t.IO[t.Any] | None = None) -> None:
310 echo(self.format_message(), file=file, err=True, color=self.ctx.color)
313class FileError(ClickException):
314 """Raised if a file cannot be opened."""
316 def __init__(self, filename: str, hint: str | None = None) -> None:
317 if hint is None:
318 hint = _("unknown error")
320 super().__init__(hint)
321 self.ui_filename: str = format_filename(filename)
322 self.filename = filename
324 def format_message(self) -> str:
325 return _("Could not open file {filename!r}: {message}").format(
326 filename=self.ui_filename, message=self.message
327 )
330class Abort(RuntimeError):
331 """An internal signalling exception that signals Click to abort."""
334class Exit(RuntimeError):
335 """An exception that indicates that the application should exit with some
336 status code.
338 :param code: the status code to exit with.
339 """
341 __slots__ = ("exit_code",)
343 def __init__(self, code: int = 0) -> None:
344 self.exit_code: int = code