Skip to content

Commit

Permalink
Merge pull request #9 from github/deduplicate
Browse files Browse the repository at this point in the history
Merge duplicate contributors
  • Loading branch information
zkoppert committed Oct 11, 2023
2 parents 13c1b63 + 9afef70 commit 7464884
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 53 deletions.
55 changes: 51 additions & 4 deletions contributor_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# "username" : "zkoppert",
# "new_contributor" : "False",
# "avatar_url" : "https://avatars.githubusercontent.com/u/29484535?v=4",
# "contribution_count" : "1261",
# "contribution_count" : 1261,
# "commit_url" : "https://github.com/github/contributors/commits?author=zkoppert&since=2023-10-01&until=2023-10-05"
# }
# ]
Expand All @@ -19,7 +19,12 @@ def __new__(cls, *args, **kwargs): # pylint: disable=unused-argument
return super().__new__(cls)

def __init__(
self, username, new_contributor, avatar_url, contribution_count, commit_url
self,
username: str,
new_contributor: bool,
avatar_url: str,
contribution_count: int,
commit_url: str,
):
"""Initialize the contributor_stats object"""
new_contributor = False
Expand All @@ -38,9 +43,51 @@ def __repr__(self) -> str:
f"contribution_count={self.contribution_count}, commit_url={self.commit_url})"
)

def __eq__(self, other) -> bool:
"""Check if two contributor_stats objects are equal"""
return (
self.username == other.username
and self.new_contributor == other.new_contributor
and self.avatar_url == other.avatar_url
and self.contribution_count == other.contribution_count
and self.commit_url == other.commit_url
)


def is_new_contributor(username: str, returning_contributors: list) -> bool:
"""Check if the contributor is new or returning"""
if username in returning_contributors:
return True
for contributor in returning_contributors:
if username in contributor.username:
return True
return False


def merge_contributors(contributors: list) -> list:
"""Merge contributors with the same username"""
merged_contributors = []
for contributor_list in contributors:
for contributor in contributor_list:
# if the contributor is already in the merged list, merge their relavent attributes
if contributor.username in [c.username for c in merged_contributors]:
for merged_contributor in merged_contributors:
if merged_contributor.username == contributor.username:
# Merge the contribution counts via addition
merged_contributor.contribution_count += (
contributor.contribution_count
)
# Merge the commit urls via concatenation
merged_contributor.commit_url = (
merged_contributor.commit_url
+ ", "
+ contributor.commit_url
)
# Merge the new_contributor attribute via OR
merged_contributor.new_contributor = (
merged_contributor.new_contributor
or contributor.new_contributor
)

else:
merged_contributors.append(contributor)

return merged_contributors
15 changes: 9 additions & 6 deletions contributors.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ def main():

# Check for new contributor if user provided start_date and end_date
if start_date and end_date:
## get the list of contributors from before start_date so we can see if contributors after start_date are new or returning
# get the list of contributors from before start_date
# so we can see if contributors after start_date are new or returning
returning_contributors = get_all_contributors(
organization,
repository,
Expand All @@ -35,13 +36,12 @@ def main():
github_connection=github_connection,
)
for contributor in contributors:
for user in contributor:
user.new_contributor = contributor_stats.is_new_contributor(
user.username, returning_contributors
)
contributor.new_contributor = contributor_stats.is_new_contributor(
contributor.username, returning_contributors
)

# Output the contributors information
print(contributors)
# print(contributors)
markdown.write_to_markdown(contributors, "contributors.md", start_date, end_date)
# write_to_json(contributors)

