Skip to content

Commit

Permalink
make mypy work in strict mode
Browse files Browse the repository at this point in the history
  • Loading branch information
dwreeves committed Oct 7, 2023
1 parent 57f7e12 commit 5b09dc2
Show file tree
Hide file tree
Showing 21 changed files with 58 additions and 50 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ This release comes after merging a huge pull-request from [@BrutalSimplicity](ht
This PR closes a number of issues:

- [#25](https://github.com/ewels/rich-click/issues/25): Add tests!
- [#38](https://github.com/ewels/rich-click/issues/38): Support `click.MultiCommand`
- [#90](https://github.com/ewels/rich-click/issues/90): `click.ClickException` should output to `stderr`
- [#88](https://github.com/ewels/rich-click/issues/88): Rich Click breaks contract of Click's `format_help` and its callers
- [#18](https://github.com/ewels/rich-click/issues/18): Options inherited from context settings aren't applied
- [#114](https://github.com/ewels/rich-click/issues/114): `ctx.exit(exit_code)` not showing nonzero exit codes.

In addition, we merged another large pull-request that adds **full static type-checking support** (see issue [#85](https://github.com/ewels/rich-click/issues/85)), and fixes many bugs - see PR [#126](https://github.com/ewels/rich-click/pull/126).

In addition:

- Add new style option `STYLE_COMMAND` [[#102](https://github.com/ewels/rich-click/pull/102)]
- Add new style option `WIDTH` (in addition to `MAX_WIDTH`), thanks to [@ealap](httpsd://github.com/ealap) [[#110](https://github.com/ewels/rich-click/pull/110)]
- Updated styling for `Usage:` line to avoid off-target effects [[#108](https://github.com/ewels/rich-click/issues/108)]
- Click 7.x support has been deprecated. [[#117](https://github.com/ewels/rich-click/pull/117)]
- Fixed error where `ctx.exit(exit_code)` would not show nonzero exit codes.[[#114](https://github.com/ewels/rich-click/issues/114)]
- Support `click.MultiCommand`. [[#38](https://github.com/ewels/rich-click/issues/38)]:

## Version 1.6.1 (2023-01-19)

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ profile = "black"
[tool.mypy]
python_version = "3.8"
scripts_are_modules = "True"
# strict = "True"
strict = "True"

[tool.pyright]
include = ["src"]
Expand Down
5 changes: 2 additions & 3 deletions src/rich_click/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# We need to manually import these instead of `from click import *` to force mypy to recognize a few type annotation overrides for the rich_click decorators.
from click.core import Argument as Argument
from click.core import Command as Command
from click.core import CommandCollection as CommandCollection
from click.core import Context as Context
from click.core import Group as Group
from click.core import Option as Option
Expand Down Expand Up @@ -83,8 +82,6 @@


def __getattr__(name: str) -> object:
import click

from rich_click._compat_click import CLICK_IS_BEFORE_VERSION_9X

if name == "RichMultiCommand" and CLICK_IS_BEFORE_VERSION_9X:
Expand All @@ -100,4 +97,6 @@ def __getattr__(name: str) -> object:
return RichMultiCommand

else:
import click

return getattr(click, name)
6 changes: 3 additions & 3 deletions src/rich_click/rich_click.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ def rich_format_help(
if isinstance(param, click.core.Argument) and not config.group_arguments_options:
argument_group_options.append(param.opts[0])
else:
list_of_option_groups: List = option_groups[-1]["options"] # type: ignore[assignment]
list_of_option_groups: List[str] = option_groups[-1]["options"] # type: ignore[assignment]
list_of_option_groups.append(param.opts[0])

# If we're not grouping arguments and we got some, prepend before default options
Expand Down Expand Up @@ -643,7 +643,7 @@ class MetavarHighlighter(RegexHighlighter):
if command in cmd_group.get("commands", []):
break
else:
commands: List = cmd_groups[-1]["commands"] # type: ignore[assignment]
commands: List[str] = cmd_groups[-1]["commands"] # type: ignore[assignment]
commands.append(command)

# Print each command group panel
Expand Down Expand Up @@ -717,7 +717,7 @@ class MetavarHighlighter(RegexHighlighter):
console.print(Padding(_make_rich_rext(config.footer_text, config.style_footer_text, formatter), (1, 1, 0, 1)))


def rich_format_error(self: click.ClickException, formatter: Optional[RichHelpFormatter] = None):
def rich_format_error(self: click.ClickException, formatter: Optional[RichHelpFormatter] = None) -> None:
"""Print richly formatted click errors.
Called by custom exception handler to print richly formatted click errors.
Expand Down
14 changes: 8 additions & 6 deletions src/rich_click/rich_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

import click
from click.utils import make_str, PacifyFlushWrapper
from rich.console import Console

from rich_click._compat_click import CLICK_IS_BEFORE_VERSION_8X
from rich_click.rich_click import rich_abort_error, rich_format_error, rich_format_help
from rich_click.rich_context import RichContext
from rich_click.rich_help_configuration import RichHelpConfiguration
from rich_click.rich_help_formatter import RichHelpFormatter


Expand Down Expand Up @@ -41,7 +43,7 @@ def _register_rich_context_settings_from_callback(self) -> None:
del self.callback.__rich_context_settings__

@property
def console(self):
def console(self) -> Optional[Console]:
"""Rich Console.
This is a separate instance from the help formatter that allows full control of the
Expand All @@ -52,7 +54,7 @@ def console(self):
return self.context_settings.get("rich_console")

@property
def help_config(self):
def help_config(self) -> Optional[RichHelpConfiguration]:
"""Rich Help Configuration."""
return self.context_settings.get("rich_help_config")

Expand Down Expand Up @@ -156,7 +158,7 @@ def main(
sys.stderr.write(self.formatter.getvalue())
sys.exit(1)

def format_help(self, ctx: click.Context, formatter: click.HelpFormatter):
def format_help(self, ctx: click.Context, formatter: click.HelpFormatter) -> None:
rich_format_help(self, ctx, formatter)


Expand All @@ -171,7 +173,7 @@ class RichMultiCommand(RichCommand, click.MultiCommand):
"""

@wraps(click.MultiCommand.__init__)
def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any) -> None: # type: ignore[no-untyped-def]
"""Initialize RichGroup class."""
click.MultiCommand.__init__(self, *args, **kwargs)
self._register_rich_context_settings_from_callback()
Expand All @@ -188,7 +190,7 @@ class RichGroup(RichCommand, click.Group):
group_class = type

@wraps(click.Group.__init__)
def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any) -> None:
"""Initialize RichGroup class."""
click.Group.__init__(self, *args, **kwargs)
self._register_rich_context_settings_from_callback()
Expand All @@ -209,4 +211,4 @@ def command(
# This method override is required for Click 7.x compatibility.
# (The command_class ClassVar was not added until 8.0.)
kwargs.setdefault("cls", self.command_class)
return super().command(*args, **kwargs)
return super().command(*args, **kwargs) # type: ignore[no-any-return]
2 changes: 1 addition & 1 deletion src/rich_click/rich_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(

self.help_config = rich_help_config

def make_formatter(self):
def make_formatter(self) -> RichHelpFormatter:
"""Create the Rich Help Formatter."""
return self.formatter_class(
width=self.terminal_width, max_width=self.max_content_width, config=self.help_config
Expand Down
Empty file added tests/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion tests/fixtures/context_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
show_default="show me in c8+",
help="Show 'default: (show me in c8+)' in click>=8.0. In click 7, no default is shown.",
)
def cli(a: str, b: str, c: str, d: str):
def cli(a: str, b: str, c: str, d: str) -> None:
"""
Test cases for context_settings.
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/custom_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
)
@click.option("--all", is_flag=True, help="Sync all the things?")
@click.option("--debug", is_flag=True, default=False, help="Enable debug mode")
def cli(input, type, all, debug) -> None:
def cli(input: str, type: str, all: bool, debug: bool) -> None:
"""
My amazing tool does all the things.
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/declarative.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

@click.group(cls=RichGroup)
@click.option("--debug/--no-debug", default=False)
def cli(debug) -> None:
def cli(debug: bool) -> None:
"""
My amazing tool does all the things.
Expand Down
4 changes: 2 additions & 2 deletions tests/fixtures/envvar.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

@click.group(context_settings=dict(auto_envvar_prefix="GREETER"))
@click.option("--debug/--no-debug")
def cli(debug) -> None:
def cli(debug: bool) -> None:
click.echo(f"Debug mode is {'on' if debug else 'off'}")


Expand All @@ -29,7 +29,7 @@ def cli(debug) -> None:
show_default=True,
help="This can be set via env var EMAIL or EMAIL_ADDRESS",
)
def greet(username, nickname, email) -> None:
def greet(username: str, nickname: str, email: str) -> None:
click.echo(f"Hello {username} ({nickname}) with email {email}!")


Expand Down
14 changes: 7 additions & 7 deletions tests/fixtures/groups_sorting.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
help="Show the debug log messages",
)
@click.version_option("1.23", prog_name="mytool")
def cli(type, debug):
def cli(type: str, debug: bool) -> None:
"""
My amazing tool does all the things.
Expand All @@ -70,30 +70,30 @@ def cli(type, debug):


@cli.command()
@click.option("--input", "-i", required=True, help="Input path")
@click.option("--input", "-i", "input_", required=True, help="Input path")
@click.option("--output", "-o", help="Output path")
@click.option("--all", is_flag=True, help="Sync all the things?")
@click.option("--all", "all_", is_flag=True, help="Sync all the things?")
@click.option("--overwrite", is_flag=True, help="Overwrite local files")
def sync(input, output, all, overwrite):
def sync(input_: str, output: str, all_: bool, overwrite: bool) -> None:
"""Synchronise all your files between two places."""
print("Syncing")


@cli.command()
@click.option("--all", is_flag=True, help="Get everything")
def download(all):
def download(all: bool) -> None:
"""Pretend to download some files from somewhere."""
print("Downloading")


@cli.command()
def auth():
def auth() -> None:
"""Authenticate the app."""
print("Downloading")


@cli.command()
def config():
def config() -> None:
"""Set up the configuration."""
print("Downloading")

Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
)
@click.option("--all", is_flag=True, help="Sync\n 1. all\n 2. the\n 3. things?")
@click.option("--debug", is_flag=True, help="# Enable `debug mode`")
def cli(input, type, all, debug) -> None:
def cli(input: str, type: str, all: bool, debug: bool) -> None:
"""
My amazing tool does _**all the things**_.
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/metavars.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
show_default=True,
help="This click choice has loads of options.",
)
def cli(debug, number) -> None:
def cli(debug: bool, number: str) -> None:
"""
My amazing tool does all the things.
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/metavars_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
show_default=True,
help="This click choice has loads of options.",
)
def cli(debug, number) -> None:
def cli(debug: bool, number: str) -> None:
"""
My amazing tool does all the things.
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/rich_markup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
)
@click.option("--all", is_flag=True, help="Sync all the things?")
@click.option("--debug", is_flag=True, help="Enable :point_right: [yellow]debug mode[/] :point_left:")
def cli(input, type, all, debug):
def cli(input: str, type: str, all: bool, debug: bool) -> None:
"""
My amazing tool does [black on blue] all the things [/].
Expand Down
6 changes: 3 additions & 3 deletions tests/fixtures/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Double newlines are preserved.""",
)
def cli(debug) -> None:
def cli(debug: bool) -> None:
"""
My amazing tool does all the things.
Expand All @@ -33,15 +33,15 @@ def cli(debug) -> None:
help="Type of file to sync",
)
@click.option("--all", is_flag=True)
def sync(type, all) -> None:
def sync(type: str, all: bool) -> None:
"""Synchronise all your files between two places.
Example command that doesn't do much except print to the terminal."""
print("Syncing")


@cli.command(short_help="Optionally use short-help for the group help text")
@click.option("--all", is_flag=True, help="Get everything")
def download(all) -> None:
def download(all: bool) -> None:
"""
Pretend to download some files from
somewhere. Multi-line help strings are unwrapped
Expand Down
6 changes: 3 additions & 3 deletions tests/fixtures/table_alignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
help="Show the debug log messages",
)
@click.version_option("1.23", prog_name="mytool")
def cli(type, debug) -> None:
def cli(type: str, debug: bool) -> None:
"""
My amazing tool does all the things.
Expand All @@ -77,7 +77,7 @@ def cli(type, debug) -> None:
@click.option("--output", "-o", help="Output path")
@click.option("--all", is_flag=True, help="Sync all the things?")
@click.option("--overwrite", is_flag=True, help="Overwrite local files")
def sync(input, output, all, overwrite) -> None:
def sync(input: str, output: str, all: bool, overwrite: bool) -> None:
"""Synchronise all your files between two places."""
print("Syncing")

Expand All @@ -87,7 +87,7 @@ def sync(input, output, all, overwrite) -> None:

@cli.command()
@click.option("--all", is_flag=True, help="Get everything")
def download(all) -> None:
def download(all: bool) -> None:
"""Pretend to download some files from somewhere."""
print("Downloading")

Expand Down
10 changes: 5 additions & 5 deletions tests/fixtures/table_styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
""",
)
@click.version_option("1.23", prog_name="mytool")
def cli(type, debug):
def cli(type: str, debug: bool) -> None:
"""
My amazing tool does all the things.
Expand All @@ -73,7 +73,7 @@ def cli(type, debug):
@click.option("--output", "-o", help="Output path")
@click.option("--all", is_flag=True, help="Sync all the things?")
@click.option("--overwrite", is_flag=True, help="Overwrite local files")
def sync(input, output, all, overwrite):
def sync(input: str, output: str, all: bool, overwrite: bool) -> None:
"""
Synchronise all your files between two places.
Curabitur congue eget lorem in lacinia.
Expand All @@ -96,7 +96,7 @@ def sync(input, output, all, overwrite):

@cli.command()
@click.option("--all", is_flag=True, help="Get everything")
def download(all):
def download(all: bool) -> None:
"""
Pretend to download some files from somewhere.
Integer bibendum libero nunc, sed aliquet ex tincidunt vel.
Expand All @@ -112,7 +112,7 @@ def download(all):


@cli.command()
def auth():
def auth() -> None:
"""
Authenticate the app.
Duis lacus nibh, feugiat a nibh a, commodo dictum libero.
Expand All @@ -128,7 +128,7 @@ def auth():


@cli.command()
def config():
def config() -> None:
"""
Set up the configuration.
Sed accumsan ornare odio dictum aliquam.
Expand Down
Loading

0 comments on commit 5b09dc2

Please sign in to comment.