Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/click/exceptions.py: 31%
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 .. versionadded:: 8.4.0
255 """
257 def __init__(
258 self,
259 command_name: str,
260 message: str | None = None,
261 possibilities: cabc.Iterable[str] | None = None,
262 ctx: Context | None = None,
263 ) -> None:
264 if message is None:
265 message = _("No such command {name!r}.").format(name=command_name)
267 super().__init__(message, ctx)
268 self.command_name = command_name
269 self.possibilities: list[str] | None = None
270 if possibilities:
271 from difflib import get_close_matches
273 self.possibilities = get_close_matches(command_name, possibilities)
275 def format_message(self) -> str:
276 if not self.possibilities:
277 return self.message
278 return f"{self.message} {_format_possibilities(self.possibilities)}"
281class BadOptionUsage(UsageError):
282 """Raised if an option is generally supplied but the use of the option
283 was incorrect. This is for instance raised if the number of arguments
284 for an option is not correct.
286 .. versionadded:: 4.0
288 :param option_name: the name of the option being used incorrectly.
289 """
291 def __init__(
292 self, option_name: str, message: str, ctx: Context | None = None
293 ) -> None:
294 super().__init__(message, ctx)
295 self.option_name = option_name
298class BadArgumentUsage(UsageError):
299 """Raised if an argument is generally supplied but the use of the argument
300 was incorrect. This is for instance raised if the number of values
301 for an argument is not correct.
303 .. versionadded:: 6.0
304 """
307class NoArgsIsHelpError(UsageError):
308 def __init__(self, ctx: Context) -> None:
309 self.ctx: Context
310 super().__init__(ctx.get_help(), ctx=ctx)
312 def show(self, file: t.IO[t.Any] | None = None) -> None:
313 echo(self.format_message(), file=file, err=True, color=self.ctx.color)
316class FileError(ClickException):
317 """Raised if a file cannot be opened."""
319 def __init__(self, filename: str, hint: str | None = None) -> None:
320 if hint is None:
321 hint = _("unknown error")
323 super().__init__(hint)
324 self.ui_filename: str = format_filename(filename)
325 self.filename = filename
327 def format_message(self) -> str:
328 return _("Could not open file {filename!r}: {message}").format(
329 filename=self.ui_filename, message=self.message
330 )
333class Abort(RuntimeError):
334 """An internal signalling exception that signals Click to abort."""
337class Exit(RuntimeError):
338 """An exception that indicates that the application should exit with some
339 status code.
341 :param code: the status code to exit with.
342 """
344 __slots__ = ("exit_code",)
346 def __init__(self, code: int = 0) -> None:
347 self.exit_code: int = code