Expand All @@ -68,6 +68,9 @@ def get_all_contributors(
else:
all_contributors.append(get_contributors(repository_obj, start_date, end_date))

# Check for duplicates and merge when usernames are equal
all_contributors = contributor_stats.merge_contributors(all_contributors)

return all_contributors


Expand Down
23 changes: 11 additions & 12 deletions markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,22 @@ def write_to_markdown(collaborators, filename, start_date, end_date):

table = headers

for repo in collaborators:
for collaborator in repo:
username = collaborator.username
contribution_count = collaborator.contribution_count
commit_url = collaborator.commit_url
new_contributor = collaborator.new_contributor
for collaborator in collaborators:
username = collaborator.username
contribution_count = collaborator.contribution_count
commit_url = collaborator.commit_url
new_contributor = collaborator.new_contributor

if start_date and end_date:
row = f"| {username} | {contribution_count} | {new_contributor} | {commit_url} |\n"
else:
row = f"| {username} | {contribution_count} | {commit_url} |\n"
if start_date and end_date:
row = f"| {username} | {contribution_count} | {new_contributor} | {commit_url} |\n"
else:
row = f"| {username} | {contribution_count} | {commit_url} |\n"

table += row
table += row

with open(filename, "w", encoding="utf-8") as markdown_file:
markdown_file.write("# Contributors\n\n")
markdown_file.write(table)
markdown_file.write(
"\n _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)\n"
"\n _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_\n"
)
59 changes: 56 additions & 3 deletions test_contributor_stats.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""This module contains the tests for the ContributorStats class."""

import unittest
from contributor_stats import ContributorStats
from contributor_stats import ContributorStats, merge_contributors


class TestContributorStats(unittest.TestCase):
Expand All @@ -17,7 +17,7 @@ def setUp(self):
"zkoppert",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
"1261",
1261,
"commit_url5",
)

Expand All @@ -31,12 +31,65 @@ def test_init(self):
self.contributor.avatar_url,
"https://avatars.githubusercontent.com/u/29484535?v=4",
)
self.assertEqual(self.contributor.contribution_count, "1261")
self.assertEqual(self.contributor.contribution_count, 1261)
self.assertEqual(
self.contributor.commit_url,
"commit_url5",
)

def test_merge_contributors(self):
"""
Test the merge_contributors function.
"""
contributor1 = ContributorStats(
"user1",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
100,
"commit_url1",
)
contributor2 = ContributorStats(
"user2",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
200,
"commit_url2",
)
contributor3 = ContributorStats(
"user1",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
150,
"commit_url3",
)
all_contributors = [
[
contributor1,
contributor2,
contributor3,
]
]
expected_result = [
ContributorStats(
"user1",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
250,
"commit_url1, commit_url3",
),
ContributorStats(
"user2",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
200,
"commit_url2",
),
]

result = merge_contributors(all_contributors)

self.assertTrue(expected_result == result)


if __name__ == "__main__":
unittest.main()
58 changes: 35 additions & 23 deletions test_contributors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import unittest
from unittest.mock import patch, MagicMock
from contributor_stats import ContributorStats
from contributors import get_contributors, get_all_contributors


Expand All @@ -19,7 +20,7 @@ def test_get_contributors(self, mock_contributor_stats):
mock_user = MagicMock()
mock_user.login = "user"
mock_user.avatar_url = "https://avatars.githubusercontent.com/u/12345678?v=4"
mock_user.contributions_count = "100"
mock_user.contributions_count = 100
mock_repo.contributors.return_value = [mock_user]
mock_repo.full_name = "owner/repo"

Expand All @@ -29,7 +30,7 @@ def test_get_contributors(self, mock_contributor_stats):
"user",
False,
"https://avatars.githubusercontent.com/u/12345678?v=4",
"100",
100,
"https://github.com/owner/repo/commits?author=user&since=2022-01-01&until=2022-12-31",
)

Expand All @@ -44,7 +45,13 @@ def test_get_all_contributors_with_organization(self, mock_get_contributors):
"repo2",
]
mock_get_contributors.return_value = [
{"username": "user", "contribution_count": "100", "commits": "commit_url"}
ContributorStats(
"user",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
100,
"commit_url",
),
]

result = get_all_contributors(
Expand All @@ -54,15 +61,14 @@ def test_get_all_contributors_with_organization(self, mock_get_contributors):
self.assertEqual(
result,
[
[
{
"username": "user",
"contribution_count": "100",
"commits": "commit_url",
}
]
]
* 2,
ContributorStats(
"user",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
200,
"commit_url, commit_url",
),
],
)
mock_get_contributors.assert_any_call("repo1", "2022-01-01", "2022-12-31")
mock_get_contributors.assert_any_call("repo2", "2022-01-01", "2022-12-31")
Expand All @@ -75,7 +81,13 @@ def test_get_all_contributors_with_repository(self, mock_get_contributors):
mock_github_connection = MagicMock()
mock_github_connection.repository.return_value = "repo"
mock_get_contributors.return_value = [
{"username": "user", "contribution_count": "100", "commits": "commit_url2"}
ContributorStats(
"user",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
100,
"commit_url2",
)
]

result = get_all_contributors(
Expand All @@ -85,13 +97,13 @@ def test_get_all_contributors_with_repository(self, mock_get_contributors):
self.assertEqual(
result,
[
[
{
"username": "user",
"contribution_count": "100",
"commits": "commit_url2",
}
]
ContributorStats(
"user",
False,
"https://avatars.githubusercontent.com/u/29484535?v=4",
100,
"commit_url2",
),
],
)
mock_get_contributors.assert_called_once_with(
Expand All @@ -107,11 +119,11 @@ def test_get_contributors_skip_users_with_no_commits(self, mock_contributor_stat
mock_user = MagicMock()
mock_user.login = "user"
mock_user.avatar_url = "https://avatars.githubusercontent.com/u/12345678?v=4"
mock_user.contributions_count = "100"
mock_user.contributions_count = 100
mock_user2 = MagicMock()
mock_user2.login = "user2"
mock_user2.avatar_url = "https://avatars.githubusercontent.com/u/12345679?v=4"
mock_user2.contributions_count = "102"
mock_user2.contributions_count = 102

mock_repo.contributors.return_value = [mock_user]
mock_repo.full_name = "owner/repo"
Expand All @@ -124,7 +136,7 @@ def test_get_contributors_skip_users_with_no_commits(self, mock_contributor_stat
"user",
False,
"https://avatars.githubusercontent.com/u/12345678?v=4",
"100",
100,
"https://github.com/owner/repo/commits?author=user&since=2022-01-01&until=2022-12-31",
)

Expand Down
11 changes: 6 additions & 5 deletions test_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ def test_write_to_markdown(self, mock_file):
# Set person2 as a new contributor since this cannot be set on initiatization of the object
person2.new_contributor = True
collaborators = [
[
person1,
person2,
]
person1,
person2,
]

write_to_markdown(collaborators, "filename", "2023-01-01", "2023-01-02")

mock_file.assert_called_once_with("filename", "w", encoding="utf-8")
mock_file().write.assert_any_call("# Contributors\n\n")
mock_file().write.assert_any_call(
"| Username | Contribution Count | New Contributor | Commits |\n| --- | --- | --- | --- |\n| user1 | 100 | False | commit url |\n| user2 | 200 | True | commit url2 |\n"
"| Username | Contribution Count | New Contributor | Commits |\n"
"| --- | --- | --- | --- |\n"
"| user1 | 100 | False | commit url |\n"
"| user2 | 200 | True | commit url2 |\n"
)


Expand Down

0 comments on commit 7464884

Please sign in to comment.