Revision 3dabe5d2 kamaki/clients/pithos_rest_api.py
b/kamaki/clients/pithos_rest_api.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
from kamaki.clients.storage import StorageClient, ClientError
|
|
34 |
from kamaki.clients.storage import StorageClient |
|
35 | 35 |
from kamaki.clients.utils import path4url, list2str |
36 | 36 |
|
37 |
|
|
37 | 38 |
class PithosRestAPI(StorageClient): |
38 | 39 |
|
39 |
def account_head(self, until = None, |
|
40 |
if_modified_since=None, if_unmodified_since=None, *args, **kwargs): |
|
40 |
def account_head(self, |
|
41 |
until=None, |
|
42 |
if_modified_since=None, |
|
43 |
if_unmodified_since=None, |
|
44 |
*args, |
|
45 |
**kwargs): |
|
41 | 46 |
""" Full Pithos+ HEAD at account level |
42 | 47 |
--- request parameters --- |
43 | 48 |
@param until (string): optional timestamp |
44 | 49 |
--- --- optional request headers --- |
45 |
@param if_modified_since (string): Retrieve if account has changed since provided timestamp |
|
46 |
@param if_unmodified_since (string): Retrieve if account has not changed since provided timestamp |
|
50 |
@param if_modified_since (string): Retrieve if account has changed |
|
51 |
since provided timestamp |
|
52 |
@param if_unmodified_since (string): Retrieve if account has not |
|
53 |
change since provided timestamp |
|
47 | 54 |
""" |
48 | 55 |
self.assert_account() |
49 | 56 |
path = path4url(self.account) |
50 | 57 |
|
51 |
self.set_param('until', until, iff = until is not None)
|
|
58 |
self.set_param('until', until, iff=until is not None)
|
|
52 | 59 |
self.set_header('If-Modified-Since', if_modified_since) |
53 | 60 |
self.set_header('If-Unmodified-Since', if_unmodified_since) |
54 | 61 |
|
55 | 62 |
success = kwargs.pop('success', 204) |
56 | 63 |
return self.head(path, *args, success=success, **kwargs) |
57 | 64 |
|
58 |
def account_get(self, limit=None, marker=None, format='json', show_only_shared=False, until=None, |
|
59 |
if_modified_since=None, if_unmodified_since=None, *args, **kwargs): |
|
65 |
def account_get(self, |
|
66 |
limit=None, |
|
67 |
marker=None, |
|
68 |
format='json', |
|
69 |
show_only_shared=False, |
|
70 |
until=None, |
|
71 |
if_modified_since=None, |
|
72 |
if_unmodified_since=None, |
|
73 |
*args, |
|
74 |
**kwargs): |
|
60 | 75 |
""" Full Pithos+ GET at account level |
61 | 76 |
--- request parameters --- |
62 |
@param limit (integer): The amount of results requested (server will use default value if None) |
|
63 |
@param marker (string): Return containers with name lexicographically after marker |
|
64 |
@param format (string): reply format can be json or xml (default: json) |
|
65 |
@param shared (bool): If true, only shared containers will be included in results |
|
77 |
@param limit (integer): The amount of results requested |
|
78 |
(server will use default value if None) |
|
79 |
@param marker (string): Return containers with name |
|
80 |
lexicographically after marker |
|
81 |
@param format (string): reply format can be json or xml |
|
82 |
(default: json) |
|
83 |
@param shared (bool): If true, only shared containers will be |
|
84 |
included in results |
|
66 | 85 |
@param until (string): optional timestamp |
67 | 86 |
--- --- optional request headers --- |
68 |
@param if_modified_since (string): Retrieve if account has changed since provided timestamp |
|
69 |
@param if_unmodified_since (string): Retrieve if account has not changed since provided timestamp |
|
87 |
@param if_modified_since (string): Retrieve if account has changed |
|
88 |
since provided timestamp |
|
89 |
@param if_unmodified_since (string): Retrieve if account has not |
|
90 |
changed since provided timestamp |
|
70 | 91 |
""" |
71 | 92 |
self.assert_account() |
72 | 93 |
|
73 |
self.set_param('format',format, iff = format is not None)
|
|
74 |
self.set_param('limit',limit, iff = limit is not None)
|
|
75 |
self.set_param('marker',marker, iff = marker is not None)
|
|
76 |
self.set_param('shared', iff = show_only_shared)
|
|
77 |
self.set_param('until',until, iff = until is not None)
|
|
94 |
self.set_param('format', format, iff=format is not None)
|
|
95 |
self.set_param('limit', limit, iff=limit is not None)
|
|
96 |
self.set_param('marker', marker, iff=marker is not None)
|
|
97 |
self.set_param('shared', iff=show_only_shared)
|
|
98 |
self.set_param('until', until, iff=until is not None)
|
|
78 | 99 |
|
79 | 100 |
self.set_header('If-Modified-Since', if_modified_since) |
80 | 101 |
self.set_header('If-Unmodified-Since', if_unmodified_since) |
81 | 102 |
|
82 | 103 |
path = path4url(self.account) |
83 | 104 |
success = kwargs.pop('success', (200, 204)) |
84 |
return self.get(path, *args, success = success, **kwargs)
|
|
105 |
return self.get(path, *args, success=success, **kwargs)
|
|
85 | 106 |
|
86 |
def account_post(self, update=True, |
|
87 |
groups={}, metadata=None, quota=None, versioning=None, *args, **kwargs): |
|
107 |
def account_post(self, |
|
108 |
update=True, |
|
109 |
groups={}, |
|
110 |
metadata=None, |
|
111 |
quota=None, |
|
112 |
versioning=None, |
|
113 |
*args, |
|
114 |
**kwargs): |
|
88 | 115 |
""" Full Pithos+ POST at account level |
89 | 116 |
--- request parameters --- |
90 | 117 |
@param update (bool): if True, Do not replace metadata/groups |
91 | 118 |
--- request headers --- |
92 | 119 |
@groups (dict): Optional user defined groups in the form |
93 |
{ 'group1':['user1', 'user2', ...],
|
|
120 |
{ 'group1':['user1', 'user2', ...], |
|
94 | 121 |
'group2':['userA', 'userB', ...], ... |
95 | 122 |
} |
96 | 123 |
@metadata (dict): Optional user defined metadata in the form |
... | ... | |
103 | 130 |
""" |
104 | 131 |
self.assert_account() |
105 | 132 |
|
106 |
self.set_param('update', iff = update)
|
|
133 |
self.set_param('update', iff=update)
|
|
107 | 134 |
|
108 | 135 |
for group, usernames in groups.items(): |
109 | 136 |
userstr = '' |
... | ... | |
111 | 138 |
for user in usernames: |
112 | 139 |
userstr = userstr + dlm + user |
113 | 140 |
dlm = ',' |
114 |
self.set_header('X-Account-Group-'+group, userstr)
|
|
141 |
self.set_header('X-Account-Group-' + group, userstr)
|
|
115 | 142 |
if metadata is not None: |
116 | 143 |
for metaname, metaval in metadata.items(): |
117 |
self.set_header('X-Account-Meta-'+metaname, metaval)
|
|
144 |
self.set_header('X-Account-Meta-' + metaname, metaval)
|
|
118 | 145 |
self.set_header('X-Account-Policy-Quota', quota) |
119 | 146 |
self.set_header('X-Account-Policy-Versioning', versioning) |
120 | 147 |
|
... | ... | |
127 | 154 |
""" Full Pithos+ HEAD at container level |
128 | 155 |
--- request params --- |
129 | 156 |
@param until (string): optional timestamp |
130 |
--- optional request headers --- |
|
131 |
@param if_modified_since (string): Retrieve if account has changed since provided timestamp |
|
132 |
@param if_unmodified_since (string): Retrieve if account has not changed since provided timestamp |
|
157 |
--- optional request headers --- |
|
158 |
@param if_modified_since (string): Retrieve if account has changed |
|
159 |
since provided timestamp |
|
160 |
@param if_unmodified_since (string): Retrieve if account has not |
|
161 |
changed since provided timestamp |
|
133 | 162 |
""" |
134 | 163 |
self.assert_container() |
135 | 164 |
|
... | ... | |
142 | 171 |
success = kwargs.pop('success', 204) |
143 | 172 |
return self.head(path, *args, success=success, **kwargs) |
144 | 173 |
|
145 |
def container_get(self, limit = None, marker = None, prefix=None, delimiter=None, path = None, |
|
146 |
format='json', meta=[], show_only_shared=False, until=None, |
|
147 |
if_modified_since=None, if_unmodified_since=None, *args, **kwargs): |
|
174 |
def container_get(self, |
|
175 |
limit=None, |
|
176 |
marker=None, |
|
177 |
prefix=None, |
|
178 |
delimiter=None, |
|
179 |
path=None, |
|
180 |
format='json', |
|
181 |
meta=[], |
|
182 |
show_only_shared=False, |
|
183 |
until=None, |
|
184 |
if_modified_since=None, |
|
185 |
if_unmodified_since=None, |
|
186 |
*args, |
|
187 |
**kwargs): |
|
148 | 188 |
""" Full Pithos+ GET at container level |
149 | 189 |
--- request parameters --- |
150 |
@param limit (integer): The amount of results requested (server qill use default value if None) |
|
151 |
@param marker (string): Return containers with name lexicographically after marker |
|
190 |
@param limit (integer): The amount of results requested |
|
191 |
(server qill use default value if None) |
|
192 |
@param marker (string): Return containers with name lexicographically |
|
193 |
after marker |
|
152 | 194 |
@param prefix (string): Return objects starting with prefix |
153 | 195 |
@param delimiter (string): Return objects up to the delimiter |
154 |
@param path (string): assume prefix = path and delimiter = / (overwrites prefix |
|
155 |
and delimiter) |
|
156 |
@param format (string): reply format can be json or xml (default: json) |
|
157 |
@param meta (list): Return objects that satisfy the key queries in the specified |
|
158 |
comma separated list (use <key>, !<key> for existence queries, <key><op><value> |
|
159 |
for value queries, where <op> can be one of =, !=, <=, >=, <, >) |
|
160 |
@param shared (bool): If true, only shared containers will be included in results |
|
196 |
@param path (string): assume prefix = path and delimiter = / |
|
197 |
(overwrites prefix and delimiter) |
|
198 |
@param format (string): reply format can be json or xml (default:json) |
|
199 |
@param meta (list): Return objects that satisfy the key queries in |
|
200 |
the specified comma separated list (use <key>, !<key> for |
|
201 |
existence queries, <key><op><value> for value queries, where <op> |
|
202 |
can be one of =, !=, <=, >=, <, >) |
|
203 |
@param shared (bool): If true, only shared containers will be included |
|
204 |
in results |
|
161 | 205 |
@param until (string): optional timestamp |
162 | 206 |
--- --- optional request headers --- |
163 |
@param if_modified_since (string): Retrieve if account has changed since provided timestamp |
|
164 |
@param if_unmodified_since (string): Retrieve if account has not changed since provided timestamp |
|
207 |
@param if_modified_since (string): Retrieve if account has changed |
|
208 |
since provided timestamp |
|
209 |
@param if_unmodified_since (string): Retrieve if account has not |
|
210 |
changed since provided timestamp |
|
165 | 211 |
""" |
166 | 212 |
self.assert_container() |
167 | 213 |
|
... | ... | |
174 | 220 |
else: |
175 | 221 |
self.set_param('path', path) |
176 | 222 |
self.set_param('shared', iff=show_only_shared) |
177 |
self.set_param('meta', list2str(meta), iff=meta is not None and len(meta) > 0) |
|
223 |
self.set_param('meta', |
|
224 |
list2str(meta), |
|
225 |
iff=meta is not None and len(meta) > 0) |
|
178 | 226 |
self.set_param('until', until, iff=until is not None) |
179 | 227 |
|
180 | 228 |
self.set_header('If-Modified-Since', if_modified_since) |
... | ... | |
184 | 232 |
success = kwargs.pop('success', 200) |
185 | 233 |
return self.get(path, *args, success=success, **kwargs) |
186 | 234 |
|
187 |
def container_put(self, quota=None, versioning=None, metadata=None, *args, **kwargs): |
|
235 |
def container_put(self, |
|
236 |
quota=None, |
|
237 |
versioning=None, |
|
238 |
metadata=None, |
|
239 |
*args, |
|
240 |
**kwargs): |
|
188 | 241 |
""" Full Pithos+ PUT at container level |
189 | 242 |
--- request headers --- |
190 | 243 |
@param quota (integer): Size limit in KB |
... | ... | |
198 | 251 |
|
199 | 252 |
if metadata is not None: |
200 | 253 |
for metaname, metaval in metadata.items(): |
201 |
self.set_header('X-Container-Meta-'+metaname, metaval)
|
|
254 |
self.set_header('X-Container-Meta-' + metaname, metaval)
|
|
202 | 255 |
self.set_header('X-Container-Policy-Quota', quota) |
203 | 256 |
self.set_header('X-Container-Policy-Versioning', versioning) |
204 | 257 |
|
205 | 258 |
path = path4url(self.account, self.container) |
206 |
success = kwargs.pop('success',(201, 202)) |
|
259 |
success = kwargs.pop('success', (201, 202))
|
|
207 | 260 |
return self.put(path, *args, success=success, **kwargs) |
208 | 261 |
|
209 |
def container_post(self, update=True, format='json', |
|
210 |
quota=None, versioning=None, metadata=None, content_type=None, content_length=None, |
|
211 |
transfer_encoding=None, *args, **kwargs): |
|
262 |
def container_post(self, |
|
263 |
update=True, |
|
264 |
format='json', |
|
265 |
quota=None, |
|
266 |
versioning=None, |
|
267 |
metadata=None, |
|
268 |
content_type=None, |
|
269 |
content_length=None, |
|
270 |
transfer_encoding=None, |
|
271 |
*args, |
|
272 |
**kwargs): |
|
212 | 273 |
""" Full Pithos+ POST at container level |
213 | 274 |
--- request params --- |
214 | 275 |
@param update (bool): if True, Do not replace metadata/groups |
... | ... | |
231 | 292 |
|
232 | 293 |
if metadata is not None: |
233 | 294 |
for metaname, metaval in metadata.items(): |
234 |
self.set_header('X-Container-Meta-'+metaname, metaval)
|
|
295 |
self.set_header('X-Container-Meta-' + metaname, metaval)
|
|
235 | 296 |
self.set_header('X-Container-Policy-Quota', quota) |
236 | 297 |
self.set_header('X-Container-Policy-Versioning', versioning) |
237 | 298 |
self.set_header('Content-Type', content_type) |
... | ... | |
245 | 306 |
def container_delete(self, until=None, delimiter=None, *args, **kwargs): |
246 | 307 |
""" Full Pithos+ DELETE at container level |
247 | 308 |
--- request parameters --- |
248 |
@param until (timestamp string): if defined, container is purged up to that time |
|
309 |
@param until (timestamp string): if defined, container is purged up to |
|
310 |
that time |
|
249 | 311 |
""" |
250 |
self.assert_container()
|
|
312 |
self.assert_container() |
|
251 | 313 |
|
252 | 314 |
self.set_param('until', until, iff=until is not None) |
253 | 315 |
self.set_param('delimiter', delimiter, iff=delimiter is not None) |
254 | 316 |
|
255 |
path=path4url(self.account, self.container)
|
|
317 |
path = path4url(self.account, self.container)
|
|
256 | 318 |
success = kwargs.pop('success', 204) |
257 | 319 |
return self.delete(path, success=success) |
258 | 320 |
|
259 |
def object_head(self, object, version=None, if_etag_match=None, if_etag_not_match = None, |
|
260 |
if_modified_since = None, if_unmodified_since = None, *args, **kwargs): |
|
321 |
def object_head(self, object, |
|
322 |
version=None, |
|
323 |
if_etag_match=None, |
|
324 |
if_etag_not_match=None, |
|
325 |
if_modified_since=None, |
|
326 |
if_unmodified_since=None, |
|
327 |
*args, |
|
328 |
**kwargs): |
|
261 | 329 |
""" Full Pithos+ HEAD at object level |
262 | 330 |
--- request parameters --- |
263 | 331 |
@param version (string): optional version identified |
... | ... | |
266 | 334 |
with etag matching with this |
267 | 335 |
@param if_etag_not_match (string): if provided, return only results |
268 | 336 |
with etag not matching with this |
269 |
@param if_modified_since (string): Retrieve if account has changed since provided timestamp |
|
270 |
@param if_unmodified_since (string): Retrieve if account has not changed since provided timestamp |
|
337 |
@param if_modified_since (string): Retrieve if account has changed |
|
338 |
since provided timestamp |
|
339 |
@param if_unmodified_since (string): Retrieve if account has not |
|
340 |
changed since provided timestamp |
|
271 | 341 |
""" |
272 | 342 |
self.assert_container() |
273 | 343 |
|
... | ... | |
278 | 348 |
self.set_header('If-Modified-Since', if_modified_since) |
279 | 349 |
self.set_header('If-Unmodified-Since', if_unmodified_since) |
280 | 350 |
|
281 |
path=path4url(self.account, self.container, object)
|
|
351 |
path = path4url(self.account, self.container, object)
|
|
282 | 352 |
success = kwargs.pop('success', 200) |
283 | 353 |
return self.head(path, *args, success=success, **kwargs) |
284 | 354 |
|
285 |
def object_get(self, object, format='json', hashmap=False, version=None, |
|
286 |
data_range=None, if_range=False, if_etag_match=None, if_etag_not_match = None, |
|
287 |
if_modified_since = None, if_unmodified_since = None, *args, **kwargs): |
|
355 |
def object_get(self, object, |
|
356 |
format='json', |
|
357 |
hashmap=False, |
|
358 |
version=None, |
|
359 |
data_range=None, |
|
360 |
if_range=False, |
|
361 |
if_etag_match=None, |
|
362 |
if_etag_not_match=None, |
|
363 |
if_modified_since=None, |
|
364 |
if_unmodified_since=None, |
|
365 |
*args, |
|
366 |
**kwargs): |
|
288 | 367 |
""" Full Pithos+ GET at object level |
289 | 368 |
--- request parameters --- |
290 | 369 |
@param format (string): json (default) or xml |
... | ... | |
292 | 371 |
@param version (string): optional version identified |
293 | 372 |
--- request headers --- |
294 | 373 |
@param data_range (string): Optional range of data to retrieve |
295 |
@param if_range (bool):
|
|
374 |
@param if_range (bool): |
|
296 | 375 |
@param if_etag_match (string): if provided, return only results |
297 | 376 |
with etag matching with this |
298 | 377 |
@param if_etag_not_match (string): if provided, return only results |
299 | 378 |
with etag not matching with this |
300 |
@param if_modified_since (string): Retrieve if account has changed since provided timestamp |
|
301 |
@param if_unmodified_since (string): Retrieve if account has not changed since provided timestamp |
|
379 |
@param if_modified_since (string): Retrieve if account has changed |
|
380 |
since provided timestamp |
|
381 |
@param if_unmodified_since (string): Retrieve if account has not |
|
382 |
changed since provided timestamp |
|
302 | 383 |
""" |
303 | 384 |
self.assert_container() |
304 | 385 |
|
... | ... | |
307 | 388 |
self.set_param('hashmap', hashmap, iff=hashmap) |
308 | 389 |
|
309 | 390 |
self.set_header('Range', data_range) |
310 |
self.set_header('If-Range', '', if_range is True and data_range is not None) |
|
391 |
self.set_header('If-Range', '', |
|
392 |
if_range is True and data_range is not None) |
|
311 | 393 |
self.set_header('If-Match', if_etag_match, ) |
312 | 394 |
self.set_header('If-None-Match', if_etag_not_match) |
313 | 395 |
self.set_header('If-Modified-Since', if_modified_since) |
314 | 396 |
self.set_header('If-Unmodified-Since', if_unmodified_since) |
315 | 397 |
|
316 |
path=path4url(self.account, self.container, object)
|
|
398 |
path = path4url(self.account, self.container, object)
|
|
317 | 399 |
success = kwargs.pop('success', 200) |
318 | 400 |
return self.get(path, *args, success=success, **kwargs) |
319 | 401 |
|
320 |
def object_put(self, object, format='json', hashmap=False, delimiter = None, if_etag_match=None, |
|
321 |
if_etag_not_match = None, etag=None, content_length = None, content_type=None, |
|
322 |
transfer_encoding=None, copy_from=None, move_from=None, source_account=None, |
|
323 |
source_version=None, content_encoding = None, content_disposition=None, manifest = None, |
|
324 |
permitions =None, public = None, metadata=None, *args, **kwargs): |
|
402 |
def object_put(self, object, |
|
403 |
format='json', |
|
404 |
hashmap=False, |
|
405 |
delimiter=None, |
|
406 |
if_etag_match=None, |
|
407 |
if_etag_not_match=None, |
|
408 |
etag=None, |
|
409 |
content_length=None, |
|
410 |
content_type=None, |
|
411 |
transfer_encoding=None, |
|
412 |
copy_from=None, |
|
413 |
move_from=None, |
|
414 |
source_account=None, |
|
415 |
source_version=None, |
|
416 |
content_encoding=None, |
|
417 |
content_disposition=None, |
|
418 |
manifest=None, |
|
419 |
permissions=None, |
|
420 |
public=None, |
|
421 |
metadata=None, |
|
422 |
*args, |
|
423 |
**kwargs): |
|
325 | 424 |
""" Full Pithos+ PUT at object level |
326 | 425 |
--- request parameters --- |
327 | 426 |
@param format (string): json (default) or xml |
... | ... | |
331 | 430 |
with etag matching with this |
332 | 431 |
@param if_etag_not_match (string): if provided, return only results |
333 | 432 |
with etag not matching with this |
334 |
@param etag (string): The MD5 hash of the object (optional to check written data) |
|
433 |
@param etag (string): The MD5 hash of the object (optional to check |
|
434 |
written data) |
|
335 | 435 |
@param content_length (integer): The size of the data written |
336 | 436 |
@param content_type (string): The MIME content type of the object |
337 |
@param transfer_encoding (string): Set to chunked to specify incremental uploading (if used, Content-Length is ignored) |
|
338 |
@param copy_from (string): The source path in the form /<container>/<object> |
|
339 |
@param move_from (string): The source path in the form /<container>/<object> |
|
437 |
@param transfer_encoding (string): Set to chunked to specify |
|
438 |
incremental uploading (if used, Content-Length is ignored) |
|
439 |
@param copy_from (string): The source path in the form |
|
440 |
/<container>/<object> |
|
441 |
@param move_from (string): The source path in the form |
|
442 |
/<container>/<object> |
|
340 | 443 |
@param source_account (string): The source account to copy/move from |
341 | 444 |
@param source_version (string): The source version to copy from |
342 | 445 |
@param conent_encoding (string): The encoding of the object |
343 |
@param content_disposition (string): The presentation style of the object |
|
344 |
@param manifest (string): Object parts prefix in /<container>/<object> form |
|
345 |
@param permitions (dict): Object permissions in the form (all fields are optional) |
|
346 |
{'read':[user1, group1, user2, ...], 'write':['user3, group2, group3, ...]} |
|
347 |
@param public (bool): If true, Object is publicly accessible, if false, not |
|
446 |
@param content_disposition (string): Presentation style of the object |
|
447 |
@param manifest (string): Object parts prefix in |
|
448 |
/<container>/<object> form |
|
449 |
@param permissions (dict): Object permissions in the form (all fields |
|
450 |
are optional) |
|
451 |
{ 'read':[user1, group1, user2, ...], |
|
452 |
'write':['user3, group2, group3, ...] |
|
453 |
} |
|
454 |
@param public (bool): If true, Object is publicly accessible, |
|
455 |
if false, not |
|
348 | 456 |
@param metadata (dict): Optional user defined metadata in the form |
349 | 457 |
{'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...} |
350 | 458 |
""" |
... | ... | |
368 | 476 |
self.set_header('Content-Disposition', content_disposition) |
369 | 477 |
self.set_header('X-Object-Manifest', manifest) |
370 | 478 |
perms = None |
371 |
if permitions is not None:
|
|
372 |
for permition_type, permition_list in permitions.items():
|
|
479 |
if permissions:
|
|
480 |
for permission_type, permission_list in permissions.items():
|
|
373 | 481 |
if perms is None: |
374 |
perms = '' #Remove permitions
|
|
375 |
if len(permition_list) == 0:
|
|
482 |
perms = '' # Remove permissions
|
|
483 |
if len(permission_list) == 0:
|
|
376 | 484 |
continue |
377 |
perms += ';'+permition_type if len(perms) > 0 else permition_type |
|
378 |
perms += '='+list2str(permition_list, seperator=',') |
|
485 |
if len(perms): |
|
486 |
perms += ';' |
|
487 |
perms += '%s=%s'\ |
|
488 |
% (permission_type, list2str(permission_list, seperator=',')) |
|
379 | 489 |
self.set_header('X-Object-Sharing', perms) |
380 | 490 |
self.set_header('X-Object-Public', public) |
381 | 491 |
if metadata is not None: |
382 | 492 |
for key, val in metadata.items(): |
383 |
self.set_header('X-Object-Meta-'+key, val)
|
|
493 |
self.set_header('X-Object-Meta-' + key, val)
|
|
384 | 494 |
|
385 |
path=path4url(self.account, self.container, object)
|
|
495 |
path = path4url(self.account, self.container, object)
|
|
386 | 496 |
success = kwargs.pop('success', 201) |
387 | 497 |
return self.put(path, *args, success=success, **kwargs) |
388 | 498 |
|
389 |
def object_copy(self, object, destination, format='json', ignore_content_type=False, |
|
390 |
if_etag_match=None, if_etag_not_match=None, destination_account=None, |
|
391 |
content_type=None, content_encoding=None, content_disposition=None, source_version=None, |
|
392 |
permitions=None, public=False, metadata=None, *args, **kwargs): |
|
499 |
def object_copy(self, object, destination, |
|
500 |
format='json', |
|
501 |
ignore_content_type=False, |
|
502 |
if_etag_match=None, |
|
503 |
if_etag_not_match=None, |
|
504 |
destination_account=None, |
|
505 |
content_type=None, |
|
506 |
content_encoding=None, |
|
507 |
content_disposition=None, |
|
508 |
source_version=None, |
|
509 |
permissions=None, |
|
510 |
public=False, |
|
511 |
metadata=None, |
|
512 |
*args, |
|
513 |
**kwargs): |
|
393 | 514 |
""" Full Pithos+ COPY at object level |
394 | 515 |
--- request parameters --- |
395 | 516 |
@param format (string): json (default) or xml |
... | ... | |
399 | 520 |
with etag matching with this |
400 | 521 |
@param if_etag_not_match (string): if provided, copy only results |
401 | 522 |
with etag not matching with this |
402 |
@param destination (string): The destination path in the form /<container>/<object> |
|
523 |
@param destination (string): The destination path in the form |
|
524 |
/<container>/<object> |
|
403 | 525 |
@param destination_account (string): The destination account to copy to |
404 | 526 |
@param content_type (string): The MIME content type of the object |
405 | 527 |
@param content_encoding (string): The encoding of the object |
406 |
@param content_disposition (string): The presentation style of the object
|
|
528 |
@param content_disposition (string): Object resentation style
|
|
407 | 529 |
@param source_version (string): The source version to copy from |
408 |
@param permitions (dict): Object permissions in the form (all fields are optional) |
|
409 |
{'read':[user1, group1, user2, ...], 'write':['user3, group2, group3, ...]} |
|
410 |
permitions override source permitions, removing any old permitions |
|
411 |
@param public (bool): If true, Object is publicly accessible, if else, not |
|
530 |
@param permissions (dict): Object permissions in the form |
|
531 |
(all fields are optional) |
|
532 |
{ 'read':[user1, group1, user2, ...], |
|
533 |
'write':['user3, group2, group3, ...] |
|
534 |
} |
|
535 |
permissions override source permissions, |
|
536 |
removing any old permissions |
|
537 |
@param public (bool): If true, Object is publicly accessible |
|
412 | 538 |
@param metadata (dict): Optional user defined metadata in the form |
413 |
{'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...}
|
|
414 |
Metadata are appended to the source metadata. In case of same keys, they
|
|
415 |
replace the old metadata
|
|
539 |
{'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...} |
|
540 |
Metadata are appended to the source metadata. In case of same
|
|
541 |
keys, they replace the old metadata
|
|
416 | 542 |
""" |
417 | 543 |
self.assert_container() |
418 | 544 |
|
... | ... | |
428 | 554 |
self.set_header('Content-Disposition', content_disposition) |
429 | 555 |
self.set_header('X-Source-Version', source_version) |
430 | 556 |
perms = None |
431 |
if permitions is not None:
|
|
432 |
for permition_type, permition_list in permitions.items():
|
|
557 |
if permissions:
|
|
558 |
for permission_type, permission_list in permissions.items():
|
|
433 | 559 |
if perms is None: |
434 |
perms = '' #Remove permitions
|
|
435 |
if len(permition_list) == 0:
|
|
560 |
perms = '' # Remove permissions
|
|
561 |
if len(permission_list) == 0:
|
|
436 | 562 |
continue |
437 |
perms += ';'+permition_type if len(perms) > 0 else permition_type |
|
438 |
perms += '='+list2str(permition_list, seperator=',') |
|
563 |
if len(perms): |
|
564 |
perms += ';' |
|
565 |
perms += '%s=%s'\ |
|
566 |
% (permission_type, list2str(permission_list, seperator=',')) |
|
439 | 567 |
self.set_header('X-Object-Sharing', perms) |
440 | 568 |
self.set_header('X-Object-Public', public) |
441 | 569 |
if metadata is not None: |
442 | 570 |
for key, val in metadata.items(): |
443 |
self.set_header('X-Object-Meta-'+key, val)
|
|
571 |
self.set_header('X-Object-Meta-' + key, val)
|
|
444 | 572 |
|
445 | 573 |
path = path4url(self.account, self.container, object) |
446 | 574 |
success = kwargs.pop('success', 201) |
447 | 575 |
return self.copy(path, *args, success=success, **kwargs) |
448 | 576 |
|
449 |
def object_move(self, object, format='json', ignore_content_type=False, |
|
450 |
if_etag_match=None, if_etag_not_match=None, destination=None, destination_account=None, |
|
451 |
content_type=None, content_encoding=None, content_disposition=None, permitions={}, |
|
452 |
public=False, metadata={}, *args, **kwargs): |
|
577 |
def object_move(self, object, |
|
578 |
format='json', |
|
579 |
ignore_content_type=False, |
|
580 |
if_etag_match=None, |
|
581 |
if_etag_not_match=None, |
|
582 |
destination=None, |
|
583 |
destination_account=None, |
|
584 |
content_type=None, |
|
585 |
content_encoding=None, |
|
586 |
content_disposition=None, |
|
587 |
permissions={}, |
|
588 |
public=False, |
|
589 |
metadata={}, |
|
590 |
*args, |
|
591 |
**kwargs): |
|
453 | 592 |
""" Full Pithos+ COPY at object level |
454 | 593 |
--- request parameters --- |
455 | 594 |
@param format (string): json (default) or xml |
... | ... | |
459 | 598 |
with etag matching with this |
460 | 599 |
@param if_etag_not_match (string): if provided, return only results |
461 | 600 |
with etag not matching with this |
462 |
@param destination (string): The destination path in the form /<container>/<object> |
|
601 |
@param destination (string): The destination path in the form |
|
602 |
/<container>/<object> |
|
463 | 603 |
@param destination_account (string): The destination account to copy to |
464 | 604 |
@param content_type (string): The MIME content type of the object |
465 | 605 |
@param content_encoding (string): The encoding of the object |
466 |
@param content_disposition (string): The presentation style of the object
|
|
606 |
@param content_disposition (string): Object presentation style
|
|
467 | 607 |
@param source_version (string): The source version to copy from |
468 |
@param permitions (dict): Object permissions in the form (all fields are optional) |
|
469 |
{'read':[user1, group1, user2, ...], 'write':['user3, group2, group3, ...]} |
|
470 |
@param public (bool): If true, Object is publicly accessible, if false, not |
|
608 |
@param permissions (dict): Object permissions in the form |
|
609 |
(all fields are optional) |
|
610 |
{ 'read':[user1, group1, user2, ...], |
|
611 |
'write':['user3, group2, group3, ...] |
|
612 |
} |
|
613 |
@param public (bool): If true, Object is publicly accessible |
|
471 | 614 |
@param metadata (dict): Optional user defined metadata in the form |
472 | 615 |
{'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...} |
473 | 616 |
""" |
... | ... | |
484 | 627 |
self.set_header('Content-Encoding', content_encoding) |
485 | 628 |
self.set_header('Content-Disposition', content_disposition) |
486 | 629 |
perms = None |
487 |
for permition_type, permition_list in permitions.items():
|
|
630 |
for permission_type, permission_list in permissions.items():
|
|
488 | 631 |
if perms is None: |
489 |
perms = '' #Remove permitions
|
|
490 |
if len(permition_list) == 0:
|
|
632 |
perms = '' # Remove permissions
|
|
633 |
if len(permission_list) == 0:
|
|
491 | 634 |
continue |
492 |
perms += ';'+permition_type if len(perms) > 0 else permition_type |
|
493 |
perms += '='+list2str(permition_list, seperator=',') |
|
635 |
if len(perms): |
|
636 |
perms += ';' |
|
637 |
perms += '%s=%s'\ |
|
638 |
% (permission_type, list2str(permission_list, seperator=',')) |
|
494 | 639 |
self.set_header('X-Object-Sharing', perms) |
495 | 640 |
self.set_header('X-Object-Public', public) |
496 | 641 |
for key, val in metadata.items(): |
497 |
self.set_header('X-Object-Meta-'+key, val)
|
|
642 |
self.set_header('X-Object-Meta-' + key, val)
|
|
498 | 643 |
|
499 | 644 |
path = path4url(self.account, self.container, object) |
500 | 645 |
success = kwargs.pop('success', 201) |
501 | 646 |
return self.move(path, *args, success=success, **kwargs) |
502 | 647 |
|
503 |
def object_post(self, object, format='json', update=True, |
|
504 |
if_etag_match=None, if_etag_not_match=None, content_length=None, content_type=None, |
|
505 |
content_range=None, transfer_encoding=None, content_encoding=None, content_disposition=None, |
|
506 |
source_object=None, source_account=None, source_version=None, object_bytes=None, |
|
507 |
manifest=None, permitions={}, public=False, metadata={}, *args, **kwargs): |
|
648 |
def object_post(self, object, |
|
649 |
format='json', |
|
650 |
update=True, |
|
651 |
if_etag_match=None, |
|
652 |
if_etag_not_match=None, |
|
653 |
content_length=None, |
|
654 |
content_type=None, |
|
655 |
content_range=None, |
|
656 |
transfer_encoding=None, |
|
657 |
content_encoding=None, |
|
658 |
content_disposition=None, |
|
659 |
source_object=None, |
|
660 |
source_account=None, |
|
661 |
source_version=None, |
|
662 |
object_bytes=None, |
|
663 |
manifest=None, |
|
664 |
permissions={}, |
|
665 |
public=False, |
|
666 |
metadata={}, |
|
667 |
*args, |
|
668 |
**kwargs): |
|
508 | 669 |
""" Full Pithos+ POST at object level |
509 | 670 |
--- request parameters --- |
510 | 671 |
@param format (string): json (default) or xml |
... | ... | |
517 | 678 |
@param content_length (string): The size of the data written |
518 | 679 |
@param content_type (string): The MIME content type of the object |
519 | 680 |
@param content_range (string): The range of data supplied |
520 |
@param transfer_encoding (string): Set to chunked to specify incremental uploading
|
|
521 |
(if used, Content-Length is ignored)
|
|
681 |
@param transfer_encoding (string): Set to chunked to specify |
|
682 |
incremental uploading (if used, Content-Length is ignored)
|
|
522 | 683 |
@param content_encoding (string): The encoding of the object |
523 |
@param content_disposition (string): The presentation style of the object |
|
524 |
@param source_object (string): Update with data from the object at path /<container>/<object> |
|
684 |
@param content_disposition (string): Object presentation style |
|
685 |
@param source_object (string): Update with data from the object at |
|
686 |
path /<container>/<object> |
|
525 | 687 |
@param source_account (string): The source account to update from |
526 | 688 |
@param source_version (string): The source version to copy from |
527 | 689 |
@param object_bytes (integer): The updated objects final size |
528 |
@param manifest (string): Object parts prefix in /<container>/<object> form |
|
529 |
@param permitions (dict): Object permissions in the form (all fields are optional) |
|
530 |
{'read':[user1, group1, user2, ...], 'write':['user3, group2, group3, ...]} |
|
531 |
@param public (bool): If true, Object is publicly accessible, if false, not |
|
690 |
@param manifest (string): Object parts prefix as /<container>/<object> |
|
691 |
@param permissions (dict): Object permissions in the form (all fields |
|
692 |
are optional) |
|
693 |
{ 'read':[user1, group1, user2, ...], |
|
694 |
'write':['user3, group2, group3, ...] |
|
695 |
} |
|
696 |
@param public (bool): If true, Object is publicly accessible |
|
532 | 697 |
@param metadata (dict): Optional user defined metadata in the form |
533 | 698 |
{'meta-key-1':'meta-value-1', 'meta-key-2':'meta-value-2', ...} |
534 | 699 |
""" |
535 | 700 |
self.assert_container() |
536 | 701 |
|
537 | 702 |
self.set_param('format', format, iff=format is not None) |
538 |
self.set_param('update', iff = update)
|
|
703 |
self.set_param('update', iff=update)
|
|
539 | 704 |
|
540 | 705 |
self.set_header('If-Match', if_etag_match) |
541 | 706 |
self.set_header('If-None-Match', if_etag_not_match) |
542 |
self.set_header('Content-Length', content_length, iff=transfer_encoding is None) |
|
707 |
self.set_header('Content-Length', |
|
708 |
content_length, |
|
709 |
iff=transfer_encoding is None) |
|
543 | 710 |
self.set_header('Content-Type', content_type) |
544 | 711 |
self.set_header('Content-Range', content_range) |
545 | 712 |
self.set_header('Transfer-Encoding', transfer_encoding) |
... | ... | |
551 | 718 |
self.set_header('X-Object-Bytes', object_bytes) |
552 | 719 |
self.set_header('X-Object-Manifest', manifest) |
553 | 720 |
perms = None |
554 |
for permition_type, permition_list in permitions.items():
|
|
721 |
for permission_type, permission_list in permissions.items():
|
|
555 | 722 |
if perms is None: |
556 |
perms = '' #Remove permitions
|
|
557 |
if len(permition_list) == 0:
|
|
723 |
perms = '' # Remove permissions
|
|
724 |
if len(permission_list) == 0:
|
|
558 | 725 |
continue |
559 |
perms += ';'+permition_type if len(perms) > 0 else permition_type |
|
560 |
perms += '='+list2str(permition_list, seperator=',') |
|
726 |
if len(perms): |
|
727 |
perms += ';' |
|
728 |
perms += '%s=%s'\ |
|
729 |
% (permission_type, list2str(permission_list, seperator=',')) |
|
561 | 730 |
self.set_header('X-Object-Sharing', perms) |
562 | 731 |
self.set_header('X-Object-Public', public) |
563 | 732 |
for key, val in metadata.items(): |
564 |
self.set_header('X-Object-Meta-'+key, val)
|
|
733 |
self.set_header('X-Object-Meta-' + key, val)
|
|
565 | 734 |
|
566 | 735 |
path = path4url(self.account, self.container, object) |
567 |
success=kwargs.pop('success', (202, 204))
|
|
736 |
success = kwargs.pop('success', (202, 204))
|
|
568 | 737 |
return self.post(path, *args, success=success, **kwargs) |
569 |
|
|
570 |
def object_delete(self, object, until=None, delimiter=None, *args, **kwargs): |
|
738 |
|
|
739 |
def object_delete(self, object, |
|
740 |
until=None, |
|
741 |
delimiter=None, |
|
742 |
*args, |
|
743 |
**kwargs): |
|
571 | 744 |
""" Full Pithos+ DELETE at object level |
572 |
--- request parameters ---
|
|
745 |
--- request parameters --- |
|
573 | 746 |
@param until (string): Optional timestamp |
574 | 747 |
""" |
575 | 748 |
self.assert_container() |
... | ... | |
579 | 752 |
|
580 | 753 |
path = path4url(self.account, self.container, object) |
581 | 754 |
success = kwargs.pop('success', 204) |
582 |
return self.delete(path, *args, success=success, **kwargs) |
|
755 |
return self.delete(path, *args, success=success, **kwargs) |
Also available in: Unified diff