Importing whole sections.
[edumed.git] / catalogue / management / commands / importlessons.py
1 # -*- coding: utf-8 -*-
2 # This file is part of EduMed, licensed under GNU Affero GPLv3 or later.
3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4 #
5 import os
6 import sys
7 import time
8 from optparse import make_option
9 from django.conf import settings
10 from django.core.management.base import BaseCommand
11 from django.core.management.color import color_style
12 from django.core.files import File
13
14 from librarian import IOFile
15 from catalogue.models import Lesson, Section
16
17 #from search import Index
18
19
20 class Command(BaseCommand):
21     option_list = BaseCommand.option_list + (
22         make_option('-q', '--quiet', action='store_false', dest='verbose', default=True,
23             help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
24     )
25     help = 'Imports lessons from the specified directories.'
26     args = 'directory [directory ...]'
27
28     def import_book(self, file_path, options):
29         verbose = options.get('verbose')
30         iofile = IOFile.from_filename(file_path)
31         basename, ext = file_path.rsplit('.', 1)
32         if os.path.isdir(basename):
33             for att_name in os.listdir(basename):
34                 iofile.attachments[att_name] = IOFile.from_filename(
35                     os.path.join(basename, att_name))
36         lesson = Lesson.publish(iofile)
37
38     def handle(self, *directories, **options):
39         from django.db import transaction
40
41         self.style = color_style()
42         
43         verbose = options.get('verbose')
44
45         # Start transaction management.
46         transaction.commit_unless_managed()
47         transaction.enter_transaction_management()
48         transaction.managed(True)
49
50         files_imported = 0
51         files_skipped = 0
52
53         for dir_name in directories:
54             if not os.path.isdir(dir_name):
55                 print self.style.ERROR("%s: Not a directory. Skipping." % dir_name)
56             else:
57                 # files queue
58                 files = sorted(os.listdir(dir_name))
59                 postponed = {}
60                 while files:
61                     file_name = files.pop(0)
62                     file_path = os.path.join(dir_name, file_name)
63                     file_base, ext = os.path.splitext(file_path)
64
65                     # Skip files that are not XML files
66                     if not ext == '.xml':
67                         continue
68
69                     if verbose > 0:
70                         print "Parsing '%s'" % file_path
71                     else:
72                         sys.stdout.write('.')
73                         sys.stdout.flush()
74
75                     # Import book files
76                     try:
77                         self.import_book(file_path, options)
78                         files_imported += 1
79                         transaction.commit()
80                     except Section.IncompleteError:
81                         if file_name not in postponed or postponed[file_name] < files_imported:
82                             # Push it back into the queue, maybe the missing lessons will show up.
83                             if verbose > 0:
84                                 print self.style.NOTICE('Waiting for missing lessons.')
85                             files.append(file_name)
86                             postponed[file_name] = files_imported
87                         else:
88                             # We're in a loop, nothing's being imported - some lesson is really missing.
89                             raise e
90                     except BaseException, e:
91                         print e
92                         files_skipped += 1
93
94         # Print results
95         print
96         print "Results: %d files imported, %d skipped, %d total." % (
97             files_imported, files_skipped, files_imported + files_skipped)
98         print
99
100         transaction.commit()
101         transaction.leave_transaction_management()