From ff612f284e16bd3c2966db0e252654d5dfeefe38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Rinc=C3=B3n=20Blanco?= Date: Tue, 19 Dec 2023 19:36:43 +0100 Subject: [PATCH] Make `core:warnings_as_errors` accept a list (#15297) * Sketch warns as errors array * Fix logic * Raise even when not printing anything * Add list of warn tags to conf descriptions --- conan/api/output.py | 27 ++++++++++--------- conan/internal/conan_app.py | 5 ++-- conans/model/conf.py | 6 +++-- .../integration/command_v2/test_output.py | 20 ++++++++------ 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/conan/api/output.py b/conan/api/output.py index ad8e541c379..d42f0347d50 100644 --- a/conan/api/output.py +++ b/conan/api/output.py @@ -1,3 +1,4 @@ +import fnmatch import sys from colorama import Fore, Style @@ -51,7 +52,7 @@ class ConanOutput: # Singleton _conan_output_level = LEVEL_STATUS _silent_warn_tags = [] - _warnings_as_errors = False + _warnings_as_errors = [] def __init__(self, scope=""): self.stream = sys.stderr @@ -62,7 +63,7 @@ def __init__(self, scope=""): @classmethod def define_silence_warnings(cls, warnings): - cls._silent_warn_tags = warnings or [] + cls._silent_warn_tags = warnings @classmethod def set_warnings_as_errors(cls, value): @@ -208,28 +209,30 @@ def success(self, msg): self._write_message(msg, fg=Color.BRIGHT_GREEN) return self + @staticmethod + def _warn_tag_matches(warn_tag, patterns): + lookup_tag = warn_tag or "unknown" + return any(fnmatch.fnmatch(lookup_tag, pattern) for pattern in patterns) + def warning(self, msg, warn_tag=None): - def _skip_warning(): - return (warn_tag is not None and warn_tag in self._silent_warn_tags - or warn_tag is None and "unknown" in self._silent_warn_tags) - if self._conan_output_level <= LEVEL_WARNING or (self._warnings_as_errors and self._conan_output_level <= LEVEL_ERROR): - if _skip_warning(): + _treat_as_error = self._warn_tag_matches(warn_tag, self._warnings_as_errors) + if self._conan_output_level <= LEVEL_WARNING or (_treat_as_error and self._conan_output_level <= LEVEL_ERROR): + if self._warn_tag_matches(warn_tag, self._silent_warn_tags): return self warn_tag_msg = "" if warn_tag is None else f"{warn_tag}: " output = f"{warn_tag_msg}{msg}" - if self._warnings_as_errors: + if _treat_as_error: self.error(output) else: self._write_message(f"WARN: {output}", Color.YELLOW) return self def error(self, msg, error_type=None): + if self._warnings_as_errors and error_type != "exception": + raise ConanException(msg) if self._conan_output_level <= LEVEL_ERROR: - if self._warnings_as_errors and error_type != "exception": - raise ConanException(msg) - else: - self._write_message("ERROR: {}".format(msg), Color.RED) + self._write_message("ERROR: {}".format(msg), Color.RED) return self def flush(self): diff --git a/conan/internal/conan_app.py b/conan/internal/conan_app.py index 38f8cab84d3..a0c3f384462 100644 --- a/conan/internal/conan_app.py +++ b/conan/internal/conan_app.py @@ -65,5 +65,6 @@ def __init__(self, cache_folder, global_conf): @staticmethod def _configure(global_conf): ConanOutput.set_warnings_as_errors(global_conf.get("core:warnings_as_errors", - default=False, check_type=bool)) - ConanOutput.define_silence_warnings(global_conf.get("core:skip_warnings", check_type=list)) + default=[], check_type=list)) + ConanOutput.define_silence_warnings(global_conf.get("core:skip_warnings", + default=[], check_type=list)) diff --git a/conans/model/conf.py b/conans/model/conf.py index 0d8e378ed12..91fbb133d97 100644 --- a/conans/model/conf.py +++ b/conans/model/conf.py @@ -11,8 +11,10 @@ BUILT_IN_CONFS = { "core:required_conan_version": "Raise if current version does not match the defined range.", "core:non_interactive": "Disable interactive user input, raises error if input necessary", - "core:warnings_as_errors": "Treat warnings as errors", - "core:skip_warnings": "Do not show warnings in this list", + "core:warnings_as_errors": "Treat warnings matching any of the patterns in this list as errors and then raise an exception. " + "Current warning tags are 'network', 'deprecated'", + "core:skip_warnings": "Do not show warnings matching any of the patterns in this list. " + "Current warning tags are 'network', 'deprecated'", "core:default_profile": "Defines the default host profile ('default' by default)", "core:default_build_profile": "Defines the default build profile ('default' by default)", "core:allow_uppercase_pkg_names": "Temporarily (will be removed in 2.X) allow uppercase names", diff --git a/conans/test/integration/command_v2/test_output.py b/conans/test/integration/command_v2/test_output.py index 75e3afc1e56..3c40fefef0f 100644 --- a/conans/test/integration/command_v2/test_output.py +++ b/conans/test/integration/command_v2/test_output.py @@ -186,31 +186,31 @@ def test_output_level_envvar(): class TestWarningHandling: warning_lines = ("self.output.warning('Tagged warning', warn_tag='tag')", - "self.output.warning('Untagged warning')") + "self.output.warning('Untagged warning')") error_lines = ("self.output.error('Tagged error', error_type='exception')", "self.output.error('Untagged error')") - def test_warning_as_error(self): + def test_warning_as_error_deprecated_syntax(self): t = TestClient(light=True) t.save({"conanfile.py": GenConanfile("foo", "1.0").with_package(*self.warning_lines)}) - t.save_home({"global.conf": "core:warnings_as_errors=False"}) + t.save_home({"global.conf": "core:warnings_as_errors=[]"}) t.run("create . -vwarning") assert "WARN: Untagged warning" in t.out assert "WARN: tag: Tagged warning" in t.out - t.save_home({"global.conf": "core:warnings_as_errors=True"}) + t.save_home({"global.conf": "core:warnings_as_errors=['*']"}) t.run("create . -vwarning", assert_error=True) assert "ConanException: tag: Tagged warning" in t.out # We bailed early, didn't get a chance to print this one assert "Untagged warning" not in t.out - t.save_home({"global.conf": """core:warnings_as_errors=True\ncore:skip_warnings=["tag"]"""}) + t.save_home({"global.conf": """core:warnings_as_errors=['*']\ncore:skip_warnings=["tag"]"""}) t.run("create . -verror", assert_error=True) assert "ConanException: Untagged warning" in t.out assert "Tagged warning" not in t.out - t.save_home({"global.conf": "core:warnings_as_errors=False"}) + t.save_home({"global.conf": "core:warnings_as_errors=[]"}) t.run("create . -verror") assert "ERROR: Untagged warning" not in t.out assert "ERROR: tag: Tagged warning" not in t.out @@ -243,12 +243,16 @@ def test_exception_errors(self): t = TestClient(light=True) t.save({"conanfile.py": GenConanfile("foo", "1.0").with_package(*self.error_lines)}) - t.save_home({"global.conf": "core:warnings_as_errors=False"}) + t.save_home({"global.conf": "core:warnings_as_errors=[]"}) t.run("create .") assert "ERROR: Tagged error" in t.out assert "ERROR: Untagged error" in t.out - t.save_home({"global.conf": "core:warnings_as_errors=True"}) + t.save_home({"global.conf": "core:warnings_as_errors=['*']"}) t.run("create .", assert_error=True) assert "ERROR: Tagged error" in t.out assert "ConanException: Untagged error" in t.out + + t.run("create . -vquiet", assert_error=True) + assert "ERROR: Tagged error" not in t.out + assert "ConanException: Untagged error" not in t.out