Skip to content

Commit

Permalink
Merge pull request #113 from dwreeves/matrix-strategy-for-ci
Browse files Browse the repository at this point in the history
Add matrix strategy for CI + fix for Click 7.x.
  • Loading branch information
ewels authored Jul 16, 2023
2 parents 8e7523c + 6a1d888 commit 12f52d2
Show file tree
Hide file tree
Showing 98 changed files with 2,457 additions and 30 deletions.
28 changes: 18 additions & 10 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
name: Test Coverage
on:
push:
pull_request:

on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.9.x, 3.10.x, 3.11.x]
click: [7.0.*, 8.0.*, 8.1.*] # Skip click 7.1 since regression coverage is strictly higher in 7.0.
rich: [12.*, 13.*]
steps:
- name: Checkout
- name: Check out the repo
uses: actions/checkout@v3

- name: Setup Python
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.7.13"
python-version: ${{ matrix.python }}

- name: Install Dependencies
run: pip install '.[dev]'
- name: Install dependencies
run: |
pip install '.[dev]'
pip install --upgrade "click==$CLICK_VERSION"
pip install --upgrade "rich==$RICH_VERSION"
env:
CLICK_VERSION: ${{ matrix.click }}
RICH_VERSION: ${{ matrix.rich }}

- name: Run Tests
- name: Run tests
run: pytest --cov --cov-report xml
18 changes: 14 additions & 4 deletions .github/workflows/test-examples.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
name: Test Examples
on: [push, pull_request]
jobs:
test_examples:
examples:
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.7.x, 3.8.x, 3.9.x, 3.10.x, 3.11.x]
click: [7.0.*, 8.0.*, 8.1.*] # Skip click 7.1 since regression coverage is strictly higher in 7.0.
steps:
- name: Check out the repo
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}

- name: Install rich-click
run: pip install .
- name: Install rich-click and click
run: |
pip install .
pip install --upgrade "click==$CLICK_VERSION"
env:
CLICK_VERSION: ${{ matrix.click }}

- name: Test examples
run: |
Expand Down
14 changes: 14 additions & 0 deletions src/rich_click/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from . import rich_click # noqa: F401

