From c29b20a49e455ab31dc9314e30398fae12f48ee3 Mon Sep 17 00:00:00 2001 From: Marco Enrico Piras Date: Tue, 10 Sep 2024 11:41:58 +0200 Subject: [PATCH 1/7] feat(cli): :sparkles: wrap console object --- rocrate_validator/cli/commands/validate.py | 3 +-- rocrate_validator/cli/main.py | 3 +-- rocrate_validator/cli/utils.py | 13 +++++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/rocrate_validator/cli/commands/validate.py b/rocrate_validator/cli/commands/validate.py index 7a2892a9..e31a2295 100644 --- a/rocrate_validator/cli/commands/validate.py +++ b/rocrate_validator/cli/commands/validate.py @@ -24,7 +24,6 @@ from InquirerPy import prompt from InquirerPy.base.control import Choice from rich.align import Align -from rich.console import Console from rich.layout import Layout from rich.live import Live from rich.markdown import Markdown @@ -38,7 +37,7 @@ from rocrate_validator import services from rocrate_validator.cli.commands.errors import handle_error from rocrate_validator.cli.main import cli, click -from rocrate_validator.cli.utils import get_app_header_rule +from rocrate_validator.cli.utils import Console, get_app_header_rule from rocrate_validator.colors import get_severity_color from rocrate_validator.events import Event, EventType, Subscriber from rocrate_validator.models import (LevelCollection, Profile, Severity, diff --git a/rocrate_validator/cli/main.py b/rocrate_validator/cli/main.py index 59ae62ba..c3876e19 100644 --- a/rocrate_validator/cli/main.py +++ b/rocrate_validator/cli/main.py @@ -15,10 +15,9 @@ import sys import rich_click as click -from rich.console import Console import rocrate_validator.log as logging -from rocrate_validator.cli.utils import SystemPager +from rocrate_validator.cli.utils import Console, SystemPager from rocrate_validator.utils import get_version # set up logging diff --git a/rocrate_validator/cli/utils.py b/rocrate_validator/cli/utils.py index 42e3a386..0a065d3f 100644 --- a/rocrate_validator/cli/utils.py +++ b/rocrate_validator/cli/utils.py @@ -18,6 +18,7 @@ import textwrap from typing import Any, Optional +from rich.console import Console as BaseConsole from rich.padding import Padding from rich.pager import Pager from rich.rule import Rule @@ -62,3 +63,15 @@ def _pager(self, content: str) -> Any: def show(self, content: str) -> None: """Use the same pager used by pydoc.""" self._pager(content) + + +class Console(BaseConsole): + """Rich Console with optional color disabling.""" + + def __init__(self, *args, disabled: bool = False, **kwargs): + super().__init__(*args, **kwargs) + self.disabled = disabled + + def print(self, *args, **kwargs): + if not self.disabled: + super().print(*args, **kwargs) From 7ec5ddb409cadd38389774659a82955c0e3be962 Mon Sep 17 00:00:00 2001 From: Marco Enrico Piras Date: Tue, 10 Sep 2024 11:48:06 +0200 Subject: [PATCH 2/7] feat(cli): :sparkles: do not print formatted validation report when format is different `text` --- rocrate_validator/cli/commands/validate.py | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/rocrate_validator/cli/commands/validate.py b/rocrate_validator/cli/commands/validate.py index e31a2295..d4cb0ffe 100644 --- a/rocrate_validator/cli/commands/validate.py +++ b/rocrate_validator/cli/commands/validate.py @@ -255,7 +255,8 @@ def validate(ctx, } # Print the application header - console.print(get_app_header_rule()) + if output_format == "text": + console.print(get_app_header_rule()) # Get the available profiles available_profiles = services.get_profiles(profiles_path) @@ -328,12 +329,18 @@ def validate(ctx, report_layout = ValidationReportLayout(console, validation_settings, profile_stats, None) # Validate RO-Crate against the profile and get the validation result - result: ValidationResult = report_layout.live( - lambda: services.validate( - validation_settings, - subscribers=[report_layout.progress_monitor] + result: ValidationResult = None + if output_format == "text": + result: ValidationResult = report_layout.live( + lambda: services.validate( + validation_settings, + subscribers=[report_layout.progress_monitor] + ) + ) + else: + result: ValidationResult = services.validate( + validation_settings ) - ) # store the cumulative validation result is_valid = is_valid and result.passed(LevelCollection.get(requirement_severity).severity) @@ -341,12 +348,12 @@ def validate(ctx, # Print the validation result if not result.passed(): verbose_choice = "n" - if interactive and not verbose and enable_pager: + if interactive and not verbose and enable_pager and not output_format == "json": verbose_choice = get_single_char(console, choices=['y', 'n'], message=( "[bold] > Do you want to see the validation details? " "([magenta]y/n[/magenta]): [/bold]" - )) + )) if verbose_choice == "y" or verbose: report_layout.show_validation_details(pager, enable_pager=enable_pager) From c4a2276fdc4136d04ee13220f9e7f2c1e243b38d Mon Sep 17 00:00:00 2001 From: Marco Enrico Piras Date: Tue, 10 Sep 2024 11:49:03 +0200 Subject: [PATCH 3/7] feat(cli): :sparkles: output JSON to stdout when `--format=json` --- rocrate_validator/cli/commands/validate.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rocrate_validator/cli/commands/validate.py b/rocrate_validator/cli/commands/validate.py index d4cb0ffe..73df2171 100644 --- a/rocrate_validator/cli/commands/validate.py +++ b/rocrate_validator/cli/commands/validate.py @@ -357,6 +357,9 @@ def validate(ctx, if verbose_choice == "y" or verbose: report_layout.show_validation_details(pager, enable_pager=enable_pager) + if output_format == "json": + console.print(result.to_json()) + if output_file: # Print the validation report to a file if output_format == "json": From af846fc746399b27efa828e94cdb76371942efd5 Mon Sep 17 00:00:00 2001 From: Marco Enrico Piras Date: Tue, 10 Sep 2024 12:09:31 +0200 Subject: [PATCH 4/7] refactor(cli): :wastebasket: remove internal settings from the JSON report --- rocrate_validator/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rocrate_validator/models.py b/rocrate_validator/models.py index 22119a3e..8c356783 100644 --- a/rocrate_validator/models.py +++ b/rocrate_validator/models.py @@ -1138,9 +1138,11 @@ def __eq__(self, other: object) -> bool: return self._issues == other._issues def to_dict(self) -> dict: + allowed_properties = ["data_path", "profiles_path", + "profile_identifier", "inherit_profiles", "requirement_severity", "abort_on_first"] return { "rocrate": str(self.rocrate_path), - "validation_settings": self.validation_settings, + "validation_settings": {key: self.validation_settings[key] for key in allowed_properties if key in self.validation_settings}, "passed": self.passed(self.context.settings["requirement_severity"]), "issues": [issue.to_dict() for issue in self.issues] } From c6dd4530608ff7f85670ac0b72d438c1d09b22dc Mon Sep 17 00:00:00 2001 From: Marco Enrico Piras Date: Tue, 10 Sep 2024 12:14:43 +0200 Subject: [PATCH 5/7] refactor(docs): :bulb: update comment --- rocrate_validator/cli/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocrate_validator/cli/utils.py b/rocrate_validator/cli/utils.py index 0a065d3f..5ad48c7c 100644 --- a/rocrate_validator/cli/utils.py +++ b/rocrate_validator/cli/utils.py @@ -66,7 +66,7 @@ def show(self, content: str) -> None: class Console(BaseConsole): - """Rich Console with optional color disabling.""" + """Rich console that can be disabled.""" def __init__(self, *args, disabled: bool = False, **kwargs): super().__init__(*args, **kwargs) From 6678dd53cf3d8d6ea57d85cfbdc7726bf27f63b6 Mon Sep 17 00:00:00 2001 From: Marco Enrico Piras Date: Tue, 10 Sep 2024 12:37:40 +0200 Subject: [PATCH 6/7] refactor(utils): :rotating_light: fix flake8 warning E501 --- rocrate_validator/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rocrate_validator/models.py b/rocrate_validator/models.py index 8c356783..734022ce 100644 --- a/rocrate_validator/models.py +++ b/rocrate_validator/models.py @@ -1142,7 +1142,8 @@ def to_dict(self) -> dict: "profile_identifier", "inherit_profiles", "requirement_severity", "abort_on_first"] return { "rocrate": str(self.rocrate_path), - "validation_settings": {key: self.validation_settings[key] for key in allowed_properties if key in self.validation_settings}, + "validation_settings": {key: self.validation_settings[key] + for key in allowed_properties if key in self.validation_settings}, "passed": self.passed(self.context.settings["requirement_severity"]), "issues": [issue.to_dict() for issue in self.issues] } From 5f27c2ddc0d586c59a3c618e009c783b5b2d88d6 Mon Sep 17 00:00:00 2001 From: Marco Enrico Piras Date: Wed, 18 Sep 2024 10:56:02 +0200 Subject: [PATCH 7/7] fix(cli): :sparkles: suppress the `stdout` output when the `-o` option is specified --- rocrate_validator/cli/commands/validate.py | 31 ++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/rocrate_validator/cli/commands/validate.py b/rocrate_validator/cli/commands/validate.py index 73df2171..500e9c46 100644 --- a/rocrate_validator/cli/commands/validate.py +++ b/rocrate_validator/cli/commands/validate.py @@ -255,7 +255,7 @@ def validate(ctx, } # Print the application header - if output_format == "text": + if output_format == "text" and output_file is None: console.print(get_app_header_rule()) # Get the available profiles @@ -331,12 +331,14 @@ def validate(ctx, # Validate RO-Crate against the profile and get the validation result result: ValidationResult = None if output_format == "text": + console.disabled = output_file is not None result: ValidationResult = report_layout.live( lambda: services.validate( validation_settings, subscribers=[report_layout.progress_monitor] ) ) + console.disabled = False else: result: ValidationResult = services.validate( validation_settings @@ -346,18 +348,19 @@ def validate(ctx, is_valid = is_valid and result.passed(LevelCollection.get(requirement_severity).severity) # Print the validation result - if not result.passed(): - verbose_choice = "n" - if interactive and not verbose and enable_pager and not output_format == "json": - verbose_choice = get_single_char(console, choices=['y', 'n'], - message=( - "[bold] > Do you want to see the validation details? " - "([magenta]y/n[/magenta]): [/bold]" - )) - if verbose_choice == "y" or verbose: - report_layout.show_validation_details(pager, enable_pager=enable_pager) - - if output_format == "json": + if output_format == "text" and not output_file: + if not result.passed(): + verbose_choice = "n" + if interactive and not verbose and enable_pager: + verbose_choice = get_single_char(console, choices=['y', 'n'], + message=( + "[bold] > Do you want to see the validation details? " + "([magenta]y/n[/magenta]): [/bold]" + )) + if verbose_choice == "y" or verbose: + report_layout.show_validation_details(pager, enable_pager=enable_pager) + + if output_format == "json" and not output_file: console.print(result.to_json()) if output_file: @@ -370,7 +373,7 @@ def validate(ctx, c = Console(file=f, color_system=None, width=output_line_width, height=31) c.print(report_layout.layout) report_layout.console = c - if not result.passed(): + if not result.passed() and verbose: report_layout.show_validation_details(None, enable_pager=False) # Interrupt the validation if the fail fast mode is enabled