disable search
[wolnelektury.git] / src / catalogue / management / commands / checkintegrity.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 from optparse import make_option
6 from django.core.management.base import BaseCommand
7
8 from catalogue.models import Book
9 from librarian import ParseError
10
11
12 class Command(BaseCommand):
13     option_list = BaseCommand.option_list + (
14         make_option('-q', '--quiet', action='store_false', dest='verbose', default=True,
15                     help='Suppress output'),
16         make_option('-d', '--dry-run', action='store_true', dest='dry_run', default=False,
17                     help="Just check for problems, don't fix them"),
18     )
19     help = 'Checks integrity of catalogue data.'
20
21     def handle(self, **options):
22         from django.db import transaction
23
24         verbose = options['verbose']
25
26         with transaction.atomic():
27             for book in Book.objects.all().iterator():
28                 try:
29                     info = book.wldocument().book_info
30                 except ParseError:
31                     if verbose:
32                         print "ERROR! Bad XML for book:", book.slug
33                         print "To resolve: republish."
34                         print
35                 else:
36                     should_be = [p.slug for p in info.parts]
37                     is_now = [p.slug for p in book.children.all().order_by('parent_number')]
38                     if should_be != is_now:
39                         if verbose:
40                             print "ERROR! Wrong children for book:", book.slug
41                             # print "Is:       ", is_now
42                             # print "Should be:", should_be
43                             from difflib import ndiff
44                             print '\n'.join(ndiff(is_now, should_be))
45                             print "To resolve: republish parent book."
46                             print
47
48                 # Check for ancestry.
49                 parents = []
50                 parent = book.parent
51                 while parent:
52                     parents.append(parent)
53                     parent = parent.parent
54                 ancestors = list(book.ancestor.all())
55                 if set(ancestors) != set(parents):
56                     if options['verbose']:
57                         print "Wrong ancestry for book:", book
58                         print "Is:       ", ", ".join(ancestors)
59                         print "Should be:", ", ".join(parents)
60                     if not options['dry_run']:
61                         book.repopulate_ancestors()
62                         if options['verbose']:
63                             print "Fixed."
64                     if options['verbose']:
65                         print
66
67                 # TODO: check metadata tags, reset counters