from rich_click._compat_click import CLICK_IS_BEFORE_VERSION_8X as _CLICK_IS_BEFORE_VERSION_8X
from rich_click.rich_command import RichCommand
from rich_click.rich_context import RichContext
from rich_click.rich_group import RichGroup
Expand Down Expand Up @@ -110,6 +111,19 @@ def rich_config(console: Optional[Console] = None, help_config: Optional[RichHel
help_config: Rich help configuration that is used internally to format help messages and exceptions
Defaults to None.
"""
if _CLICK_IS_BEFORE_VERSION_8X:

def decorator_with_warning(obj):
import warnings

warnings.warn(
"`rich_config()` does not work with versions of click prior to version 8.0.0."
" Please update to a newer version of click to use this functionality.",
RuntimeWarning,
)
return obj

return decorator_with_warning

@overload
def decorator(obj: Union[RichCommand, RichGroup]) -> Union[RichCommand, RichGroup]:
Expand Down
5 changes: 5 additions & 0 deletions src/rich_click/_compat_click.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from distutils.version import LooseVersion

import click

CLICK_IS_BEFORE_VERSION_8X = LooseVersion(click.__version__) < LooseVersion("8.0.0")
3 changes: 2 additions & 1 deletion src/rich_click/rich_click.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ def _get_rich_formatter(formatter: Optional[click.HelpFormatter] = None) -> Rich
_formatter = formatter
return _formatter

return RichHelpFormatter(config=get_module_help_configuration())
_formatter = RichHelpFormatter(config=get_module_help_configuration())
return _formatter


def _make_rich_rext(
Expand Down
18 changes: 16 additions & 2 deletions src/rich_click/rich_group.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import sys
from typing import Optional, Type
from typing import Any, Callable, Optional, overload, Type, Union

import click

Expand All @@ -17,7 +17,7 @@ class RichGroup(click.Group):
"""

context_class: Type[RichContext] = RichContext
command_class = RichCommand
command_class: Type[RichCommand] = RichCommand
group_class = type

def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -77,3 +77,17 @@ def main(self, *args, standalone_mode: bool = True, **kwargs):

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

@overload
def command(self, __func: Callable[..., Any]) -> click.Command:
...

@overload
def command(self, *args: Any, **kwargs: Any) -> Callable[[Callable[..., Any]], click.Command]:
...

def command(self, *args: Any, **kwargs: Any) -> Union[Callable[[Callable[..., Any]], click.Command], click.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)
7 changes: 7 additions & 0 deletions src/rich_click/rich_help_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@
import rich.theme
from rich.console import Console

from rich_click._compat_click import CLICK_IS_BEFORE_VERSION_8X
from rich_click.rich_help_configuration import RichHelpConfiguration


class TerminalBuffer(StringIO):
"""String buffer that should be detected as a terminal device."""

def write(self, __s: str) -> int:
if CLICK_IS_BEFORE_VERSION_8X:
return sys.stdout.write(__s)
else:
return super().write(__s)

def isatty(self) -> bool:
return sys.stdout.isatty()

Expand Down
30 changes: 24 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from typing_extensions import Protocol

import rich_click.rich_click as rc
from rich_click._compat_click import CLICK_IS_BEFORE_VERSION_8X
from rich_click.rich_command import RichCommand
from rich_click.rich_group import RichGroup
from rich_click.rich_help_configuration import OptionHighlighter, RichHelpConfiguration
Expand All @@ -40,6 +41,11 @@ def expectations_dir(root_dir: Path):
return root_dir / "expectations"


@pytest.fixture
def click_major_version() -> int:
return int(click.__version__.split(".")[0])


class AssertStr:
def __call__(self, actual: str, expectation: Union[str, Path]):
"""Assert strings by normalizining line endings
Expand All @@ -61,8 +67,8 @@ def assertion(actual: str, expectation: Union[str, Path]):
expected = ""
else:
expected = expectation
normalized_expected = [line.strip() for line in expected.strip().splitlines() if line.strip()]
normalized_actual = [line.strip() for line in actual.strip().splitlines() if line.strip()]
normalized_expected = "\n".join([line.strip() for line in expected.strip().splitlines() if line.strip()])
normalized_actual = "\n".join([line.strip() for line in actual.strip().splitlines() if line.strip()])

try:
assert normalized_expected == normalized_actual
Expand Down Expand Up @@ -109,6 +115,7 @@ def assertion(actual: Dict[str, Any], expectation: Union[Path, Dict[str, Any]]):
# need to perform a roundtrip to convert to
# supported json data types (i.e. tuple -> list, datetime -> str, etc...)
actual = roundtrip(actual)

try:
assert actual == expected
except Exception:
Expand All @@ -130,7 +137,12 @@ def initialize_rich_click():
reload(rc)
# default config settings from https://github.com/Textualize/rich/blob/master/tests/render.py
rc.MAX_WIDTH = 100
rc.COLOR_SYSTEM = "truecolor"

# Click <8 tests fail unless we set the COLOR_SYSTEM to None.
if CLICK_IS_BEFORE_VERSION_8X:
rc.COLOR_SYSTEM = None
else:
rc.COLOR_SYSTEM = "truecolor"
rc.FORCE_TERMINAL = True


Expand Down Expand Up @@ -236,6 +248,7 @@ def assert_rich_format(
load_command,
assert_dicts,
assert_str,
click_major_version,
):
def config_to_dict(config: RichHelpConfiguration):
config_dict = asdict(config)
Expand Down Expand Up @@ -263,14 +276,19 @@ def assertion(
result = invoke(command, args)

assert command.formatter is not None

if error:
assert isinstance(result.exception, error)
actual = replace_link_ids(command.formatter.getvalue())
assert result.exit_code != 0
if CLICK_IS_BEFORE_VERSION_8X:
actual = replace_link_ids(result.stdout)
else:
actual = replace_link_ids(command.formatter.getvalue())
else:
actual = replace_link_ids(result.stdout)

expectation_output_path = expectations_dir / f"{request.node.name}.out"
expectation_config_path = expectations_dir / f"{request.node.name}.config.json"
expectation_output_path = expectations_dir / f"{request.node.name}-click{click_major_version}.out"
expectation_config_path = expectations_dir / f"{request.node.name}-click{click_major_version}.config.json"
if os.getenv("UPDATE_EXPECTATIONS"):
with open(expectation_output_path, "w") as stream:
stream.write(actual)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"style_option": "bold cyan",
"style_argument": "bold cyan",
"style_command": "bold cyan",
"style_switch": "bold green",
"style_metavar": "bold yellow",
"style_metavar_append": "dim yellow",
"style_metavar_separator": "dim",
"style_header_text": "",
"style_footer_text": "",
"style_usage": "yellow",
"style_usage_command": "bold",
"style_deprecated": "red",
"style_helptext_first_line": "",
"style_helptext": "dim",
"style_option_help": "",
"style_option_default": "dim",
"style_option_envvar": "dim yellow",
"style_required_short": "red",
"style_required_long": "dim red",
"style_options_panel_border": "dim",
"align_options_panel": "left",
"style_options_table_show_lines": false,
"style_options_table_leading": 0,
"style_options_table_pad_edge": false,
"style_options_table_padding": [0, 1],
"style_options_table_box": "",
"style_options_table_row_styles": null,
"style_options_table_border_style": null,
"style_commands_panel_border": "dim",
"align_commands_panel": "left",
"style_commands_table_show_lines": false,
"style_commands_table_leading": 0,
"style_commands_table_pad_edge": false,
"style_commands_table_padding": [0, 1],
"style_commands_table_box": "",
"style_commands_table_row_styles": null,
"style_commands_table_border_style": null,
"style_errors_panel_border": "red",
"align_errors_panel": "left",
"style_errors_suggestion": "dim",
"style_aborted": "red",
"max_width": 100,
"color_system": null,
"force_terminal": true,
"header_text": null,
"footer_text": null,
"deprecated_string": "(Deprecated) ",
"default_string": "[default: {}]",
"envvar_string": "[env var: {}]",
"required_short_string": "*",
"required_long_string": "[required]",
"range_string": " [{}]",
"append_metavars_help_string": "({})",
"arguments_panel_title": "Arguments",
"options_panel_title": "Options",
"commands_panel_title": "Commands",
"errors_panel_title": "Error",
"errors_suggestion": null,
"errors_epilogue": null,
"aborted_text": "Aborted.",
"show_arguments": true,
"show_metavars_column": true,
"append_metavars_help": false,
"group_arguments_options": false,
"option_envvar_first": false,
"use_markdown": false,
"use_markdown_emoji": true,
"use_rich_markup": false,
"command_groups": {},
"option_groups": {},
"use_click_short_help": false,
"highlighter": [
"(^|\\W)(?P<switch>\\-\\w+)(?![a-zA-Z0-9])",
"(^|\\W)(?P<option>\\-\\-[\\w\\-]+)(?![a-zA-Z0-9])",
"(?P<metavar>\\<[^\\>]+\\>)"
],
"legacy_windows": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

Usage: cli [OPTIONS] INPUT

My amazing tool does all the things.
This is a minimal example based on documentation from the 'click' package.
You can try using --help at the top level and also for specific group subcommands.

╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────────╮
│ * INPUT PATH [required] │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ --type TEXT Type of file to sync [default: files] │
│ --all Sync all the things? │
│ --debug Enable debug mode │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯

Loading

0 comments on commit 12f52d2

Please sign in to comment.