def create_pull_request( self, owner, repo, title, head, base, body=None, maintainer_can_modify=None, draft=None, ): url = "/repos/{owner}/{repo}/pulls".format(owner=owner, repo=repo) params = {"title": title, "head": head, "base": base} if body: params["body"] = body if maintainer_can_modify: params["maintainer_can_modify"] = maintainer_can_modify if draft: params["draft"] = draft self.response = Response( self.post(url, params=params, **{"Accept": _mime}), "PullRequest") return self.response.transform()
def start_source_import( self, owner, repo, vcs_url, vcs_username, vcs_password, tfvc_project=None, vcs=SourceControlType.NONE, ): url = f"/repos/{owner}/{repo}/import" params = { "vcs": vcs.value, "vcs_url": vcs_url, "vcs_username": vcs_username, "vcs_password": vcs_password, } if vcs == SourceControlType.TFVC: params.update({"tfvc_project": tfvc_project}) self.response = Response( self.put(url, params=params, **{"Accept": _mime}), "Import") 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 is_gist_starred(self, gist_id): url = "/gists/{gist_id}/star".format(gist_id=gist_id) code = Response(self.get(url), "").status_code if code == 204: return True elif code == 404: return False else: raise ErrorAPICode( "The url:{url} returned status code: {code}. Maybe try after sometime?".format( url=url, code=code ) )
def create_release( self, owner, repo, tag_name, target_commitish, name, body, draft=False, prerelease=False, ): params = { "tag_name": tag_name, "target_commitish": target_commitish, "name": name, "body": body, "draft": draft, "prerelease": prerelease, } url = f"/repos/{owner}/{repo}/releases" self.response = Response(self.post(url, params=params), "Release") return self.response.transform()
def user_is_following(self, username, target_user): url = "/users/{username}/following/{target_user}".format( username=username, target_user=target_user) self.response = Response( self.get( url, **{ "Accept": "application/vnd.github.giant-sentry-fist-preview+json" }, ), "", ) if self.response.status_code == 204: return True elif self.response.status_code == 404: return False else: raise ErrorAPICode( "API has returned an Unexpected response code - {status_code}." "It should either be 204 or 404.".format( status_code=self.response.status_code))
def follow(self, username): url = "/user/following/{username}".format(username=username) self.response = Response( self.put( url, **{ "Accept": "application/vnd.github.giant-sentry-fist-preview+json", "Content-Length": "0", }, ), "", ) if self.response.status_code == 204: return True elif self.response.status_code == 404: return False else: raise ErrorAPICode( "API has returned an Unexpected response code - {status_code}." "It should either be 204 or 404.".format( status_code=self.response.status_code))
class StatusMixin: def create_status(self, owner, repo, sha, state, target_url, description, context): url = f"/repos/{owner}/{repo}/statuses/{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 = f"/repos/{owner}/{repo}/commits/{ref}/statuses" self.response = Response(self.get(url), "Statuses") return self.response.transform() def combined_status_for_ref(self, owner, repo, ref): url = f"/repos/{owner}/{repo}/commits/{ref}/status" self.response = Response(self.get(url), "CombinedStatus") return self.response.transform()
class TrafficMixin: def referrers(self, owner, repo): url = f"/repos/{owner}/{repo}/traffic/popular/referrers" self.response = Response(self.get(url), "Referrers") return self.response.transform() def paths(self, owner, repo): url = f"/repos/{owner}/{repo}/traffic/popular/paths" self.response = Response(self.get(url), "Paths") return self.response.transform() def views(self, owner, repo, per="day"): url = f"/repos/{owner}/{repo}/traffic/views" params = {"per": per} self.response = Response(self.get(url, params=params), "Views") return self.response.transform() def clones(self, owner, repo, per="day"): url = f"/repos/{owner}/{repo}/traffic/popular/paths" params = {"per": per} self.response = Response(self.get(url, params=params), "Clones") return self.response.transform()
def user_issues( self, filter=IssueFilter.ASSIGNED, state=IssueState.OPEN, labels="", sort=IssueSort.CREATED, direction=IssueDirection.DESCENDING, since="", ): url = "/user/issues" params = [ ("filter", filter.value), ("state", state.value), ("labels", labels), ("sort", sort.value), ("direction", direction.value), ("since", since), ] self.response = Response( self.get(url, params=params, **{"Accept": IssueCustomMediaType}), "Issues") return self.response.transform()
class CollaboratorsMixin: def repo_collaborators(self, owner, repo, affiliation="all"): url = "/repos/{owner}/{repo}/collaborators".format(owner=owner, repo=repo) self.response = Response( self.get(url, params={"affiliation": affiliation}, **_mime), "Collaborators") return self.response.transform() def is_collaborator(self, owner, repo, username): url = "/repos/{owner}/{repo}/collaborators/{username}".format( owner=owner, repo=repo, username=username) self.response = Response(self.get(url, **_mime), "") return self.response.status_code == 204 def user_permission(self, owner, repo, username): url = "/repos/{owner}/{repo}/collaborators/{username}/permission".format( owner=owner, repo=repo, username=username) self.response = Response(self.get(url, **_mime), "") return self.response.transform() def add_user_as_collaborator(self, owner, repo, username, permission=CollabPermission.PUSH): url = "/repos/{owner}/{repo}/collaborators/{username}".format( owner=owner, repo=repo, username=username) self.response = Response( self.put(url, params={"permission": permission.value}, **_mime), "User") return self.response.transform() def remove_user_as_collaborator(self, owner, repo, username): url = "/repos/{owner}/{repo}/collaborators/{username}".format( owner=owner, repo=repo, username=username) self.response = Response(self.delete(url, **_mime), "User") return self.response.status_code == 204
class CodeOfConductMixin: def codes_of_conduct(self, **kwargs): url = "/codes_of_conduct" self.response = Response(self.get(url, **{"Accept": _mime}, **kwargs), "COCs") return self.response.transform() def code_of_conduct(self, key, **kwargs): url = "/codes_of_conduct/{key}".format(key=key) self.response = Response(self.get(url, **{"Accept": _mime}, **kwargs), "COC") return self.response.transform() def repo_code_of_conduct(self, owner, repo): url = "/repos/{owner}/{repo}".format(owner=owner, repo=repo) self.response = Response(self.get(url, **{"Accept": _mime}), "RepoCOC") return self.response.transform() def contents_of_repo_code_of_conduct(self, owner, repo): url = "/repos/{owner}/{repo}/community/code_of_conduct".format( owner=owner, repo=repo) self.response = Response(self.get(url, **{"Accept": _mime}), "RepoCOC") return self.response.transform()
def edit_repo_hook( self, owner, repo, hook_id, config, events, add_events, remove_events, active=True, ): url = f"/repos/{owner}/{repo}/hooks/{hook_id}" assert isinstance(config, dict) assert isinstance(events, (list, tuple)) params = { "active": active, "events": events, "add_events": add_events, "remove_events": remove_events, "config": config, } self.response = Response(self.patch(url, params=params), "Hook") return self.response.transform()
def create_content_attachment(self, content_reference_id, title, body, **kwargs): url = "/content_references/{content_reference_id}/attachments".format( content_reference_id=content_reference_id) self._check_app_token() _mime = "application/vnd.github.corsair-preview+json" self.response = Response( self.post( url, params={ "title": title, "body": body }, **{ "Authorization": "Bearer {app_token}".format(app_token=self.app_token), "Accept": _mime, }, **kwargs), "", ) return self.response.transform()
def update_pr_review_enforcement_of_protected_branch( self, owner, repo, branch, dismissal_restrictions, dismiss_stale_reviews, require_code_owner_reviews, required_approving_review_count, ): _mime = "application/vnd.github.luke-cage-preview+json" params = { "dismissal_restrictions": dismissal_restrictions, "dismiss_stale_reviews": dismiss_stale_reviews, "require_code_owner_reviews": require_code_owner_reviews, "required_approving_review_count": required_approving_review_count, } url = "/repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews".format( owner=owner, repo=repo, branch=branch) self.response = Response( self.patch(url, params=params, **{"Accept": _mime}), "PRReviewEnforcement") return self.response.transform()
def starred_by( self, username, sort=Sort.CREATED, direction=Direction.DESC, starred_at=False, **kwargs, ): if sort not in Sort: raise ValueError("'sort' must be of type Sort") if direction not in Direction: raise ValueError("'direction' must be of type Direction") url = f"/users/{username}/starred" params = [("sort", sort.value), ("direction", direction.value)] if starred_at: kwargs.update( { "Accept": f"application/vnd.github.v{config.api_version}.star+{config.api_mime_type}" } ) self.response = Response(self.get(url, params, **kwargs), "StarRepos") return self.response.transform()
def hover_card(self, username, subject_tye=SubjectType.NONE, subject_id=None): if bool(subject_tye.value) != bool( subject_id): # Python shortcut for XOR. raise ValueError( "subject_type and subject_id both should provided or both left out" ) params = [] if subject_id and subject_tye.value: params = [("subject_type", subject_tye.value), ("subject_id", subject_id)] url = "/users/{username}/hovercard".format(username=username) self.response = Response( self.get( url, params=params, **{"Accept": "application/vnd.github.hagar-preview+json"}, ), "HoverCard", ) return self.response.transform()
def org_user_issues( self, org, filter=Filter.Assigned, state=State.Open, labels="", sort=Sort.Created, direction=Direction.Descending, since="", ): url = f"/org/{org}/issues" params = [ ("filter", filter.value), ("state", state.value), ("labels", labels), ("sort", sort.value), ("direction", direction.value), ("since", since), ] self.response = Response( self.get(url, params=params, **{"Accept": IssueCustomMediaType}), "Issues") return self.response.transform()
def user_repos(self, username, **kwargs): params = [] if "type" in kwargs: type = kwargs.pop("type") if not isinstance(type, RepoType): raise ValueError( "'{type}' should be instance of Type".format(type=type)) if type not in RepoType: raise ValueError( "'{type}' should either be 'ALL', 'OWNER', 'PUBLIC', 'PRIVATE', or 'MEMBER'" .format(type=type)) params.append(("type", type.value)) if "sort" in kwargs: sort = kwargs.pop("sort") if not isinstance(sort, RepoSort): raise ValueError( "{sort} should be instance of Sort".format(sort=sort)) if sort not in RepoSort: raise ValueError( "'{sort}' should either be 'CREATED', 'UPDATED', 'PUSHED', or 'FULLNAME'" .format(sort=sort)) params.append(("sort", sort.value)) if "direction" in kwargs: direction = kwargs.pop("direction") if not isinstance(direction, RepoDirection): raise ValueError( "'{direction}' is not an instance of Direction".format( direction=direction)) if direction not in RepoDirection: raise ValueError( "'{direction}' should either be 'ASC', or 'DESC'".format( direction=direction)) params.append(("direction", direction.value)) url = "/users/{username}/repos".format(username=username) self.response = Response(self.get_basic(url, params=params, **kwargs), "Repos") return self.response.transform()
class WatchingMixin: def list_watchers(self, owner, repo, **kwargs): url = f"/repos/{owner}/{repo}/subscribers" self.response = Response(self.get(url, **kwargs), "Watchers") return self.response.transform() def repos_watched_by(self, username, **kwargs): url = f"/users/{username}/subscriptions" self.response = Response(self.get(url, **kwargs), "WatchedRepos") return self.response.transform() def repos_watched(self, **kwargs): url = "/user/subscriptions" self.response = Response(self.get(url, **kwargs), "WatchedRepos") return self.response.transform() def repo_subscription(self, owner, repo, **kwargs): url = f"/repos/{owner}/{repo}/subscription" self.response = Response(self.get(url, **kwargs), "RepoSubscription") return self.response.transform() def set_subscription(self, owner, repo, subscribed=True, ignored=False, **kwargs): url = f"repos/{owner}/{repo}/subscription" params = [("subscribed", subscribed), ("ignored", ignored)] self.response = Response(self.put(url, params=params, **kwargs), "Subscription") return self.response.transform() def delete_subscription(self, owner, repo, **kwargs): url = f"repos/{owner}/{repo}/subscription" self.response = Response(self.delete(url, **kwargs), "") return self.response.status_code == 204
class CollaboratorsMixin: def project_collaborators(self, project_id, collaborators=Collaborators.ALL): """ Lists the collaborators for an organization project. """ url = "/projects/{project_id}/collaborators".format(project_id=project_id) params = {"collaborators": collaborators.value} self.response = Response( self.get(url, params=params, **_accept_header), "Collaborators" ) return self.response.transform() def review_permission_level(self, project_id, username): url = "/projects/{project_id}/collaborators/{username}/permission".format( project_id=project_id, username=username ) self.response = Response(self.get(url, **_accept_header), "Permission") return self.response.transform() def add_user_collaborator(self, project_id, username, permission=Permission.WRITE): url = "/projects/{project_id}/collaborators/{username}".format( project_id=project_id, username=username ) params = {"permission": permission.value} self.response = Response(self.put(url, params=params, **_accept_header), "") return self.response.status_code == 204 def delete_user_collaborator(self, project_id, username): url = "/projects/{project_id}/collaborators/{username}".format( project_id=project_id, username=username ) self.response = Response(self.delete(url, **_accept_header), "") return self.response.status_code == 204
def create_team_in_org( self, org, name, description, maintainers, repo_names, privacy, permission, parent_team_id, ): params = { "name": name, "description": description, "maintainers": maintainers, "permission": permission, "privacy": privacy, "repo_names": repo_names, "parent_team_id": parent_team_id, } url = "/orgs/{org}/teams".format(org=org) self.response = Response( self.post(url, params=params, **{"Accept": _mime}), "OrgTeam") return self.response.transform()
def edit_release( self, owner, repo, release_id, tag_name, target_commitish, name, body, draft=False, prerelease=False, ): params = { "tag_name": tag_name, "target_commitish": target_commitish, "name": name, "body": body, "draft": draft, "prerelease": prerelease, } url = "/repos/{owner}/{repo}/releases/{release_id}".format( owner=owner, repo=repo, release_id=release_id) self.response = Response(self.patch(url, params=params), "Release") return self.response.transform()
class TeamDiscussionsMixin: def team_discussions(self, team_id): url = "/teams/{team_id}/discussions".format(team_id=team_id) self.response = Response(self.get(url, **{"Accept": _mime}), "TeamDiscussions") return self.response.transform() def team_discussion(self, team_id, discussion_number): url = "/teams/{team_id}/discussions/{discussion_number}".format( team_id=team_id, discussion_number=discussion_number) self.response = Response(self.get(url, **{"Accept": _mime}), "TeamDiscussion") return self.response.transform() def create_team_discussion(self, team_id, title, body, private=False): url = "/teams/{team_id}/discussions".format(team_id=team_id) params = {"title": title, "body": body, "private": private} self.response = Response( self.post(url, params=params, **{"Accept": _mime}), "TeamDiscussion") return self.response.transform() def edit_team_discussion(self, team_id, discussion_number, title, body): url = "/teams/{team_id}/discussions/{discussion_number}".format( team_id=team_id, discussion_number=discussion_number) params = {"title": title, "body": body} self.response = Response( self.patch(url, params=params, **{"Accept": _mime}), "TeamDiscussion") return self.response.transform() def delete_team_discussion(self, team_id, discussion_number): url = "/teams/{team_id}/discussions/{discussion_number}".format( team_id=team_id, discussion_number=discussion_number) self.response = Response(self.delete(url, **{"Accept": _mime}), "") return self.response.status_code == 204
def notifications_in_repo( self, owner, repo, all=False, participating=False, since=None, before=None, **kwargs, ): """ List all notifications for the current user. """ url = "/repos/{owner}/{repo}/notifications".format(owner=owner, repo=repo) params = { "all": all, "participating": participating, "since": since, "before": before, } self.response = Response(self.get(url, params=params, **kwargs), "NotificationsRepo") return self.response.transform()
def notifications_in_repo( self, owner, repo, all=False, participating=False, since=None, before=None, **kwargs, ): """ List all notifications for the current user. """ url = f"/repos/{owner}/{repo}/notifications" params = [ ("all", all), ("participating", participating), ("since", since), ("before", before), ] self.response = Response( self.get(url, params=params, **kwargs), "NotificationsRepo" ) return self.response.transform()
def unblock(self, username): """ Unblock a user """ url = "/user/blocks/{username}".format(username=username) self.response = Response( self.delete( url, **{ "Accept": "application/vnd.github.giant-sentry-fist-preview+json" }, ), "", ) if self.response.status_code == 204: return True elif self.response.status_code == 404: return False else: raise ErrorAPICode( "API has returned an Unexpected response code - {status_code}." "It should either be 204 or 404.".format( status_code=self.response.status_code))
class OutsideCollabMixin: def outside_collaborators(self, org, filter="all"): url = "/orgs/{org}/outside_collaborators".format(org=org) params = {"filter": filter} self.response = Response(self.get(url, params=params), "OutsideCollaborators") return self.response.transform() def delete_outside_collaborator(self, org, username): url = "/orgs/{org}/outside_collaborators/{username}".format( org=org, username=username) self.response = Response(self.delete(url), "") if self.response.status_code == 204: return True raise ValueError( "delete_outside_collaborator(.....) returned {status_code}, instead of 204." .format(status_code=self.response.status_code)) def convert_member_to_outside_collaborator(self, org, username): """ When an organization member is converted to an outside collaborator, they'll only have access to the repositories that their current team membership allows. The user will no longer be a member of the organization. Response Status: 204 No Content Response if user is not a member of the organization Status: 403 Forbidden Response if user is the last owner of the organization Status: 403 Forbidden :param org: :param username: :return: """ url = "/orgs/{org}/outside_collaborators/{username}".format( org=org, username=username) self.response = Response(self.put(url), "") if self.response.status_code == 204: return True raise ValueError( "convert_member_to_outside_collaborator(.....) returned {status_code}, instead of 204." .format(status_code=self.response.status_code))
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 licenses(self, **kwargs): url = "/licenses" self.response = Response(self.get(url, **kwargs), "Licenses") return self.response.transform()