~ubuntu-branches/ubuntu/karmic/calibre/karmic

« back to all changes in this revision

Viewing changes to src/calibre/ebooks/lrf/rtf/convert_from.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-30 12:49:41 UTC
  • mfrom: (1.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730124941-qjdsmri25zt8zocn
Tags: 0.6.3+dfsg-0ubuntu1
* New upstream release. Please see http://calibre.kovidgoyal.net/new_in_6/
  for the list of new features and changes.
* remove_postinstall.patch: Update for new version.
* build_debug.patch: Does not apply any more, disable for now. Might not be
  necessary any more.
* debian/copyright: Fix reference to versionless GPL.
* debian/rules: Drop obsolete dh_desktop call.
* debian/rules: Add workaround for weird Python 2.6 setuptools behaviour of
  putting compiled .so files into src/calibre/plugins/calibre/plugins
  instead of src/calibre/plugins.
* debian/rules: Drop hal fdi moving, new upstream version does not use hal
  any more. Drop hal dependency, too.
* debian/rules: Install udev rules into /lib/udev/rules.d.
* Add debian/calibre.preinst: Remove unmodified
  /etc/udev/rules.d/95-calibre.rules on upgrade.
* debian/control: Bump Python dependencies to 2.6, since upstream needs
  it now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
__license__   = 'GPL v3'
2
 
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
3
 
import os, sys, shutil, logging, glob
4
 
 
5
 
from lxml import etree
6
 
 
7
 
from calibre.ebooks.lrf import option_parser as lrf_option_parser
8
 
from calibre.ebooks.metadata.meta import get_metadata
9
 
from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
10
 
from calibre import setup_cli_handlers
11
 
from calibre.libwand import convert, WandException
12
 
from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup
13
 
from calibre.ebooks.lrf.rtf.xsl import xhtml
14
 
from calibre.ebooks.rtf2xml.ParseRtf import RtfInvalidCodeException
15
 
from calibre.ptempfile import PersistentTemporaryDirectory
16
 
from calibre.ebooks.metadata import MetaInformation
17
 
from calibre.ebooks.metadata.opf import OPFCreator 
18
 
 
19
 
def option_parser():
20
 
    parser = lrf_option_parser(
21
 
_('''%prog [options] mybook.rtf
22
 
 
23
 
 
24
 
%prog converts mybook.rtf to mybook.lrf''')
25
 
        )
26
 
    parser.add_option('--keep-intermediate-files', action='store_true', default=False)
27
 
    return parser
28
 
 
29
 
def convert_images(html, logger):
30
 
    wmfs = glob.glob('*.wmf') + glob.glob('*.WMF')
31
 
    for wmf in wmfs:
32
 
        target = os.path.join(os.path.dirname(wmf), os.path.splitext(os.path.basename(wmf))[0]+'.jpg')
33
 
        try:
34
 
            convert(wmf, target)
35
 
            html = html.replace(os.path.basename(wmf), os.path.basename(target))
36
 
        except WandException, err:
37
 
            logger.warning(u'Unable to convert image %s with error: %s'%(wmf, unicode(err)))
38
 
            continue
39
 
    return html
40
 
 
41
 
def process_file(path, options, logger=None):
42
 
    if logger is None:
43
 
        level = logging.DEBUG if options.verbose else logging.INFO
44
 
        logger = logging.getLogger('rtf2lrf')
45
 
        setup_cli_handlers(logger, level)
46
 
    rtf = os.path.abspath(os.path.expanduser(path))
47
 
    f = open(rtf, 'rb')
48
 
    mi = get_metadata(f, 'rtf')
49
 
    f.close()
50
 
    tdir = PersistentTemporaryDirectory('_rtf2lrf')
51
 
    html = generate_html(rtf, tdir)
52
 
    cwd = os.getcwdu()
53
 
    try:
54
 
        if not options.output:
55
 
            ext = '.lrs' if options.lrs else '.lrf'
56
 
            options.output = os.path.abspath(os.path.basename(os.path.splitext(path)[0]) + ext)
57
 
        options.output = os.path.abspath(os.path.expanduser(options.output))
58
 
        if not mi.title:
59
 
            mi.title = os.path.splitext(os.path.basename(rtf))[0]
60
 
        if (not options.title or options.title == 'Unknown'):
61
 
            options.title = mi.title
62
 
        if (not options.author or options.author == 'Unknown') and mi.author:
63
 
            options.author = mi.author
64
 
        if (not options.category or options.category == 'Unknown') and mi.category:
65
 
            options.category = mi.category
66
 
        if (not options.freetext or options.freetext == 'Unknown') and mi.comments:
67
 
            options.freetext = mi.comments
68
 
        os.chdir(tdir)
69
 
        html_process_file(html, options, logger)
70
 
    finally:
71
 
        os.chdir(cwd)
72
 
        if hasattr(options, 'keep_intermediate_files') and options.keep_intermediate_files:
73
 
            logger.debug('Intermediate files in '+ tdir)
74
 
        else:
75
 
            shutil.rmtree(tdir)
76
 
 
77
 
def main(args=sys.argv, logger=None):
78
 
    parser = option_parser()
79
 
    options, args = parser.parse_args(args)
80
 
    if len(args) != 2:
81
 
        parser.print_help()
82
 
        print
83
 
        print 'No rtf file specified'
84
 
        return 1
85
 
    process_file(args[1], options, logger)
86
 
    return 0
87
 
    
88
 
 
89
 
def generate_xml(rtfpath, tdir):
90
 
    from calibre.ebooks.rtf2xml.ParseRtf import ParseRtf
91
 
    ofile = os.path.join(tdir, 'index.xml')
92
 
    cwd = os.getcwdu()
93
 
    os.chdir(tdir)
94
 
    rtfpath = os.path.abspath(rtfpath)
95
 
    try:
96
 
        parser = ParseRtf(
97
 
            in_file    = rtfpath,
98
 
            out_file   = ofile,
99
 
            # Convert symbol fonts to unicode equivelents. Default
100
 
            # is 1
101
 
            convert_symbol = 1,
102
 
    
103
 
            # Convert Zapf fonts to unicode equivelents. Default
104
 
            # is 1.
105
 
            convert_zapf = 1,
106
 
    
107
 
            # Convert Wingding fonts to unicode equivelents.
108
 
            # Default is 1.
109
 
            convert_wingdings = 1,
110
 
    
111
 
            # Convert RTF caps to real caps.
112
 
            # Default is 1.
113
 
            convert_caps = 1,
114
 
    
115
 
            # Indent resulting XML.
116
 
            # Default is 0 (no indent).
117
 
            indent = 1,
118
 
    
119
 
            # Form lists from RTF. Default is 1.
120
 
            form_lists = 1,
121
 
    
122
 
            # Convert headings to sections. Default is 0.
123
 
            headings_to_sections = 1,
124
 
    
125
 
            # Group paragraphs with the same style name. Default is 1.
126
 
            group_styles = 1,
127
 
    
128
 
            # Group borders. Default is 1.
129
 
            group_borders = 1,
130
 
    
131
 
            # Write or do not write paragraphs. Default is 0.
132
 
            empty_paragraphs = 0,
133
 
        )
134
 
        parser.parse_rtf()
135
 
    finally:
136
 
        os.chdir(cwd)
137
 
    return ofile
138
 
 
139
 
 
140
 
def generate_html(rtfpath, tdir):
141
 
    print 'Converting RTF to XML...'
142
 
    rtfpath = os.path.abspath(rtfpath)
143
 
    try:
144
 
        xml = generate_xml(rtfpath, tdir)
145
 
    except RtfInvalidCodeException:
146
 
        raise Exception(_('This RTF file has a feature calibre does not support. Convert it to HTML and then convert it.'))
147
 
    tdir = os.path.dirname(xml)
148
 
    cwd = os.getcwdu()
149
 
    os.chdir(tdir)
150
 
    try:
151
 
        print 'Parsing XML...'
152
 
        parser = etree.XMLParser(recover=True, no_network=True)
153
 
        try:
154
 
            doc = etree.parse(xml, parser)
155
 
        except:
156
 
            raise
157
 
            print 'Parsing failed. Trying to clean up XML...'
158
 
            soup = BeautifulStoneSoup(open(xml, 'rb').read())
159
 
            doc = etree.fromstring(str(soup))
160
 
        print 'Converting XML to HTML...'
161
 
        styledoc = etree.fromstring(xhtml)
162
 
        
163
 
        transform = etree.XSLT(styledoc)
164
 
        result = transform(doc)
165
 
        tdir = os.path.dirname(xml)
166
 
        html = os.path.join(tdir, 'index.html')
167
 
        f = open(html, 'wb')
168
 
        res = transform.tostring(result)
169
 
        res = res[:100].replace('xmlns:html', 'xmlns') + res[100:]
170
 
        f.write(res)
171
 
        f.close()
172
 
        try:
173
 
            mi = get_metadata(open(rtfpath, 'rb'), 'rtf')
174
 
        except:
175
 
            mi = MetaInformation(None, None)
176
 
        if not mi.title:
177
 
            mi.title = os.path.splitext(os.path.basename(rtfpath))[0]
178
 
        if not mi.authors:
179
 
            mi.authors = [_('Unknown')]
180
 
        opf = OPFCreator(tdir, mi)
181
 
        opf.create_manifest([('index.html', None)])
182
 
        opf.create_spine(['index.html'])
183
 
        opf.render(open('metadata.opf', 'wb'))
184
 
    finally:
185
 
        os.chdir(cwd)
186
 
    return html
187
 
            
188
 
if __name__ == '__main__':
189
 
    sys.exit(main())    
190
 
        
 
 
b'\\ No newline at end of file'