Skip to content

Commit

Permalink
Add --exclude-from option to CLI
Browse files Browse the repository at this point in the history
Include a few tests demonstrating the successful use of --exclude-from.
Rely on unit tests in previous commits for verifying the underlying
exclude-from functionality.
  • Loading branch information
jherland committed Mar 12, 2024
1 parent d9ed0df commit b6407f2
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 8 deletions.
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,6 @@ fawltydeps --exclude tests/

The format of the exclude patterns is the same as used by `.gitignore` files,
[see here for a full description](https://git-scm.com/docs/gitignore#_pattern_format).
(Note that some patterns that must be interpreted relative to the location of a
`.gitignore` file are not (yet) supported by FawltyDeps. Search for "relative"
in the linked page to see which pattern types are not yet supported.)

When the `--exclude` option is not specified, its default value is `".*"`, which
matches all paths that start with a dot (`.`), aka. "hidden" paths. In the above
Expand All @@ -324,8 +321,18 @@ example, if you want to exclude both hidden paths, and everything under
fawltydeps --exclude tests/ ".*"
```

The `--exclude` patterns have lower priority than any paths you pass directly
on the command line, e.g. in this command:
(The extra quotes here are needed to prevent the shell from interpreting and
replacing the `*` wildcard.)

You can also point to exclude patterns stored in a file, with the
`--exclude-from` option. E.g. to read exclude patterns from `./my_excludes.txt`:

```sh
fawltydeps --exclude-from my_excludes.txt
```

Exclude patterns have lower priority than any paths you pass directly on the
command line, e.g. in this command:

```sh
fawltydeps --code my_file.py --exclude my_file.py
Expand All @@ -340,9 +347,6 @@ notebooks:
fawltydeps --code my_dir --exclude "*.ipynb"
```

(The extra quotes here are needed to prevent the shell from interpreting and
replacing the `*` wildcard.)

### Ignoring irrelevant results

There may be `import` statements in your code that should not be considered an
Expand Down
11 changes: 11 additions & 0 deletions fawltydeps/cli_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,17 @@ def populate_parser_paths_options(parser: argparse._ActionsContainer) -> None:
" Defaults to '.*', meaning that hidden/dot paths are excluded."
),
)
parser.add_argument(
"--exclude-from",
nargs="+",
action="union",
type=Path,
metavar="PATH",
help=(
"Files containing exclude patterns to apply when looking for code"
" (imports), dependency declarations and/or Python environments."
),
)
parser.add_argument(
"--install-deps",
dest="install_deps",
Expand Down
66 changes: 66 additions & 0 deletions tests/test_cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,46 @@ def test_list_sources_detailed__from_both_python_file_and_stdin(fake_project):
assert returncode == 0


def test_list_sources__with_exclude_from(fake_project):
tmp_path = fake_project(
files_with_imports={
"code.py": ["foo"],
str(Path("subdir", "notebook.ipynb")): ["foo"],
str(Path("subdir", "other.py")): ["foo"],
},
files_with_declared_deps={
"pyproject.toml": ["foo"],
"requirements.txt": ["foo"],
"setup.cfg": ["foo"],
"setup.py": ["foo"],
},
fake_venvs={"venvs/my_venv": {}},
extra_file_contents={
"my_ignore": dedent(
"""
subdir/*.py
/setup.*
*envs
"""
)
},
)
output, returncode = run_fawltydeps_function(
"--list-sources", f"{tmp_path}", "--exclude-from", f"{tmp_path / 'my_ignore'}"
)
expect = [
str(tmp_path / filename)
for filename in [
"code.py",
str(Path("subdir", "notebook.ipynb")),
"requirements.txt",
"pyproject.toml",
]
]
assert_unordered_equivalence(output.splitlines()[:-2], expect)
assert returncode == 0


@dataclass
class ProjectTestVector:
"""Test vectors for FawltyDeps Settings configuration."""
Expand Down Expand Up @@ -1279,6 +1319,32 @@ def test_cmdline_on_ignored_undeclared_option(
).splitlines(),
id="generate_toml_config_with_install_deps",
),
pytest.param(
{"exclude": ["/foo/bar", "baz/*"]},
["--list-sources", "--exclude-from", "my_ignore", "--generate-toml-config"],
dedent(
f"""\
# Copy this TOML section into your pyproject.toml to configure FawltyDeps
# (default values are commented)
[tool.fawltydeps]
actions = ['list_sources']
# output_format = 'human_summary'
# code = ['.']
# deps = ['.']
# pyenvs = ['.']
# ignore_undeclared = []
# ignore_unused = {sorted(DEFAULT_IGNORE_UNUSED)}
# deps_parser_choice = ...
# install_deps = false
exclude = ['/foo/bar', 'baz/*']
exclude_from = ['my_ignore']
# verbosity = 0
# custom_mapping_file = []
# [tool.fawltydeps.custom_mapping]
"""
).splitlines(),
id="generate_toml_config_with_list_sources_exclude_and_exclude_from",
),
],
)
def test_cmdline_args_in_combination_with_config_file(
Expand Down

0 comments on commit b6407f2

Please sign in to comment.