Package u1rest :: Package lib :: Module client
[hide private]
[frames] | no frames]

Source Code for Module u1rest.lib.client

  1  #Copyright (C) 2011 by John O'Brien 
  2  # 
  3  #Permission is hereby granted, free of charge, to any person obtaining a copy 
  4  #of this software and associated documentation files (the "Software"), to deal 
  5  #in the Software without restriction, including without limitation the rights 
  6  #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
  7  #copies of the Software, and to permit persons to whom the Software is 
  8  #furnished to do so, subject to the following conditions: 
  9  # 
 10  #The above copyright notice and this permission notice shall be included in 
 11  #all copies or substantial portions of the Software. 
 12  # 
 13  #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 14  #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 15  #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 16  #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 17  #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 18  #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 19  #THE SOFTWARE. 
 20  """Client classes used by REST Client.""" 
 21  #pylint: disable=R0903 
 22  import urllib 
 23  import urllib2 
 24  import urlparse 
 25  import json 
 26   
 27   
 28   
29 -class BaseClient(object):
30 """Base client to provide common functionaility.""" 31 # pylint: disable=R0201
32 - def __init__(self, http_host, auth):
33 """Ubuntu One RESTful Client.""" 34 self.auth = auth 35 self.http_host = http_host
36
37 - def get_url_from_path(self, path, params=None):
38 """Using the path, parameters and host, create a URL. 39 40 @param path: The url path 41 @param params: A dict of parameters to be used as a query string. 42 """ 43 path = urllib.quote(path.encode('utf-8'), '~/[]()') 44 if params: 45 path = "%s?%s" % (path, urllib.urlencode(params)) 46 return urlparse.urljoin(self.http_host, path)
47
48 - def _get_authenticated_request(self, url, params=None, method='GET', 49 data=None):
50 """Helper to get a urllib2.Request object with the auth headers.""" 51 headers = self.auth.get_auth_headers(url, params, method) 52 request = urllib2.Request(url, data, headers) 53 request.get_method = lambda: method 54 return request
55
56 - def _handle_request(self, request):
57 """Helper to handle urllib2.Resquest object.""" 58 opener = urllib2.build_opener(urllib2.BaseHandler) 59 try: 60 return opener.open(request, timeout=30) 61 except urllib2.URLError, ex: 62 raise Exception( 63 "Error opening %s\n%s" % (request.get_full_url(), ex.message))
64 65
66 -class ResourceClient(BaseClient):
67 """A client used to handle authenticated REST Requests.""" 68
69 - def __init__(self, http_host, auth, base_api_path):
70 super(ResourceClient, self).__init__(http_host, auth) 71 self.base_path = base_api_path
72
73 - def process_request(self, path, method, params=None, data=None):
74 """Process a REST request. 75 76 This is specifically for JSON request/responses. The data, for PUT must 77 be serializable by JSON. The http responses must be JSON serializable as 78 well. 79 """ 80 url = self.get_url_from_path(path, params) 81 if method == 'PUT' and data: 82 data = json.dumps(data) 83 else: 84 data = None 85 request = self._get_authenticated_request(url, params, method, data) 86 request.add_header('Content-Type', 'application/json') 87 response = self._handle_request(request) 88 content = response.read() 89 try: 90 return json.loads(content) 91 except ValueError: 92 raise Exception("JSON could not be decoded.\n%s\n%s" % (url, 93 content))
94
95 - def _get_path(self, path):
96 """Join the path with the API base path. 97 98 This also removes trailing slashes wish are not part of the resource. 99 """ 100 if path: 101 return self.base_path + '/' + path.lstrip("/") 102 return self.base_path
103
104 - def get_resource(self, path="", params=None):
105 """Get a Resource.""" 106 return self.process_request( 107 self._get_path(path), 'GET', params=params)
108
109 - def delete_resource(self, path, params=None):
110 """Delete a Resource.""" 111 return self.process_request( 112 self._get_path(path), 'DELETE', params=params)
113
114 - def put_resource(self, path, data=None, params=None):
115 """PUT a Resource.""" 116 return self.process_request( 117 self._get_path(path), 'PUT', params=params, data=data)
118