Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

165 lines
5.6KB

  1. # Copyright (C) 2016-Today: Odoo Community Association (OCA)
  2. # @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
  3. # @author: Sébastien BEAU <sebastien.beau@akretion.com>
  4. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  5. import json
  6. import logging
  7. import requests
  8. from requests.auth import AuthBase, HTTPBasicAuth
  9. from odoo import _, exceptions
  10. _logger = logging.getLogger(__name__)
  11. _MAX_NUMBER_REQUEST = 30
  12. _BASE_URL = "https://api.github.com/"
  13. _GITHUB_URL = "https://github.com/"
  14. _GITHUB_TYPE = [
  15. ("organization", "Organization"),
  16. ("repository", "Repository"),
  17. ("user", "User"),
  18. ]
  19. _GITHUB_TYPE_URL = {
  20. "organization": {"url_get_by_name": "orgs/%s"},
  21. "user": {"url_get_by_id": "user/%s", "url_get_by_name": "users/%s"},
  22. "repository": {
  23. "url_get_by_id": "repositories/%s",
  24. "url_get_by_name": "repos/%s",
  25. "url_create": "orgs/%s/repos",
  26. },
  27. "team": {"url_get_by_id": "teams/%s", "url_create": "orgs/%s/teams"},
  28. "organization_members": {"url_get_by_name": "orgs/%s/members"},
  29. "organization_repositories": {"url_get_by_name": "orgs/%s/repos"},
  30. "organization_teams": {"url_get_by_name": "orgs/%s/teams"},
  31. "team_members_member": {"url_get_by_name": "teams/%s/members?role=member"},
  32. "team_members_maintainer": {"url_get_by_name": "teams/%s/members?role=maintainer"},
  33. "team_repositories": {"url_get_by_name": "teams/%s/repos"},
  34. "repository_branches": {"url_get_by_name": "repos/%s/branches"},
  35. }
  36. _CODE_401 = 401
  37. _CODE_403 = 403
  38. _CODE_422 = 422
  39. _CODE_200 = 200
  40. _CODE_201 = 201
  41. class Github(object):
  42. def __init__(self, github_type, login, password, max_try, token=None):
  43. super().__init__()
  44. self.github_type = github_type
  45. self.max_try = max_try
  46. if token:
  47. self.auth = HTTPTokenAuth(token)
  48. else:
  49. self.auth = HTTPBasicAuth(login, password)
  50. def _build_url(self, arguments, url_type, page):
  51. arguments = arguments and arguments or {}
  52. url = _GITHUB_TYPE_URL[self.github_type][url_type]
  53. if self.github_type not in _GITHUB_TYPE_URL.keys():
  54. raise exceptions.Warning(_("'%s' is not implemented.") % self.github_type)
  55. complete_url = _BASE_URL + url % tuple(arguments)
  56. if page:
  57. complete_url += (
  58. "?" in complete_url and "&" or "?"
  59. ) + "per_page=%d&page=%d" % (_MAX_NUMBER_REQUEST, page)
  60. return complete_url
  61. def list(self, arguments):
  62. page = 1
  63. datas = []
  64. while True:
  65. pending_datas = self.get(arguments, False, page)
  66. datas += pending_datas
  67. if pending_datas == [] or len(pending_datas) < _MAX_NUMBER_REQUEST:
  68. break
  69. page += 1
  70. return datas
  71. def get_by_url(self, url, call_type, data=False):
  72. _logger.info("Calling %s" % url)
  73. for i in range(self.max_try):
  74. try:
  75. if call_type == "get":
  76. response = requests.get(url, auth=self.auth)
  77. break
  78. elif call_type == "post":
  79. json_data = json.dumps(data)
  80. response = requests.post(url, auth=self.auth, data=json_data)
  81. break
  82. except Exception as err:
  83. _logger.warning(
  84. "URL Call Error. %d/%d. URL: %s", i, self.max_try, err.__str__(),
  85. )
  86. else:
  87. raise exceptions.Warning(_("Maximum attempts reached."))
  88. if isinstance(self.auth, HTTPBasicAuth):
  89. auth_err_msg = _("login '%s'") % self.auth.login
  90. elif isinstance(self.auth, HTTPTokenAuth):
  91. auth_err_msg = _("provided token")
  92. if response.status_code == _CODE_401:
  93. raise exceptions.Warning(
  94. _(
  95. "401 - Unable to authenticate to Github with the %s.\n"
  96. "You should check your credentials in the Odoo"
  97. " configuration file."
  98. )
  99. % auth_err_msg
  100. )
  101. elif response.status_code == _CODE_403:
  102. raise exceptions.Warning(
  103. _(
  104. "Unable to realize the current operation. The %s"
  105. " does not have the correct access rights."
  106. )
  107. % auth_err_msg
  108. )
  109. elif response.status_code == _CODE_422:
  110. raise exceptions.Warning(
  111. _(
  112. "Unable to realize the current operation. Possible reasons:\n"
  113. " * You try to create a duplicated item\n"
  114. " * Some of the arguments are incorrect"
  115. )
  116. )
  117. elif response.status_code not in [_CODE_200, _CODE_201]:
  118. raise exceptions.Warning(
  119. _("The call to '%s' failed:\n" "- Status Code: %d\n" "- Reason: %s")
  120. % (response.url, response.status_code, response.reason)
  121. )
  122. return response.json()
  123. def get(self, arguments, by_id=False, page=None):
  124. url = self._build_url(
  125. arguments, by_id and "url_get_by_id" or "url_get_by_name", page
  126. )
  127. return self.get_by_url(url, "get")
  128. def create(self, arguments, data):
  129. # pylint: disable=method-required-super
  130. url = self._build_url(arguments, "url_create", None)
  131. res = self.get_by_url(url, "post", data)
  132. return res
  133. class HTTPTokenAuth(AuthBase):
  134. header_format_str = "token {}"
  135. def __init__(self, token):
  136. self.token = token
  137. def __call__(self, request):
  138. request.headers["Authorization"] = self.header_format_str.format(self.token)
  139. return request
上海开阖软件有限公司 沪ICP备12045867号-1