Merge ~barryprice/spade/+git/spade:black into spade:master

Proposed by Barry Price
Status: Needs review
Proposed branch: ~barryprice/spade/+git/spade:black
Merge into: spade:master
Prerequisite: ~barryprice/spade/+git/spade:flake8
Diff against target: 905 lines (+201/-191)
10 files modified
Makefile (+2/-1)
spade/AzureBucket.py (+61/-63)
spade/BucketObject.py (+2/-3)
spade/GCEBucket.py (+14/-33)
spade/LocalBucket.py (+15/-3)
spade/ObjectIO.py (+5/-8)
spade/S3Bucket.py (+61/-43)
spade/Spade.py (+14/-8)
spade/StdioBucket.py (+1/-1)
spade/SwiftBucket.py (+26/-28)
Reviewer Review Type Date Requested Status
Haw Loeung +1 Approve
Review via email: mp+394573@code.launchpad.net

This proposal supersedes a proposal from 2020-11-27.

Commit message

Reformatted with black

To post a comment you must log in.
Revision history for this message
Haw Loeung (hloeung) wrote :

LGTM

review: Approve (+1)

Unmerged commits

1734965... by Barry Price

Merge branch 'flake8' into black

6817bc5... by Barry Price

Merge branch 'master' into flake8

c85283a... by Barry Price

Typo

a86afa5... by Barry Price

Reformatted with black

aa2d273... by Barry Price

Address all Flake8 errors bar complexity (noqa: C901)

7e34f18... by Barry Price

