From aabb02f0776f4b9fff69f9904eb7f49d830a0cfe Mon Sep 17 00:00:00 2001 From: Isabel Drost-Fromm Date: Fri, 13 Oct 2023 16:05:14 +0200 Subject: [PATCH] Replaces references to avg with stats. In previous commits pure averages were replace by a dict of avg, median, 90th percentile. This makes that switch visible in docs, method names, variable names. --- issue_metrics.py | 36 +++++++++++++++++----------------- labels.py | 4 ++-- test_issue_metrics.py | 12 ++++++------ test_labels.py | 10 +++++----- test_time_to_answer.py | 14 ++++++------- test_time_to_close.py | 16 +++++++-------- test_time_to_first_response.py | 24 +++++++++++------------ time_to_answer.py | 12 ++++++------ time_to_close.py | 14 ++++++------- time_to_first_response.py | 10 +++++----- 10 files changed, 76 insertions(+), 76 deletions(-) diff --git a/issue_metrics.py b/issue_metrics.py index d9102a6..ef3c81b 100644 --- a/issue_metrics.py +++ b/issue_metrics.py @@ -32,14 +32,14 @@ from classes import IssueWithMetrics from discussions import get_discussions from json_writer import write_to_json -from labels import get_average_time_in_labels, get_label_metrics +from labels import get_stats_time_in_labels, get_label_metrics from markdown_writer import write_to_markdown -from time_to_answer import get_average_time_to_answer, measure_time_to_answer -from time_to_close import get_average_time_to_close, measure_time_to_close +from time_to_answer import get_stats_time_to_answer, measure_time_to_answer +from time_to_close import get_stats_time_to_close, measure_time_to_close from time_to_ready_for_review import get_time_to_ready_for_review from time_to_merge import measure_time_to_merge from time_to_first_response import ( - get_average_time_to_first_response, + get_stats_time_to_first_response, measure_time_to_first_response, ) @@ -317,36 +317,36 @@ def main(): ignore_users=ignore_users, ) - average_time_to_first_response = get_average_time_to_first_response( + stats_time_to_first_response = get_stats_time_to_first_response( issues_with_metrics ) - average_time_to_close = None + stats_time_to_close = None if num_issues_closed > 0: - average_time_to_close = get_average_time_to_close(issues_with_metrics) + stats_time_to_close = get_stats_time_to_close(issues_with_metrics) - average_time_to_answer = get_average_time_to_answer(issues_with_metrics) + stats_time_to_answer = get_stats_time_to_answer(issues_with_metrics) - # Get the average time in label for each label and store it in a dictionary + # Get stats describing the time in label for each label and store it in a dictionary # where the key is the label and the value is the average time - average_time_in_labels = get_average_time_in_labels(issues_with_metrics, labels) + stats_time_in_labels = get_stats_time_in_labels(issues_with_metrics, labels) # Write the results to json and a markdown file write_to_json( issues_with_metrics, - average_time_to_first_response, - average_time_to_close, - average_time_to_answer, - average_time_in_labels, + stats_time_to_first_response, + stats_time_to_close, + stats_time_to_answer, + stats_time_in_labels, num_issues_open, num_issues_closed, search_query, ) write_to_markdown( issues_with_metrics, - average_time_to_first_response, - average_time_to_close, - average_time_to_answer, - average_time_in_labels, + stats_time_to_first_response, + stats_time_to_close, + stats_time_to_answer, + stats_time_in_labels, num_issues_open, num_issues_closed, labels, diff --git a/labels.py b/labels.py index 1d4fe91..8544ee4 100644 --- a/labels.py +++ b/labels.py @@ -89,11 +89,11 @@ def get_label_metrics(issue: github3.issues.Issue, labels: List[str]) -> dict: return label_metrics -def get_average_time_in_labels( +def get_stats_time_in_labels( issues_with_metrics: List[IssueWithMetrics], labels: List[str], ) -> dict[str, timedelta]: - """Calculate the average time spent in each label.""" + """Calculate stats describing time spent in each label.""" time_in_labels = {} for issue in issues_with_metrics: if issue.label_metrics: diff --git a/test_issue_metrics.py b/test_issue_metrics.py index 7b6d965..fdedb9c 100644 --- a/test_issue_metrics.py +++ b/test_issue_metrics.py @@ -133,7 +133,7 @@ class TestMain(unittest.TestCase): @patch("issue_metrics.auth_to_github") @patch("issue_metrics.search_issues") @patch("issue_metrics.measure_time_to_first_response") - @patch("issue_metrics.get_average_time_to_first_response") + @patch("issue_metrics.get_stats_time_to_first_response") @patch.dict( os.environ, { @@ -142,7 +142,7 @@ class TestMain(unittest.TestCase): ) def test_main( self, - mock_get_average_time_to_first_response, + mock_get_stats_time_to_first_response, mock_measure_time_to_first_response, mock_search_issues, mock_auth_to_github, @@ -179,10 +179,10 @@ def test_main( ] mock_measure_time_to_first_response.return_value = mock_issues_with_ttfr - # Set up the mock get_average_time_to_first_response function - mock_average_time_to_first_response = 15 - mock_get_average_time_to_first_response.return_value = ( - mock_average_time_to_first_response + # Set up the mock get_stats_time_to_first_response function + mock_stats_time_to_first_response = 15 + mock_get_stats_time_to_first_response.return_value = ( + mock_stats_time_to_first_response ) # Call main and check that it runs without errors diff --git a/test_labels.py b/test_labels.py index a7b0d81..35c07e0 100644 --- a/test_labels.py +++ b/test_labels.py @@ -7,7 +7,7 @@ import pytz from classes import IssueWithMetrics -from labels import get_average_time_in_labels, get_label_events, get_label_metrics +from labels import get_stats_time_in_labels, get_label_events, get_label_metrics class TestLabels(unittest.TestCase): @@ -69,7 +69,7 @@ def test_get_label_metrics_open_issue(self): class TestGetAverageTimeInLabels(unittest.TestCase): - """Unit tests for get_average_time_in_labels""" + """Unit tests for get_stats_time_in_labels""" def setUp(self): self.issues_with_metrics = MagicMock() @@ -79,10 +79,10 @@ def setUp(self): ), ] - def test_get_average_time_in_labels(self): - """Test get_average_time_in_labels""" + def test_get_stats_time_in_labels(self): + """Test get_stats_time_in_labels""" labels = ["bug", "feature"] - metrics = get_average_time_in_labels(self.issues_with_metrics, labels) + metrics = get_stats_time_in_labels(self.issues_with_metrics, labels) print(metrics) self.assertEqual(len(metrics['avg']), 2) self.assertEqual(metrics['avg']["bug"], timedelta(days=2)) diff --git a/test_time_to_answer.py b/test_time_to_answer.py index aab97db..700079d 100644 --- a/test_time_to_answer.py +++ b/test_time_to_answer.py @@ -5,16 +5,16 @@ from typing import List from classes import IssueWithMetrics -from time_to_answer import get_average_time_to_answer, measure_time_to_answer +from time_to_answer import get_stats_time_to_answer, measure_time_to_answer class TestGetAverageTimeToAnswer(unittest.TestCase): - """A test case for the get_average_time_to_answer function. + """A test case for the get_stats_time_to_answer function. This test case includes three test methods: - test_returns_none_for_empty_list - test_returns_none_for_list_with_no_time_to_answer - - test_returns_average_time_to_answer + - test_returns_stats_time_to_answer """ def test_returns_none_for_empty_list(self): @@ -23,7 +23,7 @@ def test_returns_none_for_empty_list(self): issues_with_metrics: List[IssueWithMetrics] = [] # Act - result = get_average_time_to_answer(issues_with_metrics) + result = get_stats_time_to_answer(issues_with_metrics) # Assert self.assertIsNone(result) @@ -40,12 +40,12 @@ def test_returns_none_for_list_with_no_time_to_answer(self): ] # Act - result = get_average_time_to_answer(issues_with_metrics) + result = get_stats_time_to_answer(issues_with_metrics) # Assert self.assertIsNone(result) - def test_returns_average_time_to_answer(self): + def test_returns_stats_time_to_answer(self): """ Tests that the function correctly calculates the average time to answer for a list of issues with time to answer. @@ -59,7 +59,7 @@ def test_returns_average_time_to_answer(self): ] # Act - result = get_average_time_to_answer(issues_with_metrics)['avg'] + result = get_stats_time_to_answer(issues_with_metrics)['avg'] # Assert self.assertEqual(result, timedelta(seconds=20)) diff --git a/test_time_to_close.py b/test_time_to_close.py index 723461d..c459615 100644 --- a/test_time_to_close.py +++ b/test_time_to_close.py @@ -1,12 +1,12 @@ """A module containing unit tests for the time_to_close module. This module contains unit tests for the measure_time_to_close and -get_average_time_to_close functions in the time_to_close module. +get_stats_time_to_close functions in the time_to_close module. The tests use mock GitHub issues to test the functions' behavior. Classes: TestMeasureTimeToClose: A class to test the measure_time_to_close function. - TestGetAverageTimeToClose: A class to test the get_average_time_to_close function. + TestGetStatsTimeToClose: A class to test the get_stats_time_to_close function. """ from datetime import timedelta @@ -14,13 +14,13 @@ from unittest.mock import MagicMock from classes import IssueWithMetrics -from time_to_close import get_average_time_to_close, measure_time_to_close +from time_to_close import get_stats_time_to_close, measure_time_to_close class TestGetAverageTimeToClose(unittest.TestCase): - """Test suite for the get_average_time_to_close function.""" + """Test suite for the get_stats_time_to_close function.""" - def test_get_average_time_to_close(self): + def test_get_stats_time_to_close(self): """Test that the function correctly calculates the average time to close.""" # Create mock data issues_with_metrics = [ @@ -44,11 +44,11 @@ def test_get_average_time_to_close(self): ] # Call the function and check the result - result = get_average_time_to_close(issues_with_metrics)['avg'] + result = get_stats_time_to_close(issues_with_metrics)['avg'] expected_result = timedelta(days=3) self.assertEqual(result, expected_result) - def test_get_average_time_to_close_no_issues(self): + def test_get_stats_time_to_close_no_issues(self): """Test that the function returns None if there are no issues with time to close.""" # Create mock data issues_with_metrics = [ @@ -64,7 +64,7 @@ def test_get_average_time_to_close_no_issues(self): ] # Call the function and check the result - result = get_average_time_to_close(issues_with_metrics) + result = get_stats_time_to_close(issues_with_metrics) expected_result = None self.assertEqual(result, expected_result) diff --git a/test_time_to_first_response.py b/test_time_to_first_response.py index a54b296..a1a124a 100644 --- a/test_time_to_first_response.py +++ b/test_time_to_first_response.py @@ -1,13 +1,13 @@ """A module containing unit tests for the time_to_first_response module. This module contains unit tests for the measure_time_to_first_response and -get_average_time_to_first_response functions in the time_to_first_response module. +get_stats_time_to_first_response functions in the time_to_first_response module. The tests use mock GitHub issues and comments to test the functions' behavior. Classes: TestMeasureTimeToFirstResponse: A class to test the measure_time_to_first_response function. TestGetAverageTimeToFirstResponse: A class to test the - get_average_time_to_first_response function. + get_stats_time_to_first_response function. """ import unittest @@ -16,7 +16,7 @@ from classes import IssueWithMetrics from time_to_first_response import ( - get_average_time_to_first_response, + get_stats_time_to_first_response, measure_time_to_first_response, ) @@ -311,14 +311,14 @@ def test_measure_time_to_first_response_ignore_bot(self): self.assertEqual(result, expected_result) -class TestGetAverageTimeToFirstResponse(unittest.TestCase): - """Test the get_average_time_to_first_response function.""" +class TestGetStatsTimeToFirstResponse(unittest.TestCase): + """Test the get_stats_time_to_first_response function.""" - def test_get_average_time_to_first_response(self): - """Test that get_average_time_to_first_response calculates the correct average. + def test_get_stats_time_to_first_response(self): + """Test that get_stats_time_to_first_response calculates the correct average. This test creates a list of mock GitHub issues with time to first response - attributes, calls get_average_time_to_first_response with the list, and + attributes, calls get_stats_time_to_first_response with the list, and checks that the function returns the correct average time to first response. """ @@ -334,12 +334,12 @@ def test_get_average_time_to_first_response(self): ] # Call the function and check the result - result = get_average_time_to_first_response(issues_with_metrics)['avg'] + result = get_stats_time_to_first_response(issues_with_metrics)['avg'] expected_result = timedelta(days=1.5) self.assertEqual(result, expected_result) - def test_get_average_time_to_first_response_with_all_none(self): - """Test that get_average_time_to_first_response with all None data.""" + def test_get_stats_time_to_first_response_with_all_none(self): + """Test that get_stats_time_to_first_response with all None data.""" # Create mock data with all None issues_with_metrics = [ @@ -348,6 +348,6 @@ def test_get_average_time_to_first_response_with_all_none(self): ] # Call the function and check the result - result = get_average_time_to_first_response(issues_with_metrics) + result = get_stats_time_to_first_response(issues_with_metrics) expected_result = None self.assertEqual(result, expected_result) diff --git a/time_to_answer.py b/time_to_answer.py index 5b153d6..c33b414 100644 --- a/time_to_answer.py +++ b/time_to_answer.py @@ -1,13 +1,13 @@ """A module for measuring the time it takes to answer a GitHub discussion. This module provides functions for measuring the time it takes to answer a GitHub -discussion, as well as calculating the average time to answer for a list of discussions. +discussion, as well as calculating stats describing the time to answer for a list of discussions. Functions: - get_average_time_to_answer( + get_stats_time_to_answer( issues_with_metrics: List[IssueWithMetrics] ) -> Union[timedelta, None]: - Calculate the average time to answer for a list of issues with metrics. + Calculate stats describing the time to answer for a list of issues with metrics. measure_time_to_answer( discussion: dict ) -> Union[timedelta, None]: @@ -22,11 +22,11 @@ from classes import IssueWithMetrics -def get_average_time_to_answer( +def get_stats_time_to_answer( issues_with_metrics: List[IssueWithMetrics], ) -> Union[timedelta, None]: """ - Calculate the average time to answer for a list of issues. + Calculate stats describing the time to answer for a list of issues. """ # Filter out issues with no time to answer issues_with_time_to_answer = [ @@ -40,7 +40,7 @@ def get_average_time_to_answer( if issue.time_to_answer: answer_times.append(issue.time_to_answer.total_seconds()) - # Calculate the average time to answer + # Calculate stats describing time to answer num_issues_with_time_to_answer = len(issues_with_time_to_answer) if num_issues_with_time_to_answer > 0: average_time_to_answer = numpy.average(answer_times) diff --git a/time_to_close.py b/time_to_close.py index fe2ba1b..aead394 100644 --- a/time_to_close.py +++ b/time_to_close.py @@ -1,7 +1,7 @@ """A module for measuring the time it takes to close a GitHub issue or discussion. This module provides functions for measuring the time it takes to close a GitHub issue -or discussion, as well as calculating the average time to close for a list of issues. +or discussion, as well as calculating stats describing the time to close for a list of issues. Functions: measure_time_to_close( @@ -9,10 +9,10 @@ discussion: Union[dict, None] ) -> Union[timedelta, None]: Measure the time it takes to close an issue or discussion. - get_average_time_to_close( + get_stats_time_to_close( issues_with_metrics: List[IssueWithMetrics] ) -> Union[timedelta, None]: - Calculate the average time to close for a list of issues with metrics. + Calculate stats describing the time to close for a list of issues with metrics. """ from datetime import datetime, timedelta @@ -55,17 +55,17 @@ def measure_time_to_close( return None -def get_average_time_to_close( +def get_stats_time_to_close( issues_with_metrics: List[IssueWithMetrics], ) -> Union[timedelta, None]: - """Calculate the average time to close for a list of issues. + """Calculate stats describing the time to close for a list of issues. Args: issues_with_metrics (List[IssueWithMetrics]): A list of issues with metrics. Each issue should be a issue_with_metrics tuple. Returns: - Union[float, None]: The average time to close for the issues. + Union[Dict{string: float}, None]: Stats describing the time to close for the issues. """ # Filter out issues with no time to close @@ -81,7 +81,7 @@ def get_average_time_to_close( if issue.time_to_close: close_times.append(issue.time_to_close.total_seconds()) - # Calculate the average time to close + # Calculate stats describing time to close num_issues_with_time_to_close = len(issues_with_time_to_close) if num_issues_with_time_to_close > 0 and total_time_to_close is not None: average_time_to_close = numpy.average(close_times) diff --git a/time_to_first_response.py b/time_to_first_response.py index 63b571a..e764be5 100644 --- a/time_to_first_response.py +++ b/time_to_first_response.py @@ -11,10 +11,10 @@ pull_request: Union[github3.pulls.PullRequest, None], ) -> Union[timedelta, None]: Measure the time to first response for a single issue or a discussion. - get_average_time_to_first_response( + get_stats_time_to_first_response( issues: List[IssueWithMetrics] ) -> Union[timedelta, None]: - Calculate the average time to first response for a list of issues with metrics. + Calculate stats describing time to first response for a list of issues with metrics. """ from datetime import datetime, timedelta @@ -122,16 +122,16 @@ def ignore_comment( or (ready_for_review_at and comment_created_at < ready_for_review_at)) -def get_average_time_to_first_response( +def get_stats_time_to_first_response( issues: List[IssueWithMetrics], ) -> Union[timedelta, None]: - """Calculate the average time to first response for a list of issues. + """Calculate the stats describing time to first response for a list of issues. Args: issues (List[IssueWithMetrics]): A list of GitHub issues with metrics attached. Returns: - datetime.timedelta: The average time to first response for the issues in seconds. + Union[Dict{String: datetime.timedelta}, None]: The stats describing time to first response for the issues in seconds. """ response_times = []