GeezerVison is showing github.com — add pull request API · mpdaugherty/python-github3@4539f80
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: pygithub3/core/client.py +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -81,7 +81,7 @@ def request(self, verb, request, **kwargs): | 81 | 81 |
| 82 | 82 | def get(self, request, **kwargs): | 83 | 83 | response = self.request('get', request, **kwargs) | 84 | | - assert response.status_code == 200 | | 84 | + # there are valid GET responses that != 200 | 85 | 85 | return response | 86 | 86 |
| 87 | 87 | def post(self, request, **kwargs): | |
Collapse file Copy file name to clipboardExpand all lines: pygithub3/exceptions.py +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -37,6 +37,6 @@ class UnprocessableEntity(Exception): | 37 | 37 | class NotFound(Exception): | 38 | 38 | """ Raised when server response is 404 | 39 | 39 |
| 40 | | - Catched with a pygithub3-exception to `services.base.Service._bool` method | | 40 | + Caught with a pygithub3-exception to `services.base.Service._bool` method | 41 | 41 | """ | 42 | 42 | pass |
Collapse file Copy file name to clipboardExpand all lines: pygithub3/github.py +9Lines changed: 9 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -17,9 +17,11 @@ def __init__(self, **config): | 17 | 17 | from pygithub3.services.users import User | 18 | 18 | from pygithub3.services.repos import Repo | 19 | 19 | from pygithub3.services.gists import Gist | | 20 | + from pygithub3.services.pull_requests import PullRequests | 20 | 21 | self._users = User(**config) | 21 | 22 | self._repos = Repo(**config) | 22 | 23 | self._gists = Gist(**config) | | 24 | + self._pull_requests = PullRequests(**config) | 23 | 25 |
| 24 | 26 | @property | 25 | 27 | def remaining_requests(self): | @@ -47,3 +49,10 @@ def gists(self): | 47 | 49 | :ref:`Gists service <Gists service>` | 48 | 50 | """ | 49 | 51 | return self._gists | | 52 | + | | 53 | + @property | | 54 | + def pull_requests(self): | | 55 | + """ | | 56 | + :ref:`Pull Requests service <Pull Requests service` | | 57 | + """ | | 58 | + return self._pull_requests |
Collapse file Copy file name to clipboard +62Lines changed: 62 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +from pygithub3.requests.base import Request, ValidationError | | 2 | +from pygithub3.resources.base import Raw | | 3 | +from pygithub3.resources.pull_requests import PullRequest, File | | 4 | +from pygithub3.resources.repos import Commit | | 5 | + | | 6 | + | | 7 | +class List(Request): | | 8 | + uri = 'repos/{user}/{repo}/pulls' | | 9 | + resource = PullRequest | | 10 | + | | 11 | + | | 12 | +class Get(Request): | | 13 | + uri = 'repos/{user}/{repo}/pulls/{number}' | | 14 | + resource = PullRequest | | 15 | + | | 16 | + | | 17 | +class Create(Request): | | 18 | + uri = 'repos/{user}/{repo}/pulls' | | 19 | + resource = PullRequest | | 20 | + body_schema = { | | 21 | + 'schema': ('title', 'body', 'base', 'head', 'issue'), | | 22 | + 'required': ('base', 'head'), | | 23 | + } | | 24 | + | | 25 | + def validate_body(self, parsed): | | 26 | + if (not ('title' in parsed and 'body' in parsed) and | | 27 | + not 'issue' in parsed): | | 28 | + raise ValidationError('pull request creation requires either an ' | | 29 | + 'issue number or a title and body') | | 30 | + | | 31 | +class Update(Request): | | 32 | + uri = 'repos/{user}/{repo}/pulls/{number}' | | 33 | + resource = PullRequest | | 34 | + body_schema = { | | 35 | + 'schema': ('title', 'body', 'state'), | | 36 | + 'required': (), | | 37 | + } | | 38 | + | | 39 | + def validate_body(self, body): | | 40 | + if 'state' in body and body['state'] not in ['open', 'closed']: | | 41 | + raise ValidationError('If a state is specified, it must be one ' | | 42 | + 'of "open" or "closed"') | | 43 | + | | 44 | + | | 45 | +class List_commits(Request): | | 46 | + uri = 'repos/{user}/{repo}/pulls/{number}/commits' | | 47 | + resource = Commit | | 48 | + | | 49 | + | | 50 | +class List_files(Request): | | 51 | + uri = 'repos/{user}/{repo}/pulls/{number}/files' | | 52 | + resource = File | | 53 | + | | 54 | + | | 55 | +class Merge_status(Request): | | 56 | + uri = 'repos/{user}/{repo}/pulls/{number}/merge' | | 57 | + resource = Raw | | 58 | + | | 59 | + | | 60 | +class Merge(Request): | | 61 | + uri = 'repos/{user}/{repo}/pulls/{number}/merge' | | 62 | + resource = Raw |
Collapse file Copy file name to clipboard +43Lines changed: 43 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +from pygithub3.requests.base import Request | | 2 | +from pygithub3.resources.pull_requests import Comment | | 3 | + | | 4 | + | | 5 | +class List(Request): | | 6 | + uri = 'repos/{user}/{repo}/pulls/{number}/comments' | | 7 | + resource = Comment | | 8 | + | | 9 | + | | 10 | +class Get(Request): | | 11 | + uri = 'repos/{user}/{repo}/pulls/comments/{number}' | | 12 | + resource = Comment | | 13 | + | | 14 | + | | 15 | +class Create(Request): | | 16 | + uri = 'repos/{user}/{repo}/pulls/{number}/comments' | | 17 | + resource = Comment | | 18 | + body_schema = { | | 19 | + 'schema': ('body', 'commit_id', 'path', 'position', 'in_reply_to'), | | 20 | + 'required': ('body',), | | 21 | + } | | 22 | + | | 23 | + def validate_body(self, body): | | 24 | + if (not ('commit_id' in body and | | 25 | + 'path' in body and | | 26 | + 'position' in body) and | | 27 | + not 'in_reply_to' in body): | | 28 | + raise ValidationError('supply either in_reply_to or commit_id, ' | | 29 | + 'path, and position') | | 30 | + | | 31 | + | | 32 | +class Edit(Request): | | 33 | + uri = 'repos/{user}/{repo}/pulls/comments/{number}' | | 34 | + resource = Comment | | 35 | + body_schema = { | | 36 | + 'schema': ('body',), | | 37 | + 'required': ('body',), | | 38 | + } | | 39 | + | | 40 | + | | 41 | +class Delete(Request): | | 42 | + uri = 'repos/{user}/{repo}/pulls/comments/{number}' | | 43 | + resource = Comment |
Collapse file Copy file name to clipboard +20Lines changed: 20 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +from .base import Resource | | 2 | + | | 3 | + | | 4 | +class PullRequest(Resource): | | 5 | + _dates = ('created_at', 'updated_at', 'closed_at', 'merged_at') | | 6 | + | | 7 | + def __str__(self): | | 8 | + return '<PullRequest (%s)>' % getattr(self, 'title', '') | | 9 | + | | 10 | + | | 11 | +class File(Resource): | | 12 | + def __str__(self): | | 13 | + return '<File (%s)>' % getattr(self, 'filename', '') | | 14 | + | | 15 | + | | 16 | +class Comment(Resource): | | 17 | + _dates = ('created_at', 'updated_at') | | 18 | + | | 19 | + def __str__(self): | | 20 | + return '<Comment (#%s)>' % getattr(self, 'id', '') |
Collapse file Copy file name to clipboard +129Lines changed: 129 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +from pygithub3.exceptions import BadRequest, NotFound | | 2 | +from pygithub3.services.base import Service, MimeTypeMixin | | 3 | +from .comments import Comments | | 4 | + | | 5 | + | | 6 | +class PullRequests(Service, MimeTypeMixin): | | 7 | + """Consume `Pull Request API <http://developer.github.com/v3/pulls/>`_""" | | 8 | + | | 9 | + def __init__(self, **config): | | 10 | + self.comments = Comments(**config) | | 11 | + super(PullRequests, self).__init__(**config) | | 12 | + | | 13 | + def list(self, user=None, repo=None): | | 14 | + """List all of the pull requests for a repo | | 15 | +
| | 16 | + :param str user: Username | | 17 | + :param str repo: Repository | | 18 | +
| | 19 | + """ | | 20 | + return self._get_result( | | 21 | + self.make_request('pull_requests.list', user=user, repo=repo) | | 22 | + ) | | 23 | + | | 24 | + def get(self, number, user=None, repo=None): | | 25 | + """Get a single pull request | | 26 | +
| | 27 | + :param str number: The number of the pull request to get | | 28 | + :param str user: Username | | 29 | + :param str repo: Repository | | 30 | +
| | 31 | + """ | | 32 | + return self._get( | | 33 | + self.make_request('pull_requests.get', number=number, user=user, | | 34 | + repo=repo) | | 35 | + ) | | 36 | + | | 37 | + def create(self, body, user=None, repo=None): | | 38 | + """Create a pull request | | 39 | +
| | 40 | + :param dict body: Data for the new pull request | | 41 | + :param str user: Username | | 42 | + :param str repo: Repository | | 43 | +
| | 44 | + """ | | 45 | + return self._post( | | 46 | + self.make_request('pull_requests.create', body=body, user=user, | | 47 | + repo=repo) | | 48 | + ) | | 49 | + | | 50 | + def update(self, number, body, user=None, repo=None): | | 51 | + """Update a pull request | | 52 | +
| | 53 | + :param str number: The number of the the pull request to update | | 54 | + :param dict body: The data to update the pull request with | | 55 | + :param str user: Username | | 56 | + :param str repo: Repository | | 57 | +
| | 58 | + """ | | 59 | + return self._patch( | | 60 | + self.make_request('pull_requests.update', number=number, | | 61 | + body=body, user=user, repo=repo) | | 62 | + ) | | 63 | + | | 64 | + def list_commits(self, number, user=None, repo=None): | | 65 | + """List the commits for a pull request | | 66 | +
| | 67 | + :param str number: The number of the pull request to list commits for | | 68 | + :param str user: Username | | 69 | + :param str repo: Repository | | 70 | +
| | 71 | + """ | | 72 | + return self._get_result( | | 73 | + self.make_request('pull_requests.list_commits', number=number, | | 74 | + user=user, repo=repo) | | 75 | + ) | | 76 | + | | 77 | + def list_files(self, number, user=None, repo=None): | | 78 | + """List the files for a pull request | | 79 | +
| | 80 | + :param str number: The number of the pull request to list files for | | 81 | + :param str user: Username | | 82 | + :param str repo: Repository | | 83 | +
| | 84 | + """ | | 85 | + return self._get_result( | | 86 | + self.make_request('pull_requests.list_files', number=number, | | 87 | + user=user, repo=repo) | | 88 | + ) | | 89 | + | | 90 | + def merge_status(self, number, user=None, repo=None): | | 91 | + """Gets whether a pull request has been merged or not. | | 92 | +
| | 93 | + :param str number: The pull request to check | | 94 | + :param str user: Username | | 95 | + :param str repo: Repository | | 96 | +
| | 97 | + """ | | 98 | + # for this to work with a proper Resource, we would need to pass the | | 99 | + # response's status code to the Resource constructor, and that's kind | | 100 | + # of scary | | 101 | + try: | | 102 | + resp = self._client.get( | | 103 | + self.make_request('pull_requests.merge_status', number=number, | | 104 | + user=user, repo=repo) | | 105 | + ) | | 106 | + except NotFound: | | 107 | + return False | | 108 | + code = resp.status_code | | 109 | + if code == 204: | | 110 | + return True | | 111 | + # TODO: more flexible way to return arbitrary objects based on | | 112 | + # response. Probably something on Request | | 113 | + raise BadRequest('got code %s: %s' % (code, resp.content)) | | 114 | + # again, I'm sorry. | | 115 | + | | 116 | + def merge(self, number, message='', user=None, repo=None): | | 117 | + """Merge a pull request. | | 118 | +
| | 119 | + :param str number: The pull request to merge | | 120 | + :param str user: Username | | 121 | + :param str repo: Repository | | 122 | +
| | 123 | + """ | | 124 | + # so, the API docs don't actually say what the status code will be in | | 125 | + # the case of a merge failure. I hope it's not a 404. | | 126 | + return self._put( | | 127 | + self.make_request('pull_requests.merge', number=number, | | 128 | + message=message, user=user, repo=repo) | | 129 | + ) |
Collapse file Copy file name to clipboard +73Lines changed: 73 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +from pygithub3.services.base import Service, MimeTypeMixin | | 2 | + | | 3 | + | | 4 | +class Comments(Service, MimeTypeMixin): | | 5 | + """Consume `Review Comments API | | 6 | + <http://developer.github.com/v3/pulls/comments/>`_ | | 7 | +
| | 8 | + """ | | 9 | + | | 10 | + def list(self, number, user=None, repo=None): | | 11 | + """List all the comments for a pull request | | 12 | +
| | 13 | + :param str number: The number of the pull request | | 14 | + :param str user: Username | | 15 | + :param str repo: Repository | | 16 | +
| | 17 | + """ | | 18 | + return self._get_result( | | 19 | + self.make_request('pull_requests.comments.list', number=number, | | 20 | + user=user, repo=repo) | | 21 | + ) | | 22 | + | | 23 | + def get(self, number, user=None, repo=None): | | 24 | + """Get a single comment | | 25 | +
| | 26 | + :param str number: The comment to get | | 27 | + :param str user: Username | | 28 | + :param str repo: Repository | | 29 | +
| | 30 | + """ | | 31 | + return self._get( | | 32 | + self.make_request('pull_requests.comments.get', number=number, | | 33 | + user=user, repo=repo) | | 34 | + ) | | 35 | + | | 36 | + def create(self, number, body, user=None, repo=None): | | 37 | + """Create a comment | | 38 | +
| | 39 | + :param str number: the pull request to comment on | | 40 | + :param str user: Username | | 41 | + :param str repo: Repository | | 42 | +
| | 43 | + """ | | 44 | + return self._post( | | 45 | + self.make_request('pull_requests.comments.create', number=number, | | 46 | + body=body, user=user, repo=repo) | | 47 | + ) | | 48 | + | | 49 | + def edit(self, number, body, user=None, repo=None): | | 50 | + """Edit a comment | | 51 | +
| | 52 | + :param str number: The id of the comment to edit | | 53 | + :param str user: Username | | 54 | + :param str repo: Repository | | 55 | +
| | 56 | + """ | | 57 | + return self._patch( | | 58 | + self.make_request('pull_requests.comments.edit', number=number, | | 59 | + body=body, user=user, repo=repo) | | 60 | + ) | | 61 | + | | 62 | + def delete(self, number, user=None, repo=None): | | 63 | + """Delete a comment | | 64 | +
| | 65 | + :param str number: The comment to delete | | 66 | + :param str user: Username | | 67 | + :param str repo: Repository | | 68 | +
| | 69 | + """ | | 70 | + return self._delete( | | 71 | + self.make_request('pull_requests.comments.delete', number=number, | | 72 | + user=user, repo=repo) | | 73 | + ) |
|