Modernise, switch to python3 exclusively

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/Makefile b/Makefile
2index 03544a4..ceb744e 100644
3--- a/Makefile
4+++ b/Makefile
5@@ -2,7 +2,8 @@ version := $(shell python3 -c "from spade import __version__; print(__version__)
6 tempfiles_snap := snap/snapcraft.yaml spade*.snap
7
8 blacken:
9- @echo "Normalising python layout with black (but not really)."
10+ @echo "Normalising python layout with black"
11+ @tox -e black
12
13 lint: blacken
14 @echo "Running flake8"
15diff --git a/spade/AzureBucket.py b/spade/AzureBucket.py
16index 0f7a62d..e04830a 100644
17--- a/spade/AzureBucket.py
18+++ b/spade/AzureBucket.py
19@@ -26,15 +26,14 @@ from spade.ObjectIO import ObjectIO
20
21 DEFAULT_BLOCKSIZE = 1024 * 1024 * 10
22 DEFAULT_DELIMITER = "/"
23-AZURE_SEGMENTSIZE = 1024 * 1024 * 4 # Azure block (segment) limit = 4MB
24+AZURE_SEGMENTSIZE = 1024 * 1024 * 4 # Azure block (segment) limit = 4MB
25 MAX_AZURE_OBJECTSIZE = 64 * 1024 * 1024 # Azure block blob limit = 64MB
26 USER_META_PREFIX = "x-ms-meta-"
27
28
29-class AzureBucket():
30+class AzureBucket:
31 def __init__(self, creds):
32- wanted = ["private_key",
33- "storage_account"]
34+ wanted = ["private_key", "storage_account"]
35 for k in wanted:
36 if k not in creds:
37 # Missing creds
38@@ -67,9 +66,19 @@ class AzureBucket():
39 def _create_azure_auth_signature(self, bucket, headers, query, method):
40 # Note: auth_headers are in a specific order
41 # see https://msdn.microsoft.com/en-gb/library/azure/dd179428.aspx
42- auth_headers = ("Content-Encoding", "Content-Language", "Content-Length", "Content-MD5",
43- "Content-Type", "Date", "If-Modified-Since", "If-Match", "If-None-Match",
44- "If-Unmodified-Since", "Range")
45+ auth_headers = (
46+ "Content-Encoding",
47+ "Content-Language",
48+ "Content-Length",
49+ "Content-MD5",
50+ "Content-Type",
51+ "Date",
52+ "If-Modified-Since",
53+ "If-Match",
54+ "If-None-Match",
55+ "If-Unmodified-Since",
56+ "Range",
57+ )
58 canonicalized_headers = self._dict_to_str(headers, strip_final=False, startswith="x-ms-")
59 query_string = self._dict_to_str(query)
60
61@@ -84,9 +93,11 @@ class AzureBucket():
62 signature += canonicalized_headers
63 signature += canonicalized_resource
64
65- encoded_sig = base64.b64encode(hmac.new(base64.b64decode(self.primaryKey),
66- msg=signature.encode("utf-8"),
67- digestmod=hashlib.sha256).digest())
68+ encoded_sig = base64.b64encode(
69+ hmac.new(
70+ base64.b64decode(self.primaryKey), msg=signature.encode("utf-8"), digestmod=hashlib.sha256
71+ ).digest()
72+ )
73 return encoded_sig.decode('utf-8')
74
75 # Requests documented here: https://msdn.microsoft.com/en-GB/library/azure/dd135733.aspx
76@@ -104,10 +115,9 @@ class AzureBucket():
77 headers["Authorization"] = "SharedKey {}:{}".format(self.storageAccount, auth)
78
79 query_string = self._dict_to_str(query, kv_sep="=", entry_sep="&")
80- response, content = h.request(uri=self.blobUri + bucket + "?" + query_string,
81- method=method,
82- body=body,
83- headers=headers)
84+ response, content = h.request(
85+ uri=self.blobUri + bucket + "?" + query_string, method=method, body=body, headers=headers
86+ )
87 return response, content
88
89 def listBuckets(self):
90@@ -153,9 +163,7 @@ class AzureBucket():
91
92 def getBucketMetadata(self, bucketName):
93 # Standard metadata
94- response, content = self._send_azure_request(bucketName,
95- query={"restype": "container"},
96- method="HEAD")
97+ response, content = self._send_azure_request(bucketName, query={"restype": "container"}, method="HEAD")
98 if response.get("status") == "200":
99 co = BucketObject(bucketName)
100 co.size = int(response.get("content-length", 0))
101@@ -169,9 +177,7 @@ class AzureBucket():
102
103 # User-defined metadata
104 query = {"restype": "container", "comp": "metadata"}
105- response, content = self._send_azure_request(bucketName,
106- query=query,
107- method="HEAD")
108+ response, content = self._send_azure_request(bucketName, query=query, method="HEAD")
109 if response.get("status") == "200":
110 for k, v in response.items():
111 if k.lower().startswith(USER_META_PREFIX):
112@@ -187,8 +193,7 @@ class AzureBucket():
113
114 def getObjectMetadata(self, bucketName, objectName):
115 # Standard metadata
116- response, content = self._send_azure_request(bucketName + "/" + objectName,
117- method="HEAD")
118+ response, content = self._send_azure_request(bucketName + "/" + objectName, method="HEAD")
119 if response.get("status") == "200":
120 co = BucketObject(objectName)
121 co.size = int(response.get("content-length", 0))
122@@ -201,9 +206,9 @@ class AzureBucket():
123 raise BucketError("Azure Failed to find object metadata")
124
125 # User-defined metadata
126- response, content = self._send_azure_request(bucketName + "/" + objectName,
127- query={"comp": "metadata"},
128- method="HEAD")
129+ response, content = self._send_azure_request(
130+ bucketName + "/" + objectName, query={"comp": "metadata"}, method="HEAD"
131+ )
132 if response.get("status") == "200":
133 for k, v in response.items():
134 if k.lower().startswith(USER_META_PREFIX):
135@@ -225,9 +230,13 @@ class AzureBucket():
136 return metadata.rawMetadata.get("etag", "")
137
138 def setObjectMetadata(self, bucketName, objectName, metadata, overwrite=False):
139- systemMetadata = ["x-ms-blob-cache-control", "x-ms-blob-content-type",
140- "x-ms-blob-content-md5", "x-ms-blob-content-encoding",
141- "x-ms-blob-content-language"]
142+ systemMetadata = [
143+ "x-ms-blob-cache-control",
144+ "x-ms-blob-content-type",
145+ "x-ms-blob-content-md5",
146+ "x-ms-blob-content-encoding",
147+ "x-ms-blob-content-language",
148+ ]
149
150 newStandardMetadata = {}
151 newUserMetadata = {}
152@@ -252,18 +261,16 @@ class AzureBucket():
153 newUserMetadata[USER_META_PREFIX + k] = v
154
155 # Standard metadata
156- response, content = self._send_azure_request(bucketName + "/" + objectName,
157- query={"comp": "properties"},
158- headers=newStandardMetadata,
159- method="PUT")
160+ response, content = self._send_azure_request(
161+ bucketName + "/" + objectName, query={"comp": "properties"}, headers=newStandardMetadata, method="PUT"
162+ )
163 if response.get("status") != "200":
164 raise BucketError("Azure Failed to set standard object metadata")
165
166 # User metadata
167- response, content = self._send_azure_request(bucketName + "/" + objectName,
168- query={"comp": "metadata"},
169- headers=newUserMetadata,
170- method="PUT")
171+ response, content = self._send_azure_request(
172+ bucketName + "/" + objectName, query={"comp": "metadata"}, headers=newUserMetadata, method="PUT"
173+ )
174 if response.get("status") != "200":
175 raise BucketError("Azure Failed to set user object metadata")
176 return
177@@ -272,8 +279,7 @@ class AzureBucket():
178 headers = {}
179 if rangeStart is not None and rangeEnd is not None:
180 headers["Range"] = "bytes={}-{}".format(rangeStart, rangeEnd)
181- response, content = self._send_azure_request(bucketName + "/" + objectName,
182- headers=headers)
183+ response, content = self._send_azure_request(bucketName + "/" + objectName, headers=headers)
184 if response.get("status") == "200" or response.get("status") == "206":
185 return content
186 elif response.get("status") == "416":
187@@ -293,11 +299,13 @@ class AzureBucket():
188 blockId = base64.b64encode("{:06}".format(blockNumber).encode('utf-8')).decode('utf-8')
189 headers = {}
190 headers["Content-Length"] = str(len(blockContent))
191- response, content = self._send_azure_request(bucketName + "/" + objectName,
192- query={"comp": "block", "blockid": blockId},
193- headers=headers,
194- body=blockContent,
195- method="PUT")
196+ response, content = self._send_azure_request(
197+ bucketName + "/" + objectName,
198+ query={"comp": "block", "blockid": blockId},
199+ headers=headers,
200+ body=blockContent,
201+ method="PUT",
202+ )
203 if not response.get("status") == "201":
204 raise BucketError("Azure Failed to upload multi-part block")
205 blockList.append(blockId)
206@@ -312,11 +320,9 @@ class AzureBucket():
207 xml += "</BlockList>\n"
208 headers = {}
209 headers["Content-Length"] = str(len(xml))
210- response, content = self._send_azure_request(bucketName + "/" + objectName,
211- query={"comp": "blocklist"},
212- headers=headers,
213- body=xml,
214- method="PUT")
215+ response, content = self._send_azure_request(
216+ bucketName + "/" + objectName, query={"comp": "blocklist"}, headers=headers, body=xml, method="PUT"
217+ )
218 if not response.get("status") == "201":
219 raise BucketError("Azure Failed to upload blocklist")
220 return
221@@ -329,10 +335,9 @@ class AzureBucket():
222 headers["Content-Length"] = str(size)
223 headers["Content-Type"] = "application/octet-stream"
224 headers["x-ms-blob-type"] = "BlockBlob"
225- response, content = self._send_azure_request(bucketName + "/" + objectName,
226- headers=headers,
227- body=src,
228- method="PUT")
229+ response, content = self._send_azure_request(
230+ bucketName + "/" + objectName, headers=headers, body=src, method="PUT"
231+ )
232 if response.get("status") == "201":
233 return
234 else:
235@@ -342,8 +347,7 @@ class AzureBucket():
236 return ObjectIO(self, bucketName, objectName, blockSize)
237
238 def deleteObject(self, bucketName, objectName):
239- response, content = self._send_azure_request(bucketName + "/" + objectName,
240- method="DELETE")
241+ response, content = self._send_azure_request(bucketName + "/" + objectName, method="DELETE")
242 if response.get("status") == "202":
243 return
244 else:
245@@ -351,9 +355,7 @@ class AzureBucket():
246
247 def createBucket(self, bucketName):
248 query = {"restype": "container"}
249- response, content = self._send_azure_request(bucketName,
250- query=query,
251- method="PUT")
252+ response, content = self._send_azure_request(bucketName, query=query, method="PUT")
253 if response.get("status") == "201":
254 return
255 else:
256@@ -362,9 +364,7 @@ class AzureBucket():
257 # Note: Azure doesn't care if the container is empty or not
258 def deleteBucket(self, bucketName):
259 query = {"restype": "container"}
260- response, content = self._send_azure_request(bucketName,
261- query=query,
262- method="DELETE")
263+ response, content = self._send_azure_request(bucketName, query=query, method="DELETE")
264 if response.get("status") == "202":
265 return
266 else:
267@@ -378,9 +378,7 @@ class AzureBucket():
268 return []
269
270 query = {"restype": "container", "comp": "acl"}
271- response, content = self._send_azure_request(bucketName,
272- query=query,
273- method="HEAD")
274+ response, content = self._send_azure_request(bucketName, query=query, method="HEAD")
275 if response.get("status") != "200":
276 raise BucketError("Azure Failed to read ACL data")
277
278diff --git a/spade/BucketObject.py b/spade/BucketObject.py
279index 9f8a258..7d35d24 100644
280--- a/spade/BucketObject.py
281+++ b/spade/BucketObject.py
282@@ -1,5 +1,4 @@
283-class BucketObject():
284-
285+class BucketObject:
286 class ObjectType:
287 File = 0
288 Directory = 1
289@@ -18,7 +17,7 @@ class BucketError(Exception):
290 pass
291
292
293-class BucketAcl():
294+class BucketAcl:
295 def __init__(self):
296 self.acls = {}
297
298diff --git a/spade/GCEBucket.py b/spade/GCEBucket.py
299index 2029886..56761f1 100644
300--- a/spade/GCEBucket.py
301+++ b/spade/GCEBucket.py
302@@ -23,6 +23,7 @@ import datetime
303 import base64
304 from apiclient import discovery, errors
305 from apiclient.http import MediaIoBaseUpload
306+
307 try:
308 from oauth2client.service_account import ServiceAccountCredentials
309 except ImportError:
310@@ -34,11 +35,9 @@ DEFAULT_BLOCKSIZE = 1024 * 1024 * 10
311 DEFAULT_DELIMITER = "/"
312
313
314-class GCEBucket():
315+class GCEBucket:
316 def __init__(self, creds):
317- wanted = ["client_email",
318- "private_key",
319- "project"]
320+ wanted = ["client_email", "private_key", "project"]
321 for k in wanted:
322 if k not in creds:
323 # Missing creds
324@@ -47,12 +46,9 @@ class GCEBucket():
325 # httplib2.debuglevel = 4
326 cloud_storage_auth_scope = 'https://www.googleapis.com/auth/devstorage.full_control'
327 try:
328- c = ServiceAccountCredentials.from_json_keyfile_dict(creds,
329- scopes=cloud_storage_auth_scope)
330+ c = ServiceAccountCredentials.from_json_keyfile_dict(creds, scopes=cloud_storage_auth_scope)
331 except NameError:
332- c = SignedJwtAssertionCredentials(creds['client_email'],
333- creds['private_key'],
334- cloud_storage_auth_scope)
335+ c = SignedJwtAssertionCredentials(creds['client_email'], creds['private_key'], cloud_storage_auth_scope)
336 http = c.authorize(httplib2.Http())
337 self.gce = discovery.build('storage', 'v1', http=http)
338 self.project = creds["project"]
339@@ -79,10 +75,7 @@ class GCEBucket():
340 def listBucketContents(self, bucketName, path=None, delimiter=DEFAULT_DELIMITER):
341 contents = []
342 fields_to_return = 'nextPageToken,prefixes,items'
343- req = self.gce.objects().list(bucket=bucketName,
344- prefix=path,
345- delimiter=delimiter,
346- fields=fields_to_return)
347+ req = self.gce.objects().list(bucket=bucketName, prefix=path, delimiter=delimiter, fields=fields_to_return)
348 while req:
349 try:
350 resp = req.execute()
351@@ -106,8 +99,7 @@ class GCEBucket():
352 return contents
353
354 def getBucketMetadata(self, bucketName):
355- req = self.gce.buckets().get(bucket=bucketName,
356- projection="full")
357+ req = self.gce.buckets().get(bucket=bucketName, projection="full")
358 try:
359 resp = req.execute()
360 except errors.HttpError:
361@@ -126,9 +118,7 @@ class GCEBucket():
362 raise BucketError("GCE Setting bucket metadata is not supported in GCE")
363
364 def getObjectMetadata(self, bucketName, objectName):
365- req = self.gce.objects().get(bucket=bucketName,
366- object=objectName,
367- projection="full")
368+ req = self.gce.objects().get(bucket=bucketName, object=objectName, projection="full")
369 try:
370 resp = req.execute()
371 except errors.HttpError:
372@@ -157,8 +147,7 @@ class GCEBucket():
373 return hexChecksum
374
375 def setObjectMetadata(self, bucketName, objectName, metadata, overwrite=False):
376- systemMetadata = ["cacheControl", "contentDisposition", "contentEncoding",
377- "contentLanguage", "contentType"]
378+ systemMetadata = ["cacheControl", "contentDisposition", "contentEncoding", "contentLanguage", "contentType"]
379 newMetadata = {}
380 m = self.getObjectMetadata(bucketName, objectName)
381 # Keep existing acls, system metadata and (optionally) user metadata
382@@ -177,9 +166,7 @@ class GCEBucket():
383 newMetadata[k] = v
384 else:
385 newMetadata["metadata"][k] = v
386- req = self.gce.objects().update(bucket=bucketName,
387- object=objectName,
388- body=newMetadata)
389+ req = self.gce.objects().update(bucket=bucketName, object=objectName, body=newMetadata)
390 try:
391 req.execute()
392 except errors.HttpError:
393@@ -190,22 +177,18 @@ class GCEBucket():
394 headers = {}
395 if rangeStart is not None and rangeEnd is not None:
396 headers['range'] = "bytes={}-{}".format(rangeStart, rangeEnd)
397- req = self.gce.objects().get_media(bucket=bucketName,
398- object=objectName)
399+ req = self.gce.objects().get_media(bucket=bucketName, object=objectName)
400 http = req.http
401 resp, data = http.request(req.uri, headers=headers)
402 if resp.get("status") == "416":
403 # Requested range not satisfiable
404 data = ""
405 elif resp.get("status")[0] != "2":
406- raise(BucketError("GCE Failed to find object"))
407+ raise (BucketError("GCE Failed to find object"))
408 return data
409
410 def putObject(self, bucketName, objectName, src, size, blockSize=DEFAULT_BLOCKSIZE):
411- media = MediaIoBaseUpload(src,
412- mimetype="application/octet-stream",
413- chunksize=blockSize,
414- resumable=True)
415+ media = MediaIoBaseUpload(src, mimetype="application/octet-stream", chunksize=blockSize, resumable=True)
416 req = self.gce.objects().insert(bucket=bucketName, name=objectName, media_body=media)
417 resp = None
418 while resp is None:
419@@ -243,9 +226,7 @@ class GCEBucket():
420 return
421
422 aclTypes = ["list", "read", "write"]
423- aclTypeMap = {"read": "READER",
424- "write": "WRITER",
425- "list": "READER"}
426+ aclTypeMap = {"read": "READER", "write": "WRITER", "list": "READER"}
427
428 def translateAcl(self, aclData, aliases):
429 """
430diff --git a/spade/LocalBucket.py b/spade/LocalBucket.py
431index f2293ec..9f3f974 100644
432--- a/spade/LocalBucket.py
433+++ b/spade/LocalBucket.py
434@@ -10,7 +10,7 @@ DEFAULT_BLOCKSIZE = 1024 * 1024 * 10
435 DEFAULT_DELIMITER = "/"
436
437
438-class LocalBucket():
439+class LocalBucket:
440 def __init__(self, creds):
441 wanted = ["bucket_root"]
442 for k in wanted:
443@@ -79,8 +79,20 @@ class LocalBucket():
444 co.date = self.standardTimestamp(stat.st_mtime)
445 co.contentType = "text/plain"
446 raw = {}
447- for num, name in enumerate(["st_mode", "st_ino", "st_dev", "st_nlink", "st_uid",
448- "st_gid", "st_size", "st_atime", "st_mtime", "st_ctime"]):
449+ for num, name in enumerate(
450+ [
451+ "st_mode",
452+ "st_ino",
453+ "st_dev",
454+ "st_nlink",
455+ "st_uid",
456+ "st_gid",
457+ "st_size",
458+ "st_atime",
459+ "st_mtime",
460+ "st_ctime",
461+ ]
462+ ):
463 raw[name] = stat[num]
464 co.rawMetadata = raw
465 return co
466diff --git a/spade/ObjectIO.py b/spade/ObjectIO.py
467index fc2b38f..dfdb804 100644
468--- a/spade/ObjectIO.py
469+++ b/spade/ObjectIO.py
470@@ -2,7 +2,7 @@ import os
471 from spade.BucketObject import BucketError
472
473
474-class ObjectIO():
475+class ObjectIO:
476 def __init__(self, parent, bucketName, objectName, blockSize=-1):
477 self.parent = parent
478 self.bucketName = bucketName
479@@ -36,10 +36,7 @@ class ObjectIO():
480 if self.closed:
481 raise ValueError
482
483- data = self.parent.getObject(self.bucketName,
484- self.objectName,
485- self.pos,
486- min(self.pos + n - 1, self.len))
487+ data = self.parent.getObject(self.bucketName, self.objectName, self.pos, min(self.pos + n - 1, self.len))
488 self.pos = self.pos + len(data)
489 return data
490
491@@ -56,19 +53,19 @@ class ObjectIO():
492 while self.readlinePos < len(self.readlineBuffer):
493 lineEndPos = self.readlineBuffer.find(b"\n", self.readlinePos)
494 if lineEndPos >= 0:
495- line = self.readlineBuffer[self.readlinePos:lineEndPos + 1].decode('utf-8')
496+ line = self.readlineBuffer[self.readlinePos : lineEndPos + 1].decode('utf-8')
497 self.readlinePos = lineEndPos + 1
498 return line
499 else:
500 newData = self.read(self.blockSize)
501 if not newData:
502 return
503- self.readlineBuffer = self.readlineBuffer[self.readlinePos:] + newData
504+ self.readlineBuffer = self.readlineBuffer[self.readlinePos :] + newData
505 self.readlinePos = 0
506
507 # In case the last line has no newline
508 if self.readlinePos < len(self.readlineBuffer):
509- return self.readlineBuffer[self.readlinePos:]
510+ return self.readlineBuffer[self.readlinePos :]
511
512 def readlines(self):
513 while True:
514diff --git a/spade/S3Bucket.py b/spade/S3Bucket.py
515index 6d3036e..67f38fb 100644
516--- a/spade/S3Bucket.py
517+++ b/spade/S3Bucket.py
518@@ -25,15 +25,13 @@ from spade.ObjectIO import ObjectIO
519 DEFAULT_BLOCKSIZE = 1024 * 1024 * 10
520 DEFAULT_DELIMITER = "/"
521 MAX_S3_OBJECTSIZE = 5 * 1024 * 1024 * 1024 # S3 object PUT limit = 5GB
522-S3_SEGMENTSIZE = 1024 * 1024 * 1024 # Use 1GB segments for large object uploads
523+S3_SEGMENTSIZE = 1024 * 1024 * 1024 # Use 1GB segments for large object uploads
524 USER_META_PREFIX = "x-amz-meta-"
525
526
527-class S3Bucket():
528+class S3Bucket:
529 def __init__(self, creds):
530- wanted = ["aws_access_key_id",
531- "aws_secret_access_key",
532- "aws_region"]
533+ wanted = ["aws_access_key_id", "aws_secret_access_key", "aws_region"]
534 for k in wanted:
535 if k not in creds:
536 # Missing creds
537@@ -44,8 +42,9 @@ class S3Bucket():
538
539 def oldLibraryFixes(self):
540 try:
541- self.regions = [{"name": region.name, "endpoint": region.endpoint}
542- for region in boto.regioninfo.get_regions("s3")]
543+ self.regions = [
544+ {"name": region.name, "endpoint": region.endpoint} for region in boto.regioninfo.get_regions("s3")
545+ ]
546 except AttributeError:
547 # Old boto library doesn't have this, so we'll use the ones we know about
548 self.regions = [
549@@ -63,9 +62,22 @@ class S3Bucket():
550 {'name': 'us-east-1', 'endpoint': 's3.amazonaws.com'},
551 ]
552
553- self.base_fields = set(['content-length', 'content-language', 'content-disposition',
554- 'content-encoding', 'expires', 'content-md5', 'last-modified',
555- 'etag', 'cache-control', 'date', 'content-type', 'x-robots-tag'])
556+ self.base_fields = set(
557+ [
558+ 'content-length',
559+ 'content-language',
560+ 'content-disposition',
561+ 'content-encoding',
562+ 'expires',
563+ 'content-md5',
564+ 'last-modified',
565+ 'etag',
566+ 'cache-control',
567+ 'date',
568+ 'content-type',
569+ 'x-robots-tag',
570+ ]
571+ )
572
573 def _connect(self):
574 self.endpoint = None
575@@ -78,11 +90,13 @@ class S3Bucket():
576 if not self.endpoint:
577 raise NotImplementedError
578
579- self.s3 = boto.s3.connection.S3Connection(self.creds['aws_access_key_id'],
580- self.creds['aws_secret_access_key'],
581- is_secure=True,
582- host=self.endpoint,
583- calling_format=OrdinaryCallingFormat())
584+ self.s3 = boto.s3.connection.S3Connection(
585+ self.creds['aws_access_key_id'],
586+ self.creds['aws_secret_access_key'],
587+ is_secure=True,
588+ host=self.endpoint,
589+ calling_format=OrdinaryCallingFormat(),
590+ )
591
592 # Boto/S3 gives a 301 redirect response if we try to access a bucket
593 # in another region, so make sure we're in the right one
594@@ -94,7 +108,7 @@ class S3Bucket():
595
596 # Strip off the first section (the current region)
597 try:
598- websiteEndpoint = websiteEndpoint[websiteEndpoint.find(".") + 1:]
599+ websiteEndpoint = websiteEndpoint[websiteEndpoint.find(".") + 1 :]
600 except UnboundLocalError:
601 raise BucketError("S3 Failed to find bucket")
602
603@@ -176,10 +190,12 @@ class S3Bucket():
604 return metadata.rawMetadata.get("etag", "").strip('"')
605
606 def setObjectMetadata(self, bucketName, objectName, metadata, overwrite=False):
607- systemMetadata = ["x-amz-server-side-encryption",
608- "x-amz-storage-class",
609- "x-amz-website-redirect-location",
610- "x-amz-server-side-encryption-aws-kms-key-id"]
611+ systemMetadata = [
612+ "x-amz-server-side-encryption",
613+ "x-amz-storage-class",
614+ "x-amz-website-redirect-location",
615+ "x-amz-server-side-encryption-aws-kms-key-id",
616+ ]
617 self.confirmRegion(bucketName)
618
619 # Metadata to remove (if any)
620@@ -300,19 +316,17 @@ class S3Bucket():
621 return
622
623 aclTypes = ["list", "read", "write", "readacl", "writeacl"]
624- aclTypeMap = {"read": "READ",
625- "write": "WRITE",
626- "list": "READ",
627- "readacl": "READ_ACP",
628- "writeacl": "WRITE_ACP"}
629+ aclTypeMap = {"read": "READ", "write": "WRITE", "list": "READ", "readacl": "READ_ACP", "writeacl": "WRITE_ACP"}
630
631 def createAclData(self, user, type):
632- aclData = {"s3_display_name": None,
633- "s3_id": user,
634- "s3_uri": None,
635- "s3_email_address": None,
636- "s3_type": "CanonicalUser",
637- "s3_permission": self.aclTypeMap[type]}
638+ aclData = {
639+ "s3_display_name": None,
640+ "s3_id": user,
641+ "s3_uri": None,
642+ "s3_email_address": None,
643+ "s3_type": "CanonicalUser",
644+ "s3_permission": self.aclTypeMap[type],
645+ }
646 return aclData
647
648 def translateAcl(self, aclData, aliases):
649@@ -343,12 +357,14 @@ class S3Bucket():
650
651 acls = BucketAcl()
652 for grant in acl.acl.grants:
653- aclData = {"s3_display_name": grant.display_name,
654- "s3_id": grant.id,
655- "s3_uri": grant.uri,
656- "s3_email_address": grant.email_address,
657- "s3_type": grant.type,
658- "s3_permission": grant.permission}
659+ aclData = {
660+ "s3_display_name": grant.display_name,
661+ "s3_id": grant.id,
662+ "s3_uri": grant.uri,
663+ "s3_email_address": grant.email_address,
664+ "s3_type": grant.type,
665+ "s3_permission": grant.permission,
666+ }
667 if grant.permission in ["READ", "FULL_CONTROL"]:
668 if objectName:
669 acls.add("read", aclData)
670@@ -392,12 +408,14 @@ class S3Bucket():
671 uniqueAcls.append(user)
672
673 for user in uniqueAcls:
674- grant = boto.s3.acl.Grant(permission=user["s3_permission"],
675- type=user["s3_type"],
676- id=user["s3_id"],
677- display_name=user["s3_display_name"],
678- uri=user["s3_uri"],
679- email_address=["s3_email_address"])
680+ grant = boto.s3.acl.Grant(
681+ permission=user["s3_permission"],
682+ type=user["s3_type"],
683+ id=user["s3_id"],
684+ display_name=user["s3_display_name"],
685+ uri=user["s3_uri"],
686+ email_address=["s3_email_address"],
687+ )
688 s3acl.acl.add_grant(grant)
689
690 try:
691diff --git a/spade/Spade.py b/spade/Spade.py
692index b8f4b12..5ebdfc0 100644
693--- a/spade/Spade.py
694+++ b/spade/Spade.py
695@@ -6,21 +6,25 @@ import re
696 import json
697 import fnmatch
698 from spade.BucketObject import BucketObject, BucketError
699+
700 try:
701 from urllib.parse import urlparse
702 except ImportError:
703 from urlparse import urlparse
704
705 import gzip
706+
707 compressionMethods = ["gzip"]
708 if sys.version_info.major >= 3 and sys.version_info.minor >= 3:
709 import bz2
710+
711 compressionMethods.append("bzip2")
712 import lzma
713+
714 compressionMethods.append("xz")
715 else:
716 # Define a fake lzma.LZMAError
717- class lzma():
718+ class lzma:
719 class LZMAError(Exception):
720 pass
721
722@@ -29,7 +33,7 @@ DEFAULT_BLOCKSIZE = 1024 * 1024 * 10
723 DEFAULT_DELIMITER = "/"
724
725
726-class Result():
727+class Result:
728 def __init__(self):
729 self.output = []
730 self.error = None
731@@ -38,7 +42,7 @@ class Result():
732 return "<Result object. output: '{}' error: '{}'>".format(self.output, self.error)
733
734
735-class Bucket():
736+class Bucket:
737 def __init__(self, configFile):
738 self.configFile = configFile
739 self.config = json.loads(open(configFile, 'r').read())
740@@ -102,21 +106,27 @@ class Bucket():
741
742 if bucketType == "swift":
743 from spade.SwiftBucket import SwiftBucket
744+
745 return SwiftBucket(self.creds[scheme])
746 elif bucketType == "s3":
747 from spade.S3Bucket import S3Bucket
748+
749 return S3Bucket(self.creds[scheme])
750 elif bucketType == "gce":
751 from spade.GCEBucket import GCEBucket
752+
753 return GCEBucket(self.creds[scheme])
754 elif bucketType == "azure":
755 from spade.AzureBucket import AzureBucket
756+
757 return AzureBucket(self.creds[scheme])
758 elif bucketType == "local":
759 from spade.LocalBucket import LocalBucket
760+
761 return LocalBucket(self.creds[scheme])
762 elif bucketType == "stdio":
763 from spade.StdioBucket import StdioBucket
764+
765 return StdioBucket(self.creds[scheme])
766 else:
767 raise NotImplementedError
768@@ -449,11 +459,7 @@ class Bucket():
769 ret.error = e
770 yield ret
771 try:
772- dstBucket.putObject(dstUrl.netloc,
773- dstObjName,
774- fSrc,
775- objMetadata.size,
776- blockSize=args.blockSize)
777+ dstBucket.putObject(dstUrl.netloc, dstObjName, fSrc, objMetadata.size, blockSize=args.blockSize)
778 except BucketError as e:
779 ret.error = e
780 fSrc.close()
781diff --git a/spade/StdioBucket.py b/spade/StdioBucket.py
782index ef6cb43..31ba1f6 100644
783--- a/spade/StdioBucket.py
784+++ b/spade/StdioBucket.py
785@@ -8,7 +8,7 @@ from spade.ObjectIO import ObjectIO
786 DEFAULT_BLOCKSIZE = 1024 * 1024 * 10
787
788
789-class StdioBucket():
790+class StdioBucket:
791 def __init__(self, creds):
792 return
793
794diff --git a/spade/SwiftBucket.py b/spade/SwiftBucket.py
795index 2125b85..0c3adb0 100644
796--- a/spade/SwiftBucket.py
797+++ b/spade/SwiftBucket.py
798@@ -23,19 +23,15 @@ from spade.ObjectIO import ObjectIO
799
800 DEFAULT_BLOCKSIZE = 1024 * 1024 * 10
801 DEFAULT_DELIMITER = "/"
802-MAX_SWIFT_OBJECTSIZE = 5 * 1024 * 1024 * 1024 # Swift object limit = 5GB
803-SWIFT_SEGMENTSIZE = 1024 * 1024 * 1024 # Use 1GB segments for large object uploads
804+MAX_SWIFT_OBJECTSIZE = 5 * 1024 * 1024 * 1024 # Swift object limit = 5GB
805+SWIFT_SEGMENTSIZE = 1024 * 1024 * 1024 # Use 1GB segments for large object uploads
806 USER_META_PREFIX = "x-object-meta-"
807 ACL_META_PREFIX = "x-container-"
808
809
810-class SwiftBucket():
811+class SwiftBucket:
812 def __init__(self, creds):
813- wanted = ["os_username",
814- "os_password",
815- "os_tenant_name",
816- "os_auth_url",
817- "os_region_name"]
818+ wanted = ["os_username", "os_password", "os_tenant_name", "os_auth_url", "os_region_name"]
819 for k in wanted:
820 if k not in creds:
821 # Missing creds
822@@ -51,7 +47,8 @@ class SwiftBucket():
823 key=creds["os_password"],
824 retries=5,
825 auth_version="2.0",
826- os_options=options)
827+ os_options=options,
828+ )
829
830 def standardTimestamp(self, timestamp):
831 try:
832@@ -109,8 +106,7 @@ class SwiftBucket():
833 return co
834
835 def setBucketMetadata(self, bucketName, metadata, overwrite=False): # noqa: C901
836- systemMetadata = ["content-type", "x-container-bytes-used",
837- "x-container-object-count:", "x-timestamp"]
838+ systemMetadata = ["content-type", "x-container-bytes-used", "x-container-object-count:", "x-timestamp"]
839 newMetadata = {}
840 # Keep existing system metadata and (optionally) user metadata
841 m = self.getBucketMetadata(bucketName)
842@@ -163,8 +159,14 @@ class SwiftBucket():
843 return metadata.rawMetadata.get("etag", "").strip('"')
844
845 def setObjectMetadata(self, bucketName, objectName, metadata, overwrite=False):
846- systemMetadata = ["content-type", "content-encoding", "content-disposition",
847- "x-delete-at", "x-delete-after", "etag"]
848+ systemMetadata = [
849+ "content-type",
850+ "content-encoding",
851+ "content-disposition",
852+ "x-delete-at",
853+ "x-delete-after",
854+ "etag",
855+ ]
856 newMetadata = {}
857 # Keep existing system metadata and (optionally) user metadata
858 m = self.getObjectMetadata(bucketName, objectName)
859@@ -223,11 +225,13 @@ class SwiftBucket():
860 segmentName = '{}/{}/{}/{}/{:08d}'.format(objectName, mtime, size, SWIFT_SEGMENTSIZE, segmentId)
861 segmentId += 1
862 try:
863- self.swift.put_object(segmentBucketName,
864- segmentName,
865- src,
866- content_length=segmentSize,
867- content_type="application/octet-stream")
868+ self.swift.put_object(
869+ segmentBucketName,
870+ segmentName,
871+ src,
872+ content_length=segmentSize,
873+ content_type="application/octet-stream",
874+ )
875 except swiftclient.ClientException:
876 raise BucketError("Swift Failed to put large object segment")
877 bytesRead += segmentSize
878@@ -239,12 +243,9 @@ class SwiftBucket():
879 'x-object-meta-mtime': mtime,
880 }
881 try:
882- self.swift.put_object(bucketName,
883- objectName,
884- '',
885- content_length=0,
886- content_type="application/octet-stream",
887- headers=headers)
888+ self.swift.put_object(
889+ bucketName, objectName, '', content_length=0, content_type="application/octet-stream", headers=headers
890+ )
891 except swiftclient.ClientException:
892 raise BucketError("Swift Failed to put large object manifest")
893 return
894@@ -254,10 +255,7 @@ class SwiftBucket():
895 return self.putLargeObject(bucketName, objectName, src, size, min(blockSize, SWIFT_SEGMENTSIZE))
896
897 try:
898- self.swift.put_object(bucketName,
899- objectName,
900- src,
901- content_type="application/octet-stream")
902+ self.swift.put_object(bucketName, objectName, src, content_type="application/octet-stream")
903 except swiftclient.exceptions.ClientException:
904 raise BucketError("Swift Failed to put object")
905 return

Subscribers

People subscribed via source and target branches

to all changes: