stupid bug in epub
[librarian.git] / librarian / book2anything.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
5 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
6 #
7 import os.path
8 import optparse
9
10 from librarian import ParseError
11 from librarian.document import Document
12
13
14 class Option(object):
15     """Option for optparse. Use it like `optparse.OptionParser.add_option`."""
16     def __init__(self, *names, **options):
17         self.names = names
18         self.options = options
19
20     def add(self, parser):
21         parser.add_option(*self.names, **self.options)
22
23     def name(self):
24         return self.options['dest']
25
26     def value(self, options):
27         return getattr(options, self.name())
28
29
30 class Book2Anything(object):
31     """A class for creating book2... scripts.
32     
33     Subclass it for any format you want to convert to.
34     """
35     format_cls = None  # A formats.Format subclass
36     document_options = []  # List of Option objects for document options.
37     format_options = []  # List of Option objects for format customization.
38     build_options = []  # List of Option objects for build options.
39
40     @classmethod
41     def run(cls):
42         # Parse commandline arguments
43         usage = """Usage: %%prog [options] SOURCE [SOURCE...]
44         Convert SOURCE files to %s.""" % cls.format_cls.format_name
45
46         parser = optparse.OptionParser(usage=usage)
47
48         parser.add_option(
49             '-v', '--verbose',
50             action='store_true', dest='verbose', default=False,
51             help='print status messages to stdout')
52         parser.add_option(
53             '-o', '--output-file',
54             dest='output_file', metavar='FILE',
55             help='specifies the output file')
56         for option in cls.document_options + cls.format_options + cls.build_options:
57             option.add(parser)
58
59         options, input_filenames = parser.parse_args()
60
61         if len(input_filenames) < 1:
62             parser.print_help()
63             return 1
64
65         # Prepare additional args for document.
66         document_args = {}
67         for option in cls.document_options:
68             document_args[option.name()] = option.value(options)
69         # Prepare additional args for format.
70         format_args = {}
71         for option in cls.format_options:
72             format_args[option.name()] = option.value(options)
73         # Prepare additional args for build.
74         build_args = {}
75         for option in cls.build_options:
76             build_args[option.name()] = option.value(options)
77
78         # Do some real work
79         try:
80             for main_input in input_filenames:
81                 if options.verbose:
82                     print main_input
83
84                 # Do the transformation.
85                 doc = Document.from_file(main_input, **document_args)
86                 format_ = cls.format_cls(doc, **format_args)
87
88                 # Where to write output?
89                 if not options.output_file:
90                     output_file = os.path.splitext(main_input)[0] + '.' + format_.format_ext
91                 else:
92                     output_file = None
93             
94                 output = format_.build(**build_args)
95                 output.save_as(output_file)
96
97         except ParseError, e:
98             print '%(file)s:%(name)s:%(message)s' % {
99                 'file': main_input,
100                 'name': e.__class__.__name__,
101                 'message': e
102             }