new librarian sub-module: custom pdfs
[wolnelektury.git] / apps / catalogue / utils.py
index d5ef2b7..0134701 100644 (file)
@@ -13,7 +13,7 @@ from django.utils.hashcompat import sha_constructor
 from django.conf import settings
 from celery.task import task
 from os import mkdir, path, unlink
-from errno import EEXIST
+from errno import EEXIST, ENOENT
 from fcntl import flock, LOCK_EX
 from zipfile import ZipFile
 
@@ -55,8 +55,8 @@ class ExistingFile(UploadedFile):
         pass
 
 
-class BookImportDocProvider(DocProvider):
-    """Used for joined EPUB and PDF files."""
+class ORMDocProvider(DocProvider):
+    """Used for getting books' children."""
 
     def __init__(self, book):
         self.book = book
@@ -69,19 +69,34 @@ class BookImportDocProvider(DocProvider):
 
 
 class LockFile(object):
+    """
+    A file lock monitor class; createas an ${objname}.lock
+    file in directory dir, and locks it exclusively.
+    To be used in 'with' construct.
+    """
     def __init__(self, dir, objname):
         self.lockname = path.join(dir, objname + ".lock")
 
-    def __entry__(self):
+    def __enter__(self):
         self.lock = open(self.lockname, 'w')
         flock(self.lock, LOCK_EX)
 
     def __exit__(self, *err):
+        try:
+            unlink(self.lockname)
+        except OSError as oe:
+            if oe.errno != oe.EEXIST:
+                raise oe
         self.lock.close()
-        unlink(self.lockname)
 
 
+@task
 def create_zip(paths, zip_slug):
+    """
+    Creates a zip in MEDIA_ROOT/zip directory containing files from path.
+    Resulting archive filename is ${zip_slug}.zip
+    Returns it's path relative to MEDIA_ROOT (no initial slash)
+    """
     # directory to store zip files
     zip_path = path.join(settings.MEDIA_ROOT, 'zip')
 
@@ -94,22 +109,25 @@ def create_zip(paths, zip_slug):
 
     with LockFile(zip_path, zip_slug):
         if not path.exists(path.join(zip_path, zip_filename)):
-            with ZipFile(path.join(zip_path, zip_filename), 'w') as zipf:
-                for p in paths:
-                    zipf.write(p, path.basename(p))
+            zipf = ZipFile(path.join(zip_path, zip_filename), 'w')
+            try:
+                for arcname, p in paths:
+                    if arcname is None:
+                        arcname = path.basename(p)
+                    zipf.write(p, arcname)
+            finally:
+                zipf.close()
 
         return 'zip/' + zip_filename
 
 
 def remove_zip(zip_slug):
+    """
+    removes the ${zip_slug}.zip file from zip store.
+    """
     zip_file = path.join(settings.MEDIA_ROOT, 'zip', zip_slug + '.zip')
     try:
         unlink(zip_file)
     except OSError as oe:
-        if oe.errno != EEXIST:
+        if oe.errno != ENOENT:
             raise oe
-
-
-@task
-def create_zip_task(*args):
-    return create_zip(*args)