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

Source Code for Module couchdbkit.resource

  1  # -*- coding: utf-8 - 
  2  # 
  3  # This file is part of couchdbkit released under the MIT license.  
  4  # See the NOTICE for more information. 
  5   
  6  """  
  7  couchdb.resource 
  8  ~~~~~~~~~~~~~~~~~~~~~~ 
  9   
 10  This module providess a common interface for all CouchDB request. This 
 11  module makes HTTP request using :mod:`httplib2` module or :mod:`pycurl`  
 12  if available. Just use set transport argument for this. 
 13   
 14  Example:  
 15       
 16      >>> resource = CouchdbResource() 
 17      >>> info = resource.get() 
 18      >>> info['couchdb'] 
 19      u'Welcome' 
 20   
 21  """ 
 22  import base64 
 23  import re 
 24  import socket 
 25  import sys 
 26  import time 
 27  import types 
 28   
 29   
 30  from restkit import Resource, ClientResponse 
 31  from restkit.errors import ResourceError, RequestFailed, RequestError 
 32  from restkit.util import url_quote 
 33     
 34  from . import __version__ 
 35  from .exceptions import ResourceNotFound, ResourceConflict, \ 
 36  PreconditionFailed 
 37  from .utils import json 
 38   
 39  USER_AGENT = 'couchdbkit/%s' % __version__ 
 40   
 41  RequestFailed = RequestFailed 
42 43 -class CouchDBResponse(ClientResponse):
44 45 @property
46 - def json_body(self):
47 try: 48 return json.loads(self.body_string()) 49 except ValueError: 50 return self.body_string()
51
52 53 -class CouchdbResource(Resource):
54
55 - def __init__(self, uri="http://127.0.0.1:5984", **client_opts):
56 """Constructor for a `CouchdbResource` object. 57 58 CouchdbResource represent an HTTP resource to CouchDB. 59 60 @param uri: str, full uri to the server. 61 """ 62 client_opts['response_class'] = CouchDBResponse 63 64 Resource.__init__(self, uri=uri, **client_opts) 65 self.safe = ":/%"
66
67 - def copy(self, path=None, headers=None, **params):
68 """ add copy to HTTP verbs """ 69 return self.request('COPY', path=path, headers=headers, **params)
70
71 - def request(self, method, path=None, payload=None, headers=None, **params):
72 """ Perform HTTP call to the couchdb server and manage 73 JSON conversions, support GET, POST, PUT and DELETE. 74 75 Usage example, get infos of a couchdb server on 76 http://127.0.0.1:5984 : 77 78 79 import couchdbkit.CouchdbResource 80 resource = couchdbkit.CouchdbResource() 81 infos = resource.request('GET') 82 83 @param method: str, the HTTP action to be performed: 84 'GET', 'HEAD', 'POST', 'PUT', or 'DELETE' 85 @param path: str or list, path to add to the uri 86 @param data: str or string or any object that could be 87 converted to JSON. 88 @param headers: dict, optional headers that will 89 be added to HTTP request. 90 @param raw: boolean, response return a Response object 91 @param params: Optional parameterss added to the request. 92 Parameterss are for example the parameters for a view. See 93 `CouchDB View API reference 94 <http://wiki.apache.org/couchdb/HTTP_view_API>`_ for example. 95 96 @return: tuple (data, resp), where resp is an `httplib2.Response` 97 object and data a python object (often a dict). 98 """ 99 100 headers = headers or {} 101 headers.setdefault('Accept', 'application/json') 102 headers.setdefault('User-Agent', USER_AGENT) 103 104 if payload is not None: 105 #TODO: handle case we want to put in payload json file. 106 if not hasattr(payload, 'read') and not isinstance(payload, basestring): 107 payload = json.dumps(payload).encode('utf-8') 108 headers.setdefault('Content-Type', 'application/json') 109 110 params = encode_params(params) 111 try: 112 resp = Resource.request(self, method, path=path, 113 payload=payload, headers=headers, **params) 114 115 except ResourceError, e: 116 msg = getattr(e, 'msg', '') 117 if e.response and msg: 118 if e.response.headers.get('content-type') == 'application/json': 119 try: 120 msg = json.loads(msg) 121 except ValueError: 122 pass 123 124 if type(msg) is dict: 125 error = msg.get('reason') 126 else: 127 error = msg 128 129 if e.status_int == 404: 130 raise ResourceNotFound(error, http_code=404, 131 response=e.response) 132 133 elif e.status_int == 409: 134 raise ResourceConflict(error, http_code=409, 135 response=e.response) 136 elif e.status_int == 412: 137 raise PreconditionFailed(error, http_code=412, 138 response=e.response) 139 else: 140 raise 141 except: 142 raise 143 144 return resp
145
146 -def encode_params(params):
147 """ encode parameters in json if needed """ 148 _params = {} 149 if params: 150 for name, value in params.items(): 151 if name in ('key', 'startkey', 'endkey'): 152 value = json.dumps(value) 153 elif value is None: 154 continue 155 elif not isinstance(value, basestring): 156 value = json.dumps(value) 157 _params[name] = value 158 return _params
159
160 -def escape_docid(docid):
161 if docid.startswith('/'): 162 docid = docid[1:] 163 if docid.startswith('_design'): 164 docid = '_design/%s' % url_quote(docid[8:], safe='') 165 else: 166 docid = url_quote(docid, safe='') 167 return docid
168 169 re_sp = re.compile('\s')
170 -def encode_attachments(attachments):
171 for k, v in attachments.iteritems(): 172 if v.get('stub', False): 173 continue 174 else: 175 v['data'] = re_sp.sub('', base64.b64encode(v['data'])) 176 return attachments
177