8000 Support for Project Cards · pythonthings/github3.py@9733e5d · GitHub
[go: up one dir, main page]

Skip to content
< 8000 script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/sessions-eed3aa0554dd.js" defer="defer">

Commit 9733e5d

Browse files
rco-abletonsigmavirus24
authored andcommitted
Support for Project Cards
1 parent a48abb8 commit 9733e5d

12 files changed

+417
-0
lines changed

github3/projects.py

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,95 @@ def _update_attributes(self, project_column):
159159
def _repr(self):
160160
return '<ProjectColumn [#{0}]>'.format(self.id)
161161

162+
def card(self, id):
163+
"""Get a project card with the given ID.
164+
165+
:param int id: (required), the card ID
166+
:returns: :class:`ProjectCard <github3.projects.ProjectCard>` or None
167+
"""
168+
url = self._build_url(
169+
'projects/columns/cards', str(id), base_url=self._github_url)
170+
json = self._json(self._get(url, headers=Project.CUSTOM_HEADERS), 200)
171+
return self._instance_or_null(ProjectCard, json)
172+
173+
def cards(self, number=-1, etag=None):
174+
"""Iterate over the cards in this column.
175+
176+
:param int number: (optional), number of cards to return. Default:
177+
-1 returns all available cards.
178+
:param str etag: (optional), ETag from a previous request to the same
179+
endpoint
180+
:returns: generator of
181+
:class:`ProjectCard <github3.project.ProjectCard>`
182+
"""
183+
url = self._build_url(
184+
'projects/columns',
185+
str(self.id),
186+
'cards',
187+
base_url=self._github_url
188+
)
189+
return self._iter(
190+
int(number),
191+
url,
192+
ProjectCard,
193+
headers=Project.CUSTOM_HEADERS,
194+
etag=etag
195+
)
196+
197+
@requires_auth
198+
def create_card_with_content_id(self, content_id, content_type):
199+
"""Create a content card in this project column.
200+
201+
:param int content_id: (required), the ID of the content
202+
:param str content_type: (required), the type of the content
203+
:returns: :class:`ProjectCard <github3.projects.ProjectCard>` or none
204+
"""
205+
if not content_id or not content_type:
206+
return None
207+
208+
url = self._build_url(
209+
'projects/columns',
210+
str(self.id),
211+ 'cards',
212+
base_url=self._github_url
213+
)
214+
json = None
215+
data = {'content_id': content_id, 'content_type': content_type}
216+
json = self._json(self._post(
217+
url, data=data, headers=Project.CUSTOM_HEADERS), 201)
218+
return self._instance_or_null(ProjectCard, json)
219+
220+
@requires_auth
221+
def create_card_with_issue(self, issue):
222+
"""Create a card in this project column linked with an Issue.
223+
224+
:param :class:`Issue <github3.issues.Issue>`: (required), an issue
225+
with which to link the card
226+
:returns: :class:`ProjectCard <github3.projects.ProjectCard>` or none
227+
"""
228+
if not issue:
229+
return None
230+
return self.create_card_with_content_id(issue.id, 'Issue')
231+
232+
@requires_auth
233+
def create_card_with_note(self, note):
234+
"""Create a note card in this project column.
235+
236+
:param str note: (required), the note content
237+
:returns: :class:`ProjectCard <github3.projects.ProjectCard>` or none
238+
"""
239+
url = self._build_url(
240+
'projects/columns',
241+
str(self.id),
242+
'cards',
243+
base_url=self._github_url
244+
)
245+
json = None
246+
if note:
247+
json = self._json(self._post(
248+
url, data={'note': note}, headers=Project.CUSTOM_HEADERS), 201)
249+
return self._instance_or_null(ProjectCard, json)
250+
162251
@requires_auth
163252
def delete(self):
164253
"""Delete this column.
@@ -213,3 +302,91 @@ def update(self, name=None):
213302
self._update_attributes(json)
214303
return True
215304
return False
305+
306+
307+
class ProjectCard(models.GitHubCore):
308+
"""The :class:`ProjectCard <ProjectCard>` object.
309+
310+
See http://developer.github.com/v3/projects/cards/
311+
"""
312+
313+
def _update_attributes(self, project_card):
314+
#: The URL of this card's parent column
315+
self.column_url = self._get_attribute(project_card, 'column_url')
316+
317+
#: The URL of this card's associated content
318+
self.content_url = self._get_attribute(project_card, 'content_url')
319+
320+
#: datetime object representing the last time the object was created
321+
self.created_at = self._strptime_attribute(project_card, 'created_at')
322+
323+
#: The ID of this card
324+
self.id = self._get_attribute(project_card, 'id')
325+
326+
#: The note attached to the card
327+
self.note = self._get_attribute(project_card, 'note')
328+
329+
#: datetime object representing the last time the object was changed
330+
self.updated_at = self._strptime_attribute(project_card, 'updated_at')
331+
332+
def _repr(self):
333+
return '<ProjectCard [#{0}]>'.format(self.id)
334+
335+
@requires_auth
336+
def delete(self):
337+
"""Delete this card.
338+
339+
:returns: bool
340+
"""
341+
url = self._build_url(
342+
'projects/columns/cards', self.id, base_url=self._github_url)
343+
return self._boolean(self._delete(
344+
url, headers=Project.CUSTOM_HEADERS), 204, 404)
345+
346+
@requires_auth
347+
def move(self, position, column_id):
348+
"""Move this card.
349+
350+
:param str position: (required), can be one of `top`, `bottom`, or
351+
`after:<card-id>`, where `<card-id>` is the id value of a card
352+
in the same column, or in the new column specified by `column_id`.
353+
:param int column_id: (required), the id value of a column in the
354+
same project.
355+
:returns: bool
356+
"""
357+
if not position or not column_id:
358+
return False
359+
360+
url = self._build_url(
361+
'projects/columns/cards',
362+
self.id,
363+
'moves',
364+
base_url=self._github_url
365+
)
366+
data = {'position': position, 'column_id': column_id}
367+
return self._boolean(self._post(
368+
url, data=data, headers=Project.CUSTOM_HEADERS), 201, 404)
369+
370+
@requires_auth
371+
def update(self, note=None):
372+
"""Update this card.
373+
374+
:param str note: (optional), the card's note content. Only valid for
375+
cards without another type of content, so this cannot be specified
376+
if the card already has a content_id and content_type.
377+
:returns: bool
378+
"""
379+
data = {'note': note}
380+
json = None
381+
self._remove_none(data)
382+
383+
if data:
384+
url = self._build_url(
385+
'projects/columns/cards', self.id, base_url=self._github_url)
386+
json = self._json(self._patch(
387+
url, data=dumps(data), headers=Project.CUSTOM_HEADERS), 200)
388+
389+
if json:
390+
self._update_attributes(json)
391+
return True
392+
return False
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"recorded_with": "betamax/0.8.0", "http_interactions": [{"recorded_at": "2017-02-21T16:49:06", "request": {"uri": "https://api.github.com/repos/sigmavirus24/github3.py", "headers": {"User-Agent": "github3.py/1.0.0a4", "Authorization": "token <AUTH_TOKEN>", "Accept": "application/vnd.github.drax-preview+json", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/json", "Accept-Charset": "utf-8"}, "body": {"string": "", "encoding": "utf-8"}, "method": "GET"}, "response": {"url": "https://api.github.com/repos/sigmavirus24/github3.py", "headers": {"X-OAuth-Scopes": "repo", "Transfer-Encoding": "chunked", "X-RateLimit-Remaining": "4876", "Cache-Control": "private, max-age=60, s-maxage=60", "X-GitHub-Media-Type": "github.drax-preview; format=json", "X-Served-By": "d0b3c2c33a23690498aa8e70a435a259", "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", "X-Accepted-OAuth-Scopes": "repo", "Access-Control-Expose-Headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "Date": "Tue, 21 Feb 2017 16:48:55 GMT", "Access-Control-Allow-Origin": "*", "ETag": "W/\"9063dcd15c2604b3ce4d2e39d2f94104\"", "X-RateLimit-Reset": "1487698380", "Last-Modified": "Tue, 15 Nov 2016 14:09:50 GMT", "X-Frame-Options": "deny", "Content-Security-Policy": "default-src 'none'", "Content-Type": "application/json; charset=utf-8", "Server": "GitHub.com", "X-RateLimit-Limit": "5000", "X-Content-Type-Options": "nosniff", "X-XSS-Protection": "1; mode=block", "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "Status": "200 OK", "X-GitHub-Request-Id": "C611:7030:7B43D60:99D6956:58AC6F77", "Content-Encoding": "gzip"}, "body": {"string": "", "base64_string": "H4sIAAAAAAAAA+2YTW/jNhCG/4qhax0zjrtxV0CxLdB7L3vqxaAl2iJCkQJJOU2E/Pe+I+rLDnblNffQQ4AgUWTy4evhDDkzTSLzJN1uflt/3m62y0TzUiRp4oXzVlQmWSaHWqld9/rPvRLe6L/E6asxyrHJMPOshU3SJlHmKDUQF2NBopXWm8dH/KyXCT9xz+2utgqDC+8rlzIWXrrVUfqi3tdO2MxoL7RfZaZkNeunfzn9vgHxaDsKoRO8uKBVsiOF6cA59l5X4Ut1oSOs3856P/5glDLPYF2Kv2I5Nkwm07YgqY+3gzC5YcYXApbE13sjo0jnb5LWTmwY/dnJnFAOO2RFfou8birEkWO8NYzcqWXWe5dZWXlp9E0yzwAAGnvkWr7ym4EAOHBI4E2C2okAiBMc9SZCmNmwysoTz17ITFZkQp5g+9upFwhA/UtF0f33xGK0I9KLHc9LCtsDV068LZNWicdgb2uxRHz+QIhMj4VcDJtNZ8KiUjwTi4OxC8t1bsqF+LcSVpZkuQXeLJxZGL2CKox56vTMxHVr/8s4nYog1My+fJ+BqAUBop7ESxyIAA3D7y7CMhwBfG8s92buPJmReEZq2PRf8icveBknvSWAVBgTac2WAJJ0rhZXOfjMd29BjvVhpOtyH87Ca4Jnhh0QUMudk0ctRJwVB0rD+gN7j1DIikhuD2lYeGr3nB/jxBIAnL0y+zgQ7lPWUhrmCh5uKb+L1kdYgpxRrTjEiyXIQEUqFLk7rVCiDEzcjx4OEKe0h7Cms6ri+ljzYyR2oGDv6R4/8tfZbGcmikYMmJTTWbmvf8KZN4JIa0gtEPuRZh05I7VNWL6fCc3ZYJL5tFYoSzmXL8wgO8aZ//8MLvnrJZv+n09wrhBMkIaNh3S4Bjp8lIW7e6BXOl2kqyPiHKOHsOaXivuCzjGsVXEromR3DNbsOZKv1WrVFIK3CXgpbGwwBwRY3GYFMsoopU0PQUJUct+m9QcSmiPNV4bncfYdKCCGvYxSGxBTL6hQzMZJbAlTZCkVimWjI8/cETOFa+PlQWbX1DYzgXdGar44qTOx5Eot4b1eZhL+jFqSthL5qIg0UkDgi6CbEIoZJeDacZa3IkAaForTXFTKvMQfSRMOxbMVqHvyHfeoVx7u14936/Xd+tPX9a/p/ef00/0/GFNX+eyYqnbFBLO9u39oMQ/pZpuut4TBIdu5N57Q/Ph202EoZqidgZnOFePMP8Z56bcaNN28TMFPL0LqB1Y9Xd5/V8yF2sKUokJSkqQawUP15iue0QKa5BaZqTUsfr9MnrlHMowbfHzV5yM9oOBuF2J7qE/xZjw8+qIVL5/lk5wOIh1uKCtDYTguVEprTdeTClpNJXS3Vi/oIdSmoEDt5PMkxSe9+vbDXBx4rfwuZOTwp5I7jy4ZymthS3wDaoFQz6wrvkOtTZ7TS6bTJjyjJlcyE9oNZpz2PT4abxNXpLrqfT/go/H20Xh71yT6/zXetPDPaDZNTr9pVdMdVZu3/wAZB5Q1uBcAAA==", "encoding": "utf-8"}, "status": {"code": 200, "message": "OK"}}}, {"recorded_at": "2017-02-21T16:49:06", "request": {"uri": "https://api.github.com/projects/400903", "headers": {"User-Agent": "github3.py/1.0.0a4", "Authorization": "token <AUTH_TOKEN>", "Accept": "application/vnd.github.inertia-preview+json", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/json", "Accept-Charset": "utf-8"}, "body": {"string": "", "encoding": "utf-8"}, "method": "GET"}, "response": {"url": "https://api.github.com/projects/400903", "headers": {"X-OAuth-Scopes": "repo", "Transfer-Encoding": "chunked", "X-RateLimit-Remaining": "4875", "Cache-Control": "private, max-age=60, s-maxage=60", "X-GitHub-Media-Type": "github.inertia-preview; format=json", "X-Served-By": "ef96c2e493b28ffea49b891b085ed2dd", "X-Content-Type-Options": "nosniff", "X-Accepted-OAuth-Scopes": "repo", "Access-Control-Expose-Headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "Date": "Tue, 21 Feb 2017 16:48:55 GMT", "Access-Control-Allow-Origin": "*", "ETag": "W/\"fd9a8d41859b997b0f7927298c91141a\"", "X-RateLimit-Reset": "1487698380", "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", "X-Frame-Options": "deny", "Content-Security-Policy": "default-src 'none'", "Content-Type": "application/json; charset=utf-8", "Server": "GitHub.com", "X-RateLimit-Limit": "5000", "X-XSS-Protection": "1; mode=block", "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "Status": "200 OK", "X-GitHub-Request-Id": "C611:7030:7B43D83:99D698D:58AC6F77", "Content-Encoding": "gzip"}, "body": {"string": "", "base64_string": "H4sIAAAAAAAAA52T0Y6bMBBFf6Xyc7KGkDRdpKqq1E/YvuxLZGCWuDIeyx5YpSj/3hlCqyapUiVPIDzn+s5lZlT47iHu+uhUqfZEIZVam2CfWkv7vnqqsdMRAib9tXJA6L/B8ILokiZIJCdqoW7SIeIPqCnpdZY9ZwWX1+j6zqfbl15geoYYt40qT1oL5U0HbFy8fJgJrqiwOfBXfvN9V0FU5WahEhmSWgzgxUQEQ8hHo3LYWs8nscalOXU5X5Pnq22RP28XygyGzFVO08dUzGH1CVjCE3iacuv1b/7L8Fkab+MsIy2IvZvBiVzS56b21LmL3P7+UWcNvKFz+M4at4O+ukb/Adnh6d369jERBkeNtJcR43aOEoJNdLelCRq1PHa2ERn+nTFCc6+tGWNTMvfHcRruSa+vUh1tIIv/G83rxM5gFsPYGm9/mofEGE6sMW3dve1NEMMw8BDeTZ+oUYdoB1MfJJYINdiBc35M8QJnQToE2cLvPA2SuiXYmaaT/XszLsFx3ky+0RDXrbJ8u8xWy1X+km/KbFOuN6/M9aHhbf5Hzcdy/aksild1/AXc5rbU2wQAAA==", "encoding": "utf-8"}, "status": {"code": 200, "message": "OK"}}}, {"recorded_at": "2017-02-21T16:49:06", "request": {"uri": "https://api.github.com/projects/columns/698994", "headers": {"User-Agent": "github3.py/1.0.0a4", "Authorization": "token <AUTH_TOKEN>", "Accept": "application/vnd.github.inertia-preview+json", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/json", "Accept-Charset": "utf-8"}, "body": {"string": "", "encoding": "utf-8"}, "method": "GET"}, "response": {"url": "https://api.github.com/projects/columns/698994", "headers": {"X-OAuth-Scopes": "repo", "Transfer-Encoding": "chunked", "X-RateLimit-Remaining": "4874", "Cache-Control": "private, max-age=60, s-maxage=60", "X-GitHub-Media-Type": "github.inertia-preview; format=json", "X-Served-By": "49aa99f015c25437a7443c4d3a58cd17", "X-Content-Type-Options": "nosniff", "X-Accepted-OAuth-Scopes": "repo", "Access-Control-Expose-Headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "Date": "Tue, 21 Feb 2017 16:48:56 GMT", "Access-Control-Allow-Origin": "*", "ETag": "W/\"d120abf3e73fb3d0e826b2e11e683327\"", "X-RateLimit-Reset": "1487698380", "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", "X-Frame-Options": "deny", "Content-Security-Policy": "default-src 'none'", "Content-Type": "application/json; charset=utf-8", "Server": "GitHub.com", "X-RateLimit-Limit": "5000", "X-XSS-Protection": "1; mode=block", "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "Status": "200 OK", "X-GitHub-Request-Id": "C611:7030:7B43D9C:99D69B4:58AC6F77", "Content-Encoding": "gzip"}, "body": {"string": "", "base64_string": "H4sIAAAAAAAAA42OOQ7CMBBFr4KmTuJxNuI5B1WayNgWCcpieakQd8cQGiSKtDPv/f8fEN0MBGMI1hNj0k7FbQpjvBZqW5h1292o4Jna5risnrWiE6KGDL6f4ZheIwqskqak0/6g9NvJPmqKmDTQPiODVS4mrd/JE38XOCOD0YMM6V4iP+dY5iW/8IawoQb7xESr/zMt1R1VVQ/PFxezhN4YAQAA", "encoding": "utf-8"}, "status": {"code": 200, "message": "OK"}}}, {"recorded_at": "2017-02-21T16:49:06", "request": {"uri": "https://api.github.com/projects/columns/cards/1809795", "headers": {"User-Agent": "github3.py/1.0.0a4", "Authorization": "token <AUTH_TOKEN>", "Accept": "application/vnd.github.inertia-preview+json", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/json", "Accept-Charset": "utf-8"}, "body": {"string": "", "encoding": "utf-8"}, "method": "GET"}, "response": {"url": "https://api.github.com/projects/columns/cards/1809795", "headers": {"X-OAuth-Scopes": "repo", "Transfer-Encoding": "chunked", "X-RateLimit-Remaining": "4873", "Cache-Control": "private, max-age=60, s-maxage=60", "X-GitHub-Media-Type": "github.inertia-preview; format=json", "X-Served-By": "139317cebd6caf9cd03889139437f00b", "X-Content-Type-Options": "nosniff", "X-Accepted-OAuth-Scopes": "repo", "Access-Control-Expose-Headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "Date": "Tue, 21 Feb 2017 16:48:56 GMT", "Access-Control-Allow-Origin": "*", "ETag": "W/\"a3bbdfdd49703ef72609c4fde6472937\"", "X-RateLimit-Reset": "1487698380", "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", "X-Frame-Options": "deny", "Content-Security-Policy": "default-src 'none'", "Content-Type": "application/json; charset=utf-8", "Server": "GitHub.com", "X-RateLimit-Limit": "5000", "X-XSS-Protection": "1; mode=block", "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP", "Status": "200 OK", "X-GitHub-Request-Id": "C611:7030:7B43DB8:99D69C1:58AC6F78", "Content-Encoding": "gzip"}, "body": {"string": "", "base64_string": "H4sIAAAAAAAAA52TQW6DMBBFr1J5HeIAaQhIVS/RbrqJHJiAK2MjeyBKUe7eMaFVoVIksrJl5j//+Xh61lrFMlYhNi7jXDRyXUqs2uM6NzVvrPmEHB3PjWprTauwhePhfpMm6TNbsdv5YRlkl+7TdEtqWbBsZK2YNgjkBMHh07AnugWBxrKsZ8qUUtNnm5tAHBWg0T+AMEriME1WTHQChZ2bGQ5dPLbVOiCERtA4dNjycNS/di8xIUs7Yrw5Rgd3e/M4x6emKqzVzMSfSKe1J6OUORNj7nr6H/5dw3+F5PC2l7p8DELCnhusgKKjdq4+BOlwsaVB1HO/HGThMY6St1AstTXKyNRZk5+eW2jMwGuPLreyQWn0YnsTMcGMLYWWX+IhGIkdMbyxxUYGEYmho0e4WH1T9TSashP5xcdiIQfZUc6PEWdyAuKl8aP4Tq/Bpy4RDqKo/fydhHJwHSeTbhRIddEmTIJNFEThW7jLtnEWpR+ka5tC4N2a6zey8nnZfwQAAA==", "encoding": "utf-8"}, "status": {"code": 200, "message": "OK"}}}, {"recorded_at": "2017-02-21T16:49:07", "request": {"uri": "https://api.github.com/projects/columns/cards/1809795", "headers": {"User-Agent": "github3.py/1.0.0a4", "Authorization": "token <AUTH_TOKEN>", "Accept": "application/vnd.github.inertia-preview+json", "Connection": "keep-alive", "Content-Length": "0", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/json", "Accept-Charset": "utf-8"}, "body": {"string": "", "encoding": "utf-8"}, "method": "DELETE"}, "response": {"url": "https://api.github.com/projects/columns/cards/1809795", "headers": {"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", "X-OAuth-Scopes": "repo", "X-Frame-Options": "deny", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "X-GitHub-Media-Type": "github.inertia-preview; format=json", "X-GitHub-Request-Id": "C611:7030:7B43DCE:99D69ED:58AC6F78", "Server": "GitHub.com", "X-RateLimit-Limit": "5000", "Content-Security-Policy": "default-src 'none'", "X-Served-By": "2c18a09f3ac5e4dd1e004af7c5a94769", "X-Content-Type-Options": "nosniff", "Vary": "Accept-Encoding", "X-Accepted-OAuth-Scopes": "repo", "X-RateLimit-Remaining": "4872", "Date": "Tue, 21 Feb 2017 16:48:56 GMT", "Status": "204 No Content", "X-XSS-Protection": "1; mode=block", "X-RateLimit-Reset": "1487698380"}, "body": {"string": "", "encoding": null}, "status": {"code": 204, "message": "No Content"}}}]}

0 commit comments

Comments
 (0)
0