Skip to content

Commit 74692c5

Browse files
feat: Warn when a dependency set is unused (#163)
1 parent c4b57b3 commit 74692c5

File tree

7 files changed

+142
-2
lines changed

7 files changed

+142
-2
lines changed

.pre-commit-hooks.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
language: python
66
files: "dependencies.yaml"
77
pass_filenames: false
8+
args: [--warn-all, --strict]

src/rapids_dependency_file_generator/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
a Conda environment from ``dependencies.yaml``.
66
"""
77

8-
from . import _config, _rapids_dependency_file_generator
8+
from . import _config, _rapids_dependency_file_generator, _warnings
99
from ._config import * # noqa: F401,F403
1010
from ._rapids_dependency_file_generator import * # noqa: F401,F403
1111
from ._version import __version__
12+
from ._warnings import * # noqa: F401,F403
1213

1314
__all__ = [
1415
"__version__",
1516
*_config.__all__,
1617
*_rapids_dependency_file_generator.__all__,
18+
*_warnings.__all__,
1719
]

src/rapids_dependency_file_generator/_cli.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import argparse
22
import os
3+
import warnings
34

5+
from . import DependencyFileGeneratorWarning
46
from ._config import Output, load_config_from_file
57
from ._constants import cli_name, default_dependency_file_path
68
from ._rapids_dependency_file_generator import (
79
delete_existing_files,
810
make_dependency_files,
911
)
12+
from ._rapids_dependency_file_validator import UnusedDependencySetWarning
1013
from ._version import __version__ as version
1114

1215

@@ -80,6 +83,27 @@ def validate_args(argv):
8083
help="Show the version and exit.",
8184
)
8285

86+
parser.add_argument(
87+
"--warn-all",
88+
default=False,
89+
action="store_true",
90+
help="Activate all warnings.",
91+
)
92+
93+
parser.add_argument(
94+
"--warn-unused-dependencies",
95+
default=False,
96+
action="store_true",
97+
help="Warn if there are unused dependency sets.",
98+
)
99+
100+
parser.add_argument(
101+
"--strict",
102+
default=False,
103+
action="store_true",
104+
help="Treat warnings as errors.",
105+
)
106+
83107
args = parser.parse_args(argv)
84108

85109
dependent_arg_keys = ["file_key", "output", "matrix"]
@@ -118,6 +142,11 @@ def main(argv=None) -> None:
118142
print(f"{cli_name}, version {version}")
119143
return
120144

145+
if args.strict:
146+
warnings.simplefilter("error", category=DependencyFileGeneratorWarning)
147+
if not args.warn_unused_dependencies and not args.warn_all:
148+
warnings.simplefilter("ignore", category=UnusedDependencySetWarning)
149+
121150
parsed_config = load_config_from_file(args.config)
122151

123152
matrix = generate_matrix(args.matrix)

src/rapids_dependency_file_generator/_rapids_dependency_file_validator.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
import sys
66
import textwrap
77
import typing
8+
import warnings
89

910
import jsonschema
1011
from jsonschema.exceptions import best_match
1112

13+
from ._warnings import UnusedDependencySetWarning
14+
1215
SCHEMA = json.loads(importlib.resources.files(__package__).joinpath("schema.json").read_bytes())
1316

1417

@@ -32,3 +35,10 @@ def validate_dependencies(dependencies: dict[str, typing.Any]) -> None:
3235
best_matching_error = best_match(errors)
3336
print("\n", textwrap.indent(str(best_matching_error), "\t"), "\n", file=sys.stderr)
3437
raise RuntimeError("The provided dependencies data is invalid.")
38+
39+
unused_dependency_sets = set(dependencies["dependencies"].keys())
40+
unused_dependency_sets.difference_update(
41+
i for file_config in dependencies["files"].values() for i in file_config["includes"]
42+
)
43+
for dep in sorted(unused_dependency_sets):
44+
warnings.warn(f'Dependency set "{dep}" is not referred to anywhere in "files:"', UnusedDependencySetWarning)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
__all__ = [
2+
"DependencyFileGeneratorWarning",
3+
]
4+
5+
6+
class DependencyFileGeneratorWarning(UserWarning):
7+
pass
8+
9+
10+
class UnusedDependencySetWarning(DependencyFileGeneratorWarning):
11+
pass

tests/test_cli.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
import contextlib
2+
import os.path
3+
from textwrap import dedent
4+
15
import pytest
26

3-
from rapids_dependency_file_generator._cli import generate_matrix, validate_args
7+
from rapids_dependency_file_generator._cli import generate_matrix, main, validate_args
8+
from rapids_dependency_file_generator._rapids_dependency_file_validator import UnusedDependencySetWarning
49

510

611
def test_generate_matrix():
@@ -181,3 +186,52 @@ def test_validate_args():
181186

182187
args = validate_args(["--version"])
183188
assert args.version
189+
190+
191+
@pytest.mark.parametrize(
192+
["extra_args", "context"],
193+
[
194+
(
195+
[],
196+
contextlib.nullcontext(),
197+
),
198+
(
199+
["--strict"],
200+
contextlib.nullcontext(),
201+
),
202+
(
203+
["--warn-unused-dependencies"],
204+
pytest.warns(UnusedDependencySetWarning),
205+
),
206+
(
207+
["--warn-unused-dependencies", "--strict"],
208+
pytest.raises(UnusedDependencySetWarning),
209+
),
210+
(
211+
["--warn-all"],
212+
pytest.warns(UnusedDependencySetWarning),
213+
),
214+
(
215+
["--warn-all", "--strict"],
216+
pytest.raises(UnusedDependencySetWarning),
217+
),
218+
],
219+
)
220+
def test_warnings(tmp_path, extra_args, context):
221+
config_file = os.path.join(tmp_path, "dependencies.yaml")
222+
with open(config_file, "w") as f:
223+
f.write(dedent("""
224+
files:
225+
all:
226+
output: conda
227+
includes: [a]
228+
channels: []
229+
dependencies:
230+
a:
231+
common: []
232+
b:
233+
common: []
234+
"""))
235+
236+
with context:
237+
main(["--config", config_file, *extra_args])
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import pytest
2+
from rapids_dependency_file_generator._rapids_dependency_file_validator import UnusedDependencySetWarning, validate_dependencies
3+
4+
5+
def test_validate_dependencies_warn_on_unused_deps():
6+
with pytest.warns(UnusedDependencySetWarning) as warnings:
7+
validate_dependencies({
8+
"files": {
9+
"all": {
10+
"output": "conda",
11+
"includes": ["a", "b"],
12+
}
13+
},
14+
"channels": [],
15+
"dependencies": {
16+
"a": {
17+
"common": [],
18+
},
19+
"b": {
20+
"common": [],
21+
},
22+
"d": {
23+
"common": [],
24+
},
25+
"c": {
26+
"common": [],
27+
},
28+
},
29+
})
30+
31+
assert len(warnings) == 2
32+
assert warnings[0].message.args[0] == 'Dependency set "c" is not referred to anywhere in "files:"'
33+
assert warnings[1].message.args[0] == 'Dependency set "d" is not referred to anywhere in "files:"'

0 commit comments

Comments
 (0)