diff --git a/src/rapids_pre_commit_hooks/utils/dependencies_yaml.py b/src/rapids_pre_commit_hooks/utils/dependencies_yaml.py index 4f729ef..65e4253 100644 --- a/src/rapids_pre_commit_hooks/utils/dependencies_yaml.py +++ b/src/rapids_pre_commit_hooks/utils/dependencies_yaml.py @@ -8,8 +8,8 @@ from .yaml import ( Anchor, - AnchorPreservingLoader, check_and_mark_anchor, + load_with_anchors, node_has_type, ) @@ -914,13 +914,8 @@ def traverse_root( def traverse_dependencies_yaml(handler: Handler, content: str) -> None: - loader = AnchorPreservingLoader(content) - try: - root = loader.get_single_node() - assert root is not None - finally: - loader.dispose() - traverse_root(handler, loader.document_anchors[0], set(), root) + root, anchors = load_with_anchors(content) + traverse_root(handler, anchors, set(), root) def is_python_output_type(output_type: str) -> bool: diff --git a/src/rapids_pre_commit_hooks/utils/yaml.py b/src/rapids_pre_commit_hooks/utils/yaml.py index 137ce84..0d4be09 100644 --- a/src/rapids_pre_commit_hooks/utils/yaml.py +++ b/src/rapids_pre_commit_hooks/utils/yaml.py @@ -68,3 +68,13 @@ def check_and_mark_anchor( def is_reference_anchor(anchor: "Optional[Anchor]") -> bool: return anchor is not None and anchor.anchor_type == AnchorType.REFERENCE + + +def load_with_anchors(stream) -> "tuple[yaml.Node, dict[str, yaml.Node]]": + loader = AnchorPreservingLoader(stream) + try: + root = loader.get_single_node() + assert root is not None + return root, dict(loader.document_anchors[0]) + finally: + loader.dispose() diff --git a/tests/rapids_pre_commit_hooks/dependencies/test_cuda_suffixed.py b/tests/rapids_pre_commit_hooks/dependencies/test_cuda_suffixed.py index ca3098b..57f5303 100644 --- a/tests/rapids_pre_commit_hooks/dependencies/test_cuda_suffixed.py +++ b/tests/rapids_pre_commit_hooks/dependencies/test_cuda_suffixed.py @@ -11,7 +11,11 @@ CUDASuffixedHandler, ) from rapids_pre_commit_hooks.utils import dependencies_yaml -from rapids_pre_commit_hooks.utils.yaml import Anchor, AnchorType +from rapids_pre_commit_hooks.utils.yaml import ( + Anchor, + AnchorType, + load_with_anchors, +) from rapids_pre_commit_hooks_test_utils import ( find_yaml_node_for_span, parse_named_spans, @@ -19,14 +23,6 @@ ) -def _compose(content): - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - return loader.get_single_node() - finally: - loader.dispose() - - class TestCUDASuffixedHandler: @pytest.mark.parametrize( ["output_type", "expected"], @@ -49,7 +45,7 @@ def test_handle_output_type(self, output_type, expected): assert context.has_python_output_type is True def test_handle_common(self): - composed = _compose( + composed, _ = load_with_anchors( """\ common: packages: [] @@ -143,7 +139,7 @@ def test_handle_common_item( warnings, ): content, spans = parse_named_spans(content, dict) - composed = _compose(content) + composed, _ = load_with_anchors(content) common_key, common = composed.value[0] linter = lint.Linter( "dependencies.yaml", content, "verify-dependencies" @@ -616,7 +612,7 @@ def test_handle_specific_item( warnings, ): content, spans = parse_named_spans(content, dict) - composed = _compose(content) + composed, _ = load_with_anchors(content) linter = lint.Linter( "dependencies.yaml", content, "verify-dependencies" ) @@ -682,7 +678,7 @@ def test_handle_matrix(self): + cuda_suffixed: "true" """ ) - composed = _compose(content) + composed, _ = load_with_anchors(content) matrix_key, matrix = composed.value[0] context = CUDASuffixedHandler.MatricesItemContext() handler = CUDASuffixedHandler(Mock(), Mock()) @@ -770,7 +766,7 @@ def test_handle_matrix_item( expected_cuda_major, has_cuda_node, ): - composed = _compose(content) + composed, _ = load_with_anchors(content) key, value = composed.value[0] context = CUDASuffixedHandler.MatricesItemContext() handler = CUDASuffixedHandler(Mock(), Mock()) @@ -907,7 +903,7 @@ def test_handle_package( suffixed_names, unsuffixed_names, ): - package_node = _compose(requirement) + package_node, _ = load_with_anchors(requirement) rapids_version = SimpleNamespace(cuda_suffixed_packages={"package"}) context = CUDASuffixedHandler.PackagesContext( CUDASuffixedHandler.MatricesItemContext(), @@ -1191,11 +1187,7 @@ def test_handle_package( def test_check_cuda_suffixed_integration(content, warnings): content, spans = parse_named_spans(content, dict) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, anchors = load_with_anchors(content) args = Mock() linter = lint.Linter("dependencies.yaml", content, "verify-dependencies") @@ -1208,9 +1200,7 @@ def test_check_cuda_suffixed_integration(content, warnings): "get_rapids_version", return_value=rapids_version, ): - dependencies_yaml.traverse_root( - handler, loader.document_anchors[0], set(), composed - ) + dependencies_yaml.traverse_root(handler, anchors, set(), composed) assert linter.warnings == zip_expected_warnings( spans.get("warnings", []), warnings diff --git a/tests/rapids_pre_commit_hooks/dependencies/test_naming_conventions.py b/tests/rapids_pre_commit_hooks/dependencies/test_naming_conventions.py index 35a8690..1052163 100644 --- a/tests/rapids_pre_commit_hooks/dependencies/test_naming_conventions.py +++ b/tests/rapids_pre_commit_hooks/dependencies/test_naming_conventions.py @@ -10,20 +10,13 @@ NamingConventionsHandler, ) from rapids_pre_commit_hooks.utils import dependencies_yaml +from rapids_pre_commit_hooks.utils.yaml import load_with_anchors from rapids_pre_commit_hooks_test_utils import ( parse_named_spans, zip_expected_warnings, ) -def _compose(content): - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - return loader.get_single_node() - finally: - loader.dispose() - - class TestNamingConventionsHandler: @pytest.mark.parametrize( ["content", "expected_warnings"], @@ -186,7 +179,7 @@ class TestNamingConventionsHandler: ) def test_handle_files_item(self, content, expected_warnings): content, spans = parse_named_spans(content, dict) - root = _compose(content) + root, _ = load_with_anchors(content) files = root.value[0][1] file_key, file_value = files.value[0] file_fields = {key.value: value for key, value in file_value.value} @@ -348,19 +341,13 @@ def test_handle_extras_key(self): def test_check_naming_conventions_integration(content, warnings): content, spans = parse_named_spans(content, dict) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, anchors = load_with_anchors(content) args = Mock() linter = lint.Linter("dependencies.yaml", content, "verify-dependencies") handler = NamingConventionsHandler(linter, args) - dependencies_yaml.traverse_root( - handler, loader.document_anchors[0], set(), composed - ) + dependencies_yaml.traverse_root(handler, anchors, set(), composed) assert linter.warnings == zip_expected_warnings( spans.get("warnings", []), warnings diff --git a/tests/rapids_pre_commit_hooks/dependencies/test_use_cuda_wheels.py b/tests/rapids_pre_commit_hooks/dependencies/test_use_cuda_wheels.py index ca4f114..595b86c 100644 --- a/tests/rapids_pre_commit_hooks/dependencies/test_use_cuda_wheels.py +++ b/tests/rapids_pre_commit_hooks/dependencies/test_use_cuda_wheels.py @@ -13,7 +13,11 @@ is_nvidia_library_package, ) from rapids_pre_commit_hooks.utils import dependencies_yaml -from rapids_pre_commit_hooks.utils.yaml import Anchor, AnchorType +from rapids_pre_commit_hooks.utils.yaml import ( + Anchor, + AnchorType, + load_with_anchors, +) from rapids_pre_commit_hooks_test_utils import ( find_yaml_node_for_span, parse_named_spans, @@ -142,11 +146,7 @@ def test_handle_common( linter = lint.Linter( "dependencies.yaml", content, "verify-dependencies" ) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, _ = load_with_anchors(content) common_key, common = composed.value[0] handler = UseCUDAWheelsHandler(linter, args) @@ -303,11 +303,7 @@ def test_handle_matrices_item( linter = lint.Linter( "dependencies.yaml", content, "verify-dependencies" ) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, _ = load_with_anchors(content) handler = UseCUDAWheelsHandler(linter, args) with handler.handle_specific_item(Mock(), composed) as item_context: @@ -355,11 +351,7 @@ def test_handle_matrix(self): linter = lint.Linter( "dependencies.yaml", content, "verify-dependencies" ) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, _ = load_with_anchors(content) matrix_key = find_yaml_node_for_span(composed, spans["matrix_key"]) matrix = find_yaml_node_for_span(composed, spans["matrix"]) @@ -408,11 +400,7 @@ def test_handle_matrix_item(self, content, expected_has_use_cuda_wheels): linter = lint.Linter( "dependencies.yaml", content, "verify-dependencies" ) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, _ = load_with_anchors(content) matrix_item_key, matrix_item = composed.value[0] handler = UseCUDAWheelsHandler(linter, args) @@ -498,11 +486,7 @@ def test_handle_packages( linter = lint.Linter( "dependencies.yaml", content, "verify-dependencies" ) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, _ = load_with_anchors(content) packages_key = find_yaml_node_for_span(composed, spans["packages_key"]) packages = find_yaml_node_for_span(composed, spans["packages"]) @@ -621,11 +605,7 @@ def test_handle_package( linter = lint.Linter( "dependencies.yaml", content, "verify-dependencies" ) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - package_node = loader.get_single_node() - finally: - loader.dispose() + package_node, _ = load_with_anchors(content) handler = UseCUDAWheelsHandler(linter, args) packages_context = Mock( @@ -991,19 +971,13 @@ def test_handle_package( def test_check_use_cuda_wheels_integration(content, warnings): content, spans = parse_named_spans(content, dict) - loader = dependencies_yaml.AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, anchors = load_with_anchors(content) args = Mock() linter = lint.Linter("dependencies.yaml", content, "verify-dependencies") handler = UseCUDAWheelsHandler(linter, args) - dependencies_yaml.traverse_root( - handler, loader.document_anchors[0], set(), composed - ) + dependencies_yaml.traverse_root(handler, anchors, set(), composed) assert linter.warnings == zip_expected_warnings( spans.get("warnings", []), warnings ) diff --git a/tests/rapids_pre_commit_hooks/test_alpha_spec.py b/tests/rapids_pre_commit_hooks/test_alpha_spec.py index 24f8e1a..7d230ec 100644 --- a/tests/rapids_pre_commit_hooks/test_alpha_spec.py +++ b/tests/rapids_pre_commit_hooks/test_alpha_spec.py @@ -17,8 +17,8 @@ from rapids_pre_commit_hooks import alpha_spec, lint from rapids_pre_commit_hooks.utils.yaml import ( Anchor, - AnchorPreservingLoader, AnchorType, + load_with_anchors, ) from rapids_pre_commit_hooks_test_utils import ( parse_named_spans, @@ -421,11 +421,7 @@ def test_handle_package( ): args = Mock(mode=mode) linter = lint.Linter("dependencies.yaml", content, "verify-alpha-spec") - loader = AnchorPreservingLoader(content) - try: - composed = loader.get_single_node() - finally: - loader.dispose() + composed, _ = load_with_anchors(content) handler = alpha_spec.AlphaSpecHandler(linter, args) item_context = alpha_spec.AlphaSpecHandler.ItemContext( has_python_output_type=True diff --git a/tests/rapids_pre_commit_hooks/utils/test_dependencies_yaml.py b/tests/rapids_pre_commit_hooks/utils/test_dependencies_yaml.py index 455e289..dcbbbae 100644 --- a/tests/rapids_pre_commit_hooks/utils/test_dependencies_yaml.py +++ b/tests/rapids_pre_commit_hooks/utils/test_dependencies_yaml.py @@ -4,10 +4,13 @@ from unittest.mock import MagicMock, Mock, call, patch import pytest -import yaml -from rapids_pre_commit_hooks.utils.yaml import Anchor, AnchorType from rapids_pre_commit_hooks.utils import dependencies_yaml +from rapids_pre_commit_hooks.utils.yaml import ( + Anchor, + AnchorType, + load_with_anchors, +) from rapids_pre_commit_hooks_test_utils import ( find_yaml_node_for_span, parse_named_spans, @@ -223,7 +226,7 @@ def test_no_context(self, hook_name, hook_args): def test_traverse_file_output_item(): - file_output = yaml.SafeLoader("[pyproject]").get_single_node() + file_output, _ = load_with_anchors("[pyproject]") file_output_item = file_output.value[0] file_output_context = Mock() manager = MagicMock() @@ -276,7 +279,7 @@ def test_traverse_file_output_item(): ) def test_traverse_file_output(content): content, spans = parse_named_spans(content) - files_item = yaml.SafeLoader(content).get_single_node() + files_item, _ = load_with_anchors(content) output_key = find_yaml_node_for_span(files_item, spans["key_node"]) output = find_yaml_node_for_span(files_item, spans["node"]) files_item_context = Mock() @@ -335,7 +338,7 @@ def test_traverse_file_output(content): ], ) def test_traverse_string_value(function_name, handler_name, content): - parent = yaml.SafeLoader(content).get_single_node() + parent, _ = load_with_anchors(content) key, value = parent.value[0] parent_context = Mock() manager = MagicMock() @@ -353,11 +356,13 @@ def test_traverse_string_value(function_name, handler_name, content): def test_traverse_extras(): - files_item = yaml.SafeLoader("""\ + files_item, _ = load_with_anchors( + """\ extras: table: project.optional-dependencies key: test - """).get_single_node() + """ + ) extras_key, extras = files_item.value[0] files_item_context = Mock() manager = MagicMock() @@ -401,13 +406,15 @@ def test_traverse_extras(): def test_traverse_files_item(): - files = yaml.SafeLoader("""\ + files, _ = load_with_anchors( + """\ test: output: pyproject extras: {} pyproject_dir: python includes: [] - """).get_single_node() + """ + ) files_item_key, files_item = files.value[0] files_context = Mock() manager = MagicMock() @@ -463,11 +470,13 @@ def test_traverse_files_item(): def test_traverse_files(): - root = yaml.SafeLoader("""\ + root, _ = load_with_anchors( + """\ files: test: {} all: {} - """).get_single_node() + """ + ) files_key, files = root.value[0] root_context = Mock() manager = MagicMock() @@ -540,7 +549,7 @@ def test_traverse_files(): ) def test_traverse_package(content, used_anchors, anchor): content, spans = parse_named_spans(content) - composed = yaml.SafeLoader(content).get_single_node() + composed, _ = load_with_anchors(content) package = find_yaml_node_for_span(composed, spans["node"]) packages_context = Mock() manager = MagicMock() @@ -616,7 +625,7 @@ def test_traverse_package(content, used_anchors, anchor): ) def test_traverse_packages(content, used_anchors, used_anchors_after, anchor): content, spans = parse_named_spans(content) - composed = yaml.SafeLoader(content).get_single_node() + composed, _ = load_with_anchors(content) packages_key = find_yaml_node_for_span(composed, spans["packages_key"]) packages = find_yaml_node_for_span(composed, spans["packages"]) item_context = Mock() @@ -668,9 +677,11 @@ def test_traverse_packages(content, used_anchors, used_anchors_after, anchor): def test_traverse_output_type(): - output_types = yaml.SafeLoader("""\ + output_types, _ = load_with_anchors( + """\ [requirements] - """).get_single_node() + """ + ) output_type = output_types.value[0] output_types_context = Mock() manager = MagicMock() @@ -721,7 +732,7 @@ def test_traverse_output_type(): ) def test_traverse_output_types(content): content, spans = parse_named_spans(content) - item = yaml.SafeLoader(content).get_single_node() + item, _ = load_with_anchors(content) output_types_key = find_yaml_node_for_span(item, spans["key_node"]) output_types = find_yaml_node_for_span(item, spans["node"]) item_context = Mock() @@ -758,10 +769,12 @@ def test_traverse_output_types(content): def test_traverse_common_item(): - common = yaml.SafeLoader("""\ + common, _ = load_with_anchors( + """\ - output_types: pyproject packages: [] - """).get_single_node() + """ + ) common_item = common.value[0] common_context = Mock() manager = MagicMock() @@ -805,11 +818,13 @@ def test_traverse_common_item(): def test_traverse_common(): - dependency_set = yaml.SafeLoader("""\ + dependency_set, _ = load_with_anchors( + """\ common: - {} - {} - """).get_single_node() + """ + ) common_key, common = dependency_set.value[0] dependency_set_context = Mock() manager = MagicMock() @@ -854,9 +869,11 @@ def test_traverse_common(): def test_traverse_matrix_item(): - matrix = yaml.SafeLoader("""\ + matrix, _ = load_with_anchors( + """\ value_1: "true" - """).get_single_node() + """ + ) matrix_item_key, matrix_item = matrix.value[0] matrix_context = Mock() manager = MagicMock() @@ -879,11 +896,13 @@ def test_traverse_matrix_item(): def test_traverse_matrix(): - matrices_item = yaml.SafeLoader("""\ + matrices_item, _ = load_with_anchors( + """\ matrix: value_1: "true" value_2: "true" - """).get_single_node() + """ + ) matrix_key, matrix = matrices_item.value[0] matrices_item_context = Mock() manager = MagicMock() @@ -924,10 +943,12 @@ def test_traverse_matrix(): def test_traverse_matrices_item(): - matrices = yaml.SafeLoader("""\ + matrices, _ = load_with_anchors( + """\ - matrix: {} packages: [] - """).get_single_node() + """ + ) matrices_item = matrices.value[0] matrices_context = Mock() manager = MagicMock() @@ -971,12 +992,14 @@ def test_traverse_matrices_item(): def test_traverse_matrices(): - specific_item = yaml.SafeLoader("""\ + specific_item, _ = load_with_anchors( + """\ matrices: - {} - {} - {} - """).get_single_node() + """ + ) matrices_key, matrices = specific_item.value[0] specific_item_context = Mock() manager = MagicMock() @@ -1030,10 +1053,12 @@ def test_traverse_matrices(): def test_traverse_specific_item(): - specific = yaml.SafeLoader("""\ + specific, _ = load_with_anchors( + """\ - output_types: pyproject matrices: [] - """).get_single_node() + """ + ) specific_item = specific.value[0] specific_context = Mock() manager = MagicMock() @@ -1077,12 +1102,14 @@ def test_traverse_specific_item(): def test_traverse_specific(): - dependency_set = yaml.SafeLoader("""\ + dependency_set, _ = load_with_anchors( + """\ specific: - {} - {} - {} - """).get_single_node() + """ + ) specific_key, specific = dependency_set.value[0] dependency_set_context = Mock() manager = MagicMock() @@ -1136,11 +1163,13 @@ def test_traverse_specific(): def test_traverse_dependency_set(): - dependencies = yaml.SafeLoader("""\ + dependencies, _ = load_with_anchors( + """\ dependency_set_1: common: {} specific: {} - """).get_single_node() + """ + ) dependency_set_key, dependency_set = dependencies.value[0] dependencies_context = Mock() manager = MagicMock() @@ -1193,11 +1222,13 @@ def test_traverse_dependency_set(): def test_traverse_dependencies(): - root = yaml.SafeLoader("""\ + root, _ = load_with_anchors( + """\ dependencies: dependency_set_1: {} dependency_set_2: {} - """).get_single_node() + """ + ) dependencies_key, dependencies = root.value[0] root_context = Mock() manager = MagicMock() @@ -1244,11 +1275,13 @@ def test_traverse_dependencies(): def test_traverse_root(): - root = yaml.SafeLoader("""\ + root, _ = load_with_anchors( + """\ files: {} channels: [] dependencies: {} - """).get_single_node() + """ + ) manager = MagicMock() expected_calls = [ diff --git a/tests/rapids_pre_commit_hooks/utils/test_yaml.py b/tests/rapids_pre_commit_hooks/utils/test_yaml.py index 3f6885b..f8f84c4 100644 --- a/tests/rapids_pre_commit_hooks/utils/test_yaml.py +++ b/tests/rapids_pre_commit_hooks/utils/test_yaml.py @@ -7,20 +7,16 @@ from rapids_pre_commit_hooks.utils.yaml import ( Anchor, - AnchorPreservingLoader, AnchorType, check_and_mark_anchor, is_reference_anchor, + load_with_anchors, ) -def test_anchor_preserving_loader(): - loader = AnchorPreservingLoader("- &a A\n- *a") - try: - root = loader.get_single_node() - finally: - loader.dispose() - assert loader.document_anchors == [{"a": root.value[0]}] +def test_load_with_anchors(): + root, anchors = load_with_anchors("- &a A\n- *a") + assert anchors == {"a": root.value[0]} @pytest.mark.parametrize( diff --git a/tests/test_testing_utils.py b/tests/test_testing_utils.py index 1f1e8d2..d11047c 100644 --- a/tests/test_testing_utils.py +++ b/tests/test_testing_utils.py @@ -6,7 +6,7 @@ import pytest from rapids_pre_commit_hooks.lint import LintWarning, Note, Replacement -from rapids_pre_commit_hooks.utils.yaml import AnchorPreservingLoader +from rapids_pre_commit_hooks.utils.yaml import load_with_anchors from rapids_pre_commit_hooks_test_utils import ( ParseError, find_yaml_node_for_span, @@ -853,10 +853,6 @@ def test_zip_expected_warnings(content, warnings, expected_warnings): ) def test_find_yaml_node_for_span(content, node_lambda): content, spans = parse_named_spans(content) - loader = AnchorPreservingLoader(content) - try: - root = loader.get_single_node() - finally: - loader.dispose() + root, _ = load_with_anchors(content) assert find_yaml_node_for_span(root, spans["node"]) == node_lambda(root)