Package grassyknoll :: Package client :: Module RestClient
[hide private]

Source Code for Module grassyknoll.client.RestClient

  1  """a low-level client for a L{RestCollection}""" 
  2   
  3  import httplib2 
  4  import urllib 
  5  from grassyknoll.serial import JsonSerial 
  6   
  7  from grassyknoll.lib.meta import FactoryMixin 
  8   
9 -class RestClient(FactoryMixin):
10 """A low-level client for a L{RestCollection} 11 12 @ivar base_uri: url to the server. Must end in / 13 @type base_uri: string 14 15 @ivar mimetype: mimetype to use for when communicating with server 16 @type mimetype: string 17 18 @ivar headers: common request headers to send to server 19 @type headers: dict 20 21 @ivar http: a connection for talking to the server 22 @type http: L{httplib2.Http} 23 """ 24 25 mimetype='application/json' 26 base_uri="http://localhost:8080/" 27
28 - def __init__(self, base_uri=None, mimetype=None):
29 if base_uri is not None: 30 self.base_uri=base_uri 31 assert self.base_uri.endswith('/') 32 33 if mimetype is not None: 34 self.mimetype=mimetype 35 36 self.headers={'Accept':self.mimetype} 37 38 self.http=httplib2.Http() 39 self.http.force_exception_to_status_code=True 40 self.ignore_etag=True
41
42 - def list(self):
43 """list documents 44 45 @returns: response and body 46 @rtype: tuple of L{httplib2.Response}, string 47 """ 48 response, content=self.http.request(self.base_uri, headers=self.headers) 49 return response, content
50
51 - def retrieve(self, id, fields=None):
52 """retrieve a single result 53 54 @arg id: the id of the result to retrieve 55 @type id: unicode 56 57 @arg fields: names of fields to retrieve. If None, retrieve all fields. 58 @type fields: list of string 59 60 @returns: response and body 61 @rtype: tuple of L{httplib2.Response}, string 62 """ 63 fields=" ".join(fields) if fields else fields 64 uri=self.base_uri+id+self.query_string(fields=fields) 65 66 return self.http.request(uri, headers=self.headers)
67
68 - def retrieveMany(self, ids, fields=None):
69 """retrieve several results 70 71 @arg ids: the ids of the result to retrieve 72 @type ids: list of unicode 73 74 @arg fields: names of fields to retrieve. If None, retrieve all fields. 75 @type fields: list of string 76 77 @returns: response and body 78 @rtype: tuple of L{httplib2.Response}, string 79 """ 80 assert isinstance(ids, (list, tuple)) 81 fields=",".join(fields) if fields else fields 82 ids=",".join(ids) 83 uri=self.base_uri+'__id__/'+ids+self.query_string(fields=fields) 84 85 return self.http.request(uri, headers=self.headers)
86
87 - def create(self, doc, id=None):
88 """create a single document 89 90 @arg doc: a document to create 91 @type doc: dict of unicode => basic python types 92 93 @arg id: the id of the document to create. If None and no C{__id__} is 94 present in doc, an id will be assigned by server. 95 @type id: unicode 96 97 @returns: response and body 98 @rtype: tuple of L{httplib2.Response}, string 99 """ 100 headers=self.headers.copy() 101 headers['Content-Type']=self.mimetype 102 headers['Content-Encoding']='utf-8' 103 104 if id is not None: 105 uri=self.base_uri+id 106 method='PUT' 107 else: 108 uri=self.base_uri+'__append__/' 109 method='POST' 110 111 json=JsonSerial.dumps(doc) 112 return self.http.request(uri, method, body=json, headers=headers)
113
114 - def createMany(self, docs):
115 """create several documents 116 117 @arg docs: documents to create. All docs must have an C{__id__} 118 @type doc: list of dicts of unicode => basic python types 119 120 @returns: response and body 121 @rtype: tuple of L{httplib2.Response}, string 122 """ 123 headers=self.headers.copy() 124 headers['Content-Type']=self.mimetype 125 headers['Content-Encoding']='utf-8' 126 127 uri=self.base_uri+'__extend__/' 128 method='POST' 129 130 json=JsonSerial.dumps(docs) 131 return self.http.request(uri, method, body=json, headers=headers)
132
133 - def delete(self, id):
134 """delete a single document 135 136 @arg id: id of the document to delete 137 @type id: unicode 138 139 @returns: response and body 140 @rtype: tuple of L{httplib2.Response}, string 141 """ 142 uri=self.base_uri+id 143 return self.http.request(uri, headers=self.headers, 144 method='DELETE')
145
146 - def deleteMany(self, ids):
147 """delete several documents 148 149 @arg ids: ids of the documents to delete 150 @type id: list of unicode 151 152 @returns: response and body 153 @rtype: tuple of L{httplib2.Response}, string 154 """ 155 assert isinstance(ids, (list, tuple)) 156 ids=",".join(ids) 157 uri=self.base_uri+'__id__/'+ids 158 return self.http.request(uri, headers=self.headers, 159 method='DELETE')
160
161 - def query(self, name, **kwargs):
162 query=self.query_string(**kwargs) 163 164 uri=self.base_uri+'__query__/'+name+query 165 return self.http.request(uri, headers=self.headers)
166 167 ## internal ## 168 @staticmethod
169 - def query_string(**d):
170 """return a query string fragment from kwargs. For internal use""" 171 qstring=urllib.urlencode([(k, v) for k, v 172 in sorted(d.iteritems()) 173 if v is not None]) 174 175 if qstring: return "?"+qstring 176 else: return ""
177