Revision e3fd7f91 pithos/lib/client.py
b/pithos/lib/client.py | ||
---|---|---|
4 | 4 |
import json |
5 | 5 |
import types |
6 | 6 |
import socket |
7 |
import pithos.api.faults |
|
8 |
|
|
9 |
ERROR_CODES = {304:'Not Modified', |
|
10 |
400:'Bad Request', |
|
11 |
401:'Unauthorized', |
|
12 |
404:'Not Found', |
|
13 |
409:'Conflict', |
|
14 |
411:'Length Required', |
|
15 |
412:'Precondition Failed', |
|
16 |
416:'Range Not Satisfiable', |
|
17 |
422:'Unprocessable Entity', |
|
18 |
503:'Service Unavailable'} |
|
7 | 19 |
|
8 | 20 |
class Fault(Exception): |
9 |
def __init__(self, data=''): |
|
21 |
def __init__(self, data='', status=None): |
|
22 |
if data == '' and status in ERROR_CODES.keys(): |
|
23 |
data = ERROR_CODES[status] |
|
10 | 24 |
Exception.__init__(self, data) |
11 | 25 |
self.data = data |
12 |
|
|
26 |
self.status = status |
|
13 | 27 |
|
14 | 28 |
class Client(object): |
15 | 29 |
def __init__(self, host, account, api='v1', verbose=False, debug=False): |
... | ... | |
20 | 34 |
self.api = api |
21 | 35 |
self.verbose = verbose or debug |
22 | 36 |
self.debug = debug |
23 |
|
|
37 |
|
|
24 | 38 |
def _chunked_transfer(self, path, method='PUT', f=stdin, headers=None, |
25 | 39 |
blocksize=1024): |
26 | 40 |
http = HTTPConnection(self.host) |
... | ... | |
58 | 72 |
|
59 | 73 |
# get response |
60 | 74 |
resp = http.getresponse() |
75 |
|
|
61 | 76 |
headers = dict(resp.getheaders()) |
62 | 77 |
|
63 | 78 |
if self.verbose: |
... | ... | |
71 | 86 |
print data |
72 | 87 |
|
73 | 88 |
|
89 |
if data: |
|
90 |
assert data[-1] == '\n' |
|
91 |
#remove trailing enter |
|
92 |
data = data and data[:-1] or data |
|
93 |
|
|
94 |
if int(resp.status) in ERROR_CODES.keys(): |
|
95 |
raise Fault(data, int(resp.status)) |
|
96 |
|
|
74 | 97 |
return resp.status, headers, data |
75 | 98 |
|
76 | 99 |
def req(self, method, path, body=None, headers=None, format='text', |
... | ... | |
96 | 119 |
kwargs['body'] = body |
97 | 120 |
kwargs['headers']['Content-Type'] = 'application/octet-stream' |
98 | 121 |
#print '****', method, full_path, kwargs |
99 |
#TODO catch socket.error |
|
100 |
conn.request(method, full_path, **kwargs) |
|
122 |
try: |
|
123 |
conn.request(method, full_path, **kwargs) |
|
124 |
except socket.error, e: |
|
125 |
raise Fault(status=503) |
|
126 |
|
|
101 | 127 |
resp = conn.getresponse() |
102 | 128 |
headers = dict(resp.getheaders()) |
103 | 129 |
|
... | ... | |
117 | 143 |
#remove trailing enter |
118 | 144 |
data = data and data[:-1] or data |
119 | 145 |
|
146 |
if int(resp.status) in ERROR_CODES.keys(): |
|
147 |
raise Fault(data, int(resp.status)) |
|
148 |
|
|
149 |
#print '*', resp.status, headers, data |
|
120 | 150 |
return resp.status, headers, data |
121 | 151 |
|
122 | 152 |
def delete(self, path, format='text'): |
... | ... | |
147 | 177 |
|
148 | 178 |
def _get_metadata(self, path, prefix=None, params=None): |
149 | 179 |
status, headers, data = self.head(path, params=params) |
150 |
if status == '404': |
|
151 |
return None |
|
152 | 180 |
prefixlen = prefix and len(prefix) or 0 |
153 | 181 |
meta = {} |
154 | 182 |
for key, val in headers.items(): |
... | ... | |
189 | 217 |
if status == 202: |
190 | 218 |
return False |
191 | 219 |
elif status != 201: |
192 |
raise Fault(data) |
|
220 |
raise Fault(data, int(status))
|
|
193 | 221 |
return True |
194 | 222 |
|
195 | 223 |
def delete_container(self, container): |
... | ... | |
222 | 250 |
path = '/%s/%s' % (container, object) |
223 | 251 |
if not chunked and f != stdin: |
224 | 252 |
data = f and f.read() or None |
225 |
self.put(path, data, headers=headers) |
|
253 |
return self.put(path, data, headers=headers)
|
|
226 | 254 |
else: |
227 |
self._chunked_transfer(path, 'PUT', f, headers=headers, |
|
255 |
return self._chunked_transfer(path, 'PUT', f, headers=headers,
|
|
228 | 256 |
blocksize=1024) |
229 | 257 |
|
230 | 258 |
def update_object(self, container, object, f=stdin, chunked=False, |
Also available in: Unified diff