From b68c331bac1358b566afe0d794ca76959686290a Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Wed, 8 Jan 2025 13:17:11 +0100 Subject: [PATCH] config: report file:line of deprecated config items --- lib/spack/spack/config.py | 11 +++++++++-- lib/spack/spack/container/__init__.py | 3 ++- lib/spack/spack/schema/__init__.py | 16 ++++++++++------ lib/spack/spack/schema/mirrors.py | 3 ++- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py index ab18ed507e4..b74bb9a7256 100644 --- a/lib/spack/spack/config.py +++ b/lib/spack/spack/config.py @@ -34,8 +34,11 @@ import os import re import sys +import warnings from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, Union +import jsonschema + from llnl.util import filesystem, lang, tty import spack.error @@ -1048,7 +1051,6 @@ def validate( This leverages the line information (start_mark, end_mark) stored on Spack YAML structures. """ - import jsonschema try: spack.schema.Validator(schema).validate(data) @@ -1057,7 +1059,12 @@ def validate( line_number = e.instance.lc.line + 1 else: line_number = None - raise ConfigFormatError(e, data, filename, line_number) from e + exception = ConfigFormatError(e, data, filename, line_number) + + if isinstance(e, spack.schema.NonFatalValidationError): + warnings.warn(str(exception)) + else: + raise exception from e # return the validated data so that we can access the raw data # mostly relevant for environments return data diff --git a/lib/spack/spack/container/__init__.py b/lib/spack/spack/container/__init__.py index cbeb5974a97..ac97ec5e61c 100644 --- a/lib/spack/spack/container/__init__.py +++ b/lib/spack/spack/container/__init__.py @@ -6,6 +6,8 @@ """ import warnings +import jsonschema + import spack.environment as ev import spack.schema.env as env import spack.util.spack_yaml as syaml @@ -30,7 +32,6 @@ def validate(configuration_file): Returns: A sanitized copy of the configuration stored in the input file """ - import jsonschema with open(configuration_file, encoding="utf-8") as f: config = syaml.load(f) diff --git a/lib/spack/spack/schema/__init__.py b/lib/spack/spack/schema/__init__.py index 298d4ef7c52..3ac25345d57 100644 --- a/lib/spack/spack/schema/__init__.py +++ b/lib/spack/spack/schema/__init__.py @@ -4,7 +4,8 @@ """This module contains jsonschema files for all of Spack's YAML formats.""" import copy import typing -import warnings + +import jsonschema import llnl.util.lang @@ -16,14 +17,14 @@ class DeprecationMessage(typing.NamedTuple): error: bool -# jsonschema is imported lazily as it is heavy to import -# and increases the start-up time +class NonFatalValidationError(jsonschema.ValidationError): + """A validation error that should only produce a warning.""" + + def _make_validator(): - import jsonschema def _validate_spec(validator, is_spec, instance, schema): """Check if the attributes on instance are valid specs.""" - import jsonschema import spack.spec_parser @@ -56,15 +57,18 @@ def _deprecated_properties(validator, deprecated, instance, schema): # Process issues errors = [] + warnings = [] for name in issues: msg = deprecations[name].message.format(name=name) if deprecations[name].error: errors.append(msg) else: - warnings.warn(msg) + warnings.append(msg) if errors: yield jsonschema.ValidationError("\n".join(errors)) + if warnings: + yield NonFatalValidationError("\n".join(warnings)) return jsonschema.validators.extend( jsonschema.Draft4Validator, diff --git a/lib/spack/spack/schema/mirrors.py b/lib/spack/spack/schema/mirrors.py index b0844ed87b2..e7cfecc5be1 100644 --- a/lib/spack/spack/schema/mirrors.py +++ b/lib/spack/spack/schema/mirrors.py @@ -9,6 +9,8 @@ """ from typing import Any, Dict +import jsonschema + #: Common properties for connection specification connection = { "url": {"type": "string"}, @@ -102,7 +104,6 @@ def update(data): - import jsonschema errors = []