From 38e1563c6fe40ffa401a136b3c7f59d0c7433fc3 Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Wed, 18 Oct 2023 14:32:43 -0700 Subject: [PATCH 1/2] Split out the summary table into 2 tables Signed-off-by: Zack Koppert --- markdown_writer.py | 15 +++++++--- test_markdown_writer.py | 66 ++++++++++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/markdown_writer.py b/markdown_writer.py index dc2d317..2b40f11 100644 --- a/markdown_writer.py +++ b/markdown_writer.py @@ -112,7 +112,7 @@ def write_to_markdown( file.write("# Issue Metrics\n\n") # Write first table with overall metrics - write_overall_metrics_table( + write_overall_metrics_tables( issues_with_metrics, average_time_to_first_response, average_time_to_close, @@ -168,7 +168,7 @@ def write_to_markdown( print("Wrote issue metrics to issue_metrics.md") -def write_overall_metrics_table( +def write_overall_metrics_tables( issues_with_metrics, stats_time_to_first_response, stats_time_to_close, @@ -180,7 +180,7 @@ def write_overall_metrics_table( columns, file, ): - """Write the overall metrics table to the markdown file.""" + """Write the overall metrics tables to the markdown file.""" file.write("| Metric | Average | Median | 90th percentile |\n") file.write("| --- | --- | --- | ---: |\n") if "Time to first response" in columns: @@ -215,13 +215,20 @@ def write_overall_metrics_table( file.write("| Time to answer | None | None | None |\n") if labels and stats_time_in_labels: for label in labels: - if f"Time spent in {label}" in columns and label in stats_time_in_labels['avg']: + if ( + f"Time spent in {label}" in columns + and label in stats_time_in_labels["avg"] + ): file.write( f"| Time spent in {label} " f"| {stats_time_in_labels['avg'][label]} " f"| {stats_time_in_labels['med'][label]} " f"| {stats_time_in_labels['90p'][label]} |\n" ) + # Write count stats to a separate table + file.write("\n") + file.write("| Metric | Count |\n") + file.write("| --- | ---: |\n") file.write(f"| Number of items that remain open | {num_issues_opened} |\n") file.write(f"| Number of items closed | {num_issues_closed} |\n") file.write(f"| Total number of items created | {len(issues_with_metrics)} |\n\n") diff --git a/test_markdown_writer.py b/test_markdown_writer.py index 152233f..fbf372f 100644 --- a/test_markdown_writer.py +++ b/test_markdown_writer.py @@ -17,6 +17,7 @@ class TestWriteToMarkdown(unittest.TestCase): """Test the write_to_markdown function.""" + maxDiff = None def test_write_to_markdown(self): @@ -50,21 +51,25 @@ def test_write_to_markdown(self): ), ] time_to_first_response = { - 'avg': timedelta(days=2), - 'med': timedelta(days=2), - '90p': timedelta(days=2)} + "avg": timedelta(days=2), + "med": timedelta(days=2), + "90p": timedelta(days=2), + } time_to_close = { - 'avg': timedelta(days=3), - 'med': timedelta(days=3), - '90p': timedelta(days=3)} + "avg": timedelta(days=3), + "med": timedelta(days=3), + "90p": timedelta(days=3), + } time_to_answer = { - 'avg': timedelta(days=4), - 'med': timedelta(days=4), - '90p': timedelta(days=4)} + "avg": timedelta(days=4), + "med": timedelta(days=4), + "90p": timedelta(days=4), + } time_in_labels = { - 'avg': {"bug": "1 day, 12:00:00"}, - 'med': {"bug": "1 day, 12:00:00"}, - '90p': {"bug": "1 day, 12:00:00"}} + "avg": {"bug": "1 day, 12:00:00"}, + "med": {"bug": "1 day, 12:00:00"}, + "90p": {"bug": "1 day, 12:00:00"}, + } num_issues_opened = 2 num_issues_closed = 1 @@ -93,6 +98,9 @@ def test_write_to_markdown(self): "| Time to close | 3 days, 0:00:00 | 3 days, 0:00:00 | 3 days, 0:00:00 |\n" "| Time to answer | 4 days, 0:00:00 | 4 days, 0:00:00 | 4 days, 0:00:00 |\n" "| Time spent in bug | 1 day, 12:00:00 | 1 day, 12:00:00 | 1 day, 12:00:00 |\n" + "\n" + "| Metric | Count |\n" + "| --- | ---: |\n" "| Number of items that remain open | 2 |\n" "| Number of items closed | 1 |\n" "| Total number of items created | 2 |\n\n" @@ -140,21 +148,25 @@ def test_write_to_markdown_with_vertical_bar_in_title(self): ), ] average_time_to_first_response = { - 'avg': timedelta(days=2), - 'med': timedelta(days=2), - '90p': timedelta(days=2)} + "avg": timedelta(days=2), + "med": timedelta(days=2), + "90p": timedelta(days=2), + } average_time_to_close = { - 'avg': timedelta(days=3), - 'med': timedelta(days=3), - '90p': timedelta(days=3)} + "avg": timedelta(days=3), + "med": timedelta(days=3), + "90p": timedelta(days=3), + } average_time_to_answer = { - 'avg': timedelta(days=4), - 'med': timedelta(days=4), - '90p': timedelta(days=4)} + "avg": timedelta(days=4), + "med": timedelta(days=4), + "90p": timedelta(days=4), + } average_time_in_labels = { - 'avg': {"bug": "1 day, 12:00:00"}, - 'med': {"bug": "1 day, 12:00:00"}, - '90p': {"bug": "1 day, 12:00:00"}} + "avg": {"bug": "1 day, 12:00:00"}, + "med": {"bug": "1 day, 12:00:00"}, + "90p": {"bug": "1 day, 12:00:00"}, + } num_issues_opened = 2 num_issues_closed = 1 @@ -182,6 +194,9 @@ def test_write_to_markdown_with_vertical_bar_in_title(self): "| Time to close | 3 days, 0:00:00 | 3 days, 0:00:00 | 3 days, 0:00:00 |\n" "| Time to answer | 4 days, 0:00:00 | 4 days, 0:00:00 | 4 days, 0:00:00 |\n" "| Time spent in bug | 1 day, 12:00:00 | 1 day, 12:00:00 | 1 day, 12:00:00 |\n" + "\n" + "| Metric | Count |\n" + "| --- | ---: |\n" "| Number of items that remain open | 2 |\n" "| Number of items closed | 1 |\n" "| Total number of items created | 2 |\n\n" @@ -288,6 +303,9 @@ def test_writes_markdown_file_with_non_hidden_columns_only(self): "# Issue Metrics\n\n" "| Metric | Average | Median | 90th percentile |\n" "| --- | --- | --- | ---: |\n" + "\n" + "| Metric | Count |\n" + "| --- | ---: |\n" "| Number of items that remain open | 2 |\n" "| Number of items closed | 1 |\n" "| Total number of items created | 2 |\n\n" From 3da633e12297baa497d452525ea5435a6cbab392 Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Thu, 19 Oct 2023 11:57:41 -0700 Subject: [PATCH 2/2] Add test and logic for skipping empty summary table Signed-off-by: Zack Koppert --- .vscode/settings.json | 6 ++- markdown_writer.py | 96 +++++++++++++++++++++++------------------ test_markdown_writer.py | 4 +- 3 files changed, 59 insertions(+), 47 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 3e99ede..60561a4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,9 @@ "." ], "python.testing.unittestEnabled": false, - "python.testing.pytestEnabled": true + "python.testing.pytestEnabled": true, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.formatting.provider": "none" } \ No newline at end of file diff --git a/markdown_writer.py b/markdown_writer.py index 2b40f11..052281a 100644 --- a/markdown_writer.py +++ b/markdown_writer.py @@ -78,6 +78,7 @@ def write_to_markdown( num_issues_closed: Union[int, None], labels=None, search_query=None, + hide_label_metrics=False, ) -> None: """Write the issues with metrics to a markdown file. @@ -94,6 +95,7 @@ def write_to_markdown( num_issues_closed (int): The number of issues that were closed. labels (List[str]): A list of the labels that are used in the issues. search_query (str): The search query used to find the issues. + hide_label_metrics (bool): Represents whether the user has chosen to hide label metrics in the output Returns: None. @@ -123,6 +125,7 @@ def write_to_markdown( labels, columns, file, + hide_label_metrics, ) # Write second table with individual issue/pr/discussion metrics @@ -179,54 +182,61 @@ def write_overall_metrics_tables( labels, columns, file, + hide_label_metrics, ): """Write the overall metrics tables to the markdown file.""" - file.write("| Metric | Average | Median | 90th percentile |\n") - file.write("| --- | --- | --- | ---: |\n") - if "Time to first response" in columns: - if stats_time_to_first_response is not None: - file.write( - f"| Time to first response " - f"| {stats_time_to_first_response['avg']} " - f"| {stats_time_to_first_response['med']} " - f"| {stats_time_to_first_response['90p']} |\n" - ) - else: - file.write("| Time to first response | None | None | None |\n") - if "Time to close" in columns: - if stats_time_to_close is not None: - file.write( - f"| Time to close " - f"| {stats_time_to_close['avg']} " - f"| {stats_time_to_close['med']} " - f"| {stats_time_to_close['90p']} |\n" - ) - else: - file.write("| Time to close | None | None | None |\n") - if "Time to answer" in columns: - if stats_time_to_answer is not None: - file.write( - f"| Time to answer " - f"| {stats_time_to_answer['avg']} " - f"| {stats_time_to_answer['med']} " - f"| {stats_time_to_answer['90p']} |\n" - ) - else: - file.write("| Time to answer | None | None | None |\n") - if labels and stats_time_in_labels: - for label in labels: - if ( - f"Time spent in {label}" in columns - and label in stats_time_in_labels["avg"] - ): + if ( + "Time to first response" in columns + or "Time to close" in columns + or "Time to answer" in columns + or (hide_label_metrics is False and len(labels) > 0) + ): + file.write("| Metric | Average | Median | 90th percentile |\n") + file.write("| --- | --- | --- | ---: |\n") + if "Time to first response" in columns: + if stats_time_to_first_response is not None: + file.write( + f"| Time to first response " + f"| {stats_time_to_first_response['avg']} " + f"| {stats_time_to_first_response['med']} " + f"| {stats_time_to_first_response['90p']} |\n" + ) + else: + file.write("| Time to first response | None | None | None |\n") + if "Time to close" in columns: + if stats_time_to_close is not None: file.write( - f"| Time spent in {label} " - f"| {stats_time_in_labels['avg'][label]} " - f"| {stats_time_in_labels['med'][label]} " - f"| {stats_time_in_labels['90p'][label]} |\n" + f"| Time to close " + f"| {stats_time_to_close['avg']} " + f"| {stats_time_to_close['med']} " + f"| {stats_time_to_close['90p']} |\n" ) + else: + file.write("| Time to close | None | None | None |\n") + if "Time to answer" in columns: + if stats_time_to_answer is not None: + file.write( + f"| Time to answer " + f"| {stats_time_to_answer['avg']} " + f"| {stats_time_to_answer['med']} " + f"| {stats_time_to_answer['90p']} |\n" + ) + else: + file.write("| Time to answer | None | None | None |\n") + if labels and stats_time_in_labels: + for label in labels: + if ( + f"Time spent in {label}" in columns + and label in stats_time_in_labels["avg"] + ): + file.write( + f"| Time spent in {label} " + f"| {stats_time_in_labels['avg'][label]} " + f"| {stats_time_in_labels['med'][label]} " + f"| {stats_time_in_labels['90p'][label]} |\n" + ) + file.write("\n") # Write count stats to a separate table - file.write("\n") file.write("| Metric | Count |\n") file.write("| --- | ---: |\n") file.write(f"| Number of items that remain open | {num_issues_opened} |\n") diff --git a/test_markdown_writer.py b/test_markdown_writer.py index fbf372f..1eac4b0 100644 --- a/test_markdown_writer.py +++ b/test_markdown_writer.py @@ -294,6 +294,7 @@ def test_writes_markdown_file_with_non_hidden_columns_only(self): num_issues_closed=num_issues_closed, labels=["label1"], search_query="repo:user/repo is:issue", + hide_label_metrics=True, ) # Check that the function writes the correct markdown file @@ -301,9 +302,6 @@ def test_writes_markdown_file_with_non_hidden_columns_only(self): content = file.read() expected_content = ( "# Issue Metrics\n\n" - "| Metric | Average | Median | 90th percentile |\n" - "| --- | --- | --- | ---: |\n" - "\n" "| Metric | Count |\n" "| --- | ---: |\n" "| Number of items that remain open | 2 |\n"