Commits

David Larlet committed 0df7506

S3: eventually send the storage to the file, thanks Marty Alchin for your suggestion! Still a work in progress.

Comments (0)

Files changed (1)

 
     def _put_file(self, name, content):
         content_type = guess_type(name)[0] or "application/x-octet-stream"
-        self.headers.update({'x-amz-acl':  self.acl, 'Content-Type': content_type})
+        self.headers.update({'x-amz-acl': self.acl, 'Content-Type': content_type})
         response = self.connection.put(self.bucket, name, content, self.headers)
 
     def _open(self, name, mode='rb'):
-        response = self.connection.get(self.bucket, name)
-        sizer = self.size
-        reader = self._read
-        writer = curry(self._put_file, name)
-        remote_file = S3StorageFile(name, response.object.data, mode, sizer, reader, writer)
+        remote_file = S3StorageFile(name, self, mode=mode)
         return remote_file
 
-    def _read(self, name, num_bytes=None):
-        if num_bytes is None:
+    def _read(self, name, start_range=None, end_range=None):
+        if start_range is None:
             headers = {}
         else:
-            headers = {'Range': 'bytes=0-%s' % (num_bytes-1,)}
+            headers = {'Range': 'bytes=%s-%s' % (start_range, end_range)}
         response = self.connection.get(self.bucket, name, headers)
-        return response.object.data
+        headers = response.http_response.msg
+        return response.object.data, headers['etag'], headers.get('content-range', None)
         
     def _save(self, name, content):
         if hasattr(content, 'chunks'):
 
 
 class S3StorageFile(File):
-    def __init__(self, name, data, mode, sizer, reader, writer):
+    def __init__(self, name, storage, mode):
         self._name = name
+        self._storage = storage
         self._mode = mode
-        self._size_from_storage = sizer
-        self._read_from_storage = reader
-        self._write_to_storage = writer
         self._is_dirty = False
-        self.file = StringIO(data)
-
+        self.file = StringIO()
+        self.start_range = 0
+    
     @property
     def size(self):
         if not hasattr(self, '_size'):
-            self._size = self._size_from_storage(self._name)
+            self._size = self._storage.size(self._name)
         return self._size
 
     def read(self, num_bytes=None):
-        self.file = StringIO(self._read_from_storage(self._name, num_bytes))
+        if num_bytes is None:
+            args = []
+            self.start_range = 0
+        else:
+            args = [self.start_range, self.start_range+num_bytes-1]
+        data, etags, content_range = self._storage._read(self._name, *args)
+        if content_range is not None:
+            current_range, size = content_range.split(' ', 1)[1].split('/', 1)
+            start_range, end_range = current_range.split('-', 1)
+            self._size, self.start_range = int(size), int(end_range)+1
+        self.file = StringIO(data)
         return self.file.getvalue()
 
     def write(self, content):
 
     def close(self):
         if self._is_dirty:
-            self._write_to_storage(self.file.getvalue())
+            self._storage._put_file(self._name, self.file.getvalue())
         self.file.close()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.