Skip to content
Snippets Groups Projects
Commit 58cbe2a8 authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Provide timestamp statistics for commits

parent eca8ffc8
No related branches found
No related tags found
No related merge requests found
......@@ -206,8 +206,8 @@ class GitlabCommit:
def get_author(self) -> Dict[str, str]:
return {'name': self.gitlab_commit.author_name, 'email': self.gitlab_commit.author_email}
def get_timestamp(self) -> str: # TODO: is a string (vs a datetime) really what we want?
return self.gitlab_commit.created_at
def get_timestamp(self) -> datetime:
return datetime.fromisoformat(self.gitlab_commit.created_at)
def get_message(self) -> str:
return self.gitlab_commit.message
......
import datetime
from typing import List, Optional, TypeVar
from typing import List, Optional, TypeVar, Set
from api.composite_user import CompositeUser
ChoiceType = TypeVar("ChoiceType")
......@@ -51,3 +53,17 @@ def semester_stamp() -> str:
else:
month = 8
return f'{year}-0{month}'
def get_students() -> Set[CompositeUser]:
filename: str
students: Set[CompositeUser]
file_not_found = True
while file_not_found:
try:
filename = input('Please provide the name of the existing student roster file: ')
students = CompositeUser.read_student_csv(filename)
file_not_found = False
except FileNotFoundError:
print(f'File "{filename}" not found.')
return students
\ No newline at end of file
import math
import textwrap
from datetime import date
from math import ceil, log10
......@@ -100,6 +101,7 @@ def display_git_contributions(project: GitlabProject):
else:
project_commits = project.get_commits(after_date=assignment_start_date)
contributions: Dict[str, int] = {} # TODO: also broaden to multiple branches?
timestamps: Dict[str, List[datetime]] = {}
contributors: Set[Tuple[str, str]] = set()
# noinspection PyShadowingNames
for commit in project_commits:
......@@ -108,14 +110,24 @@ def display_git_contributions(project: GitlabProject):
contributors.add((author['name'], author['email']))
email = author['email'] # TODO: manage aliases
size = commit.get_diff_size() # TODO: distinguish between file types
if email != 'bohn@unl.edu': # TODO: un-hard-code this
if email != 'bohn@unl.edu': # TODO: un-hard-code this -- may not be necessary with a starting date
if email not in contributions:
contributions[email] = 0
timestamps[email] = []
contributions[email] += size
print(f'Total line changes by each contributor to {project} :')
timestamps[email].append(commit.get_timestamp())
print(f'Contributions by each partner to {project} :')
for contribution in contributions:
contributor = list(filter(lambda c: c[1] == contribution, contributors))[0]
print(f'\t{str(contributions[contribution]).rjust(5)}\t{contributor}')
email = contributor[1]
timestamps[email].sort()
number_of_commits = len(timestamps[email])
print(f'\t{contributor}')
print(
f'\t{str(contributions[contribution]).rjust(5)} line changes in {str(number_of_commits).rjust(3)} commits')
print(f'\t\tFirst commit: {timestamps[email][0]}')
print(f'\t\tMedian commit: {timestamps[email][math.floor(number_of_commits/2)]}')
print(f'\t\tLast commit: {timestamps[email][-1]}')
# noinspection PyUnusedLocal
......
from prep_assignment import *
from common_functions import select_from_list
from common_functions import select_from_list, get_students
# TODO: look for opportunity to reduce DRY, relative to main function in prep_assignment
......
......@@ -6,23 +6,10 @@ from typing import Tuple
from api.canvas_classes import *
from api.gitlab_classes import *
from api.composite_user import CompositeUser
from common_functions import get_students
from course import Course
def get_students() -> Set[CompositeUser]:
filename: str
students: Set[CompositeUser]
file_not_found = True
while file_not_found:
try:
filename = input('Please provide the name of the existing student roster file: ')
students = CompositeUser.read_student_csv(filename)
file_not_found = False
except FileNotFoundError:
print(f'File "{filename}" not found.')
return students
def validate_roster_against_canvas(course_roster: Set[CompositeUser]) -> bool:
print('Validating course roster against Canvas.')
course = CanvasCourse(Course.canvas_course_id)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment