Package restkit :: Module resource
[hide private]
[frames] | no frames]

Source Code for Module restkit.resource

  1  # -*- coding: utf-8 - 
  2  # 
  3  # This file is part of restkit released under the MIT license.  
  4  # See the NOTICE for more information. 
  5   
  6   
  7  """ 
  8  restkit.resource 
  9  ~~~~~~~~~~~~~~~~ 
 10   
 11  This module provide a common interface for all HTTP request.  
 12  """ 
 13  from copy import copy 
 14  import urlparse 
 15   
 16  from restkit.errors import ResourceNotFound, Unauthorized, RequestFailed,\ 
 17  ParserError, RequestError 
 18  from restkit.client import HttpConnection 
 19  from restkit.filters import BasicAuth 
 20  from restkit import util 
 21  from restkit.pool.simple import SimplePool 
 22   
23 -class Resource(object):
24 """A class that can be instantiated for access to a RESTful resource, 25 including authentication. 26 """ 27 28 charset = 'utf-8' 29 encode_keys = True 30 safe = "/:" 31 pool_class = SimplePool 32 keepalive = True 33 basic_auth_url = True 34
35 - def __init__(self, uri, headers=None, **client_opts):
36 """Constructor for a `Resource` object. 37 38 Resource represent an HTTP resource. 39 40 :param uri: str, full uri to the server. 41 :param headers: dict, optionnal headers that will 42 be added to HTTP request. 43 :param client_opts: `restkit.client.HttpConnection` Options 44 """ 45 46 pool_instance = client_opts.get('pool_instance') 47 keepalive = client_opts.get("keepalive") or 10 48 if not pool_instance and self.keepalive: 49 pool = self.pool_class(keepalive=keepalive) 50 client_opts['pool_instance'] = pool 51 52 self.filters = client_opts.get('filters') or [] 53 if self.basic_auth_url: 54 # detect credentials from url 55 u = urlparse.urlparse(uri) 56 if u.username: 57 password = u.password or "" 58 59 # add filters 60 filters = copy(self.filters) 61 filters.append(BasicAuth(u.username, password)) 62 client_opts['filters'] = filters 63 64 # update uri 65 uri = urlparse.urlunparse((u.scheme, u.netloc.split("@")[-1], 66 u.path, u.params, u.query, u.fragment)) 67 68 self.uri = uri 69 self._headers = headers or {} 70 self.client_opts = client_opts 71 self._body_parts = []
72
73 - def __repr__(self):
74 return '<%s %s>' % (self.__class__.__name__, self.uri)
75
76 - def _set_default_attrs(self, obj):
77 for attr_name in ('charset', 'encode_keys', 'pool_class', 78 'keepalive', 'basic_auth_url'): 79 setattr(obj, attr_name, getattr(self, attr_name)) 80 return obj
81
82 - def clone(self):
83 """if you want to add a path to resource uri, you can do: 84 85 .. code-block:: python 86 87 resr2 = res.clone() 88 89 """ 90 client_opts = self.client_opts.copy() 91 client_opts["filters"] = self.filters 92 obj = self.__class__(self.uri, headers=self._headers, 93 **client_opts) 94 return self._set_default_attrs(obj)
95
96 - def __call__(self, path):
97 """if you want to add a path to resource uri, you can do: 98 99 .. code-block:: python 100 101 Resource("/path").get() 102 """ 103 104 client_opts = self.client_opts.copy() 105 client_opts["filters"] = self.filters 106 107 new_uri = util.make_uri(self.uri, path, charset=self.charset, 108 safe=self.safe, encode_keys=self.encode_keys) 109 110 obj = type(self)(new_uri, headers=self._headers, **client_opts) 111 return self._set_default_attrs(obj)
112
113 - def close(self):
114 """ Close all the connections related to the resource """ 115 pool = self.client_opts.get('pool_instance') 116 if not pool: 117 return 118 119 parsed_url = urlparse.urlparse(self.uri) 120 pool.clear_host(util.parse_netloc(parsed_url))
121
122 - def get(self, path=None, headers=None, **params):
123 """ HTTP GET 124 125 :param path: string additionnal path to the uri 126 :param headers: dict, optionnal headers that will 127 be added to HTTP request. 128 :param params: Optionnal parameterss added to the request. 129 """ 130 return self.request("GET", path=path, headers=headers, **params)
131
132 - def head(self, path=None, headers=None, **params):
133 """ HTTP HEAD 134 135 see GET for params description. 136 """ 137 return self.request("HEAD", path=path, headers=headers, **params)
138
139 - def delete(self, path=None, headers=None, **params):
140 """ HTTP DELETE 141 142 see GET for params description. 143 """ 144 return self.request("DELETE", path=path, headers=headers, **params)
145
146 - def post(self, path=None, payload=None, headers=None, **params):
147 """ HTTP POST 148 149 :param payload: string passed to the body of the request 150 :param path: string additionnal path to the uri 151 :param headers: dict, optionnal headers that will 152 be added to HTTP request. 153 :param params: Optionnal parameterss added to the request 154 """ 155 156 return self.request("POST", path=path, payload=payload, 157 headers=headers, **params)
158
159 - def put(self, path=None, payload=None, headers=None, **params):
160 """ HTTP PUT 161 162 see POST for params description. 163 """ 164 return self.request("PUT", path=path, payload=payload, 165 headers=headers, **params)
166
167 - def do_request(self, url, method='GET', payload=None, headers=None):
168 http_client = HttpConnection(**self.client_opts) 169 return http_client.request(url, method=method, body=payload, 170 headers=headers)
171
172 - def request(self, method, path=None, payload=None, headers=None, 173 **params):
174 """ HTTP request 175 176 This method may be the only one you want to override when 177 subclassing `restkit.rest.Resource`. 178 179 :param payload: string or File object passed to the body of the request 180 :param path: string additionnal path to the uri 181 :param headers: dict, optionnal headers that will 182 be added to HTTP request. 183 :param params: Optionnal parameterss added to the request 184 """ 185 186 headers = headers or [] 187 uri = util.make_uri(self.uri, path, charset=self.charset, 188 safe=self.safe, encode_keys=self.encode_keys, 189 **params) 190 191 resp = self.do_request(uri, method=method, payload=payload, 192 headers=headers) 193 194 if resp is None: 195 # race condition 196 raise ValueError("Unkown error: response object is None") 197 198 if resp.status_int >= 400: 199 if resp.status_int == 404: 200 raise ResourceNotFound(resp.body_string(), response=resp) 201 elif resp.status_int in (401, 403): 202 raise Unauthorized(resp.body_string(), 203 http_code=resp.status_int, response=resp) 204 else: 205 raise RequestFailed(resp.body_string(), 206 http_code=resp.status_int, response=resp) 207 208 return resp
209
210 - def update_uri(self, path):
211 """ 212 to set a new uri absolute path 213 """ 214 self.uri = util.make_uri(self.uri, path, charset=self.charset, 215 safe=self.safe, encode_keys=self.encode_keys)
216