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
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):
41
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
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
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
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
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
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):
166
167
168 @staticmethod
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