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

Add option to exclude files #212

Merged
merged 2 commits into from
Nov 6, 2024
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
21 changes: 19 additions & 2 deletions src/doccmd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
# we write the file ``_setuptools_scm_version.py`` on ``pip install``.
from ._setuptools_scm_version import __version__


T = TypeVar("T")


Expand Down Expand Up @@ -111,6 +110,7 @@ def _get_file_paths(
document_paths: Sequence[Path],
file_suffixes: Sequence[str],
max_depth: int,
exclude_patterns: Sequence[str],
) -> Sequence[Path]:
"""
Get the file paths from the given document paths (files and directories).
Expand All @@ -127,7 +127,10 @@ def _get_file_paths(
if len(path_part.relative_to(path).parts) <= max_depth
)
for new_file_path in new_file_paths:
if new_file_path.is_file():
if new_file_path.is_file() and not any(
new_file_path.match(path_pattern=pattern)
for pattern in exclude_patterns
):
file_paths[new_file_path] = True
return tuple(file_paths.keys())

Expand Down Expand Up @@ -548,6 +551,18 @@ def _run_args_against_docs(
show_default=False,
help="Maximum depth to search for files in directories.",
)
@click.option(
"--exclude",
"exclude_patterns",
type=str,
multiple=True,
help=(
"A glob-style pattern that matches file paths to ignore while "
"recursively discovering files in directories. "
"This option can be used multiple times. "
"Use forward slashes on all platforms."
),
)
@beartype
def main(
*,
Expand All @@ -563,6 +578,7 @@ def main(
rst_suffixes: Sequence[str],
myst_suffixes: Sequence[str],
max_depth: int,
exclude_patterns: Sequence[str],
) -> None:
"""Run commands against code blocks in the given documentation files.

Expand All @@ -580,6 +596,7 @@ def main(
document_paths=document_paths,
file_suffixes=[*myst_suffixes, *rst_suffixes],
max_depth=max_depth,
exclude_patterns=exclude_patterns,
)

_validate_files_are_known_markup_types(
Expand Down
134 changes: 134 additions & 0 deletions tests/test_doccmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2013,3 +2013,137 @@ def test_max_depth(tmp_path: Path) -> None:

assert result.stdout == expected_output
assert result.stderr == ""


def test_exclude_files_from_recursed_directories(tmp_path: Path) -> None:
"""
Files with names matching the exclude pattern are not processed when
recursing directories.
"""
runner = CliRunner(mix_stderr=False)
rst_file = tmp_path / "example.rst"
rst_content = """\
.. code-block:: python

rst_1_block
"""
rst_file.write_text(data=rst_content, encoding="utf-8")

sub_directory = tmp_path / "subdir"
sub_directory.mkdir()
rst_file_in_sub_directory = sub_directory / "subdir_example.rst"
subdir_rst_content = """\
.. code-block:: python

rst_subdir_1_block
"""
rst_file_in_sub_directory.write_text(
data=subdir_rst_content,
encoding="utf-8",
)

excluded_file = sub_directory / "exclude_me.rst"
excluded_content = """\
.. code-block:: python

excluded_block
"""
excluded_file.write_text(data=excluded_content, encoding="utf-8")

arguments = [
"--language",
"python",
"--no-pad-file",
"--command",
"cat",
"--exclude",
"exclude_*e.*",
str(tmp_path),
]
result = runner.invoke(
cli=main,
args=arguments,
catch_exceptions=False,
)
assert result.exit_code == 0, result.stderr
expected_output = textwrap.dedent(
text="""\
rst_1_block
rst_subdir_1_block
""",
)

assert result.stdout == expected_output
assert result.stderr == ""


def test_multiple_exclude_patterns(tmp_path: Path) -> None:
"""
Files matching any of the exclude patterns are not processed when recursing
directories.
"""
runner = CliRunner(mix_stderr=False)
rst_file = tmp_path / "example.rst"
rst_content = """\
.. code-block:: python

rst_1_block
"""
rst_file.write_text(data=rst_content, encoding="utf-8")

sub_directory = tmp_path / "subdir"
sub_directory.mkdir()
rst_file_in_sub_directory = sub_directory / "subdir_example.rst"
subdir_rst_content = """\
.. code-block:: python

rst_subdir_1_block
"""
rst_file_in_sub_directory.write_text(
data=subdir_rst_content,
encoding="utf-8",
)

excluded_file_1 = sub_directory / "exclude_me.rst"
excluded_content_1 = """\
.. code-block:: python

excluded_block_1
"""
excluded_file_1.write_text(data=excluded_content_1, encoding="utf-8")

excluded_file_2 = sub_directory / "ignore_me.rst"
excluded_content_2 = """\
.. code-block:: python

excluded_block_2
"""
excluded_file_2.write_text(data=excluded_content_2, encoding="utf-8")

arguments = [
"--language",
"python",
"--no-pad-file",
"--command",
"cat",
"--exclude",
"exclude_*e.*",
"--exclude",
"ignore_*e.*",
str(tmp_path),
]
result = runner.invoke(
cli=main,
args=arguments,
catch_exceptions=False,
)
assert result.exit_code == 0, result.stderr
expected_output = textwrap.dedent(
text="""\
rst_1_block
rst_subdir_1_block
""",
)

assert result.stdout == expected_output
assert result.stderr == ""
5 changes: 5 additions & 0 deletions tests/test_doccmd/test_help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ Options:
use `--myst-extension=.`. [default: .md]
--max-depth INTEGER RANGE Maximum depth to search for files in
directories. [x>=1]
--exclude TEXT A glob-style pattern that matches file paths
to ignore while recursively discovering files
in directories. This option can be used
multiple times. Use forward slashes on all
platforms.
--help Show this message and exit.