2 # -*- coding: utf-8 -*-
4 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
5 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
10 from librarian import DirDocProvider, ParseError
11 from librarian.parser import WLDocument
15 """Option for optparse. Use it like `optparse.OptionParser.add_option`."""
16 def __init__(self, *names, **options):
18 self.options = options
20 def add(self, parser):
21 parser.add_option(*self.names, **self.options)
24 return self.options['dest']
26 def value(self, options):
27 return getattr(options, self.name())
30 class Book2Anything(object):
31 """A class for creating book2... scripts.
33 Subclass it for any format you want to convert to.
35 format_name = None # Set format name, like "PDF".
36 ext = None # Set file extension, like "pdf".
37 uses_cover = False # Can it add a cover?
38 cover_optional = True # Only relevant if uses_cover
39 uses_provider = False # Does it need a DocProvider?
40 transform = None # Transform method. Uses WLDocument.as_{ext} by default.
41 parser_options = [] # List of Option objects for additional parser args.
42 transform_options = [] # List of Option objects for additional transform args.
43 transform_flags = [] # List of Option objects for supported transform flags.
47 # Parse commandline arguments
48 usage = """Usage: %%prog [options] SOURCE [SOURCE...]
49 Convert SOURCE files to %s format.""" % cls.format_name
51 parser = optparse.OptionParser(usage=usage)
55 action='store_true', dest='verbose', default=False,
56 help='print status messages to stdout')
59 action='store_true', dest='make_dir', default=False,
60 help='create a directory for author and put the output file in it')
62 '-o', '--output-file',
63 dest='output_file', metavar='FILE',
64 help='specifies the output file')
67 dest='output_dir', metavar='DIR',
68 help='specifies the directory for output')
70 if cls.cover_optional:
73 action='store_true', dest='with_cover', default=False,
74 help='create default cover')
76 '-C', '--image-cache',
77 dest='image_cache', metavar='URL',
78 help='prefix for image download cache' +
79 (' (implies --with-cover)' if cls.cover_optional else ''))
80 for option in cls.parser_options + cls.transform_options + cls.transform_flags:
83 options, input_filenames = parser.parse_args()
85 if len(input_filenames) < 1:
89 # Prepare additional args for parser.
91 for option in cls.parser_options:
92 parser_args[option.name()] = option.value(options)
93 # Prepare additional args for transform method.
94 transform_args = {"verbose": options.verbose}
95 for option in cls.transform_options:
96 transform_args[option.name()] = option.value(options)
97 # Add flags to transform_args, if any.
98 transform_flags = [flag.name() for flag in cls.transform_flags if flag.value(options)]
100 transform_args['flags'] = transform_flags
101 # Add cover support, if any.
103 from librarian.styles.wolnelektury.cover import WLCover
104 if options.image_cache:
105 def cover_class(*args, **kwargs):
106 return WLCover(image_cache=options.image_cache, *args, **kwargs)
107 transform_args['cover'] = cover_class
108 elif not cls.cover_optional or options.with_cover:
109 transform_args['cover'] = WLCover
114 for main_input in input_filenames:
118 # Where to find input?
119 if cls.uses_provider:
120 path, fname = os.path.realpath(main_input).rsplit('/', 1)
121 provider = DirDocProvider(path)
125 # Where to write output?
126 if not (options.output_file or options.output_dir):
127 output_file = os.path.splitext(main_input)[0] + '.' + cls.ext
131 # Do the transformation.
132 doc = WLDocument.from_file(main_input, provider=provider, **parser_args)
133 transform = cls.transform
134 if transform is None:
135 transform = getattr(WLDocument, 'as_%s' % cls.ext)
136 output = transform(doc, **transform_args)
138 doc.save_output_file(
139 output, output_file, options.output_dir, options.make_dir, cls.ext)
141 except ParseError, e:
142 print '%(file)s:%(name)s:%(message)s' % {
144 'name': e.__class__.__name__,