Skip to content

Commit d80e1c0

Browse files
authored
Merge pull request #171 from ananta/centralize-get-env-vars
refactor(get_env_vars): use get_env_vars() for consistent env variable retrieval
2 parents c5cb1d2 + b42c5cc commit d80e1c0

5 files changed

+146
-73
lines changed

config.py

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""A module for managing environment variables used in GitHub metrics calculation.
2+
3+
This module defines a class for encapsulating environment variables and a function to retrieve these variables.
4+
5+
Classes:
6+
EnvVars: Represents the collection of environment variables used in the script.
7+
8+
Functions:
9+
get_env_vars: Retrieves and returns an instance of EnvVars populated with environment variables.
10+
"""
11+
import os
12+
from typing import List
13+
14+
15+
class EnvVars:
16+
# pylint: disable=too-many-instance-attributes
17+
"""
18+
Environment variables
19+
20+
Attributes:
21+
search_query (str): Search query used to filter issues/prs/discussions on GitHub
22+
gh_token (str): GitHub personal access token (PAT) for API authentication
23+
labels_to_measure (List[str]): List of labels to measure how much time the lable is applied
24+
ignore_users (List[str]): List of usernames to ignore when calculating metrics
25+
github_server_url (str): URL of GitHub server (Github.com or Github Enterprise)
26+
hide_author (str): If set, the author's information is hidden in the output
27+
hide_time_to_first_response (str): If set, the time to first response metric is hidden in the output
28+
hide_time_to_close (str): If set, the time to close metric is hidden in the output
29+
hide_time_to_answer (str): If set, the time to answer discussions is hidden in the output
30+
hide_label_metrics (str): If set, the label metrics are hidden in the output
31+
"""
32+
def __init__(self, search_query: str, gh_token: str, labels_to_measure: List[str], ignore_user: List[str],
33+
github_server_url: str, hide_author: str, hide_time_to_first_response: str,
34+
hide_time_to_close: str, hide_time_to_answer: str, hide_label_metrics: str):
35+
self.search_query = search_query
36+
self.gh_token = gh_token
37+
self.labels_to_measure = labels_to_measure
38+
self.ignore_users = ignore_user
39+
self.github_server_url = github_server_url
40+
self.hide_author = hide_author
41+
self.hide_time_to_first_response = hide_time_to_first_response
42+
self.hide_time_to_close = hide_time_to_close
43+
self.hide_time_to_answer = hide_time_to_answer
44+
self.hide_label_metrics = hide_label_metrics
45+
46+
47+
def get_env_vars() -> EnvVars:
48+
"""
49+
Get the environment variables for use in the script.
50+
51+
Returns EnvVars object with all environment variables
52+
"""
53+
search_query = os.getenv("SEARCH_QUERY")
54+
if not search_query:
55+
raise ValueError("SEARCH_QUERY environment variable not set")
56+
57+
gh_token = os.getenv("GH_TOKEN")
58+
if not gh_token:
59+
raise ValueError("GITHUB_TOKEN environment variable not set")
60+
61+
labels_to_measure = os.getenv("LABELS_TO_MEASURE")
62+
if labels_to_measure:
63+
labels_to_measure = labels_to_measure.split(",")
64+
else:
65+
labels_to_measure = []
66+
67+
ignore_users = os.getenv("IGNORE_USERS")
68+
if ignore_users:
69+
ignore_users = ignore_users.split(",")
70+
else:
71+
ignore_users = []
72+
73+
github_server_url = os.getenv("GITHUB_SERVER_URL")
74+
75+
# Hidden columns
76+
hide_author = os.getenv("HIDE_AUTHOR")
77+
hide_time_to_first_response = os.getenv("HIDE_TIME_TO_FIRST_RESPONSE")
78+
hide_time_to_close = os.getenv("HIDE_TIME_TO_CLOSE")
79+
hide_time_to_answer = os.getenv("HIDE_TIME_TO_ANSWER")
80+
hide_label_metrics = os.getenv("HIDE_LABEL_METRICS")
81+
82+
return EnvVars(
83+
search_query,
84+
gh_token,
85+
labels_to_measure,
86+
ignore_users,
87+
github_server_url,
88+
hide_author,
89+
hide_time_to_first_response,
90+
hide_time_to_close,
91+
hide_time_to_answer,
92+
hide_label_metrics
93+
)

issue_metrics.py

+15-42
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
their metrics to a markdown file.
77
88
Functions:
9-
get_env_vars() -> tuple[str, str]: Get the environment variables for use
9+
get_env_vars() -> EnvVars: Get the environment variables for use
1010
in the script.
1111
search_issues(search_query: str, github_connection: github3.GitHub)
1212
-> github3.structs.SearchIterator:
@@ -21,7 +21,6 @@
2121
main(): Run the issue-metrics script.
2222
"""
2323

