Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/click/exceptions.py: 46%
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: t.ClassVar[int] = 1
41 show_color: t.Final[bool | None]
42 message: t.Final[str]
44 def __init__(self, message: str) -> None:
45 super().__init__(message)
46 # The context will be removed by the time we print the message, so cache
47 # the color settings here to be used later on (in `show`)
48 self.show_color = resolve_color_default()
49 self.message = message
51 def format_message(self) -> str:
52 return self.message
54 def __str__(self) -> str:
55 return self.message
57 def show(self, file: t.IO[t.Any] | None = None) -> None:
58 if file is None:
59 file = get_text_stderr()
61 echo(
62 _("Error: {message}").format(message=self.format_message()),
63 file=file,
64 color=self.show_color,
65 )
68class UsageError(ClickException):
69 """An internal exception that signals a usage error. This typically
70 aborts any further handling.
72 :param message: the error message to display.
73 :param ctx: optionally the context that caused this error. Click will
74 fill in the context automatically in some situations.
75 """
77 exit_code: t.ClassVar[int] = 2
79 ctx: Context | None
80 cmd: t.Final[Command | None]
82 def __init__(self, message: str, ctx: Context | None = None) -> None:
83 super().__init__(message)
84 self.ctx = ctx
85 self.cmd = self.ctx.command if self.ctx else None
87 def show(self, file: t.IO[t.Any] | None = None) -> None:
88 if file is None:
89 file = get_text_stderr()
90 color = None
91 hint = ""
92 if (
93 self.ctx is not None
94 and self.ctx.command.get_help_option(self.ctx) is not None
95 ):
96 help_names = self.ctx.command.get_help_option_names(self.ctx)
97 # Pick the longest name (like ``--help`` over ``-h``) for
98 # readability in error messages.
99 hint = _("Try '{command} {option}' for help.").format(
100 command=self.ctx.command_path,
101 option=max(help_names, key=len),
102 )
103 hint = f"{hint}\n"
104 if self.ctx is not None:
105 color = self.ctx.color
106 echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color)
107 echo(
108 _("Error: {message}").format(message=self.format_message()),
109 file=file,
110 color=color,
111 )
114class BadParameter(UsageError):
115 """An exception that formats out a standardized error message for a
116 bad parameter. This is useful when thrown from a callback or type as
117 Click will attach contextual information to it (for instance, which
118 parameter it is).
120 .. versionadded:: 2.0
122 :param param: the parameter object that caused this error. This can
123 be left out, and Click will attach this info itself
124 if possible.
125 :param param_hint: a string that shows up as parameter name. This
126 can be used as alternative to `param` in cases
127 where custom validation should happen. If it is
128 a string it's used as such, if it's a list then
129 each item is quoted and separated.
130 """
132 param: Parameter | None
133 param_hint: cabc.Sequence[str] | str | None
135 def __init__(
136 self,
137 message: str,
138 ctx: Context | None = None,
139 param: Parameter | None = None,
140 param_hint: cabc.Sequence[str] | str | None = None,
141 ) -> None:
142 super().__init__(message, ctx)
143 self.param = param
144 self.param_hint = param_hint
146 def format_message(self) -> str:
147 if self.param_hint is not None:
148 param_hint = self.param_hint
149 elif self.param is not None:
150 param_hint = self.param.get_error_hint(self.ctx)
151 else:
152 return _("Invalid value: {message}").format(message=self.message)
154 return _("Invalid value for {param_hint}: {message}").format(
155 param_hint=_join_param_hints(param_hint), message=self.message
156 )
159class MissingParameter(BadParameter):
160 """Raised if click required an option or argument but it was not
161 provided when invoking the script.
163 .. versionadded:: 4.0
165 :param param_type: a string that indicates the type of the parameter.
166 The default is to inherit the parameter type from
167 the given `param`. Valid values are ``'parameter'``,
168 ``'option'`` or ``'argument'``.
169 """
171 param_type: t.Final[str | None]
173 def __init__(
174 self,
175 message: str | None = None,
176 ctx: Context | None = None,
177 param: Parameter | None = None,
178 param_hint: cabc.Sequence[str] | str | None = None,
179 param_type: str | None = None,
180 ) -> None:
181 super().__init__(message or "", ctx, param, param_hint)
182 self.param_type = param_type
184 def format_message(self) -> str:
185 if self.param_hint is not None:
186 param_hint: cabc.Sequence[str] | str | None = self.param_hint
187 elif self.param is not None:
188 param_hint = self.param.get_error_hint(self.ctx)
189 else:
190 param_hint = None
192 param_hint = _join_param_hints(param_hint)
193 param_hint = f" {param_hint}" if param_hint else ""
195 param_type = self.param_type
196 if param_type is None and self.param is not None:
197 param_type = self.param.param_type_name
199 msg = self.message
200 if self.param is not None:
201 msg_extra = self.param.type.get_missing_message(
202 param=self.param, ctx=self.ctx
203 )
204 if msg_extra:
205 if msg:
206 msg += f". {msg_extra}"
207 else:
208 msg = msg_extra
210 msg = f" {msg}" if msg else ""
212 # Translate param_type for known types.
213 if param_type == "argument":
214 missing = _("Missing argument")
215 elif param_type == "option":
216 missing = _("Missing option")
217 elif param_type == "parameter":
218 missing = _("Missing parameter")
219 else:
220 missing = _("Missing {param_type}").format(param_type=param_type)
222 return f"{missing}{param_hint}.{msg}"
224 def __str__(self) -> str:
225 if not self.message:
226 param_name = self.param.name if self.param else None
227 return _("Missing parameter: {param_name}").format(param_name=param_name)
228 else:
229 return self.message
232class NoSuchOption(UsageError):
233 """Raised if Click attempted to handle an option that does not exist.
235 .. versionadded:: 4.0
236 """
238 option_name: t.Final[str]
239 possibilities: t.Final[list[str] | None]
241 def __init__(
242 self,
243 option_name: str,
244 message: str | None = None,
245 possibilities: cabc.Iterable[str] | None = None,
246 ctx: Context | None = None,
247 ) -> None:
248 if message is None:
249 message = _("No such option {name!r}.").format(name=option_name)
251 super().__init__(message, ctx)
252 self.option_name = option_name
254 if possibilities:
255 from difflib import get_close_matches
257 possibilities_ = get_close_matches(option_name, possibilities)
258 else:
259 possibilities_ = None
260 self.possibilities = possibilities_
262 def format_message(self) -> str:
263 if not self.possibilities:
264 return self.message
265 return f"{self.message} {_format_possibilities(self.possibilities)}"
268class NoSuchCommand(UsageError):
269 """Raised if Click attempted to handle a command that does not exist.
271 .. versionadded:: 8.4.0
272 """
274 command_name: t.Final[str]
275 possibilities: t.Final[list[str] | None]
277 def __init__(
278 self,
279 command_name: str,
280 message: str | None = None,
281 possibilities: cabc.Iterable[str] | None = None,
282 ctx: Context | None = None,
283 ) -> None:
284 if message is None:
285 message = _("No such command {name!r}.").format(name=command_name)
287 super().__init__(message, ctx)
288 self.command_name = command_name
290 if possibilities:
291 from difflib import get_close_matches
293 possibilities_ = get_close_matches(command_name, possibilities)
294 else:
295 possibilities_ = None
296 self.possibilities = possibilities_
298 def format_message(self) -> str:
299 if not self.possibilities:
300 return self.message
301 return f"{self.message} {_format_possibilities(self.possibilities)}"
304class BadOptionUsage(UsageError):
305 """Raised if an option is generally supplied but the use of the option
306 was incorrect. This is for instance raised if the number of arguments
307 for an option is not correct.
309 .. versionadded:: 4.0
311 :param option_name: the name of the option being used incorrectly.
312 """
314 option_name: t.Final[str]
316 def __init__(
317 self, option_name: str, message: str, ctx: Context | None = None
318 ) -> None:
319 super().__init__(message, ctx)
320 self.option_name = option_name
323class BadArgumentUsage(UsageError):
324 """Raised if an argument is generally supplied but the use of the argument
325 was incorrect. This is for instance raised if the number of values
326 for an argument is not correct.
328 .. versionadded:: 6.0
329 """
332class NoArgsIsHelpError(UsageError):
333 ctx: Context
335 def __init__(self, ctx: Context) -> None:
336 super().__init__(ctx.get_help(), ctx=ctx)
338 def show(self, file: t.IO[t.Any] | None = None) -> None:
339 echo(self.format_message(), file=file, err=True, color=self.ctx.color)
342class FileError(ClickException):
343 """Raised if a file cannot be opened."""
345 ui_filename: t.Final[str]
346 filename: t.Final[str]
348 def __init__(self, filename: str, hint: str | None = None) -> None:
349 if hint is None:
350 hint = _("unknown error")
352 super().__init__(hint)
353 self.ui_filename = format_filename(filename)
354 self.filename = filename
356 def format_message(self) -> str:
357 return _("Could not open file {filename!r}: {message}").format(
358 filename=self.ui_filename, message=self.message
359 )
362class Abort(RuntimeError):
363 """An internal signalling exception that signals Click to abort."""
366class Exit(RuntimeError):
367 """An exception that indicates that the application should exit with some
368 status code.
370 :param code: the status code to exit with.
371 """
373 __slots__ = ("exit_code",)
375 exit_code: t.Final[int]
377 def __init__(self, code: int = 0) -> None:
378 self.exit_code = code