Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add include and exclude cli options #246

Merged
merged 1 commit into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ These provided arguments and environment variables would result in a merged runt
none_representation = "~"
```

## Configure include and exclude files

Per default `yamlfix`, when run through cli, will include all `*.yaml` and `*.yml` files from the directories passed via the CLI. With `--exclude <glob>` and `--include <glob>` you can include or exclude specific files within those directories.

## Configuration Options

All fields configured in the [YamlfixConfig class](./reference/#yamlfix.model.YamlfixConfig) can be provided through the means mentioned in [Configuration](#configuration). Here are the currently available configuration options with short examples on their impact to provided `yaml`-files.
Expand Down
41 changes: 36 additions & 5 deletions src/yamlfix/entrypoints/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@
log = logging.getLogger(__name__)


def _find_all_yaml_files(dir_: Path) -> List[Path]:
files = [dir_.rglob(f"*.{ext}") for ext in ["yml", "yaml"]]
return [file for list_ in files for file in list_]
def _matches_any_glob(file_to_test: Path, globs: Optional[List[str]]) -> bool:
return any(file_to_test.match(glob) for glob in (globs or []))


def _find_all_yaml_files(
dir_: Path, include_globs: Optional[List[str]], exclude_globs: Optional[List[str]]
) -> List[Path]:
files = [dir_.rglob(glob) for glob in (include_globs or [])]
return [
file
for list_ in files
for file in list_
if not _matches_any_glob(file, exclude_globs)
]


@click.command()
Expand All @@ -43,12 +54,32 @@ def _find_all_yaml_files(dir_: Path) -> List[Path]:
default="YAMLFIX",
help="Read yamlfix relevant environment variables starting with this prefix.",
)
@click.option(
"--exclude",
"-e",
multiple=True,
type=str,
help="Files matching this glob pattern will be ignored.",
)
@click.option(
"--include",
"-i",
multiple=True,
type=str,
default=["*.yaml", "*.yml"],
help=(
"Files matching this glob pattern will be included, "
"unless they are also excluded. Default to '*.yaml' and '*.yml'."
),
)
@click.argument("files", type=str, required=True, nargs=-1)
def cli(
def cli( # pylint: disable=too-many-arguments
files: Tuple[str],
verbose: bool,
check: bool,
config_file: Optional[List[str]],
include: Optional[List[str]],
exclude: Optional[List[str]],
env_prefix: str,
) -> None:
"""Corrects the source code of the specified files.
Expand All @@ -67,7 +98,7 @@ def cli(
real_files = []
for provided_file in paths:
if provided_file.is_dir():
real_files.extend(_find_all_yaml_files(provided_file))
real_files.extend(_find_all_yaml_files(provided_file, include, exclude))
else:
real_files.append(provided_file)
files_to_fix = [file.open("r+") for file in real_files]
Expand Down
28 changes: 28 additions & 0 deletions tests/e2e/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,34 @@ def test_corrects_code_from_stdin(runner: CliRunner) -> None:
assert result.stdout == fixed_source


def test_include_exclude_files(runner: CliRunner, tmp_path: Path) -> None:
"""Correct only files matching include, and ignore files matching exclude."""
include1 = tmp_path / "source_1.yaml"
exclude1 = tmp_path / "source_2.txt"
(tmp_path / "foo").mkdir()
exclude2 = tmp_path / "foo" / "source_3.yaml"
test_files = [include1, exclude1, exclude2]
init_source = "program: yamlfix"
for test_file in test_files:
test_file.write_text(init_source)
fixed_source = dedent(
"""\
---
program: yamlfix
"""
)

result = runner.invoke(
cli,
[str(tmp_path)] + ["--include", "*.yaml", "--exclude", "foo/*.yaml"],
)

assert result.exit_code == 0
assert include1.read_text() == fixed_source
assert exclude1.read_text() == init_source
assert exclude2.read_text() == init_source


@pytest.mark.secondary()
@pytest.mark.parametrize(
("verbose", "requires_fixing"), product([0, 1, 2], [True, False])
Expand Down