Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
language: python
files: "dependencies.yaml"
pass_filenames: false
args: [-Wall, -Werror]
Comment thread
KyleFromNVIDIA marked this conversation as resolved.
Outdated
4 changes: 3 additions & 1 deletion src/rapids_dependency_file_generator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
a Conda environment from ``dependencies.yaml``.
"""

from . import _config, _rapids_dependency_file_generator
from . import _config, _rapids_dependency_file_generator, _warnings
from ._config import * # noqa: F401,F403
from ._rapids_dependency_file_generator import * # noqa: F401,F403
from ._version import __version__
from ._warnings import * # noqa: F401,F403

__all__ = [
"__version__",
*_config.__all__,
*_rapids_dependency_file_generator.__all__,
*_warnings.__all__,
]
29 changes: 29 additions & 0 deletions src/rapids_dependency_file_generator/_cli.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import argparse
import os
import warnings

from . import DependencyFileGeneratorWarning
from ._config import Output, load_config_from_file
from ._constants import cli_name, default_dependency_file_path
from ._rapids_dependency_file_generator import (
delete_existing_files,
make_dependency_files,
)
from ._rapids_dependency_file_validator import UnusedDependencySetWarning
from ._version import __version__ as version


Expand Down Expand Up @@ -80,6 +83,27 @@ def validate_args(argv):
help="Show the version and exit.",
)

parser.add_argument(
"--warn-all",
default=False,
action="store_true",
help="Activate all warnings.",
)

parser.add_argument(
"--warn-unused-dependencies",
default=False,
action="store_true",
help="Warn if there are unused dependency sets.",
)

parser.add_argument(
"--strict",
default=False,
action="store_true",
help="Treat warnings as errors.",
)
Comment thread
KyleFromNVIDIA marked this conversation as resolved.

args = parser.parse_args(argv)

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

if args.strict:
warnings.simplefilter("error", category=DependencyFileGeneratorWarning)
if not args.warn_unused_dependencies and not args.warn_all:
warnings.simplefilter("ignore", category=UnusedDependencySetWarning)

parsed_config = load_config_from_file(args.config)

matrix = generate_matrix(args.matrix)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import sys
import textwrap
import typing
import warnings

import jsonschema
from jsonschema.exceptions import best_match

from ._warnings import UnusedDependencySetWarning

SCHEMA = json.loads(importlib.resources.files(__package__).joinpath("schema.json").read_bytes())


Expand All @@ -32,3 +35,10 @@ def validate_dependencies(dependencies: dict[str, typing.Any]) -> None:
best_matching_error = best_match(errors)
print("\n", textwrap.indent(str(best_matching_error), "\t"), "\n", file=sys.stderr)
raise RuntimeError("The provided dependencies data is invalid.")

unused_dependency_sets = set(dependencies["dependencies"].keys())
unused_dependency_sets.difference_update(
i for file_config in dependencies["files"].values() for i in file_config["includes"]
)
for dep in sorted(unused_dependency_sets):
warnings.warn(f'Dependency set "{dep}" is not referred to anywhere in "files:"', UnusedDependencySetWarning)
11 changes: 11 additions & 0 deletions src/rapids_dependency_file_generator/_warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
__all__ = [
"DependencyFileGeneratorWarning",
]


class DependencyFileGeneratorWarning(UserWarning):
pass


class UnusedDependencySetWarning(DependencyFileGeneratorWarning):
pass
56 changes: 55 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import contextlib
import os.path
from textwrap import dedent

import pytest

from rapids_dependency_file_generator._cli import generate_matrix, validate_args
from rapids_dependency_file_generator._cli import generate_matrix, main, validate_args
from rapids_dependency_file_generator._rapids_dependency_file_validator import UnusedDependencySetWarning


def test_generate_matrix():
Expand Down Expand Up @@ -181,3 +186,52 @@ def test_validate_args():

args = validate_args(["--version"])
assert args.version


@pytest.mark.parametrize(
["extra_args", "context"],
[
(
[],
contextlib.nullcontext(),
),
(
["--strict"],
contextlib.nullcontext(),
),
(
["--warn-unused-dependencies"],
pytest.warns(UnusedDependencySetWarning),
),
(
["--warn-unused-dependencies", "--strict"],
pytest.raises(UnusedDependencySetWarning),
),
(
["--warn-all"],
pytest.warns(UnusedDependencySetWarning),
),
(
["--warn-all", "--strict"],
pytest.raises(UnusedDependencySetWarning),
),
],
)
def test_warnings(tmp_path, extra_args, context):
config_file = os.path.join(tmp_path, "dependencies.yaml")
with open(config_file, "w") as f:
f.write(dedent("""
files:
all:
output: conda
includes: [a]
channels: []
dependencies:
a:
common: []
b:
common: []
"""))

with context:
main(["--config", config_file, *extra_args])
33 changes: 33 additions & 0 deletions tests/test_rapids_dependency_file_validator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pytest
from rapids_dependency_file_generator._rapids_dependency_file_validator import UnusedDependencySetWarning, validate_dependencies


def test_validate_dependencies_warn_on_unused_deps():
Comment thread
KyleFromNVIDIA marked this conversation as resolved.
with pytest.warns(UnusedDependencySetWarning) as warnings:
validate_dependencies({
"files": {
"all": {
"output": "conda",
"includes": ["a", "b"],
}
},
"channels": [],
"dependencies": {
"a": {
"common": [],
},
"b": {
"common": [],
},
"d": {
"common": [],
},
"c": {
"common": [],
},
},
})

assert len(warnings) == 2
assert warnings[0].message.args[0] == 'Dependency set "c" is not referred to anywhere in "files:"'
assert warnings[1].message.args[0] == 'Dependency set "d" is not referred to anywhere in "files:"'