24-
import os
2524
from os.path import dirname, join
2625
import sys
2726
from typing import List, Union
@@ -42,32 +41,7 @@
4241
get_stats_time_to_first_response,
4342
measure_time_to_first_response,
4443
)
45-
46-
47-
def get_env_vars() -> tuple[str, str, List[str]]:
48-
"""
49-
Get the environment variables for use in the script.
50-
51-
Returns:
52-
str: the search query used to filter issues, prs, and discussions
53-
str: the github token used to authenticate to github.com
54-
List[str]: a list of users to ignore when calculating metrics
55-
"""
56-
search_query = os.getenv("SEARCH_QUERY")
57-
if not search_query:
58-
raise ValueError("SEARCH_QUERY environment variable not set")
59-
60-
token = os.getenv("GH_TOKEN")
61-
if not token:
62-
raise ValueError("GITHUB_TOKEN environment variable not set")
63-
64-
ignore_users = os.getenv("IGNORE_USERS")
65-
if ignore_users:
66-
ignore_users = ignore_users.split(",")
67-
else:
68-
ignore_users = []
69-
70-
return search_query, token, ignore_users
44+
from config import get_env_vars
7145

7246

7347
def search_issues(
@@ -123,17 +97,16 @@ def auth_to_github() -> github3.GitHub:
12397
Returns:
12498
github3.GitHub: A github api connection.
12599
"""
126-
if token := os.getenv("GH_TOKEN"):
127-
if not os.getenv("GITHUB_SERVER_URL"):
128-
github_connection = github3.login(token=token)
129-
elif os.getenv("GITHUB_SERVER_URL") == "https://github.com":
130-
github_connection = github3.login(token=token)
131-
else:
132-
github_connection = github3.GitHubEnterprise(
133-
os.getenv("GITHUB_SERVER_URL"), token=token
134-
)
100+
env_vars = get_env_vars()
101+
token = env_vars.gh_token
102+
github_server_url = env_vars.github_server_url
103+
104+
if github_server_url and github_server_url != "https://github.com":
105+
github_connection = github3.GitHubEnterprise(
106+
github_server_url, token=token
107+
)
135108
else:
136-
raise ValueError("GH_TOKEN environment variable not set")
109+
github_connection = github3.login(token=token)
137110

138111
return github_connection # type: ignore
139112

@@ -269,9 +242,9 @@ def main():
269242

270243
# Get the environment variables for use in the script
271244
env_vars = get_env_vars()
272-
search_query = env_vars[0]
273-
token = env_vars[1]
274-
ignore_users = env_vars[2]
245+
search_query = env_vars.search_query
246+
token = env_vars.gh_token
247+
ignore_users = env_vars.ignore_users
275248

276249
# Get the repository owner and name from the search query
277250
owner = get_owner(search_query)
@@ -284,7 +257,7 @@ def main():
284257
)
285258

286259
# Determine if there are label to measure
287-
labels = os.environ.get("LABELS_TO_MEASURE")
260+
labels = env_vars.labels_to_measure
288261
if labels:
289262
labels = labels.split(",")
290263
else:

markdown_writer.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
Get the columns that are not hidden.
2525
"""
2626

27-
import os
2827
from datetime import timedelta
2928
from typing import List, Union
3029

3130
from classes import IssueWithMetrics
31+
from config import get_env_vars
3232

3333

3434
def get_non_hidden_columns(labels) -> List[str]:
@@ -43,24 +43,27 @@ def get_non_hidden_columns(labels) -> List[str]:
4343
4444
"""
4545
columns = ["Title", "URL"]
46+
47+
env_vars = get_env_vars()
48+
4649
# Find the number of columns and which are to be hidden
47-
hide_author = os.getenv("HIDE_AUTHOR")
50+
hide_author = env_vars.hide_author
4851
if not hide_author:
4952
columns.append("Author")
5053

51-
hide_time_to_first_response = os.getenv("HIDE_TIME_TO_FIRST_RESPONSE")
54+
hide_time_to_first_response = env_vars.hide_time_to_first_response
5255
if not hide_time_to_first_response:
5356
columns.append("Time to first response")
5457

55-
hide_time_to_close = os.getenv("HIDE_TIME_TO_CLOSE")
58+
hide_time_to_close = env_vars.hide_time_to_close
5659
if not hide_time_to_close:
5760
columns.append("Time to close")
5861

59-
hide_time_to_answer = os.getenv("HIDE_TIME_TO_ANSWER")
62+
hide_time_to_answer = env_vars.hide_time_to_answer
6063
if not hide_time_to_answer:
6164
columns.append("Time to answer")
6265

63-
hide_label_metrics = os.getenv("HIDE_LABEL_METRICS")
66+
hide_label_metrics = env_vars.hide_label_metrics
6467
if not hide_label_metrics and labels:
6568
for label in labels:
6669
columns.append(f"Time spent in {label}")

test_issue_metrics.py

+11-11
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class TestAuthToGithub(unittest.TestCase):
6060
"""Test the auth_to_github function."""
6161

6262
@patch("github3.login")
63+
@patch.dict(os.environ, {"GH_TOKEN": "test_token", "SEARCH_QUERY": "is:open repo:user/repo"})
6364
def test_auth_to_github_with_token(self, mock_login):
6465
"""Test that auth_to_github works with a token.
6566
@@ -72,21 +73,16 @@ def test_auth_to_github_with_token(self, mock_login):
7273
mock_gh = MagicMock()
7374
mock_login.return_value = mock_gh
7475

75-
# Set up the environment variable
76-
os.environ["GH_TOKEN"] = "test_token"
77-
7876
# Call the function
7977
github_connection = auth_to_github()
8078

8179
# Check the results
8280
self.assertEqual(github_connection, mock_gh)
8381
mock_login.assert_called_once_with(token="test_token")
8482

83+
@patch.dict(os.environ, {}, clear=True)
8584
def test_auth_to_github_no_token(self):
8685
"""Test that auth_to_github raises a ValueError if GH_TOKEN is not set."""
87-
# Unset the GH_TOKEN environment variable
88-
if "GH_TOKEN" in os.environ:
89-
del os.environ["GH_TOKEN"]
9086

9187
# Call auth_to_github and check that it raises a ValueError
9288
with self.assertRaises(ValueError):
@@ -96,15 +92,17 @@ def test_auth_to_github_no_token(self):
9692
class TestGetEnvVars(unittest.TestCase):
9793
"""Test suite for the get_env_vars function."""
9894

95+
@patch.dict(os.environ, {"GH_TOKEN": "test_token", "SEARCH_QUERY": "is:issue is:open repo:user/repo"})
9996
def test_get_env_vars(self):
10097
"""Test that the function correctly retrieves the environment variables."""
101-
# Set the environment variables
102-
os.environ["SEARCH_QUERY"] = "is:issue is:open repo:org/repo"
10398

10499
# Call the function and check the result
105-
result = get_env_vars()
106-
expected_result = "is:issue is:open repo:org/repo"
107-
self.assertEqual(result[0], expected_result)
100+
search_query = get_env_vars().search_query
101+
gh_token = get_env_vars().gh_token
102+
gh_token_expected_result = "test_token"
103+
search_query_expected_result = "is:issue is:open repo:user/repo"
104+
self.assertEqual(gh_token, gh_token_expected_result)
105+
self.assertEqual(search_query, search_query_expected_result)
108106

109107
def test_get_env_vars_missing_query(self):
110108
"""Test that the function raises a ValueError
@@ -138,6 +136,7 @@ class TestMain(unittest.TestCase):
138136
os.environ,
139137
{
140138
"SEARCH_QUERY": "is:open repo:user/repo",
139+
"GH_TOKEN": "test_token",
141140
},
142141
)
143142
def test_main(
@@ -198,6 +197,7 @@ def test_main(
198197
os.environ,
199198
{
200199
"SEARCH_QUERY": "is:open repo:org/repo",
200+
"GH_TOKEN": "test_token",
201201
},
202202
)
203203
def test_main_no_issues_found(

test_markdown_writer.py

+18-14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
from markdown_writer import write_to_markdown
1616

1717

18+
@patch.dict(
19+
os.environ,
20+
{
21+
"SEARCH_QUERY": "is:open repo:user/repo",
22+
"GH_TOKEN": "test_token"
23+
},
24+
)
1825
class TestWriteToMarkdown(unittest.TestCase):
1926
"""Test the write_to_markdown function."""
2027

@@ -234,23 +241,20 @@ def test_write_to_markdown_no_issues(self):
234241
)
235242

236243

244+
@patch.dict(
245+
os.environ,
246+
{
247+
"SEARCH_QUERY": "is:open repo:user/repo",
248+
"GH_TOKEN": "test_token",
249+
"HIDE_TIME_TO_FIRST_RESPONSE": "True",
250+
"HIDE_TIME_TO_CLOSE": "True",
251+
"HIDE_TIME_TO_ANSWER": "True",
252+
"HIDE_LABEL_METRICS": "True"
253+
},
254+
)
237255
class TestWriteToMarkdownWithEnv(unittest.TestCase):
238256
"""Test the write_to_markdown function with the HIDE* environment variables set."""
239257

240-
def setUp(self):
241-
# Set the HIDE* environment variables to True
242-
os.environ["HIDE_TIME_TO_FIRST_RESPONSE"] = "True"
243-
os.environ["HIDE_TIME_TO_CLOSE"] = "True"
244-
os.environ["HIDE_TIME_TO_ANSWER"] = "True"
245-
os.environ["HIDE_LABEL_METRICS"] = "True"
246-
247-
def tearDown(self):
248-
# Unset the HIDE* environment variables
249-
os.environ.pop("HIDE_TIME_TO_FIRST_RESPONSE")
250-
os.environ.pop("HIDE_TIME_TO_CLOSE")
251-
os.environ.pop("HIDE_TIME_TO_ANSWER")
252-
os.environ.pop("HIDE_LABEL_METRICS")
253-
254258
def test_writes_markdown_file_with_non_hidden_columns_only(self):
255259
"""
256260
Test that write_to_markdown writes the correct

0 commit comments

Comments
 (0)