comparison venv/lib/python2.7/site-packages/github/MainClass.py @ 0:d67268158946 draft

planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author bcclaywell
date Mon, 12 Oct 2015 17:43:33 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d67268158946
1 # -*- coding: utf-8 -*-
2
3 # ########################## Copyrights and license ############################
4 # #
5 # Copyright 2013 AKFish <akfish@gmail.com> #
6 # Copyright 2013 Ed Jackson <ed.jackson@gmail.com> #
7 # Copyright 2013 Jonathan J Hunt <hunt@braincorporation.com> #
8 # Copyright 2013 Peter Golm <golm.peter@gmail.com> #
9 # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
10 # #
11 # This file is part of PyGithub. http://jacquev6.github.com/PyGithub/ #
12 # #
13 # PyGithub is free software: you can redistribute it and/or modify it under #
14 # the terms of the GNU Lesser General Public License as published by the Free #
15 # Software Foundation, either version 3 of the License, or (at your option) #
16 # any later version. #
17 # #
18 # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
19 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
20 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
21 # details. #
22 # #
23 # You should have received a copy of the GNU Lesser General Public License #
24 # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
25 # #
26 # ##############################################################################
27
28 import urllib
29 import pickle
30
31 from Requester import Requester
32 import AuthenticatedUser
33 import NamedUser
34 import Organization
35 import Gist
36 import github.PaginatedList
37 import Repository
38 import Legacy
39 import github.GithubObject
40 import HookDescription
41 import GitignoreTemplate
42 import Status
43 import StatusMessage
44 import RateLimit
45
46
47 DEFAULT_BASE_URL = "https://api.github.com"
48 DEFAULT_TIMEOUT = 10
49 DEFAULT_PER_PAGE = 30
50
51
52 class Github(object):
53 """
54 This is the main class you instanciate to access the Github API v3. Optional parameters allow different authentication methods.
55 """
56
57 def __init__(self, login_or_token=None, password=None, base_url=DEFAULT_BASE_URL, timeout=DEFAULT_TIMEOUT, client_id=None, client_secret=None, user_agent='PyGithub/Python', per_page=DEFAULT_PER_PAGE):
58 """
59 :param login_or_token: string
60 :param password: string
61 :param base_url: string
62 :param timeout: integer
63 :param client_id: string
64 :param client_secret: string
65 :param user_agent: string
66 :param per_page: int
67 """
68
69 assert login_or_token is None or isinstance(login_or_token, (str, unicode)), login_or_token
70 assert password is None or isinstance(password, (str, unicode)), password
71 assert isinstance(base_url, (str, unicode)), base_url
72 assert isinstance(timeout, (int, long)), timeout
73 assert client_id is None or isinstance(client_id, (str, unicode)), client_id
74 assert client_secret is None or isinstance(client_secret, (str, unicode)), client_secret
75 assert user_agent is None or isinstance(user_agent, (str, unicode)), user_agent
76 self.__requester = Requester(login_or_token, password, base_url, timeout, client_id, client_secret, user_agent, per_page)
77
78 def __get_FIX_REPO_GET_GIT_REF(self):
79 """
80 :type: bool
81 """
82 return self.__requester.FIX_REPO_GET_GIT_REF
83
84 def __set_FIX_REPO_GET_GIT_REF(self, value):
85 self.__requester.FIX_REPO_GET_GIT_REF = value
86
87 FIX_REPO_GET_GIT_REF = property(__get_FIX_REPO_GET_GIT_REF, __set_FIX_REPO_GET_GIT_REF)
88
89 def __get_per_page(self):
90 """
91 :type: int
92 """
93 return self.__requester.per_page
94
95 def __set_per_page(self, value):
96 self.__requester.per_page = value
97
98 # v2: Remove this property? Why should it be necessary to read/modify it after construction
99 per_page = property(__get_per_page, __set_per_page)
100
101 # v2: Provide a unified way to access values of headers of last response
102 # v2: (and add/keep ad hoc properties for specific useful headers like rate limiting, oauth scopes, etc.)
103 # v2: Return an instance of a class: using a tuple did not allow to add a field "resettime"
104 @property
105 def rate_limiting(self):
106 """
107 First value is requests remaining, second value is request limit.
108 :type: (int, int)
109 """
110 remaining, limit = self.__requester.rate_limiting
111 if limit < 0:
112 self.get_rate_limit()
113 return self.__requester.rate_limiting
114
115 @property
116 def rate_limiting_resettime(self):
117 """
118 Unix timestamp indicating when rate limiting will reset.
119 :type: int
120 """
121 if self.__requester.rate_limiting_resettime == 0:
122 self.get_rate_limit()
123 return self.__requester.rate_limiting_resettime
124
125 def get_rate_limit(self):
126 """
127 Don't forget you can access the rate limit returned in headers of last Github API v3 response, by :attr:`github.MainClass.Github.rate_limiting` and :attr:`github.MainClass.Github.rate_limiting_resettime`.
128
129 :calls: `GET /rate_limit <http://developer.github.com/v3/rate_limit>`_
130 :rtype: :class:`github.RateLimit.RateLimit`
131 """
132 headers, attributes = self.__requester.requestJsonAndCheck(
133 'GET',
134 '/rate_limit'
135 )
136 return RateLimit.RateLimit(self.__requester, headers, attributes, True)
137
138 @property
139 def oauth_scopes(self):
140 """
141 :type: list of string
142 """
143 return self.__requester.oauth_scopes
144
145 def get_user(self, login=github.GithubObject.NotSet):
146 """
147 :calls: `GET /users/:user <http://developer.github.com/v3/users>`_ or `GET /user <http://developer.github.com/v3/users>`_
148 :param login: string
149 :rtype: :class:`github.NamedUser.NamedUser`
150 """
151 assert login is github.GithubObject.NotSet or isinstance(login, (str, unicode)), login
152 if login is github.GithubObject.NotSet:
153 return AuthenticatedUser.AuthenticatedUser(self.__requester, {}, {"url": "/user"}, completed=False)
154 else:
155 headers, data = self.__requester.requestJsonAndCheck(
156 "GET",
157 "/users/" + login
158 )
159 return github.NamedUser.NamedUser(self.__requester, headers, data, completed=True)
160
161 def get_users(self, since=github.GithubObject.NotSet):
162 """
163 :calls: `GET /users <http://developer.github.com/v3/users>`_
164 :param since: integer
165 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.NamedUser.NamedUser`
166 """
167 assert since is github.GithubObject.NotSet or isinstance(since, (int, long)), since
168 url_parameters = dict()
169 if since is not github.GithubObject.NotSet:
170 url_parameters["since"] = since
171 return github.PaginatedList.PaginatedList(
172 github.NamedUser.NamedUser,
173 self.__requester,
174 "/users",
175 url_parameters
176 )
177
178 def get_organization(self, login):
179 """
180 :calls: `GET /orgs/:org <http://developer.github.com/v3/orgs>`_
181 :param login: string
182 :rtype: :class:`github.Organization.Organization`
183 """
184 assert isinstance(login, (str, unicode)), login
185 headers, data = self.__requester.requestJsonAndCheck(
186 "GET",
187 "/orgs/" + login
188 )
189 return github.Organization.Organization(self.__requester, headers, data, completed=True)
190
191 def get_repo(self, full_name_or_id):
192 """
193 :calls: `GET /repos/:owner/:repo <http://developer.github.com/v3/repos>`_ or `GET /repositories/:id <http://developer.github.com/v3/repos>`_
194 :rtype: :class:`github.Repository.Repository`
195 """
196 assert isinstance(full_name_or_id, (str, unicode, int)), full_name_or_id
197 url_base = "/repositories/" if isinstance(full_name_or_id, int) else "/repos/"
198 headers, data = self.__requester.requestJsonAndCheck(
199 "GET",
200 "%s%s" % (url_base, full_name_or_id)
201 )
202 return Repository.Repository(self.__requester, headers, data, completed=True)
203
204 def get_repos(self, since=github.GithubObject.NotSet):
205 """
206 :calls: `GET /repositories <http://developer.github.com/v3/repos/#list-all-public-repositories>`_
207 :param since: integer
208 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Repository.Repository`
209 """
210 assert since is github.GithubObject.NotSet or isinstance(since, (int, long)), since
211 url_parameters = dict()
212 if since is not github.GithubObject.NotSet:
213 url_parameters["since"] = since
214 return github.PaginatedList.PaginatedList(
215 github.Repository.Repository,
216 self.__requester,
217 "/repositories",
218 url_parameters
219 )
220
221 def get_gist(self, id):
222 """
223 :calls: `GET /gists/:id <http://developer.github.com/v3/gists>`_
224 :param id: string
225 :rtype: :class:`github.Gist.Gist`
226 """
227 assert isinstance(id, (str, unicode)), id
228 headers, data = self.__requester.requestJsonAndCheck(
229 "GET",
230 "/gists/" + id
231 )
232 return github.Gist.Gist(self.__requester, headers, data, completed=True)
233
234 def get_gists(self):
235 """
236 :calls: `GET /gists/public <http://developer.github.com/v3/gists>`_
237 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Gist.Gist`
238 """
239 return github.PaginatedList.PaginatedList(
240 github.Gist.Gist,
241 self.__requester,
242 "/gists/public",
243 None
244 )
245
246 def legacy_search_repos(self, keyword, language=github.GithubObject.NotSet):
247 """
248 :calls: `GET /legacy/repos/search/:keyword <http://developer.github.com/v3/search/legacy>`_
249 :param keyword: string
250 :param language: string
251 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Repository.Repository`
252 """
253 assert isinstance(keyword, (str, unicode)), keyword
254 assert language is github.GithubObject.NotSet or isinstance(language, (str, unicode)), language
255 args = {} if language is github.GithubObject.NotSet else {"language": language}
256 return Legacy.PaginatedList(
257 "/legacy/repos/search/" + urllib.quote_plus(keyword, safe='/%:><'),
258 args,
259 self.__requester,
260 "repositories",
261 Legacy.convertRepo,
262 github.Repository.Repository,
263 )
264
265 def legacy_search_users(self, keyword):
266 """
267 :calls: `GET /legacy/user/search/:keyword <http://developer.github.com/v3/search/legacy>`_
268 :param keyword: string
269 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.NamedUser.NamedUser`
270 """
271 assert isinstance(keyword, (str, unicode)), keyword
272 return Legacy.PaginatedList(
273 "/legacy/user/search/" + urllib.quote_plus(keyword, safe='/%:><'),
274 {},
275 self.__requester,
276 "users",
277 Legacy.convertUser,
278 github.NamedUser.NamedUser,
279 )
280
281 def legacy_search_user_by_email(self, email):
282 """
283 :calls: `GET /legacy/user/email/:email <http://developer.github.com/v3/search/legacy>`_
284 :param email: string
285 :rtype: :class:`github.NamedUser.NamedUser`
286 """
287 assert isinstance(email, (str, unicode)), email
288 headers, data = self.__requester.requestJsonAndCheck(
289 "GET",
290 "/legacy/user/email/" + email
291 )
292 return github.NamedUser.NamedUser(self.__requester, headers, Legacy.convertUser(data["user"]), completed=False)
293
294 def search_repositories(self, query, sort=github.GithubObject.NotSet, order=github.GithubObject.NotSet, **qualifiers):
295 """
296 :calls: `GET /search/repositories <http://developer.github.com/v3/search>`_
297 :param query: string
298 :param sort: string ('stars', 'forks', 'updated')
299 :param order: string ('asc', 'desc')
300 :param qualifiers: keyword dict query qualifiers
301 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Repository.Repository`
302 """
303 assert isinstance(query, (str, unicode)), query
304 url_parameters = dict()
305 if sort is not github.GithubObject.NotSet: # pragma no branch (Should be covered)
306 assert sort in ('stars', 'forks', 'updated'), sort
307 url_parameters["sort"] = sort
308 if order is not github.GithubObject.NotSet: # pragma no branch (Should be covered)
309 assert order in ('asc', 'desc'), order
310 url_parameters["order"] = order
311
312 query_chunks = []
313 if query: # pragma no branch (Should be covered)
314 query_chunks.append(query)
315
316 for qualifier, value in qualifiers.items():
317 query_chunks.append("%s:%s" % (qualifier, value))
318
319 url_parameters["q"] = ' '.join(query_chunks)
320 assert url_parameters["q"], "need at least one qualifier"
321
322 return github.PaginatedList.PaginatedList(
323 github.Repository.Repository,
324 self.__requester,
325 "/search/repositories",
326 url_parameters
327 )
328
329 def search_users(self, query, sort=github.GithubObject.NotSet, order=github.GithubObject.NotSet, **qualifiers):
330 """
331 :calls: `GET /search/users <http://developer.github.com/v3/search>`_
332 :param query: string
333 :param sort: string ('followers', 'repositories', 'joined')
334 :param order: string ('asc', 'desc')
335 :param qualifiers: keyword dict query qualifiers
336 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.NamedUser.NamedUser`
337 """
338 assert isinstance(query, (str, unicode)), query
339 url_parameters = dict()
340 if sort is not github.GithubObject.NotSet:
341 assert sort in ('followers', 'repositories', 'joined'), sort
342 url_parameters["sort"] = sort
343 if order is not github.GithubObject.NotSet:
344 assert order in ('asc', 'desc'), order
345 url_parameters["order"] = order
346
347 query_chunks = []
348 if query:
349 query_chunks.append(query)
350
351 for qualifier, value in qualifiers.items():
352 query_chunks.append("%s:%s" % (qualifier, value))
353
354 url_parameters["q"] = ' '.join(query_chunks)
355 assert url_parameters["q"], "need at least one qualifier"
356
357 return github.PaginatedList.PaginatedList(
358 github.NamedUser.NamedUser,
359 self.__requester,
360 "/search/users",
361 url_parameters
362 )
363
364 def search_issues(self, query, sort=github.GithubObject.NotSet, order=github.GithubObject.NotSet, **qualifiers):
365 """
366 :calls: `GET /search/issues <http://developer.github.com/v3/search>`_
367 :param query: string
368 :param sort: string ('comments', 'created', 'updated')
369 :param order: string ('asc', 'desc')
370 :param qualifiers: keyword dict query qualifiers
371 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Issue.Issue`
372 """
373 assert isinstance(query, (str, unicode)), query
374 url_parameters = dict()
375 if sort is not github.GithubObject.NotSet:
376 assert sort in ('comments', 'created', 'updated'), sort
377 url_parameters["sort"] = sort
378 if order is not github.GithubObject.NotSet:
379 assert order in ('asc', 'desc'), order
380 url_parameters["order"] = order
381
382 query_chunks = []
383 if query: # pragma no branch (Should be covered)
384 query_chunks.append(query)
385
386 for qualifier, value in qualifiers.items():
387 query_chunks.append("%s:%s" % (qualifier, value))
388
389 url_parameters["q"] = ' '.join(query_chunks)
390 assert url_parameters["q"], "need at least one qualifier"
391
392 return github.PaginatedList.PaginatedList(
393 github.Issue.Issue,
394 self.__requester,
395 "/search/issues",
396 url_parameters
397 )
398
399 def search_code(self, query, sort=github.GithubObject.NotSet, order=github.GithubObject.NotSet, **qualifiers):
400 """
401 :calls: `GET /search/code <http://developer.github.com/v3/search>`_
402 :param query: string
403 :param sort: string ('indexed')
404 :param order: string ('asc', 'desc')
405 :param qualifiers: keyword dict query qualifiers
406 :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.ContentFile.ContentFile`
407 """
408 assert isinstance(query, (str, unicode)), query
409 url_parameters = dict()
410 if sort is not github.GithubObject.NotSet: # pragma no branch (Should be covered)
411 assert sort in ('indexed',), sort
412 url_parameters["sort"] = sort
413 if order is not github.GithubObject.NotSet: # pragma no branch (Should be covered)
414 assert order in ('asc', 'desc'), order
415 url_parameters["order"] = order
416
417 query_chunks = []
418 if query: # pragma no branch (Should be covered)
419 query_chunks.append(query)
420
421 for qualifier, value in qualifiers.items():
422 query_chunks.append("%s:%s" % (qualifier, value))
423
424 url_parameters["q"] = ' '.join(query_chunks)
425 assert url_parameters["q"], "need at least one qualifier"
426
427 return github.PaginatedList.PaginatedList(
428 github.ContentFile.ContentFile,
429 self.__requester,
430 "/search/code",
431 url_parameters
432 )
433
434 def render_markdown(self, text, context=github.GithubObject.NotSet):
435 """
436 :calls: `POST /markdown <http://developer.github.com/v3/markdown>`_
437 :param text: string
438 :param context: :class:`github.Repository.Repository`
439 :rtype: string
440 """
441 assert isinstance(text, (str, unicode)), text
442 assert context is github.GithubObject.NotSet or isinstance(context, github.Repository.Repository), context
443 post_parameters = {
444 "text": text
445 }
446 if context is not github.GithubObject.NotSet:
447 post_parameters["mode"] = "gfm"
448 post_parameters["context"] = context._identity
449 status, headers, data = self.__requester.requestJson(
450 "POST",
451 "/markdown",
452 input=post_parameters
453 )
454 return data
455
456 def get_hook(self, name):
457 """
458 :calls: `GET /hooks/:name <http://developer.github.com/v3/repos/hooks/>`_
459 :param name: string
460 :rtype: :class:`github.HookDescription.HookDescription`
461 """
462 assert isinstance(name, (str, unicode)), name
463 headers, attributes = self.__requester.requestJsonAndCheck(
464 "GET",
465 "/hooks/" + name
466 )
467 return HookDescription.HookDescription(self.__requester, headers, attributes, completed=True)
468
469 def get_hooks(self):
470 """
471 :calls: `GET /hooks <http://developer.github.com/v3/repos/hooks/>`_
472 :rtype: list of :class:`github.HookDescription.HookDescription`
473 """
474 headers, data = self.__requester.requestJsonAndCheck(
475 "GET",
476 "/hooks"
477 )
478 return [HookDescription.HookDescription(self.__requester, headers, attributes, completed=True) for attributes in data]
479
480 def get_gitignore_templates(self):
481 """
482 :calls: `GET /gitignore/templates <http://developer.github.com/v3/gitignore>`_
483 :rtype: list of string
484 """
485 headers, data = self.__requester.requestJsonAndCheck(
486 "GET",
487 "/gitignore/templates"
488 )
489 return data
490
491 def get_gitignore_template(self, name):
492 """
493 :calls: `GET /gitignore/templates/:name <http://developer.github.com/v3/gitignore>`_
494 :rtype: :class:`github.GitignoreTemplate.GitignoreTemplate`
495 """
496 assert isinstance(name, (str, unicode)), name
497 headers, attributes = self.__requester.requestJsonAndCheck(
498 "GET",
499 "/gitignore/templates/" + name
500 )
501 return GitignoreTemplate.GitignoreTemplate(self.__requester, headers, attributes, completed=True)
502
503 def get_emojis(self):
504 """
505 :calls: `GET /emojis <http://developer.github.com/v3/emojis/>`_
506 :rtype: dictionary of type => url for emoji`
507 """
508 headers, attributes = self.__requester.requestJsonAndCheck(
509 "GET",
510 "/emojis"
511 )
512 return attributes
513
514 def create_from_raw_data(self, klass, raw_data, headers={}):
515 """
516 Creates an object from raw_data previously obtained by :attr:`github.GithubObject.GithubObject.raw_data`,
517 and optionaly headers previously obtained by :attr:`github.GithubObject.GithubObject.raw_headers`.
518
519 :param klass: the class of the object to create
520 :param raw_data: dict
521 :param headers: dict
522 :rtype: instance of class ``klass``
523 """
524 return klass(self.__requester, headers, raw_data, completed=True)
525
526 def dump(self, obj, file, protocol=0):
527 """
528 Dumps (pickles) a PyGithub object to a file-like object.
529 Some effort is made to not pickle sensitive informations like the Github credentials used in the :class:`Github` instance.
530 But NO EFFORT is made to remove sensitive information from the object's attributes.
531
532 :param obj: the object to pickle
533 :param file: the file-like object to pickle to
534 :param protocol: the `pickling protocol <http://docs.python.org/2.7/library/pickle.html#data-stream-format>`_
535 """
536 pickle.dump((obj.__class__, obj.raw_data, obj.raw_headers), file, protocol)
537
538 def load(self, f):
539 """
540 Loads (unpickles) a PyGithub object from a file-like object.
541
542 :param f: the file-like object to unpickle from
543 :return: the unpickled object
544 """
545 return self.create_from_raw_data(*pickle.load(f))
546
547 def get_api_status(self):
548 """
549 This doesn't work with a Github Enterprise installation, because it always targets https://status.github.com.
550
551 :calls: `GET /api/status.json <https://status.github.com/api>`_
552 :rtype: :class:`github.Status.Status`
553 """
554 headers, attributes = self.__requester.requestJsonAndCheck(
555 "GET",
556 "/api/status.json",
557 cnx="status"
558 )
559 return Status.Status(self.__requester, headers, attributes, completed=True)
560
561 def get_last_api_status_message(self):
562 """
563 This doesn't work with a Github Enterprise installation, because it always targets https://status.github.com.
564
565 :calls: `GET /api/last-message.json <https://status.github.com/api>`_
566 :rtype: :class:`github.StatusMessage.StatusMessage`
567 """
568 headers, attributes = self.__requester.requestJsonAndCheck(
569 "GET",
570 "/api/last-message.json",
571 cnx="status"
572 )
573 return StatusMessage.StatusMessage(self.__requester, headers, attributes, completed=True)
574
575 def get_api_status_messages(self):
576 """
577 This doesn't work with a Github Enterprise installation, because it always targets https://status.github.com.
578
579 :calls: `GET /api/messages.json <https://status.github.com/api>`_
580 :rtype: list of :class:`github.StatusMessage.StatusMessage`
581 """
582 headers, data = self.__requester.requestJsonAndCheck(
583 "GET",
584 "/api/messages.json",
585 cnx="status"
586 )
587 return [StatusMessage.StatusMessage(self.__requester, headers, attributes, completed=True) for attributes in data]