diff --git a/api/gitlab_classes.py b/api/gitlab_classes.py index 4ca6b635c0480751823758717a33742521b4287b..e1f12af13f57e3250acd8495b9978c17251c0e5f 100644 --- a/api/gitlab_classes.py +++ b/api/gitlab_classes.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, date from functools import reduce from typing import ClassVar, Dict, Iterable, List, Optional, Set, Union @@ -110,7 +110,7 @@ class GitlabIssue: """ return self.git_issue.description - def get_state(self) -> str: + def get_state(self) -> str: # TODO, deprecate and replace with is_opened & is_closed """ :return: opened or closed """ @@ -160,6 +160,19 @@ class GitlabIssue: """ return self.git_issue.web_url + def get_assignee(self) -> Optional[GitlabUser]: + assignee = self.git_issue.assignee + if assignee is None: + return None + else: + return GitlabUser(assignee['username']) + + def get_participants(self) -> List[GitlabUser]: + participants = [] + for participant in self.git_issue.participants(): + participants.append(GitlabUser(participant['username'])) + return participants + def close(self) -> None: self.git_issue.state_event = 'close' self.git_issue.save() @@ -177,7 +190,6 @@ class GitlabIssue: # milestone # assignees list of users # author user - # assignee user # user_notes_count # merge_requests_count # upvotes @@ -242,7 +254,7 @@ class GitlabCommit: # noinspection PyShadowingNames def get_diff_size_by_filetype(self) -> Dict[str, int]: - binary_like_text_files = {"css", "csv", "fxml", "html"} # TODO soft-code this + binary_like_text_files = {"css", "csv", "fxml", "html"} # TODO soft-code this # noinspection SpellCheckingInspection binary_files = {"docx", "gif", "jpg", "jpeg", "pdf", "png", "pptx", "svg", "xlsx"} # TODO this, too return_diff: Dict[str, int] = {} @@ -290,7 +302,7 @@ class GitlabCommit: def is_well_formatted(self, subject_line_length=72, message_line_length=72) -> bool: lines: List[str] = self.get_message().rstrip('\n').split('\n') return self._number_of_lines_too_long(lines, subject_line_length, message_line_length) == 0 \ - and self._has_blank_line_after_subject(lines) + and self._has_blank_line_after_subject(lines) def detail_formatting_problems(self, subject_line_length=72, message_line_length=72) -> str: lines: List[str] = self.get_message().rstrip('\n').split('\n') @@ -353,6 +365,64 @@ class GitlabMilestone: issues.append(GitlabIssue(issue)) return issues + def is_active(self) -> bool: + """ + :return: True if the milestone is active; False if the milestone is closed + """ + return self.gitlab_milestone.state == 'active' + + def is_closed(self) -> bool: + """ + :return: True if the milestone is closed; False if the milestone is active + """ + return self.gitlab_milestone.state == 'closed' + + def close(self) -> None: + self.gitlab_milestone.state_event = 'close' + self.gitlab_milestone.save() + + def get_title(self) -> str: + """ + :return: The milestone's title + """ + return self.gitlab_milestone.title + + def get_description(self) -> str: + """ + :return: The milestone's description + """ + return self.gitlab_milestone.description + + def get_created_at(self) -> date: + """ + :return: a date object representing the start date + """ + date_segments: List[str] = self.gitlab_milestone.start_date.split('-') + year = int(date_segments[0]) + month = int(date_segments[1]) + day = int(date_segments[2]) + return date(year, month, day) + + def get_due_date(self) -> date: + """ + :return: a date object representing the due date + """ + date_segments: List[str] = self.gitlab_milestone.due_date.split('-') + year = int(date_segments[0]) + month = int(date_segments[1]) + day = int(date_segments[2]) + return date(year, month, day) + + def __repr__(self) -> str: + return self.get_title() + + # other gitlab_milestone fields: + # id + # iid + # project_id + # updated_at + # created_at + class GitlabProject: git_project: Project diff --git a/commit_format_info.py b/commit_format_info.py new file mode 100644 index 0000000000000000000000000000000000000000..9f8761c1e3b8b08d3561d1ee436efaa2d9e684f0 --- /dev/null +++ b/commit_format_info.py @@ -0,0 +1,29 @@ +from api.gitlab_classes import * +from course import Course + +if __name__ == '__main__': + projects = GitlabProject.get_projects_by_group(Course.gitlab_namespace) + projects = list(filter(lambda p: p.get_name().startswith('30pair'), projects)) + projects.sort(key=lambda p: p.get_name()) + for project in projects: + commits = project.get_commits() + print(f'\n\n. >>>> {project} <<<<') + print(f'{len(commits)} commits on the master branch') + merges = 0 + reverts = 0 + well_formatted_commits = 0 + malformatted_commits = [] + for commit in commits: + if commit.is_merge(): + merges += 1 + elif commit.get_message().startswith('Revert'): + reverts += 1 + elif commit.is_well_formatted(): + well_formatted_commits += 1 + else: + malformatted_commits.append(commit) + print( + f'{merges} merges, {reverts} reverts, {well_formatted_commits} well-formatted commits, ' + f'and {len(malformatted_commits)} malformatted commits') + for commit in malformatted_commits: + print(f'{commit.detail_formatting_problems()} ({commit.get_author()})') diff --git a/milestone_sniffer.py b/milestone_sniffer.py new file mode 100644 index 0000000000000000000000000000000000000000..d7130c396abf5396fca8d3e4145d5f3190a13e2d --- /dev/null +++ b/milestone_sniffer.py @@ -0,0 +1,19 @@ +from api.gitlab_classes import * +from course import Course + +if __name__ == '__main__': + projects = sorted(list(filter(lambda p: p.get_name().startswith('36team'), + GitlabProject.get_projects_by_group(Course.gitlab_namespace))), + key=lambda p: p.get_name()) + for project in projects: + milestones = sorted(project.get_milestones(), key=lambda m: m.get_title()) + print('\n\n') + if len(milestones) == 0: + print(f'Project: {project} has no milestones') + else: + for milestone in milestones: + print(f'Project: {project}\tMilestone: {milestone}') + for issue in sorted(milestone.get_issues(), key=lambda i: i.get_project_issue_id()): + print(f'\tIssue {issue}') + print(f'\t\tCreated at {issue.get_created_at()}, assigned to {issue.get_assignee()}, updated at {issue.get_updated_at()}, closed at {issue.get_closed_at()}.') + print(f'\t\tParticipants: {issue.get_participants()}')