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