Merge branch 'master' into sunburnt
[wolnelektury.git] / apps / catalogue / management / commands / pack.py
1 # -*- coding: utf-8 -*-
2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4 #
5 import re
6 import sys
7 from cPickle import load, dump
8 from optparse import make_option
9
10 from django.core.management.base import BaseCommand
11 from django.core.management.color import color_style
12 import zipfile
13
14 from catalogue.models import Book, Tag
15
16
17 class Command(BaseCommand):
18     option_list = BaseCommand.option_list + (
19         make_option('-t', '--tags', dest='tags', metavar='SLUG,...',
20             help='Use only books tagged with this tags'),
21         make_option('-i', '--include', dest='include', metavar='SLUG,...',
22             help='Include specific books by slug'),
23         make_option('-e', '--exclude', dest='exclude', metavar='SLUG,...',
24             help='Exclude specific books by slug')
25     )
26     help = 'Prepare ZIP package with files of given type.'
27     args = '[%s] output_path.zip' % '|'.join(Book.formats)
28
29     def handle(self, ftype, path, **options):
30         self.style = color_style()
31         verbose = int(options.get('verbosity'))
32         tags = options.get('tags')
33         include = options.get('include')
34         exclude = options.get('exclude')
35
36         if ftype in Book.formats:
37             field = "%s_file" % ftype
38         else:
39             print self.style.ERROR('Unknown file type.')
40             return
41
42         books = []
43
44         if include:
45             books += list(Book.objects.filter(slug__in=include.split(',')).only('slug', field))
46
47         if tags:
48             books += list(Book.tagged.with_all(Tag.objects.filter(slug__in=tags.split(','))).only('slug', field))
49         elif not include:
50             books = list(Book.objects.all().only('slug', field))
51
52         if exclude:
53             books = [book for book in books if book.slug not in exclude.split(',')]
54
55         archive = zipfile.ZipFile(path, 'w', zipfile.ZIP_DEFLATED)
56
57         processed = skipped = 0
58         for book in books:
59             if verbose >= 2:
60                 print 'Parsing', book.slug
61             content = getattr(book, field)
62             if not content:
63                 if verbose >= 1:
64                     print self.style.NOTICE('%s has no %s file' % (book.slug, ftype))
65                 skipped += 1
66                 continue
67             archive.write(content.path, str('%s.%s' % (book.slug, ftype)))
68             processed += 1
69         archive.close()
70
71         if not processed:
72             if skipped:
73                 print self.style.ERROR("No books with %s files found" % ftype)
74             else:
75                 print self.style.ERROR("No books found")
76             return
77
78         if verbose >= 1:
79             print "%d processed, %d skipped" % (processed, skipped)
80             print "Results written to %s" % path