diff --git a/CHANGES.rst b/CHANGES.rst index 4a2a938e08..377273f68b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,6 @@ .. currentmodule:: click -Version 8.4.dev +Version 8.4.1 ------------------ Unreleased diff --git a/pyproject.toml b/pyproject.toml index d4d40e2e12..833209b67a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "click" -version = "8.4.dev" +version = "8.4.1.dev" description = "Composable command line interface toolkit" readme = "README.md" license = "BSD-3-Clause" diff --git a/src/click/exceptions.py b/src/click/exceptions.py index 4914d9cfe2..8ef08dae16 100644 --- a/src/click/exceptions.py +++ b/src/click/exceptions.py @@ -36,13 +36,16 @@ class ClickException(Exception): """An exception that Click can handle and show to the user.""" #: The exit code for this exception. - exit_code = 1 + exit_code: t.ClassVar[int] = 1 + + show_color: t.Final[bool | None] + message: t.Final[str] def __init__(self, message: str) -> None: super().__init__(message) # The context will be removed by the time we print the message, so cache # the color settings here to be used later on (in `show`) - self.show_color: bool | None = resolve_color_default() + self.show_color = resolve_color_default() self.message = message def format_message(self) -> str: @@ -71,12 +74,15 @@ class UsageError(ClickException): fill in the context automatically in some situations. """ - exit_code = 2 + exit_code: t.ClassVar[int] = 2 + + ctx: Context | None + cmd: t.Final[Command | None] def __init__(self, message: str, ctx: Context | None = None) -> None: super().__init__(message) self.ctx = ctx - self.cmd: Command | None = self.ctx.command if self.ctx else None + self.cmd = self.ctx.command if self.ctx else None def show(self, file: t.IO[t.Any] | None = None) -> None: if file is None: @@ -123,6 +129,9 @@ class BadParameter(UsageError): each item is quoted and separated. """ + param: Parameter | None + param_hint: cabc.Sequence[str] | str | None + def __init__( self, message: str, @@ -159,6 +168,8 @@ class MissingParameter(BadParameter): ``'option'`` or ``'argument'``. """ + param_type: t.Final[str | None] + def __init__( self, message: str | None = None, @@ -224,6 +235,9 @@ class NoSuchOption(UsageError): .. versionadded:: 4.0 """ + option_name: t.Final[str] + possibilities: t.Final[list[str] | None] + def __init__( self, option_name: str, @@ -236,11 +250,15 @@ def __init__( super().__init__(message, ctx) self.option_name = option_name - self.possibilities: list[str] | None = None + + # this temp variable avoids mypy complaining self.possibilities "reassignment" if possibilities: from difflib import get_close_matches - self.possibilities = get_close_matches(option_name, possibilities) + possibilities_ = get_close_matches(option_name, possibilities) + else: + possibilities_ = None + self.possibilities = possibilities_ def format_message(self) -> str: if not self.possibilities: @@ -251,6 +269,9 @@ def format_message(self) -> str: class NoSuchCommand(UsageError): """Raised if Click attempted to handle a command that does not exist.""" + command_name: t.Final[str] + possibilities: t.Final[list[str] | None] + def __init__( self, command_name: str, @@ -263,11 +284,15 @@ def __init__( super().__init__(message, ctx) self.command_name = command_name - self.possibilities: list[str] | None = None + + # this temp variable avoids mypy complaining self.possibilities "reassignment" if possibilities: from difflib import get_close_matches - self.possibilities = get_close_matches(command_name, possibilities) + possibilities_ = get_close_matches(command_name, possibilities) + else: + possibilities_ = None + self.possibilities = possibilities_ def format_message(self) -> str: if not self.possibilities: @@ -285,6 +310,8 @@ class BadOptionUsage(UsageError): :param option_name: the name of the option being used incorrectly. """ + option_name: t.Final[str] + def __init__( self, option_name: str, message: str, ctx: Context | None = None ) -> None: @@ -302,8 +329,9 @@ class BadArgumentUsage(UsageError): class NoArgsIsHelpError(UsageError): + ctx: Context + def __init__(self, ctx: Context) -> None: - self.ctx: Context super().__init__(ctx.get_help(), ctx=ctx) def show(self, file: t.IO[t.Any] | None = None) -> None: @@ -313,12 +341,15 @@ def show(self, file: t.IO[t.Any] | None = None) -> None: class FileError(ClickException): """Raised if a file cannot be opened.""" + ui_filename: t.Final[str] + filename: t.Final[str] + def __init__(self, filename: str, hint: str | None = None) -> None: if hint is None: hint = _("unknown error") super().__init__(hint) - self.ui_filename: str = format_filename(filename) + self.ui_filename = format_filename(filename) self.filename = filename def format_message(self) -> str: @@ -340,5 +371,7 @@ class Exit(RuntimeError): __slots__ = ("exit_code",) + exit_code: t.Final[int] + def __init__(self, code: int = 0) -> None: - self.exit_code: int = code + self.exit_code = code diff --git a/uv.lock b/uv.lock index 9b2d6d0fa9..5f7aca8d4e 100644 --- a/uv.lock +++ b/uv.lock @@ -173,7 +173,7 @@ wheels = [ [[package]] name = "click" -version = "8.4.dev0" +version = "8.4.1.dev0" source = { editable = "." } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" },