PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/googlecl/service.py

http://googlecl.googlecode.com/
Python | 142 lines | 78 code | 18 blank | 46 comment | 12 complexity | f3d059d8b5b8c6e089d167c4e9bf0326 MD5 | raw file
  1. # Copyright (C) 2010 Google Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """Basic service extensions for the gdata python client library for use on
  15. the command line."""
  16. import gdata.service
  17. import googlecl
  18. import googlecl.base
  19. import logging
  20. LOG = logging.getLogger(__name__)
  21. class BaseServiceCL(googlecl.base.BaseCL):
  22. """Extension of gdata.GDataService specific to GoogleCL."""
  23. def __init__(self, section, config,
  24. request_error_class=gdata.service.RequestError,
  25. *args, **kwargs):
  26. super(BaseServiceCL, self).__init__(section,
  27. config,
  28. request_error_class,
  29. *args,
  30. **kwargs)
  31. # Most services using old gdata API have to disable ssl.
  32. self.ssl = False
  33. # Used for automatic retries of Get/Delete requests that fail due to 302
  34. # errors. See BaseCL.retry_operation.
  35. self.original_get = self.Get
  36. self.original_delete = self.Delete
  37. self.original_post = self.Post
  38. self.original_put = self.Put
  39. self.Get = self.retry_get
  40. self.Delete = self.retry_delete
  41. self.Post = self.retry_post
  42. self.Put = self.retry_put
  43. LOG.debug('Initialized googlecl.service.BaseServiceCL')
  44. def retry_get(self, *args, **kwargs):
  45. """Retries the Get method."""
  46. self.original_operation = self.original_get
  47. return self.retry_operation(*args, **kwargs)
  48. def retry_delete(self, *args, **kwargs):
  49. """Retries the Delete method."""
  50. self.original_operation = self.original_delete
  51. return self.retry_operation(*args, **kwargs)
  52. def retry_post(self, *args, **kwargs):
  53. """Retries the Post method."""
  54. self.original_operation = self.original_post
  55. return self.retry_operation(*args, **kwargs)
  56. def retry_put(self, *args, **kwargs):
  57. """Retries the Put method."""
  58. self.original_operation = self.original_put
  59. return self.retry_operation(*args, **kwargs)
  60. def request_access(self, domain, display_name, scopes=None, browser=None):
  61. """Do all the steps involved with getting an OAuth access token.
  62. Keyword arguments:
  63. domain: Domain to request access for.
  64. (Sets the hd query parameter for the authorization step).
  65. display_name: Descriptor for the machine doing the requesting.
  66. scopes: String or list/tuple of strings describing scopes to request
  67. access to. Default None for default scope of service.
  68. browser: Browser to use to open authentication request url. Default None
  69. for no browser launch, and just displaying the url.
  70. Returns:
  71. True if access token was succesfully retrieved and set, otherwise False.
  72. """
  73. # Installed applications do not have a pre-registration and so follow
  74. # directions for unregistered applications
  75. self.SetOAuthInputParameters(gdata.auth.OAuthSignatureMethod.HMAC_SHA1,
  76. consumer_key='anonymous',
  77. consumer_secret='anonymous')
  78. fetch_params = {'xoauth_displayname':display_name}
  79. # First and third if statements taken from
  80. # gdata.service.GDataService.FetchOAuthRequestToken.
  81. # Need to do this detection/conversion here so we can add the 'email' API
  82. if not scopes:
  83. scopes = gdata.service.lookup_scopes(self.service)
  84. if isinstance(scopes, tuple):
  85. scopes = list(scopes)
  86. if not isinstance(scopes, list):
  87. scopes = [scopes,]
  88. scopes.extend(['https://www.googleapis.com/auth/userinfo#email'])
  89. LOG.debug('Scopes being requested: ' + str(scopes))
  90. try:
  91. request_token = self.FetchOAuthRequestToken(scopes=scopes,
  92. extra_parameters=fetch_params)
  93. except gdata.service.FetchingOAuthRequestTokenFailed, err:
  94. LOG.error(err[0]['body'].strip() + '; Request token retrieval failed!')
  95. if str(err).find('Timestamp') != -1:
  96. LOG.info('Is your system clock up to date? See the FAQ on our wiki: '
  97. 'http://code.google.com/p/googlecl/wiki/FAQ'
  98. '#Timestamp_too_far_from_current_time')
  99. return False
  100. auth_params = {'hd': domain}
  101. auth_url = self.GenerateOAuthAuthorizationURL(request_token=request_token,
  102. extra_params=auth_params)
  103. if browser is not None:
  104. try:
  105. browser.open(str(auth_url))
  106. except Exception, err:
  107. # Blanket catch of Exception is a bad idea, but don't want to pass in
  108. # error to look for.
  109. LOG.error('Failed to launch web browser: ' + unicode(err))
  110. message = ('Please log in and/or grant access via your browser at: \n%s\n\n'
  111. 'Then, in this terminal, hit enter. ' % auth_url)
  112. raw_input(message)
  113. # This upgrades the token, and if successful, sets the access token
  114. try:
  115. self.UpgradeToOAuthAccessToken(request_token)
  116. except gdata.service.TokenUpgradeFailed:
  117. LOG.error('Token upgrade failed! Could not get OAuth access token.')
  118. return False
  119. else:
  120. return True
  121. RequestAccess = request_access