Revision ae75584f pithos/lib/client.py
b/pithos/lib/client.py | ||
---|---|---|
38 | 38 |
import json |
39 | 39 |
import types |
40 | 40 |
import socket |
41 |
import urllib |
|
41 | 42 |
import pithos.api.faults |
42 | 43 |
|
43 | 44 |
ERROR_CODES = {304:'Not Modified', |
... | ... | |
71 | 72 |
self.token = token |
72 | 73 |
|
73 | 74 |
def _req(self, method, path, body=None, headers={}, format='text', |
74 |
params={}): |
|
75 |
full_path = '/%s/%s%s?format=%s' % (self.api, self.account, path, |
|
76 |
format) |
|
75 |
params={}, top_level_req=False): |
|
76 |
path = urllib.quote(path) |
|
77 |
account = '' if top_level_req else self.account |
|
78 |
full_path = '/%s/%s%s?format=%s' % (self.api, account, path, format) |
|
79 |
|
|
77 | 80 |
for k,v in params.items(): |
78 | 81 |
if v: |
79 | 82 |
full_path = '%s&%s=%s' %(full_path, k, v) |
... | ... | |
97 | 100 |
kwargs['headers'].setdefault('content-type', |
98 | 101 |
'application/octet-stream') |
99 | 102 |
kwargs['headers'].setdefault('content-length', len(body) if body else 0) |
100 |
try: |
|
101 |
#print '*', method, full_path, kwargs |
|
102 |
conn.request(method, full_path, **kwargs) |
|
103 |
except socket.error, e: |
|
104 |
raise Fault(status=503) |
|
103 |
kwargs['headers'] = _encode_headers(kwargs['headers']) |
|
104 |
#print '#', method, full_path, kwargs |
|
105 |
conn.request(method, full_path, **kwargs) |
|
106 |
|
|
107 |
#try: |
|
108 |
# conn.request(method, full_path, **kwargs) |
|
109 |
#except socket.error, e: |
|
110 |
# print '###', e[0], conn.auto_open |
|
111 |
# raise Fault(status=503) |
|
105 | 112 |
|
106 | 113 |
resp = conn.getresponse() |
107 | 114 |
headers = dict(resp.getheaders()) |
... | ... | |
128 | 135 |
def delete(self, path, format='text', params={}): |
129 | 136 |
return self._req('DELETE', path, format=format, params=params) |
130 | 137 |
|
131 |
def get(self, path, format='text', headers=None, params={}): |
|
138 |
def get(self, path, format='text', headers={}, params={}, |
|
139 |
top_level_req=False): |
|
132 | 140 |
return self._req('GET', path, headers=headers, format=format, |
133 |
params=params) |
|
141 |
params=params, top_level_req=top_level_req)
|
|
134 | 142 |
|
135 | 143 |
def head(self, path, format='text', params={}): |
136 |
return self._req('HEAD', path, format=format, params=params) |
|
144 |
return self._req('HEAD', path, format=format, params=params)
|
|
137 | 145 |
|
138 | 146 |
def post(self, path, body=None, format='text', headers=None, params={}): |
139 | 147 |
return self._req('POST', path, body, headers=headers, format=format, |
... | ... | |
142 | 150 |
def put(self, path, body=None, format='text', headers=None): |
143 | 151 |
return self._req('PUT', path, body, headers=headers, format=format) |
144 | 152 |
|
145 |
def _list(self, path, format='text', params={}, **headers): |
|
153 |
def _list(self, path, format='text', params={}, top_level_req=False, |
|
154 |
**headers): |
|
146 | 155 |
status, headers, data = self.get(path, format=format, headers=headers, |
147 |
params=params) |
|
156 |
params=params, |
|
157 |
top_level_req=top_level_req) |
|
148 | 158 |
if format == 'json': |
149 | 159 |
data = json.loads(data) if data else '' |
150 | 160 |
elif format == 'xml': |
... | ... | |
216 | 226 |
|
217 | 227 |
# Storage Account Services |
218 | 228 |
|
219 |
def list_containers(self, format='text', limit=10000, marker=None, params={},
|
|
229 |
def list_containers(self, format='text', limit=None, marker=None, params={},
|
|
220 | 230 |
**headers): |
221 | 231 |
"""lists containers""" |
222 |
if not params: |
|
223 |
params = {} |
|
224 | 232 |
params.update({'limit':limit, 'marker':marker}) |
225 | 233 |
return self._list('', format, params, **headers) |
226 | 234 |
|
... | ... | |
246 | 254 |
def _filter_trashed(self, l): |
247 | 255 |
return self._filter(l, {'trash':'true'}) |
248 | 256 |
|
249 |
def list_objects(self, container, format='text', limit=10000, marker=None,
|
|
257 |
def list_objects(self, container, format='text', limit=None, marker=None,
|
|
250 | 258 |
prefix=None, delimiter=None, path=None, |
251 | 259 |
include_trashed=False, params={}, **headers): |
252 | 260 |
"""returns a list with the container objects""" |
... | ... | |
369 | 377 |
path = '/%s/%s' % (dst_container, dst_object) |
370 | 378 |
headers = {} if not headers else headers |
371 | 379 |
for k, v in meta.items(): |
372 |
headers['x-object-meta-%s' % k] = v
|
|
380 |
headers['x-object-meta-%s' % k] = v |
|
373 | 381 |
if remove: |
374 | 382 |
headers['x-move-from'] = '/%s/%s' % (src_container, src_object) |
375 | 383 |
else: |
... | ... | |
440 | 448 |
block = f.read(blocksize) |
441 | 449 |
if block == '': |
442 | 450 |
break |
443 |
data = '%s\r\n%s\r\n' % (hex(len(block)), block)
|
|
451 |
data = '%x\r\n%s\r\n' % (len(block), block)
|
|
444 | 452 |
try: |
445 | 453 |
http.send(data) |
446 | 454 |
except: |
447 | 455 |
#retry |
448 | 456 |
http.send(data) |
449 |
data = '0x0\r\n'
|
|
457 |
data = '0\r\n\r\n'
|
|
450 | 458 |
try: |
451 | 459 |
http.send(data) |
452 | 460 |
except: |
... | ... | |
505 | 513 |
if_unmodified_since=None, limit=1000, marker=None, |
506 | 514 |
until=None): |
507 | 515 |
"""returns a list with the account containers""" |
508 |
params = {'until':until} if until else None
|
|
516 |
params = {'until':until} if until else {}
|
|
509 | 517 |
headers = {'if-modified-since':if_modified_since, |
510 | 518 |
'if-unmodified-since':if_unmodified_since} |
511 | 519 |
return OOS_Client.list_containers(self, format=format, limit=limit, |
... | ... | |
521 | 529 |
def set_account_groups(self, **groups): |
522 | 530 |
"""create account groups""" |
523 | 531 |
headers = {} |
524 |
for key, val in groups.items():
|
|
525 |
headers['x-account-group-%s' % key] = val
|
|
532 |
for k, v in groups.items():
|
|
533 |
headers['x-account-group-%s' % k] = v
|
|
526 | 534 |
params = {'update':None} |
527 | 535 |
return self.post('', headers=headers, params=params) |
528 | 536 |
|
... | ... | |
551 | 559 |
def reset_account_groups(self, **groups): |
552 | 560 |
"""overrides account groups""" |
553 | 561 |
headers = {} |
554 |
for key, val in groups.items(): |
|
555 |
headers['x-account-group-%s' % key] = val |
|
562 |
for k, v in groups.items(): |
|
563 |
v = v.strip() |
|
564 |
headers['x-account-group-%s' % k] = v |
|
556 | 565 |
meta = self.retrieve_account_metadata() |
557 | 566 |
headers.update(meta) |
558 | 567 |
return self.post('', headers=headers) |
559 | 568 |
|
560 | 569 |
# Storage Container Services |
561 | 570 |
|
562 |
def list_objects(self, container, format='text', limit=10000, marker=None,
|
|
571 |
def list_objects(self, container, format='text', limit=None, marker=None,
|
|
563 | 572 |
prefix=None, delimiter=None, path=None, |
564 | 573 |
include_trashed=False, params={}, if_modified_since=None, |
565 | 574 |
if_unmodified_since=None, meta={}, until=None): |
... | ... | |
672 | 681 |
headers.update({elem:eval(elem)}) |
673 | 682 |
|
674 | 683 |
for k,v in meta.items(): |
675 |
headers['x-object-meta-%s' %k.strip()] = v.strip() |
|
684 |
v = v.strip() |
|
685 |
headers['x-object-meta-%s' %k.strip()] = v |
|
676 | 686 |
|
677 | 687 |
return self._chunked_transfer(path, 'PUT', f, headers=headers, |
678 | 688 |
blocksize=blocksize) |
... | ... | |
738 | 748 |
headers['content_range'] = 'bytes */*' |
739 | 749 |
|
740 | 750 |
for k,v in meta.items(): |
741 |
headers['x-object-meta-%s' %k.strip()] = v.strip() |
|
751 |
v = v.strip() |
|
752 |
headers['x-object-meta-%s' %k.strip()] = v |
|
742 | 753 |
|
743 | 754 |
return self._chunked_transfer(path, 'POST', f, headers=headers, |
744 | 755 |
blocksize=blocksize) |
... | ... | |
777 | 788 |
path = '/%s/%s' % (dst_container, dst_object) |
778 | 789 |
headers = {} if not headers else headers |
779 | 790 |
for k, v in meta.items(): |
780 |
headers['x-object-meta-%s' % k] = v
|
|
791 |
headers['x-object-meta-%s' % k] = v |
|
781 | 792 |
if remove: |
782 | 793 |
headers['x-move-from'] = '/%s/%s' % (src_container, src_object) |
783 | 794 |
else: |
... | ... | |
805 | 816 |
headers['x_object_version'] = version |
806 | 817 |
return OOS_Client.move_object(self, src_container, src_object, |
807 | 818 |
dst_container, dst_object, meta=meta, |
808 |
**headers) |
|
819 |
**headers) |
|
820 |
|
|
821 |
def list_shared_by_others(self, limit=None, marker=None, format='text'): |
|
822 |
l = ['limit', 'marker'] |
|
823 |
params = {} |
|
824 |
for elem in [elem for elem in l if eval(elem)]: |
|
825 |
params[elem] = eval(elem) |
|
826 |
return self._list('', format, params, top_level_req=True) |
|
827 |
|
|
828 |
def share_object(self, container, object, l, read=True): |
|
829 |
action = 'read' if read else 'write' |
|
830 |
sharing = '%s=%s' % (action, ','.join(l)) |
|
831 |
self.update_object(container, object, f=None, x_object_sharing=sharing) |
|
832 |
|
|
833 |
def _encode_headers(headers): |
|
834 |
h = {} |
|
835 |
for k, v in headers.items(): |
|
836 |
k = urllib.quote(k) |
|
837 |
if v and type(v) == types.StringType: |
|
838 |
v = urllib.quote(v, '/=,-* :"') |
|
839 |
h[k] = v |
|
840 |
return h |
Also available in: Unified diff