| OLD | NEW |
| 1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ | 1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ |
| 2 # Copyright (c) 2010, Eucalyptus Systems, Inc. | 2 # Copyright (c) 2010, Eucalyptus Systems, Inc. |
| 3 # | 3 # |
| 4 # Permission is hereby granted, free of charge, to any person obtaining a | 4 # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 # copy of this software and associated documentation files (the | 5 # copy of this software and associated documentation files (the |
| 6 # "Software"), to deal in the Software without restriction, including | 6 # "Software"), to deal in the Software without restriction, including |
| 7 # without limitation the rights to use, copy, modify, merge, publish, dis- | 7 # without limitation the rights to use, copy, modify, merge, publish, dis- |
| 8 # tribute, sublicense, and/or sell copies of the Software, and to permit | 8 # tribute, sublicense, and/or sell copies of the Software, and to permit |
| 9 # persons to whom the Software is furnished to do so, subject to the fol- | 9 # persons to whom the Software is furnished to do so, subject to the fol- |
| 10 # lowing conditions: | 10 # lowing conditions: |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 self.part_number = int(value) | 95 self.part_number = int(value) |
| 96 elif name == 'LastModified': | 96 elif name == 'LastModified': |
| 97 self.last_modified = value | 97 self.last_modified = value |
| 98 elif name == 'ETag': | 98 elif name == 'ETag': |
| 99 self.etag = value | 99 self.etag = value |
| 100 elif name == 'Size': | 100 elif name == 'Size': |
| 101 self.size = int(value) | 101 self.size = int(value) |
| 102 else: | 102 else: |
| 103 setattr(self, name, value) | 103 setattr(self, name, value) |
| 104 | 104 |
| 105 def part_lister(mpupload, part_number_marker=''): | 105 def part_lister(mpupload, part_number_marker=None): |
| 106 """ | 106 """ |
| 107 A generator function for listing parts of a multipart upload. | 107 A generator function for listing parts of a multipart upload. |
| 108 """ | 108 """ |
| 109 more_results = True | 109 more_results = True |
| 110 part = None | 110 part = None |
| 111 while more_results: | 111 while more_results: |
| 112 parts = mpupload.get_all_parts(None, part_number_marker) | 112 parts = mpupload.get_all_parts(None, part_number_marker) |
| 113 for part in parts: | 113 for part in parts: |
| 114 yield part | 114 yield part |
| 115 part_number_marker = mpupload.next_part_number_marker | 115 part_number_marker = mpupload.next_part_number_marker |
| (...skipping 16 matching lines...) Expand all Loading... |
| 132 self.part_number_marker = None | 132 self.part_number_marker = None |
| 133 self.next_part_number_marker = None | 133 self.next_part_number_marker = None |
| 134 self.max_parts = None | 134 self.max_parts = None |
| 135 self.is_truncated = False | 135 self.is_truncated = False |
| 136 self._parts = None | 136 self._parts = None |
| 137 | 137 |
| 138 def __repr__(self): | 138 def __repr__(self): |
| 139 return '<MultiPartUpload %s>' % self.key_name | 139 return '<MultiPartUpload %s>' % self.key_name |
| 140 | 140 |
| 141 def __iter__(self): | 141 def __iter__(self): |
| 142 return part_lister(self, part_number_marker=self.part_number_marker) | 142 return part_lister(self) |
| 143 | 143 |
| 144 def to_xml(self): | 144 def to_xml(self): |
| 145 self.get_all_parts() | 145 self.get_all_parts() |
| 146 s = '<CompleteMultipartUpload>\n' | 146 s = '<CompleteMultipartUpload>\n' |
| 147 for part in self: | 147 for part in self: |
| 148 s += ' <Part>\n' | 148 s += ' <Part>\n' |
| 149 s += ' <PartNumber>%d</PartNumber>\n' % part.part_number | 149 s += ' <PartNumber>%d</PartNumber>\n' % part.part_number |
| 150 s += ' <ETag>%s</ETag>\n' % part.etag | 150 s += ' <ETag>%s</ETag>\n' % part.etag |
| 151 s += ' </Part>\n' | 151 s += ' </Part>\n' |
| 152 s += '</CompleteMultipartUpload>' | 152 s += '</CompleteMultipartUpload>' |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 response = self.bucket.connection.make_request('GET', self.bucket.name, | 205 response = self.bucket.connection.make_request('GET', self.bucket.name, |
| 206 self.key_name, | 206 self.key_name, |
| 207 query_args=query_args) | 207 query_args=query_args) |
| 208 body = response.read() | 208 body = response.read() |
| 209 if response.status == 200: | 209 if response.status == 200: |
| 210 h = handler.XmlHandler(self, self) | 210 h = handler.XmlHandler(self, self) |
| 211 xml.sax.parseString(body, h) | 211 xml.sax.parseString(body, h) |
| 212 return self._parts | 212 return self._parts |
| 213 | 213 |
| 214 def upload_part_from_file(self, fp, part_num, headers=None, replace=True, | 214 def upload_part_from_file(self, fp, part_num, headers=None, replace=True, |
| 215 cb=None, num_cb=10, policy=None, md5=None, | 215 cb=None, num_cb=10, policy=None, md5=None): |
| 216 reduced_redundancy=False): | |
| 217 """ | 216 """ |
| 218 Upload another part of this MultiPart Upload. | 217 Upload another part of this MultiPart Upload. |
| 219 | 218 |
| 220 :type fp: file | 219 :type fp: file |
| 221 :param fp: The file object you want to upload. | 220 :param fp: The file object you want to upload. |
| 222 | 221 |
| 223 :type part_num: int | 222 :type part_num: int |
| 224 :param part_num: The number of this part. | 223 :param part_num: The number of this part. |
| 225 | 224 |
| 226 The other parameters are exactly as defined for the | 225 The other parameters are exactly as defined for the |
| 227 :class:`boto.s3.key.Key` set_contents_from_file method. | 226 :class:`boto.s3.key.Key` set_contents_from_file method. |
| 228 """ | 227 """ |
| 229 if part_num < 1: | 228 if part_num < 1: |
| 230 raise ValueError('Part numbers must be greater than zero') | 229 raise ValueError('Part numbers must be greater than zero') |
| 231 query_args = 'uploadId=%s&partNumber=%d' % (self.id, part_num) | 230 query_args = 'uploadId=%s&partNumber=%d' % (self.id, part_num) |
| 232 key = self.bucket.new_key(self.key_name) | 231 key = self.bucket.new_key(self.key_name) |
| 233 key.set_contents_from_file(fp, headers, replace, cb, num_cb, policy, | 232 key.set_contents_from_file(fp, headers, replace, cb, num_cb, policy, |
| 234 md5, reduced_redundancy, query_args) | 233 md5, reduced_redundancy=False, |
| 234 query_args=query_args) |
| 235 | 235 |
| 236 def complete_upload(self): | 236 def complete_upload(self): |
| 237 """ | 237 """ |
| 238 Complete the MultiPart Upload operation. This method should | 238 Complete the MultiPart Upload operation. This method should |
| 239 be called when all parts of the file have been successfully | 239 be called when all parts of the file have been successfully |
| 240 uploaded to S3. | 240 uploaded to S3. |
| 241 | 241 |
| 242 :rtype: :class:`boto.s3.multipart.CompletedMultiPartUpload` | 242 :rtype: :class:`boto.s3.multipart.CompletedMultiPartUpload` |
| 243 :returns: An object representing the completed upload. | 243 :returns: An object representing the completed upload. |
| 244 """ | 244 """ |
| 245 xml = self.to_xml() | 245 xml = self.to_xml() |
| 246 self.bucket.complete_multipart_upload(self.key_name, | 246 return self.bucket.complete_multipart_upload(self.key_name, |
| 247 self.id, xml) | 247 self.id, xml) |
| 248 | 248 |
| 249 def cancel_upload(self): | 249 def cancel_upload(self): |
| 250 """ | 250 """ |
| 251 Cancels a MultiPart Upload operation. The storage consumed by | 251 Cancels a MultiPart Upload operation. The storage consumed by |
| 252 any previously uploaded parts will be freed. However, if any | 252 any previously uploaded parts will be freed. However, if any |
| 253 part uploads are currently in progress, those part uploads | 253 part uploads are currently in progress, those part uploads |
| 254 might or might not succeed. As a result, it might be necessary | 254 might or might not succeed. As a result, it might be necessary |
| 255 to abort a given multipart upload multiple times in order to | 255 to abort a given multipart upload multiple times in order to |
| 256 completely free all storage consumed by all parts. | 256 completely free all storage consumed by all parts. |
| 257 """ | 257 """ |
| 258 self.bucket.cancel_multipart_upload(self.key_name, self.id) | 258 self.bucket.cancel_multipart_upload(self.key_name, self.id) |
| 259 | 259 |
| 260 | 260 |
| OLD | NEW |