class StatisticsMixin: def contributors_list(self, owner, repo): url = f"/repos/{owner}/{repo}/stats/contributors" self.response = Response(self.get(url), "Contributors") return self.response.transform() def last_year_commit_activity(self, owner, repo): url = f"/repos/{owner}/{repo}/stats/commit_activity" self.response = Response(self.get(url), "Activity") return self.response.transform() def additions_deletions_per_week(self, owner, repo): url = f"/repos/{owner}/{repo}/stats/code_frequency" self.response = Response(self.get(url), "Activity") return self.response.transform() def weekly_commit_count(self, owner, repo): url = f"/repos/{owner}/{repo}/stats/participation" self.response = Response(self.get(url), "") return self.response.transform() def punchcard(self, owner, repo): url = f"/repos/{owner}/{repo}/stats/punchcard" self.response = Response(self.get(url), "PunchCard") return self.response.transform()
class DeployKeysMixin: def deploy_keys(self, owner, repo): url = "/repos/{owner}/{repo}/keys".format(owner=owner, repo=repo) self.response = Response(self.get(url), "DeployKeys") return self.response.transform() def deploy_key(self, owner, repo, key_id): url = "/repos/{owner}/{repo}/keys/{key_id}".format(owner=owner, repo=repo, key_id=key_id) self.response = Response(self.get(url), "DeployKey") return self.response.transform() def add_deploy_key(self, owner, repo, title, key, read_only): url = "/repos/{owner}/{repo}/keys/".format(owner=owner, repo=repo) params = {"title": title, "key": key, "read_only": read_only} self.response = Response(self.post(url, params=params), "DeployKey") return self.response.transform() def remove_deploy_key(self, owner, repo, key_id): url = "/repos/{owner}/{repo}/keys/{key_id}".format(owner=owner, repo=repo, key_id=key_id) self.response = Response(self.delete(url), "") return self.response.status_code == 204
class CollaboratorsMixin: def repo_collaborators(self, owner, repo, affiliation="all"): url = f"/repos/{owner}/{repo}/collaborators" self.response = Response( self.get(url, params={"affiliation": affiliation}, **{"Accept": _mime}), "Collaborators", ) return self.response.transform() def is_collaborator(self, owner, repo, username): url = f"/repos/{owner}/{repo}/collaborators/{username}" self.response = Response(self.get(url, **{"Accept": _mime}), "") return self.response.status_code == 204 def user_permission(self, owner, repo, username): url = f"/repos/{owner}/{repo}/collaborators/{username}/permission" self.response = Response(self.get(url, **{"Accept": _mime}), "") return self.response.transform() def add_user_as_collaborator(self, owner, repo, username, permission): url = f"/repos/{owner}/{repo}/collaborators/{username}" self.response = Response( self.put(url, params={"permission": permission}, **{"Accept": _mime}), "User", ) def remove_user_as_collaborator(self, owner, repo, username): url = f"/repos/{owner}/{repo}/collaborators/{username}" self.response = Response(self.delete(url, **{"Accept": _mime}), "User") return self.response.status_code == 204
class StatusMixin: def create_status(self, owner, repo, sha, state, target_url, description, context): url = "/repos/{owner}/{repo}/statuses/{sha}".format(owner=owner, repo=repo, sha=sha) params = { "state": state, "target_url": target_url, "description": description, "context": context, } self.response = Response(self.post(url, params=params), "Status") return self.response.transform() def statuses_for_ref(self, owner, repo, ref): url = "/repos/{owner}/{repo}/commits/{ref}/statuses".format( owner=owner, repo=repo, ref=ref) self.response = Response(self.get(url), "Statuses") return self.response.transform() def combined_status_for_ref(self, owner, repo, ref): url = "/repos/{owner}/{repo}/commits/{ref}/status".format(owner=owner, repo=repo, ref=ref) self.response = Response(self.get(url), "CombinedStatus") return self.response.transform()
class ReferencesMixin: def git_reference(self, owner, repo, ref): url = "/repos/{owner}/{repo}/git/ref/{ref}".format(owner=owner, repo=repo, ref=ref) self.response = Response(self.get(url), "Reference") return self.response.transform() def matching_git_references(self, owner, repo, ref): url = "/repos/{owner}/{repo}/git/matching-refs/{ref}".format( owner=owner, repo=repo, ref=ref) self.response = Response(self.get(url), "References") return self.response.transform() def create_git_reference(self, owner, repo, ref, sha): url = "/repos/{owner}/{repo}/git/refs".format(owner=owner, repo=repo) params = {"ref": ref, "sha": sha} self.response = Response(self.post(url, params=params), "Reference") return self.response.transform() def update_git_reference(self, owner, repo, ref, sha, force=False): url = "/repos/{owner}/{repo}/git/refs/{ref}".format(owner=owner, repo=repo, ref=ref) params = {"sha": sha, "force": force} self.response = Response(self.patch(url, params=params), "Reference") return self.response.transform() def delete_git_reference(self, owner, repo, ref): url = "/repos/{owner}/{repo}/git/refs/{ref}".format(owner=owner, repo=repo, ref=ref) self.response = Response(self.delete(url), "") return self.response.status_code == 204
class ReviewRequestsMixin: def pr_review_requests(self, owner, repo, pull_number): url = "/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers".format( owner=owner, repo=repo, pull_number=pull_number) self.response = Response(self.get(url), "ReviewRequests") return self.response.transform() def create_pr_review_request(self, owner, repo, pull_number, reviewers, team_reviewers): _mime = "application/vnd.github.symmetra-preview+json" url = "/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers".format( owner=owner, repo=repo, pull_number=pull_number) params = {"reviewers": reviewers, "team_reviewers": team_reviewers} self.response = Response( self.post(url, params=params, **{"Accept": _mime}), "ReviewRequest") return self.response.transform() def delete_pr_review_requests(self, owner, repo, pull_number, reviewers, team_reviewers): url = "/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers".format( owner=owner, repo=repo, pull_number=pull_number) params = {"reviewers": reviewers, "team_reviwers": team_reviewers} self.response = Response(self.delete(url, params=params), "") return self.response.status_code == 204
class InvitationMixin: def invitations(self, owner, repo): url = f"/repos/{owner}/{repo}/invitations" self.response = Response(self.get(url), "Invitations") return self.response.transform() def delete_invitation(self, owner, repo, invitation_id): url = f"/repos/{owner}/{repo}/invitations/{invitation_id}" self.response = Response(self.get(url), "") return self.response.status_code == 204 def update_invitation(self, owner, repo, invitation_id, permissions): url = f"/repos/{owner}/{repo}/invitations/{invitation_id}" self.response = Response( self.patch(url, params={"permissions": permissions}), "Invitations" ) return self.response.transform() def user_repository_invitations(self): url = f"/user/repository_invitations" self.response = Response(self.get(url), "Invitations") return self.response.transform() def accept_repository_invitations(self, invitation_id): url = f"/user/repository_invitations/{invitation_id}" self.response = Response(self.patch(url), "Invitations") return self.response.transform() def decline_repository_invitations(self, invitation_id): url = f"/user/repository_invitations/{invitation_id}" self.response = Response(self.delete(url), "Invitations") return self.response.status_code == 204
class TrafficMixin: def referrers(self, owner, repo): url = "/repos/{owner}/{repo}/traffic/popular/referrers".format( owner=owner, repo=repo) self.response = Response(self.get(url), "Referrers") return self.response.transform() def paths(self, owner, repo): url = "/repos/{owner}/{repo}/traffic/popular/paths".format(owner=owner, repo=repo) self.response = Response(self.get(url), "Paths") return self.response.transform() def views(self, owner, repo, per="day"): url = "/repos/{owner}/{repo}/traffic/views".format(owner=owner, repo=repo) params = {"per": per} self.response = Response(self.get(url, params=params), "Views") return self.response.transform() def clones(self, owner, repo, per="day"): url = "/repos/{owner}/{repo}/traffic/popular/paths".format(owner=owner, repo=repo) params = {"per": per} self.response = Response(self.get(url, params=params), "Clones") return self.response.transform()
class TeamDiscussionCommentsMixin: def team_discussion_comments(self, team_id, discussion_number, direction=TeamDiscussionCommentDirection.DSC): url = "/teams/{team_id}/discussions/{discussion_number}/comments".format( team_id=team_id, discussion_number=discussion_number) params = {"direction": direction.value} self.response = Response( self.get(url, params=params, **{"Accept": _mime}), "OrgTeam") return self.response.transform() def team_discussion_comment( self, team_id, discussion_number, comment_number, direction=TeamDiscussionCommentDirection.DSC, ): url = "/teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}".format( team_id=team_id, discussion_number=discussion_number, comment_number=comment_number, ) params = {"direction": direction.value} self.response = Response( self.get(url, params=params, **{"Accept": _mime}), "OrgTeam") return self.response.transform() def create_team_discussion_comment(self, team_id, discussion_number, body): url = "/teams/{team_id}/discussions/{discussion_number}/comments".format( team_id=team_id, discussion_number=discussion_number) params = {"body": body} self.response = Response( self.post(url, params=params, **{"Accept": _mime}), "OrgTeam") return self.response.transform() def edit_team_discussion_comment(self, team_id, discussion_number, comment_number, body): url = "/teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}".format( team_id=team_id, discussion_number=discussion_number, comment_number=comment_number, ) params = {"body": body} self.response = Response( self.patch(url, params=params, **{"Accept": _mime}), "OrgTeam") return self.response.transform() def delete_team_discussion_comment(self, team_id, discussion_number, comment_number): url = "/teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}".format( team_id=team_id, discussion_number=discussion_number, comment_number=comment_number, ) self.response = Response(self.delete(url, **{"Accept": _mime}), "") return self.response.status_code == 204
class CardsMixin: def project_cards(self, column_id, archived_state=ArchivedState.NOT_ARCHIVED): url = "/projects/columns/{column_id}/cards".format(column_id=column_id) params = {"column_id": column_id, "archived_state": archived_state.value} self.response = Response( self.get(url, params=params, **_accept_header), "ProjectCards" ) return self.response.transform() def project_card(self, card_id): url = "/projects/columns/cards/{card_id}".format(card_id=card_id) self.response = Response(self.get(url, **_accept_header), "ProjectCard") return self.response.transform() def create_project_card( self, column_id, note=None, content_id=None, content_type=None ): if note: if content_id is not None or content_type is not None: raise ValueError( "When you specify note, you should not specify content_id and content_type." ) params = [("note", note)] else: if content_id is None or content_type is None: raise ValueError( "When you do not specify note, you should specify both content_id and content_type." ) params = {"content_id": int(content_id), "content_type": content_type} url = "/projects/columns/{column_id}/cards".format(column_id=column_id) self.response = Response( self.post(url, params=params, **_accept_header), "ProjectCard" ) return self.response.transform() def update_project_card(self, card_id, archived, note=None): params = {"archived": archived, "note": note} url = "/projects/columns/cards/{card_id}".format(card_id=card_id) self.response = Response( self.patch(url, params=params, **_accept_header), "ProjectCard" ) return self.response.transform() def delete_project_card(self, card_id): url = "/projects/columns/cards/{card_id}".format(card_id=card_id) self.response = Response(self.delete(url, **_accept_header), "ProjectCard") return self.response.status_code == 204 def move_project_card(self, card_id, position, column_id): url = "/projects/columns/cards/{card_id}/moves".format(card_id=card_id) if position not in CardPosition: raise ValueError("position should be of type CardPosition.") params = {"position": position.value.format(card_id), "column_id": column_id} self.response = Response( self.post(url, params=params, **_accept_header), "ProjectCard" ) return self.response.transform()
class UserMigrationMixin: def start_user_migration(self, repositories, lock_repositories=False, exclude_attachments=False): url = "/user/migrations" assert isinstance(repositories, (list, tuple)) for repo in repositories: assert isinstance(repo, str) params = { "repositories": repositories, "lock_repositories": lock_repositories } self.response = Response( self.post(url, params=params, **{"Accept": _mime}), "UserMigration") return self.response.transform() def user_migrations(self): """ Lists all migrations a user has started. :return: """ url = "/user/migrations" self.response = Response(self.get(url, **{"Accept": _mime}), "UserMigrations") return self.response.transform() def user_migration_status(self, migration_id): url = f"/user/migrations/{migration_id}" self.response = Response(self.get(url, **{"Accept": _mime}), "UserMigrations") return self.response.transform() def download_user_migration_archive(self, migration_id): url = f"/user/migrations/{migration_id}/archive" self.response = Response(self.get(url, **{"Accept": _mime}), "UserMigrations") return self.response.transform() def delete_user_migration_archive(self, migration_id): url = f"/user/migrations/{migration_id}/archive" self.response = Response(self.delete(url, **{"Accept": _mime}), "") if self.response.status_code == 204: return True raise ValueError( f"delete_user_migration_archive(......) should return 204, but it returned {self.response.status_code}" ) def unlock_user_repository(self, migration_id, repo_name): url = f"/user/migrations/{migration_id}/repos/{repo_name}/lock" self.response = Response(self.delete(url, **{"Accept": _mime}), "") if self.response.status_code == 204: return True raise ValueError( f"unlock_user_repository(......) should return 204, but it returned {self.response.status_code}" )
class ContentsMixin: def readme(self, owner, repo, ref="master", media_type=None): url = "/repos/{owner}/{repo}/readme".format(owner=owner, repo=repo) self.response = Response(self.get(url, params={"ref": ref}), "Readme") return self.response.transform() def contents(self, owner, repo, path, ref="master"): url = "/repos/{owner}/{repo}/contents/{path}".format(owner=owner, repo=repo, path=path) self.response = Response(self.get(url, params={"ref": ref}), "Contents") return self.response.transform() def create_update_file(self, owner, repo, path, message, content, sha, branch, committer, author): url = "/repos/{owner}/{repo}/contents/{path}".format(owner=owner, repo=repo, path=path) params = { "message": message, "content": content, "sha": sha, "branch": branch, "committer": committer, "author": author, } self.response = Response(self.put(url, params=params), "File") return self.response.transform() def delete_file( self, owner, repo, path, message, sha, committer=None, author=None, branch="master", ): url = "/repos/{owner}/{repo}/contents/{path}".format(owner=owner, repo=repo, path=path) params = {"message": message, "sha": sha, "branch": branch} if committer: params["committer"] = committer if author: params["author"] = author self.response = Response(self.delete(url, params=params), "File") return self.response.transform() def get_archive_link(self, owner, repo, archive_format, ref): url = "/repos/{owner}/{repo}/{archive_format}/{ref}".format( owner=owner, repo=repo, archive_format=archive_format, ref=ref) self.response = Response(self.get(url), "Archive") return self.response.transform()
class ColumnsMixin: def project_columns(self, project_id): url = "/projects/{project_id}/columns".format(project_id=project_id) self.response = Response( self.get(url, **{"Accept": _project_accept_header}), "Columns") return self.response.transform() def project_column(self, column_id): url = "/projects/columns/{column_id}".format(column_id=column_id) self.response = Response( self.get(url, **{"Accept": _project_accept_header}), "Column") return self.response.transform() def create_project_column(self, project_id, name): url = "/projects/{project_id}/columns".format(project_id=project_id) params = [("name", name)] self.response = Response( self.post(url, params=params, **{"Accept": _project_accept_header}), "Column", ) return self.response.transform() def update_project_column(self, column_id, name): url = "/projects/columns/{column_id}".format(column_id=column_id) params = [("name", name)] self.response = Response( self.patch(url, params=params, **{"Accept": _project_accept_header}), "Column", ) return self.response.transform() def delete_project_column(self, column_id): url = "/projects/columns/{column_id}".format(column_id=column_id) self.response = Response( self.delete(url, **{"Accept": _project_accept_header}), "Column") return self.response.status_code == 204 def move_project_column(self, column_id, position): url = "/projects/columns/{column_id}/moves".format(column_id=column_id) if position not in CardPosition: raise ValueError("position should be of type CardPosition.") params = [("position", position.value)] self.response = Response( self.post(url, params=params, **{"Accept": _project_accept_header}), "Column", ) return self.response.transform()
class MilestoneMixin: def milestones( self, owner, repo, state=MilestoneState.OPEN, sort=MilestoneSort.DUE_ON, direction=MilestoneDirection.ASC, ): url = "/repos/{owner}/{repo}/milestones".format(owner=owner, repo=repo) params = { "state": state.value, "sort": sort.value, "direction": direction.value, } self.response = Response(self.get(url, params=params), "Milestones") return self.response.transform() def milestone(self, owner, repo, milestone_number): url = "/repos/{owner}/{repo}/milestones/{milestone_number}".format( owner=owner, repo=repo, milestone_number=milestone_number ) self.response = Response(self.get(url), "Milestone") return self.response.transform() def create_milestone(self, owner, repo, title, state, description, due_on): url = "/repos/{owner}/{repo}/milestones".format(owner=owner, repo=repo) params = { "title": title, "state": state, "description": description, "due_on": due_on, } self.response = Response(self.post(url, params=params), "Milestone") return self.response.transform() def update_milestone( self, owner, repo, milestone_number, title, state, description, due_on ): url = "/repos/{owner}/{repo}/milestones/{milestone_number}".format( owner=owner, repo=repo, milestone_number=milestone_number ) params = { "title": title, "state": state, "description": description, "due_on": due_on, } self.response = Response(self.patch(url, param=params), "Milestone") return self.response.transform() def delete_milestone(self, owner, repo, milestone_number): url = "/repos/{owner}/{repo}/milestones/{milestone_number}".format( owner=owner, repo=repo, milestone_number=milestone_number ) self.response = Response(self.delete(url), "") return self.response.status_code == 204
class OrganizationMigrationMixin: def start_org_migration(self, org, repositories, lock_repositories=False, exclude_attachments=False): url = "/orgs/{org}/migrations".format(org=org) params = { "repositories": repositories, "lock_repositories": lock_repositories, "exclude_attachments": exclude_attachments, } self.response = Response( self.post(url, params=params, **{"Accept": _mime}), "OrgMigration") return self.response.transform() def org_migrations(self, org): url = "/orgs/{org}/migrations".format(org=org) self.response = Response(self.get(url, **{"Accept": _mime}), "OrgMigrations") return self.response.transform() def org_migration_status(self, org, migration_id): url = "/orgs/{org}/migrations/{migration_id}".format( org=org, migration_id=migration_id) self.response = Response(self.get(url, **{"Accept": _mime}), "OrgMigrations") return self.response.transform() def download_migration_archive(self, org, migration_id): url = "/orgs/{org}/migrations/{migration_id}/archive".format( org=org, migration_id=migration_id) self.response = Response(self.get(url, **{"Accept": _mime}), "OrgMigrations") return self.response.transform() def delete_org_migration_archive(self, org, migration_id): url = "/orgs/{org}/migrations/{migration_id}/archive".format( org=org, migration_id=migration_id) self.response = Response(self.delete(url, **{"Accept": _mime}), "OrgMigrations") if self.response.status_code == 204: return True raise ValueError( "delete_org_migration_archive(.....) returned {status_code}, it should return 204." .format(status_code=self.response.status_code)) def unlock_org_repository(self, org, migration_id, repo_name): url = "/orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock".format( org=org, migration_id=migration_id, repo_name=repo_name) self.response = Response(self.delete(url, **{"Accept": _mime}), "OrgMigrations") if self.response.status_code == 204: return True raise ValueError( "unlock_org_repository(.....) returned {status_code}, it should return 204." .format(status_code=self.response.status_code))
class GPGKeysMixin: def list_gpg_keys(self, username): url = f"/users/{username}/gpg_keys" self.response = Response( self.get( url, **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "GPGKeys", ) return self.response.transform() def gpg_keys(self): url = f"/users/gpg_keys" self.response = Response( self.get( url, **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "GPGKeys", ) return self.response.transform() def gpg_key(self, gpg_key_id): url = f"/user/gpg_keys/{gpg_key_id}" self.response = Response( self.get( url, **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "GPGKey", ) return self.response.transform() def create_public_gpg_key(self, armored_public_key): url = "/user/gpg_keys" self.response = Response( self.post( url, json=[("armored_public_key", armored_public_key)] ** {"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "SSHKey", ) return self.response.transform() def delete_public_gpg_key(self, gpg_key_id): url = f"/user/gpg_keys/{gpg_key_id}" self.response = Response( self.delete( url, **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "", ) return self.response.status_code == 204
class SSHKeysMixin: def list_public_ssh_keys(self, username): url = "/users/{username}/keys".format(username=username) self.response = Response( self.get( url, **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "SSHKeys", ) return self.response.transform() def ssh_keys(self): url = "/user/keys" self.response = Response( self.get( url, **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "SSHKeys", ) return self.response.transform() def ssh_key(self, key_id): url = "/user/keys/{key_id}".format(key_id=key_id) self.response = Response( self.get( url, **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "SSHKey", ) return self.response.transform() def create_public_ssh_key(self, title, key): url = "/user/keys" self.response = Response( self.post( url, params=[("title", title), ("key", key)], **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "SSHKey", ) return self.response.transform() def delete_public_ssh_key(self, key_id): url = "/user/keys/{key_id}".format(key_id=key_id) self.response = Response( self.delete( url, **{"Accept": "application/vnd.github.giant-sentry-fist-preview+json"}, ), "", ) return self.response.status_code == 204
class GistCommentsMixin: def gist_comments(self, gist_id, **kwargs): """ The following are the MIME types supported by this method, application/vnd.github.VERSION.raw+json application/vnd.github.VERSION.text+json application/vnd.github.VERSION.html+json application/vnd.github.VERSION.full+json :param gist_id: :param kwargs: :return: """ url = "/gists/{gist_id}/comments".format(gist_id=gist_id) self.response = Response(self.get(url, **kwargs), "GistComments") return self.response.transform() def create_gist_comment(self, gist_id, body): url = "/gists/{gist_id}/comments".format(gist_id=gist_id) params = {"body": body} self.response = Response(self.post(url, params=params), "GistComments") return self.response.transform() def edit_gist_comment(self, gist_id, comment_id, body): url = "/gists/{gist_id}/comments/{comment_id}".format( gist_id=gist_id, comment_id=comment_id) params = {"body": body} self.response = Response(self.patch(url, params=params), "GistComments") return self.response.transform() def gist_comment(self, gist_id, comment_id, **kwargs): """ The following are the MIME types supported by this method, application/vnd.github.VERSION.raw+json application/vnd.github.VERSION.text+json application/vnd.github.VERSION.html+json application/vnd.github.VERSION.full+json :param gist_id: :param kwargs: :return: """ url = "/gists/{gist_id}/comments/{comment_id}".format( gist_id=gist_id, comment_id=comment_id) self.response = Response(self.get(url, **kwargs), "GistComment") return self.response.transform() def delete_gist_comment(self, gist_id, comment_id): url = "/gists/{gist_id}/comments/{comment_id}".format( gist_id=gist_id, comment_id=comment_id) self.response = Response(self.delete(url), "") return self.response.status_code == 204
class CommentsMixin: def repo_comments(self, owner, repo): _mime = "application/vnd.github.squirrel-girl-preview" url = "/repos/{owner}/{repo}/comments".format(owner=owner, repo=repo) self.response = Response(self.get(url, **{"Accept": _mime}), "Comments") return self.response.transform() def commit_comments(self, owner, repo, commit_sha): _mime = "application/vnd.github.squirrel-girl-preview" url = "/repos/{owner}/{repo}/commits/{commit_sha}/comments".format( owner=owner, repo=repo, commit_sha=commit_sha) self.response = Response(self.get(url, **{"Accept": _mime}), "Comment") return self.response.transform() def create_commit_comment(self, owner, repo, commit_sha, body, path, position, line=None): url = "/repos/{owner}/{repo}/commits/{commit_sha}/comments".format( owner=owner, repo=repo, commit_sha=commit_sha) params = { "body": body, "path": path, "position": position, "line": line } self.response = Response(self.post(url, params=params), "Comment") return self.response.transform() def single_commit_comment(self, owner, repo, comment_id): _mime = "application/vnd.github.squirrel-girl-preview" url = "/repos/{owner}/{repo}/comments/{comment_id}".format( owner=owner, repo=repo, comment_id=comment_id) self.response = Response(self.get(url, **{"Accept": _mime}), "Comment") return self.response.transform() def update_commit_comment(self, owner, repo, comment_id, body): _mime = "application/vnd.github.squirrel-girl-preview" url = "/repos/{owner}/{repo}/comments/{comment_id}".format( owner=owner, repo=repo, comment_id=comment_id) self.response = Response(self.patch(url, **{"Accept": _mime}), "Comment") return self.response.transform() def delete_commit_comment(self, owner, repo, comment_id): url = "/repos/{owner}/{repo}/comments/{comment_id}".format( owner=owner, repo=repo, comment_id=comment_id) self.response = Response(self.delete(url), "") return self.response.status_code == 204
class GitIgnoreMixin: def git_ignore_templates(self): url = "/gitignore/templates" self.response = Response(self.get(url), "Templates") return self.response.transform() def git_ignore_template(self, name, media_type=MediaType.NONE): url = f"/gitignore/templates/{name}" self.response = Response( self.get(url, **{"Accept": media_type.value}), "Template" ) return self.response.transform()
class BlobMixin: def blob(self, owner, repo, file_sha): url = "/repos/{owner}/{repo}/git/blobs/{file_sha}".format( owner=owner, repo=repo, file_sha=file_sha) self.response = Response(self.get(url), "Blob") return self.response.transform() def create_blob(self, owner, repo, content, encoding="utf-8"): url = "/repos/{owner}/{repo}/git/blobs".format(owner=owner, repo=repo) params = {"content": content, "encoding": encoding} self.response = Response(self.post(url, params=params), "Blob") return self.response.transform()
class GitIgnoreMixin: def git_ignore_templates(self): # TODO: This API is returning [None, ..........None] # Not sure this API is working anymore. url = "/gitignore/templates" self.response = Response(self.get(url), "Templates") return self.response.transform() def git_ignore_template(self, name, media_type=MediaType.JSON): url = "/gitignore/templates/{name}".format(name=name) self.response = Response(self.get(url, **{"Accept": media_type.value}), "Template") return self.response.transform()
class WebHooksMixin: def org_hooks(self, org): url = "/orgs/{org}/hooks".format(org=org) self.response = Response(self.get(url), "WebHooks") return self.response.transform() def org_hook(self, org, hook_id): url = "/orgs/{org}/hooks/{hook_id}".format(org=org, hook_id=hook_id) self.response = Response(self.get(url), "WebHook") return self.response.transform() def create_org_hook(self, org, name, config, events=("push",), active=True): assert isinstance(config, dict) url = "/orgs/{org}/hooks/".format(org=org) params = { "name": name, "active": active, "events": list(events), "config": config, } self.response = Response(self.post(url, params=params), "WebHook") return self.response.transform() def edit_org_hook(self, org, hook_id, config, events=("push",), active=True): assert isinstance(config, dict) url = "/orgs/{org}/hooks/{hook_id}".format(org=org, hook_id=hook_id) params = {"active": active, "events": list(events), "config": config} self.response = Response(self.patch(url, params=params), "WebHook") return self.response.transform() def ping_org_hook(self, org, hook_id): url = "/orgs/{org}/hooks/{hook_id}/pings".format(org=org, hook_id=hook_id) self.response = Response(self.post(url), "") if self.response.status_code == 204: return True raise ValueError( "ping_hook(....) returned status code: {status_code}, instead of 204.".format( status_code=self.response.status_code ) ) def delete_org_hook(self, org, hook_id): url = "/orgs/{org}/hooks/{hook_id}".format(org=org, hook_id=hook_id) self.response = Response(self.delete(url), "") if self.response.status_code == 204: return True raise ValueError( "delete_hook(....) returned status code: {status_code}, instead of 204.".format( status_code=self.response.status_code ) )
class CheckSuitesMixin: def check_suite(self, owner, repo, check_suite_id, **kwargs): url = "/repos/{owner}/{repo}/check-suites/{check_suite_id}".format( owner=owner, repo=repo, check_suite_id=check_suite_id ) self.response = Response( self.get(url, **{"Accept": _mime}, **kwargs), "CheckSuite" ) return self.response.transform() def check_suite_for_ref(self, owner, repo, ref, app_id, check_name, **kwargs): url = "/repos/{owner}/{repo}/{ref}/check-suites".format( owner=owner, repo=repo, ref=ref ) params = {"app_id": app_id, "check_name": check_name} self.response = Response( self.get(url, params=params, **{"Accept": _mime}, **kwargs), "CheckSuite" ) return self.response.transform() def set_preferences_for_check_suite( self, owner, repo, auto_trigger_checks, **kwargs ): url = "/repos/{owner}/{repo}/check-suites/preferences".format( owner=owner, repo=repo ) params = {"auto_trigger_checks": auto_trigger_checks} self.response = Response( self.patch(url, params=params, **{"Accept": _mime}, **kwargs), "CheckSuite" ) return self.response.transform() def create_check_suite(self, owner, repo, head_sha, **kwargs): url = "/repos/{owner}/{repo}/check-suites".format(owner=owner, repo=repo) self.response = Response( self.post( url, params={"head_sha": head_sha}, **{"Accept": _mime}, **kwargs ), "CheckSuite", ) return self.response.transform() def rerequest_check_suite(self, owner, repo, check_suite_id, **kwargs): url = "/repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest".format( owner=owner, repo=repo, check_suite_id=check_suite_id ) self.response = Response( self.post(url, **{"Accept": _mime}, **kwargs), "CheckSuite" ) return self.response.transform()
class CommitMixin: def commits(self, owner, repo, sha=None, path=None, author=None, since=None, until=None, **kwargs): url = "/repos/{owner}/{repo}/commits".format(owner=owner, repo=repo) params = {} if sha: params["sha"] = sha if path: params["path"] = path if author: params["author"] = author if since: params["until"] = until self.response = Response(self.get(url, **kwargs), "Commits") return self.response.transform() def commit(self, owner, repo, ref): url = "/repos/{owner}/{repo}/commits/{ref}".format(owner=owner, repo=repo, ref=ref) self.response = Response(self.get(url), "Commit") return self.response.transform() def compare_commits(self, owner, repo, base, head): url = "/repos/{owner}/{repo}/compare/{base}...{head}".format( owner=owner, repo=repo, base=base, head=head) self.response = Response(self.get(url), "Compare") return self.response.transform() def branches_for_head_commit(self, owner, repo, commit_sha): _mime = "application/vnd.github.groot-preview+json" url = "/repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head".format( owner=owner, repo=repo, commit_sha=commit_sha) self.response = Response(self.get(url, **{"Accept": _mime}), "Branches") return self.response.transform() def prs_for_commit(self, owner, repo, commit_sha): _mime = "application/vnd.github.groot-preview+json" url = "/repos/{owner}/{repo}/commits/{commit_sha}/pulls".format( owner=owner, repo=repo, commit_sha=commit_sha) self.response = Response(self.get(url, **{"Accept": _mime}), "PRs") return self.response.transform()
class BranchMixin: def branches(self, owner, repo, protected=None): url = f"/repos/{owner}/{repo}/branches" params = {} if protected: params = {"protected": protected} self.response = Response(self.get(url, params=params), "Branches") return self.response.transform() def branch(self, owner, repo, branch): url = f"/repos/{owner}/{repo}/branches/{branch}" self.response = Response(self.get(url), "Branch") return self.response.transform() def protected_branch(self, owner, repo, branch): mime = "application/vnd.github.luke-cage-preview+json" url = f"/repos/{owner}/{repo}/branches/{branch}/protection" self.response = Response(self.get(url, **{"Accept": mime}), "BranchProtection") return self.response.transform() def update_branch_protection( self, owner, repo, branch, required_status_checks, enforce_admins, required_pull_request_reviews, restrictions, ): mime = "application/vnd.github.luke-cage-preview+json" url = f"/repos/{owner}/{repo}/branches/{branch}/protection" params = { "required_status_checks": required_status_checks, "enforce_admins": enforce_admins, "required_pull_request_reviews": required_pull_request_reviews, "restrictions": restrictions, } self.response = Response( self.put(url, params=params, **{"Accept": mime}), "UpdateBranchProtection") return self.response.transform() def remove_branch_protection(self, owner, repo, branch): mime = "application/vnd.github.luke-cage-preview+json" url = f"/repos/{owner}/{repo}/branches/{branch}/protection" self.response = Response(self.delete(url, **{"Accept": mime}), "") return self.response.status_code == 204
class LicenseMixin: def licenses(self, **kwargs): url = "/licenses" self.response = Response(self.get(url, **kwargs), "Licenses") return self.response.transform() def license(self, license_name, **kwargs): url = "/licenses/{license_name}".format(license_name=license_name) self.response = Response(self.get(url, **kwargs), "License") return self.response.transform() def license_contents(self, owner, repo, **kwargs): url = "/repos/{owner}/{repo}/license".format(owner=owner, repo=repo) self.response = Response(self.get(url, **kwargs), "LicenseContent") return self.response.transform()
class MarkDownMixin: def render_markdown(self, text, mode, content): url = "/markdown" params = {"text": text, "mode": mode, "content": content} self.response = Response(self.post(url, params=params), "Markdown") return self.response.transform() def render_markdown_raw_mode(self, text): url = "/markdown/raw" params = {"text": text} self.response = Response( self.post(url, params=params, **{"Content-Type": "text/plain"}), "MarkdownRaw", ) return self.response.transform()
class ForkMixin: def forks(self, owner, repo, sort=Sort.NEWEST): url = f"/repos/{owner}/{repo}/forks" self.response = Response(self.get(url, params=[("sort", sort.value)]), "Forks") return self.response.transform() def create_fork(self, owner, repo, organization=None): url = f"/repos/{owner}/{repo}/forks" params = {} if organization: params["organization"] = organization self.response = Response(self.post(url, params=params), "Fork") assert self.response.status_code == 202 return self.response.transform()
class LicenseMixin: def licenses(self): url = "/licenses" self.response = Response(self.get(url), "Licenses") return self.response.transform() def license(self, license_name): url = f"/licenses/{license_name}" self.response = Response(self.get(url), "License") return self.response.transform() def license_contents(self, owner, repo): url = f"/repos/{owner}/{repo}/license" self.response = Response(self.get(url), "LicenseContent") return self.response.transform()