| OLD | NEW |
| 1 # Copyright 2010 Google Inc. | 1 # Copyright 2010 Google Inc. |
| 2 # | 2 # |
| 3 # Permission is hereby granted, free of charge, to any person obtaining a | 3 # Permission is hereby granted, free of charge, to any person obtaining a |
| 4 # copy of this software and associated documentation files (the | 4 # copy of this software and associated documentation files (the |
| 5 # "Software"), to deal in the Software without restriction, including | 5 # "Software"), to deal in the Software without restriction, including |
| 6 # without limitation the rights to use, copy, modify, merge, publish, dis- | 6 # without limitation the rights to use, copy, modify, merge, publish, dis- |
| 7 # tribute, sublicense, and/or sell copies of the Software, and to permit | 7 # tribute, sublicense, and/or sell copies of the Software, and to permit |
| 8 # persons to whom the Software is furnished to do so, subject to the fol- | 8 # persons to whom the Software is furnished to do so, subject to the fol- |
| 9 # lowing conditions: | 9 # lowing conditions: |
| 10 # | 10 # |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 """ | 22 """ |
| 23 Provides basic mocks of core storage service classes, for unit testing: | 23 Provides basic mocks of core storage service classes, for unit testing: |
| 24 ACL, Key, Bucket, Connection, and StorageUri. We implement a subset of | 24 ACL, Key, Bucket, Connection, and StorageUri. We implement a subset of |
| 25 the interfaces defined in the real boto classes, but don't handle most | 25 the interfaces defined in the real boto classes, but don't handle most |
| 26 of the optional params (which we indicate with the constant "NOT_IMPL"). | 26 of the optional params (which we indicate with the constant "NOT_IMPL"). |
| 27 """ | 27 """ |
| 28 | 28 |
| 29 import copy | 29 import copy |
| 30 import boto | 30 import boto |
| 31 import base64 |
| 32 |
| 33 from boto.utils import compute_md5 |
| 34 from boto.s3.prefix import Prefix |
| 35 |
| 36 try: |
| 37 from hashlib import md5 |
| 38 except ImportError: |
| 39 from md5 import md5 |
| 31 | 40 |
| 32 NOT_IMPL = None | 41 NOT_IMPL = None |
| 33 | 42 |
| 34 | 43 |
| 35 class MockAcl(object): | 44 class MockAcl(object): |
| 36 | 45 |
| 37 def __init__(self, parent=NOT_IMPL): | 46 def __init__(self, parent=NOT_IMPL): |
| 38 pass | 47 pass |
| 39 | 48 |
| 40 def startElement(self, name, attrs, connection): | 49 def startElement(self, name, attrs, connection): |
| 41 pass | 50 pass |
| 42 | 51 |
| 43 def endElement(self, name, value, connection): | 52 def endElement(self, name, value, connection): |
| 44 pass | 53 pass |
| 45 | 54 |
| 46 def to_xml(self): | 55 def to_xml(self): |
| 47 return '<mock_ACL_XML/>' | 56 return '<mock_ACL_XML/>' |
| 48 | 57 |
| 49 | 58 |
| 50 class MockKey(object): | 59 class MockKey(object): |
| 51 | 60 |
| 52 def __init__(self, bucket=None, name=None): | 61 def __init__(self, bucket=None, name=None): |
| 53 self.bucket = bucket | 62 self.bucket = bucket |
| 54 self.name = name | 63 self.name = name |
| 55 self.data = None | 64 self.data = None |
| 65 self.etag = None |
| 56 self.size = None | 66 self.size = None |
| 57 self.content_encoding = None | 67 self.content_encoding = None |
| 58 self.content_type = None | 68 self.content_type = None |
| 59 self.last_modified = 'Wed, 06 Oct 2010 05:11:54 GMT' | 69 self.last_modified = 'Wed, 06 Oct 2010 05:11:54 GMT' |
| 70 self.BufferSize = 8192 |
| 71 |
| 72 def __repr__(self): |
| 73 if self.bucket: |
| 74 return '<MockKey: %s,%s>' % (self.bucket.name, self.name) |
| 75 else: |
| 76 return '<MockKey: %s>' % self.name |
| 60 | 77 |
| 61 def get_contents_as_string(self, headers=NOT_IMPL, | 78 def get_contents_as_string(self, headers=NOT_IMPL, |
| 62 cb=NOT_IMPL, num_cb=NOT_IMPL, | 79 cb=NOT_IMPL, num_cb=NOT_IMPL, |
| 63 torrent=NOT_IMPL, | 80 torrent=NOT_IMPL, |
| 64 version_id=NOT_IMPL): | 81 version_id=NOT_IMPL): |
| 65 return self.data | 82 return self.data |
| 66 | 83 |
| 67 def get_contents_to_file(self, fp, headers=NOT_IMPL, | 84 def get_contents_to_file(self, fp, headers=NOT_IMPL, |
| 68 cb=NOT_IMPL, num_cb=NOT_IMPL, | 85 cb=NOT_IMPL, num_cb=NOT_IMPL, |
| 69 torrent=NOT_IMPL, | 86 torrent=NOT_IMPL, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 86 | 103 |
| 87 def open_read(self, headers=NOT_IMPL, query_args=NOT_IMPL, | 104 def open_read(self, headers=NOT_IMPL, query_args=NOT_IMPL, |
| 88 override_num_retries=NOT_IMPL): | 105 override_num_retries=NOT_IMPL): |
| 89 pass | 106 pass |
| 90 | 107 |
| 91 def set_contents_from_file(self, fp, headers=None, replace=NOT_IMPL, | 108 def set_contents_from_file(self, fp, headers=None, replace=NOT_IMPL, |
| 92 cb=NOT_IMPL, num_cb=NOT_IMPL, | 109 cb=NOT_IMPL, num_cb=NOT_IMPL, |
| 93 policy=NOT_IMPL, md5=NOT_IMPL, | 110 policy=NOT_IMPL, md5=NOT_IMPL, |
| 94 res_upload_handler=NOT_IMPL): | 111 res_upload_handler=NOT_IMPL): |
| 95 self.data = fp.read() | 112 self.data = fp.read() |
| 113 self.set_etag() |
| 96 self.size = len(self.data) | 114 self.size = len(self.data) |
| 97 self._handle_headers(headers) | 115 self._handle_headers(headers) |
| 98 | 116 |
| 99 def set_contents_from_string(self, s, headers=NOT_IMPL, replace=NOT_IMPL, | 117 def set_contents_from_string(self, s, headers=NOT_IMPL, replace=NOT_IMPL, |
| 100 cb=NOT_IMPL, num_cb=NOT_IMPL, policy=NOT_IMPL, | 118 cb=NOT_IMPL, num_cb=NOT_IMPL, policy=NOT_IMPL, |
| 101 md5=NOT_IMPL, reduced_redundancy=NOT_IMPL): | 119 md5=NOT_IMPL, reduced_redundancy=NOT_IMPL): |
| 102 self.data = copy.copy(s) | 120 self.data = copy.copy(s) |
| 121 self.set_etag() |
| 103 self.size = len(s) | 122 self.size = len(s) |
| 104 self._handle_headers(headers) | 123 self._handle_headers(headers) |
| 105 | 124 |
| 106 def set_contents_from_filename(self, filename, headers=None, replace=NOT_IMP
L, | 125 def set_contents_from_filename(self, filename, headers=None, |
| 107 cb=NOT_IMPL, num_cb=NOT_IMPL, | 126 replace=NOT_IMPL, cb=NOT_IMPL, |
| 108 policy=NOT_IMPL, md5=NOT_IMPL, | 127 num_cb=NOT_IMPL, policy=NOT_IMPL, |
| 109 res_upload_handler=NOT_IMPL): | 128 md5=NOT_IMPL, res_upload_handler=NOT_IMPL): |
| 110 fp = open(filename, 'rb') | 129 fp = open(filename, 'rb') |
| 111 self.set_contents_from_file(fp, headers, replace, cb, num_cb, | 130 self.set_contents_from_file(fp, headers, replace, cb, num_cb, |
| 112 policy, md5, res_upload_handler) | 131 policy, md5, res_upload_handler) |
| 113 fp.close() | 132 fp.close() |
| 114 | 133 |
| 115 def copy(self, dst_bucket_name, dst_key, metadata=NOT_IMPL, | 134 def copy(self, dst_bucket_name, dst_key, metadata=NOT_IMPL, |
| 116 reduced_redundancy=NOT_IMPL, preserve_acl=NOT_IMPL): | 135 reduced_redundancy=NOT_IMPL, preserve_acl=NOT_IMPL): |
| 117 dst_bucket = self.bucket.connection.get_bucket(dst_bucket_name) | 136 dst_bucket = self.bucket.connection.get_bucket(dst_bucket_name) |
| 118 return dst_bucket.copy_key(dst_key, self.bucket.name, | 137 return dst_bucket.copy_key(dst_key, self.bucket.name, |
| 119 self.name, metadata) | 138 self.name, metadata) |
| 120 | 139 |
| 140 def set_etag(self): |
| 141 """ |
| 142 Set etag attribute by generating hex MD5 checksum on current |
| 143 contents of mock key. |
| 144 """ |
| 145 m = md5() |
| 146 m.update(self.data) |
| 147 hex_md5 = m.hexdigest() |
| 148 self.etag = hex_md5 |
| 149 |
| 150 def compute_md5(self, fp): |
| 151 """ |
| 152 :type fp: file |
| 153 :param fp: File pointer to the file to MD5 hash. The file pointer |
| 154 will be reset to the beginning of the file before the |
| 155 method returns. |
| 156 |
| 157 :rtype: tuple |
| 158 :return: A tuple containing the hex digest version of the MD5 hash |
| 159 as the first element and the base64 encoded version of the |
| 160 plain digest as the second element. |
| 161 """ |
| 162 tup = compute_md5(fp) |
| 163 # Returned values are MD5 hash, base64 encoded MD5 hash, and file size. |
| 164 # The internal implementation of compute_md5() needs to return the |
| 165 # file size but we don't want to return that value to the external |
| 166 # caller because it changes the class interface (i.e. it might |
| 167 # break some code) so we consume the third tuple value here and |
| 168 # return the remainder of the tuple to the caller, thereby preserving |
| 169 # the existing interface. |
| 170 self.size = tup[2] |
| 171 return tup[0:2] |
| 121 | 172 |
| 122 class MockBucket(object): | 173 class MockBucket(object): |
| 123 | 174 |
| 124 def __init__(self, connection=None, name=None, key_class=NOT_IMPL): | 175 def __init__(self, connection=None, name=None, key_class=NOT_IMPL): |
| 125 self.name = name | 176 self.name = name |
| 126 self.keys = {} | 177 self.keys = {} |
| 127 self.acls = {name: MockAcl()} | 178 self.acls = {name: MockAcl()} |
| 179 # default object ACLs are one per bucket and not supported for keys |
| 180 self.def_acl = MockAcl() |
| 181 self.subresources = {} |
| 128 self.connection = connection | 182 self.connection = connection |
| 183 self.logging = False |
| 184 |
| 185 def __repr__(self): |
| 186 return 'MockBucket: %s' % self.name |
| 129 | 187 |
| 130 def copy_key(self, new_key_name, src_bucket_name, | 188 def copy_key(self, new_key_name, src_bucket_name, |
| 131 src_key_name, metadata=NOT_IMPL, src_version_id=NOT_IMPL, | 189 src_key_name, metadata=NOT_IMPL, src_version_id=NOT_IMPL, |
| 132 storage_class=NOT_IMPL, preserve_acl=NOT_IMPL): | 190 storage_class=NOT_IMPL, preserve_acl=NOT_IMPL, |
| 191 encrypt_key=NOT_IMPL, headers=NOT_IMPL, query_args=NOT_IMPL): |
| 133 new_key = self.new_key(key_name=new_key_name) | 192 new_key = self.new_key(key_name=new_key_name) |
| 134 src_key = mock_connection.get_bucket( | 193 src_key = mock_connection.get_bucket( |
| 135 src_bucket_name).get_key(src_key_name) | 194 src_bucket_name).get_key(src_key_name) |
| 136 new_key.data = copy.copy(src_key.data) | 195 new_key.data = copy.copy(src_key.data) |
| 137 new_key.size = len(new_key.data) | 196 new_key.size = len(new_key.data) |
| 138 return new_key | 197 return new_key |
| 139 | 198 |
| 199 def disable_logging(self): |
| 200 self.logging = False |
| 201 |
| 202 def enable_logging(self, target_bucket_prefix): |
| 203 self.logging = True |
| 204 |
| 140 def get_acl(self, key_name='', headers=NOT_IMPL, version_id=NOT_IMPL): | 205 def get_acl(self, key_name='', headers=NOT_IMPL, version_id=NOT_IMPL): |
| 141 if key_name: | 206 if key_name: |
| 142 # Return ACL for the key. | 207 # Return ACL for the key. |
| 143 return self.acls[key_name] | 208 return self.acls[key_name] |
| 144 else: | 209 else: |
| 145 # Return ACL for the bucket. | 210 # Return ACL for the bucket. |
| 146 return self.acls[self.name] | 211 return self.acls[self.name] |
| 147 | 212 |
| 213 def get_def_acl(self, key_name=NOT_IMPL, headers=NOT_IMPL, |
| 214 version_id=NOT_IMPL): |
| 215 # Return default ACL for the bucket. |
| 216 return self.def_acl |
| 217 |
| 218 def get_subresource(self, subresource, key_name=NOT_IMPL, headers=NOT_IMPL, |
| 219 version_id=NOT_IMPL): |
| 220 if subresource in self.subresources: |
| 221 return self.subresources[subresource] |
| 222 else: |
| 223 return '<Subresource/>' |
| 224 |
| 148 def new_key(self, key_name=None): | 225 def new_key(self, key_name=None): |
| 149 mock_key = MockKey(self, key_name) | 226 mock_key = MockKey(self, key_name) |
| 150 self.keys[key_name] = mock_key | 227 self.keys[key_name] = mock_key |
| 151 self.acls[key_name] = MockAcl() | 228 self.acls[key_name] = MockAcl() |
| 152 return mock_key | 229 return mock_key |
| 153 | 230 |
| 154 def delete_key(self, key_name, headers=NOT_IMPL, | 231 def delete_key(self, key_name, headers=NOT_IMPL, |
| 155 version_id=NOT_IMPL, mfa_token=NOT_IMPL): | 232 version_id=NOT_IMPL, mfa_token=NOT_IMPL): |
| 156 if key_name not in self.keys: | 233 if key_name not in self.keys: |
| 157 raise boto.exception.StorageResponseError(404, 'Not Found') | 234 raise boto.exception.StorageResponseError(404, 'Not Found') |
| 158 del self.keys[key_name] | 235 del self.keys[key_name] |
| 159 | 236 |
| 160 def get_all_keys(self, headers=NOT_IMPL): | 237 def get_all_keys(self, headers=NOT_IMPL): |
| 161 return self.keys.itervalues() | 238 return self.keys.itervalues() |
| 162 | 239 |
| 163 def get_key(self, key_name, headers=NOT_IMPL, version_id=NOT_IMPL): | 240 def get_key(self, key_name, headers=NOT_IMPL, version_id=NOT_IMPL): |
| 164 # Emulate behavior of boto when get_key called with non-existent key. | 241 # Emulate behavior of boto when get_key called with non-existent key. |
| 165 if key_name not in self.keys: | 242 if key_name not in self.keys: |
| 166 return None | 243 return None |
| 167 return self.keys[key_name] | 244 return self.keys[key_name] |
| 168 | 245 |
| 169 def list(self, prefix='', delimiter=NOT_IMPL, marker=NOT_IMPL, | 246 def list(self, prefix='', delimiter='', marker=NOT_IMPL, |
| 170 headers=NOT_IMPL): | 247 headers=NOT_IMPL): |
| 248 prefix = prefix or '' # Turn None into '' for prefix match. |
| 171 # Return list instead of using a generator so we don't get | 249 # Return list instead of using a generator so we don't get |
| 172 # 'dictionary changed size during iteration' error when performing | 250 # 'dictionary changed size during iteration' error when performing |
| 173 # deletions while iterating (e.g., during test cleanup). | 251 # deletions while iterating (e.g., during test cleanup). |
| 174 result = [] | 252 result = [] |
| 253 key_name_set = set() |
| 175 for k in self.keys.itervalues(): | 254 for k in self.keys.itervalues(): |
| 176 if not prefix: | 255 if k.name.startswith(prefix): |
| 177 result.append(k) | 256 k_name_past_prefix = k.name[len(prefix):] |
| 178 elif k.name.startswith(prefix): | 257 if delimiter: |
| 179 result.append(k) | 258 pos = k_name_past_prefix.find(delimiter) |
| 259 else: |
| 260 pos = -1 |
| 261 if (pos != -1): |
| 262 key_or_prefix = Prefix( |
| 263 bucket=self, name=k.name[:len(prefix)+pos+1]) |
| 264 else: |
| 265 key_or_prefix = MockKey(bucket=self, name=k.name) |
| 266 if key_or_prefix.name not in key_name_set: |
| 267 key_name_set.add(key_or_prefix.name) |
| 268 result.append(key_or_prefix) |
| 180 return result | 269 return result |
| 181 | 270 |
| 182 def set_acl(self, acl_or_str, key_name='', headers=NOT_IMPL, | 271 def set_acl(self, acl_or_str, key_name='', headers=NOT_IMPL, |
| 183 version_id=NOT_IMPL): | 272 version_id=NOT_IMPL): |
| 184 # We only handle setting ACL XML here; if you pass a canned ACL | 273 # We only handle setting ACL XML here; if you pass a canned ACL |
| 185 # the get_acl call will just return that string name. | 274 # the get_acl call will just return that string name. |
| 186 if key_name: | 275 if key_name: |
| 187 # Set ACL for the key. | 276 # Set ACL for the key. |
| 188 self.acls[key_name] = acl_or_str | 277 self.acls[key_name] = MockAcl(acl_or_str) |
| 189 else: | 278 else: |
| 190 # Set ACL for the bucket. | 279 # Set ACL for the bucket. |
| 191 self.acls[self.name] = acl_or_str | 280 self.acls[self.name] = MockAcl(acl_or_str) |
| 281 |
| 282 def set_def_acl(self, acl_or_str, key_name=NOT_IMPL, headers=NOT_IMPL, |
| 283 version_id=NOT_IMPL): |
| 284 # We only handle setting ACL XML here; if you pass a canned ACL |
| 285 # the get_acl call will just return that string name. |
| 286 # Set default ACL for the bucket. |
| 287 self.def_acl = acl_or_str |
| 288 |
| 289 def set_subresource(self, subresource, value, key_name=NOT_IMPL, |
| 290 headers=NOT_IMPL, version_id=NOT_IMPL): |
| 291 self.subresources[subresource] = value |
| 192 | 292 |
| 193 | 293 |
| 194 class MockConnection(object): | 294 class MockConnection(object): |
| 195 | 295 |
| 196 def __init__(self, aws_access_key_id=NOT_IMPL, | 296 def __init__(self, aws_access_key_id=NOT_IMPL, |
| 197 aws_secret_access_key=NOT_IMPL, is_secure=NOT_IMPL, | 297 aws_secret_access_key=NOT_IMPL, is_secure=NOT_IMPL, |
| 198 port=NOT_IMPL, proxy=NOT_IMPL, proxy_port=NOT_IMPL, | 298 port=NOT_IMPL, proxy=NOT_IMPL, proxy_port=NOT_IMPL, |
| 199 proxy_user=NOT_IMPL, proxy_pass=NOT_IMPL, | 299 proxy_user=NOT_IMPL, proxy_pass=NOT_IMPL, |
| 200 host=NOT_IMPL, debug=NOT_IMPL, | 300 host=NOT_IMPL, debug=NOT_IMPL, |
| 201 https_connection_factory=NOT_IMPL, | 301 https_connection_factory=NOT_IMPL, |
| 202 calling_format=NOT_IMPL, | 302 calling_format=NOT_IMPL, |
| 203 path=NOT_IMPL, provider=NOT_IMPL, | 303 path=NOT_IMPL, provider=NOT_IMPL, |
| 204 bucket_class=NOT_IMPL): | 304 bucket_class=NOT_IMPL): |
| 205 self.buckets = {} | 305 self.buckets = {} |
| 206 | 306 |
| 207 def create_bucket(self, bucket_name, headers=NOT_IMPL, location=NOT_IMPL, | 307 def create_bucket(self, bucket_name, headers=NOT_IMPL, location=NOT_IMPL, |
| 208 policy=NOT_IMPL): | 308 policy=NOT_IMPL): |
| 209 if bucket_name in self.buckets: | 309 if bucket_name in self.buckets: |
| 210 raise boto.exception.StorageCreateError( | 310 raise boto.exception.StorageCreateError( |
| 211 409, 'BucketAlreadyOwnedByYou', 'bucket already exists') | 311 409, 'BucketAlreadyOwnedByYou', |
| 312 "<Message>Your previous request to create the named bucket " |
| 313 "succeeded and you already own it.</Message>") |
| 212 mock_bucket = MockBucket(name=bucket_name, connection=self) | 314 mock_bucket = MockBucket(name=bucket_name, connection=self) |
| 213 self.buckets[bucket_name] = mock_bucket | 315 self.buckets[bucket_name] = mock_bucket |
| 214 return mock_bucket | 316 return mock_bucket |
| 215 | 317 |
| 216 def delete_bucket(self, bucket, headers=NOT_IMPL): | 318 def delete_bucket(self, bucket, headers=NOT_IMPL): |
| 217 if bucket not in self.buckets: | 319 if bucket not in self.buckets: |
| 218 raise boto.exception.StorageResponseError(404, 'NoSuchBucket', | 320 raise boto.exception.StorageResponseError( |
| 219 'no such bucket') | 321 404, 'NoSuchBucket', '<Message>no such bucket</Message>') |
| 220 del self.buckets[bucket] | 322 del self.buckets[bucket] |
| 221 | 323 |
| 222 def get_bucket(self, bucket_name, validate=NOT_IMPL, headers=NOT_IMPL): | 324 def get_bucket(self, bucket_name, validate=NOT_IMPL, headers=NOT_IMPL): |
| 223 if bucket_name not in self.buckets: | 325 if bucket_name not in self.buckets: |
| 224 raise boto.exception.StorageResponseError(404, 'NoSuchBucket', | 326 raise boto.exception.StorageResponseError(404, 'NoSuchBucket', |
| 225 'Not Found') | 327 'Not Found') |
| 226 return self.buckets[bucket_name] | 328 return self.buckets[bucket_name] |
| 227 | 329 |
| 228 def get_all_buckets(self, headers=NOT_IMPL): | 330 def get_all_buckets(self, headers=NOT_IMPL): |
| 229 return self.buckets.itervalues() | 331 return self.buckets.itervalues() |
| 230 | 332 |
| 231 | 333 |
| 232 # We only mock a single provider/connection. | 334 # We only mock a single provider/connection. |
| 233 mock_connection = MockConnection() | 335 mock_connection = MockConnection() |
| 234 | 336 |
| 235 | 337 |
| 236 class MockBucketStorageUri(object): | 338 class MockBucketStorageUri(object): |
| 237 | 339 |
| 340 delim = '/' |
| 341 |
| 238 def __init__(self, scheme, bucket_name=None, object_name=None, | 342 def __init__(self, scheme, bucket_name=None, object_name=None, |
| 239 debug=NOT_IMPL): | 343 debug=NOT_IMPL, suppress_consec_slashes=NOT_IMPL): |
| 240 self.scheme = scheme | 344 self.scheme = scheme |
| 241 self.bucket_name = bucket_name | 345 self.bucket_name = bucket_name |
| 242 self.object_name = object_name | 346 self.object_name = object_name |
| 243 if self.bucket_name and self.object_name: | 347 if self.bucket_name and self.object_name: |
| 244 self.uri = ('%s://%s/%s' % (self.scheme, self.bucket_name, | 348 self.uri = ('%s://%s/%s' % (self.scheme, self.bucket_name, |
| 245 self.object_name)) | 349 self.object_name)) |
| 246 elif self.bucket_name: | 350 elif self.bucket_name: |
| 247 self.uri = ('%s://%s/' % (self.scheme, self.bucket_name)) | 351 self.uri = ('%s://%s/' % (self.scheme, self.bucket_name)) |
| 248 else: | 352 else: |
| 249 self.uri = ('%s://' % self.scheme) | 353 self.uri = ('%s://' % self.scheme) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 268 policy=NOT_IMPL): | 372 policy=NOT_IMPL): |
| 269 return self.connect().create_bucket(self.bucket_name) | 373 return self.connect().create_bucket(self.bucket_name) |
| 270 | 374 |
| 271 def delete_bucket(self, headers=NOT_IMPL): | 375 def delete_bucket(self, headers=NOT_IMPL): |
| 272 return self.connect().delete_bucket(self.bucket_name) | 376 return self.connect().delete_bucket(self.bucket_name) |
| 273 | 377 |
| 274 def delete_key(self, validate=NOT_IMPL, headers=NOT_IMPL, | 378 def delete_key(self, validate=NOT_IMPL, headers=NOT_IMPL, |
| 275 version_id=NOT_IMPL, mfa_token=NOT_IMPL): | 379 version_id=NOT_IMPL, mfa_token=NOT_IMPL): |
| 276 self.get_bucket().delete_key(self.object_name) | 380 self.get_bucket().delete_key(self.object_name) |
| 277 | 381 |
| 382 def disable_logging(self, validate=NOT_IMPL, headers=NOT_IMPL, |
| 383 version_id=NOT_IMPL): |
| 384 self.get_bucket().disable_logging() |
| 385 |
| 386 def enable_logging(self, target_bucket, target_prefix, validate=NOT_IMPL, |
| 387 headers=NOT_IMPL, version_id=NOT_IMPL): |
| 388 self.get_bucket().enable_logging(target_bucket) |
| 389 |
| 278 def equals(self, uri): | 390 def equals(self, uri): |
| 279 return self.uri == uri.uri | 391 return self.uri == uri.uri |
| 280 | 392 |
| 281 def get_acl(self, validate=NOT_IMPL, headers=NOT_IMPL, version_id=NOT_IMPL): | 393 def get_acl(self, validate=NOT_IMPL, headers=NOT_IMPL, version_id=NOT_IMPL): |
| 282 return self.get_bucket().get_acl(self.object_name) | 394 return self.get_bucket().get_acl(self.object_name) |
| 283 | 395 |
| 396 def get_def_acl(self, validate=NOT_IMPL, headers=NOT_IMPL, |
| 397 version_id=NOT_IMPL): |
| 398 return self.get_bucket().get_def_acl(self.object_name) |
| 399 |
| 400 def get_subresource(self, subresource, validate=NOT_IMPL, headers=NOT_IMPL, |
| 401 version_id=NOT_IMPL): |
| 402 return self.get_bucket().get_subresource(subresource, self.object_name) |
| 403 |
| 284 def get_all_buckets(self, headers=NOT_IMPL): | 404 def get_all_buckets(self, headers=NOT_IMPL): |
| 285 return self.connect().get_all_buckets() | 405 return self.connect().get_all_buckets() |
| 286 | 406 |
| 287 def get_all_keys(self, validate=NOT_IMPL, headers=NOT_IMPL): | 407 def get_all_keys(self, validate=NOT_IMPL, headers=NOT_IMPL): |
| 288 return self.get_bucket().get_all_keys(self) | 408 return self.get_bucket().get_all_keys(self) |
| 289 | 409 |
| 290 def get_bucket(self, validate=NOT_IMPL, headers=NOT_IMPL): | 410 def get_bucket(self, validate=NOT_IMPL, headers=NOT_IMPL): |
| 291 return self.connect().get_bucket(self.bucket_name) | 411 return self.connect().get_bucket(self.bucket_name) |
| 292 | 412 |
| 293 def get_key(self, validate=NOT_IMPL, headers=NOT_IMPL, | 413 def get_key(self, validate=NOT_IMPL, headers=NOT_IMPL, |
| 294 version_id=NOT_IMPL): | 414 version_id=NOT_IMPL): |
| 295 return self.get_bucket().get_key(self.object_name) | 415 return self.get_bucket().get_key(self.object_name) |
| 296 | 416 |
| 297 def is_file_uri(self): | 417 def is_file_uri(self): |
| 298 return False | 418 return False |
| 299 | 419 |
| 300 def is_cloud_uri(self): | 420 def is_cloud_uri(self): |
| 301 return True | 421 return True |
| 302 | 422 |
| 303 def names_container(self): | 423 def names_container(self): |
| 304 return not self.object_name | 424 return bool(not self.object_name) |
| 305 | 425 |
| 306 def names_singleton(self): | 426 def names_singleton(self): |
| 307 return self.object_name | 427 return bool(self.object_name) |
| 428 |
| 429 def names_directory(self): |
| 430 return False |
| 431 |
| 432 def names_provider(self): |
| 433 return bool(not self.bucket_name) |
| 434 |
| 435 def names_bucket(self): |
| 436 return self.names_container() |
| 437 |
| 438 def names_file(self): |
| 439 return False |
| 440 |
| 441 def names_object(self): |
| 442 return not self.names_container() |
| 443 |
| 444 def is_stream(self): |
| 445 return False |
| 308 | 446 |
| 309 def new_key(self, validate=NOT_IMPL, headers=NOT_IMPL): | 447 def new_key(self, validate=NOT_IMPL, headers=NOT_IMPL): |
| 310 bucket = self.get_bucket() | 448 bucket = self.get_bucket() |
| 311 return bucket.new_key(self.object_name) | 449 return bucket.new_key(self.object_name) |
| 312 | 450 |
| 313 def set_acl(self, acl_or_str, key_name='', validate=NOT_IMPL, | 451 def set_acl(self, acl_or_str, key_name='', validate=NOT_IMPL, |
| 314 headers=NOT_IMPL, version_id=NOT_IMPL): | 452 headers=NOT_IMPL, version_id=NOT_IMPL): |
| 315 self.get_bucket().set_acl(acl_or_str, key_name) | 453 self.get_bucket().set_acl(acl_or_str, key_name) |
| 454 |
| 455 def set_def_acl(self, acl_or_str, key_name=NOT_IMPL, validate=NOT_IMPL, |
| 456 headers=NOT_IMPL, version_id=NOT_IMPL): |
| 457 self.get_bucket().set_def_acl(acl_or_str) |
| 458 |
| 459 def set_subresource(self, subresource, value, validate=NOT_IMPL, |
| 460 headers=NOT_IMPL, version_id=NOT_IMPL): |
| 461 self.get_bucket().set_subresource(subresource, value, self.object_name) |
| OLD | NEW |