github.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #!/usr/bin/env python
  2. import json
  3. import os
  4. import re
  5. import sys
  6. REQUESTS_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..',
  7. 'vendor', 'requests'))
  8. sys.path.append(os.path.join(REQUESTS_DIR, 'build', 'lib'))
  9. sys.path.append(os.path.join(REQUESTS_DIR, 'build', 'lib.linux-x86_64-2.7'))
  10. import requests
  11. GITHUB_URL = 'https://api.github.com'
  12. GITHUB_UPLOAD_ASSET_URL = 'https://uploads.github.com'
  13. class GitHub:
  14. def __init__(self, access_token):
  15. self._authorization = 'token %s' % access_token
  16. pattern = '^/repos/{0}/{0}/releases/{1}/assets$'.format('[^/]+', '[0-9]+')
  17. self._releases_upload_api_pattern = re.compile(pattern)
  18. def __getattr__(self, attr):
  19. return _Callable(self, '/%s' % attr)
  20. def send(self, method, path, **kw):
  21. if not 'headers' in kw:
  22. kw['headers'] = dict()
  23. headers = kw['headers']
  24. headers['Authorization'] = self._authorization
  25. headers['Accept'] = 'application/vnd.github.manifold-preview'
  26. # Switch to a different domain for the releases uploading API.
  27. if self._releases_upload_api_pattern.match(path):
  28. url = '%s%s' % (GITHUB_UPLOAD_ASSET_URL, path)
  29. else:
  30. url = '%s%s' % (GITHUB_URL, path)
  31. # Data are sent in JSON format.
  32. if 'data' in kw:
  33. kw['data'] = json.dumps(kw['data'])
  34. r = getattr(requests, method)(url, **kw).json()
  35. if 'message' in r:
  36. raise Exception(json.dumps(r, indent=2, separators=(',', ': ')))
  37. return r
  38. class _Executable:
  39. def __init__(self, gh, method, path):
  40. self._gh = gh
  41. self._method = method
  42. self._path = path
  43. def __call__(self, **kw):
  44. return self._gh.send(self._method, self._path, **kw)
  45. class _Callable(object):
  46. def __init__(self, gh, name):
  47. self._gh = gh
  48. self._name = name
  49. def __call__(self, *args):
  50. if len(args) == 0:
  51. return self
  52. name = '%s/%s' % (self._name, '/'.join([str(arg) for arg in args]))
  53. return _Callable(self._gh, name)
  54. def __getattr__(self, attr):
  55. if attr in ['get', 'put', 'post', 'patch', 'delete']:
  56. return _Executable(self._gh, attr, self._name)
  57. name = '%s/%s' % (self._name, attr)
  58. return _Callable(self._gh, name)