[view] Add Zip view
authorVincent Michel <vincent.michel@logilab.fr>
Tue, 11 Dec 2012 18:40:17 +0100
changeset 11 8e7fc06df352
parent 10 e73465654ec7
child 12 f692e9e76067
[view] Add Zip view
views/zipview.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/views/zipview.py	Tue Dec 11 18:40:17 2012 +0100
@@ -0,0 +1,67 @@
+import os
+import os.path as osp
+import tempfile
+from contextlib import closing
+from zipfile import ZipFile, ZIP_DEFLATED
+
+from cubicweb.selectors import is_instance
+from cubicweb.view import EntityView
+
+
+def zipfiles(filepaths):
+    """generates a zip archive from `filepaths`
+
+    :param filepaths: is a dictionary mapping basename (as it will appear in the
+                      archive) to corresponding absolute filepath (where it must
+                      read from on the filesystem)
+
+    :return: a couple fileobj, filepath where `fileobj` is a standard python
+             open file objet on the generated archive, and `filepath` is an
+             absolute file path to this archive on the filesystem
+    """
+    fd, archive_filepath = tempfile.mkstemp()
+    try:
+        noext_archivename = osp.splitext(DataZipView.archive_name)[0]
+        with closing(ZipFile(archive_filepath, "w", ZIP_DEFLATED)) as zip:
+            for filename, subj, filepath in filepaths:
+                zip.write(filepath, '%s/%s/%s' % (noext_archivename, subj, filename))
+        fileobj = os.fdopen(fd)
+        fileobj.seek(0)
+        return fileobj, archive_filepath
+    except:
+        os.close(fd)
+        os.unlink(archive_filepath)
+        raise
+
+
+class DataZipView(EntityView):
+    """transforms a resultset of acte into a zip archive"""
+    __regid__ = 'data-zip'
+    __select__ = EntityView.__select__ & is_instance('Scan', 'GenomicMeasure')
+    templatable = False
+    binary = True
+    archive_name = 'brainomics_data.zip'
+
+    def set_request_content_type(self):
+        self._cw.set_content_type('application/zip', filename=self.archive_name)
+
+    def call(self):
+        if not self.cw_rset:
+            retur
+        filepaths = set()
+        for entity in self.cw_rset.entities():
+            if entity.__regid__ == 'GenomicMeasure':
+                for ext in ('.bim', '.bed', '.fam'):
+                    filepaths.add((entity.filepath.split('/')[-1]+ext, entity.concerns[0].identifier, entity.full_filepath+ext))
+            else:
+                filename = entity.type+'_'+entity.filepath.split('/')[-1]
+                filename = filename.replace(' ', '_')
+                filepaths.add((filename, entity.concerns[0].identifier, entity.full_filepath))
+            for external_resource in entity.external_resources:
+                filepaths.add((external_resource.filepath.split('/')[-1], entity.concerns[0].identifier, external_resource.full_filepath))
+        fileobj, archive_filepath = zipfiles(list(filepaths))
+        try:
+            self.w(fileobj.read())
+        finally:
+            fileobj.close()
+            os.unlink(archive_filepath)