1 # -*- coding: utf-8 -*-
3 from optparse import make_option
6 from django.contrib.auth.models import User
7 from django.core.management.base import BaseCommand
8 from django.core.management.color import color_style
9 from django.db import transaction
11 from slughifi import slughifi
12 from catalogue.models import Book
15 def common_prefix(texts):
18 min_len = min(len(text) for text in texts)
19 for i in range(min_len):
20 chars = list(set([text[i] for text in texts]))
23 common.append(chars[0])
24 return "".join(common)
27 def print_guess(dry_run=True):
28 from collections import defaultdict
29 from pipes import quote
34 res.append((re.compile(ur'__?(przedmowa)$'), -1))
35 res.append((re.compile(ur'__?(cz(esc)?|ksiega|rozdzial)__?(?P<n>\d*)$'), None))
36 res.append((re.compile(ur'__?(rozdzialy__?)?(?P<n>\d*)-'), None))
38 for r, default in res:
43 return int(m.group('n')), slug[:start]
45 return default, slug[:start]
48 def file_to_title(fname):
49 """ Returns a title-like version of a filename. """
50 parts = (p.replace('_', ' ').title() for p in fname.split('__'))
51 return ' / '.join(parts)
53 merges = defaultdict(list)
54 for b in Book.objects.all():
55 n, ns = read_slug(b.slug)
57 merges[ns].append((n, b))
59 for slug in sorted(merges.keys()):
60 merge_list = sorted(merges[slug])
61 if len(merge_list) < 2:
64 title = file_to_title(slug)
65 print "./manage.py merge_books %s--title=%s --slug=%s \\\n %s\n" % (
66 '--dry-run ' if dry_run else '',
68 " \\\n ".join(b.slug for i, b in merge_list)
72 class Command(BaseCommand):
73 option_list = BaseCommand.option_list + (
74 make_option('-s', '--slug', dest='new_slug', metavar='SLUG',
75 help='New slug of the merged book (defaults to common part of all slugs).'),
76 make_option('-t', '--title', dest='new_title', metavar='TITLE',
77 help='New title of the merged book (defaults to common part of all titles).'),
78 make_option('-q', '--quiet', action='store_false', dest='verbose', default=True,
80 make_option('-g', '--guess', action='store_true', dest='guess', default=False,
81 help='Try to guess what merges are needed (but do not apply them).'),
82 make_option('-d', '--dry-run', action='store_true', dest='dry_run', default=False,
83 help='Dry run: do not actually change anything.'),
85 help = 'Merges multiple books into one.'
88 def handle(self, *slugs, **options):
90 self.style = color_style()
92 guess = options.get('guess')
93 dry_run = options.get('dry_run')
94 new_slug = options.get('new_slug')
95 new_title = options.get('new_title')
96 verbose = options.get('verbose')
100 print "Please specify either slugs, or --guess."
106 print "Please specify some book slugs"
110 # Start transaction management.
111 transaction.commit_unless_managed()
112 transaction.enter_transaction_management()
113 transaction.managed(True)
116 books = [Book.objects.get(slug=slug) for slug in slugs]
117 common_slug = common_prefix(slugs)
118 common_title = common_prefix([b.title for b in books])
121 new_title = common_title
122 elif common_title.startswith(new_title):
123 common_title = new_title
126 new_slug = common_slug
127 elif common_slug.startswith(new_slug):
128 common_slug = new_slug
130 if dry_run and verbose:
131 print self.style.NOTICE('DRY RUN: nothing will be changed.')
135 print "New title:", self.style.NOTICE(new_title)
136 print "New slug:", self.style.NOTICE(new_slug)
139 for i, book in enumerate(books):
143 book_title = book.title[len(common_title):].replace(' / ', ' ').lstrip()
144 book_slug = book.slug[len(common_slug):].replace('__', '_').lstrip('-_')
145 for j, chunk in enumerate(book):
147 new_chunk_title = book_title + '_%d' % j
148 new_chunk_slug = book_slug + '_%d' % j
150 new_chunk_title, new_chunk_slug = book_title, book_slug
152 chunk_titles.append(new_chunk_title)
153 chunk_slugs.append(new_chunk_slug)
156 print "title: %s // %s -->\n %s // %s\nslug: %s / %s -->\n %s / %s" % (
157 book.title, chunk.comment,
158 new_title, new_chunk_title,
159 book.slug, chunk.slug,
160 new_slug, new_chunk_slug)
165 books[0].append(books[i], slugs=chunk_slugs, titles=chunk_titles)
167 book.title = new_title
170 for j, chunk in enumerate(book):
171 chunk.comment = chunk_titles[j]
172 chunk.slug = chunk_slugs[j]
177 transaction.leave_transaction_management()