From 5e1c1fd6cf54a3be677e1b34226d4ad421cae6a3 Mon Sep 17 00:00:00 2001 From: TitusSmith33 Date: Wed, 30 Oct 2024 23:23:03 -0400 Subject: [PATCH 1/4] feat: added progress bar functionality in `run_checks` in output.py --- gatorgrade/output/output.py | 125 +++++++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 36 deletions(-) diff --git a/gatorgrade/output/output.py b/gatorgrade/output/output.py index 8fc94c5b..72475f47 100644 --- a/gatorgrade/output/output.py +++ b/gatorgrade/output/output.py @@ -8,6 +8,7 @@ from typing import List from typing import Tuple from typing import Union +from rich.progress import Progress, BarColumn, TextColumn import gator import rich @@ -285,7 +286,7 @@ def write_json_or_md_file(file_name, content_type, content): def run_checks( - checks: List[Union[ShellCheck, GatorGraderCheck]], report: Tuple[str, str, str] + checks: List[Union[ShellCheck, GatorGraderCheck]], report: Tuple[str, str, str], running_mode=False, no_status_bar=False ) -> bool: """Run shell and GatorGrader checks and display whether each has passed or failed. @@ -294,44 +295,96 @@ def run_checks( Args: checks: The list of shell and GatorGrader checks to run. + running_mode: Convert the Progress Bar to update based on checks ran/not ran. + no_status_bar: Option to completely disable all Progress Bar options. """ results = [] # run each of the checks - for check in checks: - result = None - command_ran = None - # run a shell check; this means - # that it is going to run a command - # in the shell as a part of a check; - # store the command that ran in the - # field called run_command that is - # inside of a CheckResult object but - # not initialized in the constructor - if isinstance(check, ShellCheck): - result = _run_shell_check(check) - command_ran = check.command - result.run_command = command_ran - # run a check that GatorGrader implements - elif isinstance(check, GatorGraderCheck): - result = _run_gg_check(check) - # check to see if there was a command in the - # GatorGraderCheck. This code finds the index of the - # word "--command" in the check.gg_args list if it - # is available (it is not available for all of - # the various types of GatorGraderCheck instances), - # and then it adds 1 to that index to get the actual - # command run and then stores that command in the - # result.run_command field that is initialized to - # an empty string in the constructor for CheckResult - if "--command" in check.gg_args: - index_of_command = check.gg_args.index("--command") - index_of_new_command = int(index_of_command) + 1 - result.run_command = check.gg_args[index_of_new_command] - # there were results from running checks - # and thus they must be displayed - if result is not None: - result.print() - results.append(result) + # check how many tests are being ran + total_checks = len(checks) + # run checks with no progress bar + if no_status_bar: + for check in checks: + result = None + command_ran = None + # run a shell check; this means + # that it is going to run a command + # in the shell as a part of a check; + # store the command that ran in the + # field called run_command that is + # inside of a CheckResult object but + # not initialized in the constructor + if isinstance(check, ShellCheck): + result = _run_shell_check(check) + command_ran = check.command + result.run_command = command_ran + # run a check that GatorGrader implements + elif isinstance(check, GatorGraderCheck): + result = _run_gg_check(check) + # check to see if there was a command in the + # GatorGraderCheck. This code finds the index of the + # word "--command" in the check.gg_args list if it + # is available (it is not available for all of + # the various types of GatorGraderCheck instances), + # and then it adds 1 to that index to get the actual + # command run and then stores that command in the + # result.run_command field that is initialized to + # an empty string in the constructor for CheckResult + if "--command" in check.gg_args: + index_of_command = check.gg_args.index("--command") + index_of_new_command = int(index_of_command) + 1 + result.run_command = check.gg_args[index_of_new_command] + # there were results from running checks + # and thus they must be displayed + if result is not None: + result.print() + results.append(result) + else: + with Progress( + TextColumn("[progress.description]{task.description}"), + BarColumn(bar_width=40, style="red", complete_style="green", finished_style="green"), + TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), + ) as progress: + # add a progress task for tracking + task = progress.add_task("[green]Running checks...", total=total_checks) + + # run each of the checks + for check in checks: + result = None + command_ran = None + + if isinstance(check, ShellCheck): + result = _run_shell_check(check) + command_ran = check.command + result.run_command = command_ran + # run a check that GatorGrader implements + elif isinstance(check, GatorGraderCheck): + result = _run_gg_check(check) + # check to see if there was a command in the + # GatorGraderCheck. This code finds the index of the + # word "--command" in the check.gg_args list if it + # is available (it is not available for all of + # the various types of GatorGraderCheck instances), + # and then it adds 1 to that index to get the actual + # command run and then stores that command in the + # result.run_command field that is initialized to + # an empty string in the constructor for CheckResult + if "--command" in check.gg_args: + index_of_command = check.gg_args.index("--command") + index_of_new_command = int(index_of_command) + 1 + result.run_command = check.gg_args[index_of_new_command] + # there were results from running checks + # and thus they must be displayed + if result is not None: + result.print() + results.append(result) + + #update progress based on running_mode + if running_mode: + progress.update(task, advance=1) + else: + if result and result.passed: + progress.update(task, advance=1) # determine if there are failures and then display them failed_results = list(filter(lambda result: not result.passed, results)) # print failures list if there are failures to print From 77f339e355140a42653dbaa2822149ba98597ea8 Mon Sep 17 00:00:00 2001 From: TitusSmith33 Date: Wed, 30 Oct 2024 23:23:52 -0400 Subject: [PATCH 2/4] feat: added `run_status_bar` and `no_status_bar` flags for progress bar functionality in main.py --- gatorgrade/main.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gatorgrade/main.py b/gatorgrade/main.py index 42bbbd81..468fdfb0 100644 --- a/gatorgrade/main.py +++ b/gatorgrade/main.py @@ -45,6 +45,12 @@ def gatorgrade( 3. the name of the file or environment variable\ 4. use 'env md GITHUB_STEP_SUMMARY' to create GitHub job summary in GitHub Action", ), + run_status_bar: bool = typer.Option( + False, "--run_status_bar", help="Enable a progress bar for checks running/not running." + ), + no_status_bar: bool = typer.Option( + False, "--no_status_bar", help="Disable the progress bar entirely." + ) ): """Run the GatorGrader checks in the specified gatorgrade.yml file.""" # if ctx.subcommand is None then this means @@ -55,7 +61,7 @@ def gatorgrade( # there are valid checks and thus the # tool should run them with run_checks if len(checks) > 0: - checks_status = run_checks(checks, report) + checks_status = run_checks(checks, report, run_status_bar, no_status_bar) # no checks were created and this means # that, most likely, the file was not # valid and thus the tool cannot run checks From d34cebf2af042d1dfd653c4eeb3464df262b00f9 Mon Sep 17 00:00:00 2001 From: TitusSmith33 Date: Wed, 30 Oct 2024 23:35:53 -0400 Subject: [PATCH 3/4] fix: update `run_check` argument format and import statements in output.py --- gatorgrade/output/output.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/gatorgrade/output/output.py b/gatorgrade/output/output.py index 72475f47..2c356eb6 100644 --- a/gatorgrade/output/output.py +++ b/gatorgrade/output/output.py @@ -8,10 +8,12 @@ from typing import List from typing import Tuple from typing import Union -from rich.progress import Progress, BarColumn, TextColumn import gator import rich +from rich.progress import BarColumn +from rich.progress import Progress +from rich.progress import TextColumn from gatorgrade.input.checks import GatorGraderCheck from gatorgrade.input.checks import ShellCheck @@ -286,7 +288,10 @@ def write_json_or_md_file(file_name, content_type, content): def run_checks( - checks: List[Union[ShellCheck, GatorGraderCheck]], report: Tuple[str, str, str], running_mode=False, no_status_bar=False + checks: List[Union[ShellCheck, GatorGraderCheck]], + report: Tuple[str, str, str], + running_mode=False, + no_status_bar=False, ) -> bool: """Run shell and GatorGrader checks and display whether each has passed or failed. @@ -342,12 +347,17 @@ def run_checks( else: with Progress( TextColumn("[progress.description]{task.description}"), - BarColumn(bar_width=40, style="red", complete_style="green", finished_style="green"), + BarColumn( + bar_width=40, + style="red", + complete_style="green", + finished_style="green", + ), TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), ) as progress: # add a progress task for tracking task = progress.add_task("[green]Running checks...", total=total_checks) - + # run each of the checks for check in checks: result = None @@ -378,8 +388,8 @@ def run_checks( if result is not None: result.print() results.append(result) - - #update progress based on running_mode + + # update progress based on running_mode if running_mode: progress.update(task, advance=1) else: From 95d1dab2638dc12da798732f441f5031388e3fcc Mon Sep 17 00:00:00 2001 From: TitusSmith33 Date: Wed, 30 Oct 2024 23:36:20 -0400 Subject: [PATCH 4/4] fix: update gatorgrade argument format in main.py --- gatorgrade/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gatorgrade/main.py b/gatorgrade/main.py index 468fdfb0..b9377b16 100644 --- a/gatorgrade/main.py +++ b/gatorgrade/main.py @@ -46,11 +46,13 @@ def gatorgrade( 4. use 'env md GITHUB_STEP_SUMMARY' to create GitHub job summary in GitHub Action", ), run_status_bar: bool = typer.Option( - False, "--run_status_bar", help="Enable a progress bar for checks running/not running." + False, + "--run_status_bar", + help="Enable a progress bar for checks running/not running.", ), no_status_bar: bool = typer.Option( False, "--no_status_bar", help="Disable the progress bar entirely." - ) + ), ): """Run the GatorGrader checks in the specified gatorgrade.yml file.""" # if ctx.subcommand is None then this means