def delete(self, name): name = self._path(name) response = self.connection.delete(self.bucket, name) if response.http_response.status != 204: raise S3Error(response.message) if self.cache: self.cache.remove(name)
def _read(self, name, start_range=None, end_range=None): name = self._path(name) headers, range_ = {}, None if start_range is not None and end_range is not None: range_ = '%s-%s' % (start_range, end_range) elif start_range is not None: range_ = '%s' % start_range if range_ is not None: headers = {'Range': 'bytes=%s' % range_} response = self.connection.get(self.bucket, name, headers) valid_responses = [200] if start_range is not None or end_range is not None: valid_responses.append(206) if response.http_response.status not in valid_responses: raise S3Error(response.message) headers = response.http_response.msg data = response.object.data if headers.get('Content-Encoding') == 'gzip': gzf = GzipFile(mode='rb', fileobj=StringIO(data)) data = gzf.read() gzf.close() return data, headers.get('etag', None), headers.get('content-range', None)
def _put_file(self, name, content): name = self._path(name) placeholder = False if self.cache: if not self.cache.exists(name): self.cache.save(name, 0, 0) placedholder = True content_type = mimetypes.guess_type( name)[0] or "application/x-octet-stream" headers = {} for pattern in self.headers: if pattern[0].match(name): headers = pattern[1].copy() break file_pos = content.tell() content.seek(0, 2) content_length = content.tell() content.seek(0) gz_cts = getattr( settings, 'CUDDLYBUDDLY_STORAGE_S3_GZIP_CONTENT_TYPES', ('text/css', 'application/javascript', 'application/x-javascript')) gz_content = None if content_length > 1024 and content_type in gz_cts: gz_content = StringIO() gzf = GzipFile(mode='wb', fileobj=gz_content) gzf.write(content.read()) content.seek(0) gzf.close() gz_content.seek(0, 2) gz_content_length = gz_content.tell() gz_content.seek(0) if gz_content_length < content_length: content_length = gz_content_length headers.update({'Content-Encoding': 'gzip'}) else: gz_content = None headers.update({ 'Content-Type': content_type, 'Content-Length': str(content_length) }) # Httplib in < 2.6 doesn't accept file like objects. Meanwhile in # >= 2.7 it will try to join a content str object with the headers which # results in encoding problems. if sys.version_info[0] == 2 and sys.version_info[1] < 6: content_to_send = gz_content.read( ) if gz_content is not None else content.read() else: content_to_send = gz_content if gz_content is not None else content response = self.connection.put(self.bucket, name, content_to_send, headers) content.seek(file_pos) if response.http_response.status != 200: if placeholder: self.cache.remove(name) raise S3Error(response.message) if self.cache: date = response.http_response.getheader('Date') date = timegm(parsedate(date)) self.cache.save(name, size=content_length, mtime=date)
def modified_time(self, name, force_check=False): name = self._path(name) if self.cache and not force_check: last_modified = self.cache.modified_time(name) if last_modified: return datetime.fromtimestamp(last_modified) response = self.connection._make_request('HEAD', self.bucket, name) if response.status == 404: raise S3Error("Cannot find the file specified: '%s'" % name) last_modified = timegm(parsedate(response.getheader('Last-Modified'))) if self.cache: self._store_in_cache(name, response) return datetime.fromtimestamp(last_modified)