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

« back to all changes in this revision

Viewing changes to src/calibre/ebooks/lrf/any/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
 
from __future__ import with_statement
2
 
__license__   = 'GPL v3'
3
 
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
4
 
'''Convert any ebook file into a LRF file.'''
5
 
 
6
 
import sys, os, logging, shutil, tempfile, re
7
 
 
8
 
from calibre.ebooks import UnknownFormatError
9
 
from calibre.ebooks.lrf import option_parser as _option_parser
10
 
from calibre import __appname__, setup_cli_handlers, extract
11
 
from calibre.ptempfile import TemporaryDirectory
12
 
from calibre.ebooks.lrf.lit.convert_from  import process_file as lit2lrf
13
 
from calibre.ebooks.lrf.pdf.convert_from  import process_file as pdf2lrf
14
 
from calibre.ebooks.lrf.rtf.convert_from  import process_file as rtf2lrf
15
 
from calibre.ebooks.lrf.txt.convert_from  import process_file as txt2lrf
16
 
from calibre.ebooks.lrf.html.convert_from import process_file as html2lrf
17
 
from calibre.ebooks.lrf.epub.convert_from import process_file as epub2lrf
18
 
from calibre.ebooks.lrf.mobi.convert_from import process_file as mobi2lrf
19
 
from calibre.ebooks.lrf.fb2.convert_from  import process_file as fb22lrf
20
 
 
21
 
from calibre.customize.ui import run_plugins_on_postprocess, run_plugins_on_preprocess
22
 
 
23
 
def largest_file(files):
24
 
    maxsize, file = 0, None
25
 
    for f in files:
26
 
        size = os.stat(f).st_size
27
 
        if size > maxsize:
28
 
            maxsize = size
29
 
            file = f
30
 
    return file
31
 
 
32
 
def find_htmlfile(dir):
33
 
    ext_pat = re.compile(r'\.(x){0,1}htm(l){0,1}', re.IGNORECASE)
34
 
    toc_pat = re.compile(r'toc', re.IGNORECASE)
35
 
    index_pat = re.compile(r'index', re.IGNORECASE)
36
 
    toc_files, index_files, files = [], [], []
37
 
    
38
 
    for root, dirs, _files in os.walk(dir):
39
 
        for f in _files:
40
 
            f = os.path.abspath(os.path.join(root, f))
41
 
            ext = os.path.splitext(f)[1]
42
 
            if ext and ext_pat.match(ext):
43
 
                toc_files.append(f) if toc_pat.search(f) else \
44
 
                index_files.append(f) if index_pat.search(f) else \
45
 
                files.append(f)
46
 
    a = toc_files if toc_files else index_files if index_files else files
47
 
    if a:
48
 
        return largest_file(a)
49
 
 
50
 
def number_of_unhidden_files(base, listing):
51
 
    ans = 0
52
 
    for i in listing:
53
 
        i = os.path.join(base, i)
54
 
        if os.path.isdir(i) or os.path.basename(i).startswith('.'):
55
 
            continue
56
 
        ans += 1
57
 
    return ans
58
 
 
59
 
def unhidden_directories(base, listing):
60
 
    ans = []
61
 
    for i in listing:
62
 
        if os.path.isdir(os.path.join(base, i)) and not i.startswith('__') and \
63
 
           not i.startswith('.'):
64
 
            ans.append(i)
65
 
    return ans
66
 
 
67
 
def traverse_subdirs(tdir):
68
 
    temp = os.listdir(tdir)
69
 
    if number_of_unhidden_files(tdir, temp) == 0:
70
 
        try:
71
 
            cdir = os.path.join(tdir, unhidden_directories(tdir, temp)[0])
72
 
            return traverse_subdirs(cdir)
73
 
        except IndexError:
74
 
            pass
75
 
    return tdir
76
 
 
77
 
def handle_archive(path):
78
 
    tdir = tempfile.mkdtemp(prefix=__appname__+'_'+'archive_')
79
 
    extract(path, tdir)
80
 
    files = []
81
 
    cdir = traverse_subdirs(tdir)
82
 
    file = None
83
 
    exts = ['lit', 'rtf', 'fb2','pdf', 'txt', 'epub', 'mobi', 'prc']
84
 
    candidates = map(lambda x:os.path.join(cdir, x), os.listdir(cdir))
85
 
    for ext in exts:
86
 
        for f in candidates:
87
 
            if f.lower().endswith('.'+ext):
88
 
                files.append(f)
89
 
    file = largest_file(files)
90
 
    if not file:
91
 
        file = find_htmlfile(cdir)
92
 
    if isinstance(file, str):
93
 
        file = file.decode(sys.getfilesystemencoding())
94
 
    return tdir, file 
95
 
 
96
 
def odt2lrf(path, options, logger):
97
 
    from calibre.ebooks.odt.to_oeb import Extract
98
 
    from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
99
 
    
100
 
    if logger is None:
101
 
        level = logging.DEBUG if options.verbose else logging.INFO
102
 
        logger = logging.getLogger('odt2lrf')
103
 
        setup_cli_handlers(logger, level)
104
 
        
105
 
    with TemporaryDirectory('_odt2lrf') as tdir:
106
 
        opf = Extract()(path, tdir)
107
 
        options.use_spine = True
108
 
        options.encoding = 'utf-8'
109
 
        html_process_file(opf.replace('metadata.opf', 'index.html'), options, logger)
110
 
 
111
 
def process_file(path, options, logger=None):
112
 
    path = os.path.abspath(os.path.expanduser(path))
113
 
    path = run_plugins_on_preprocess(path)
114
 
    tdir = None
115
 
    if logger is None:
116
 
        level = logging.DEBUG if options.verbose else logging.INFO
117
 
        logger = logging.getLogger('any2lrf')
118
 
        setup_cli_handlers(logger, level)
119
 
    if not os.access(path, os.R_OK):
120
 
        logger.critical('Cannot read from %s', path)
121
 
        return 1
122
 
    ext = os.path.splitext(path)[1]
123
 
    if not ext or ext == '.':
124
 
        logger.critical('Unknown file type: %s', path)
125
 
        return 1
126
 
    ext = ext[1:].lower()
127
 
    cwd = os.getcwd()
128
 
    if not options.output:
129
 
        fmt = '.lrs' if options.lrs else '.lrf'
130
 
        options.output = os.path.splitext(os.path.basename(path))[0] + fmt
131
 
    options.output = os.path.abspath(os.path.expanduser(options.output))
132
 
    if ext in ['zip', 'rar', 'oebzip']:
133
 
        newpath = None
134
 
        try:
135
 
            tdir, newpath = handle_archive(path)
136
 
        except:
137
 
            logger.exception(' ')
138
 
        if not newpath:
139
 
            raise UnknownFormatError('Could not find ebook in archive')
140
 
        path = newpath
141
 
        logger.info('Found ebook in archive: %s', repr(path))
142
 
    try:
143
 
        ext = os.path.splitext(path)[1][1:].lower()
144
 
        convertor = None
145
 
        if 'htm' in ext:
146
 
            convertor = html2lrf
147
 
        elif 'lit' == ext:
148
 
            convertor = lit2lrf
149
 
        elif 'pdf' == ext:
150
 
            convertor = pdf2lrf
151
 
        elif 'rtf' == ext:
152
 
            convertor = rtf2lrf
153
 
        elif 'txt' == ext:
154
 
            convertor = txt2lrf
155
 
        elif 'epub' == ext:
156
 
            convertor = epub2lrf
157
 
        elif ext in ['mobi', 'prc', 'azw']:
158
 
            convertor = mobi2lrf
159
 
        elif ext == 'fb2':
160
 
            convertor = fb22lrf
161
 
        elif ext == 'odt':
162
 
            convertor = odt2lrf
163
 
        if not convertor:
164
 
            raise UnknownFormatError(_('Converting from %s to LRF is not supported.')%ext)
165
 
        convertor(path, options, logger)
166
 
        
167
 
    finally:
168
 
        os.chdir(cwd)
169
 
        if tdir and os.path.exists(tdir):
170
 
            shutil.rmtree(tdir)
171
 
    return 0
172
 
    
173
 
 
174
 
def option_parser(gui_mode=False):
175
 
    return _option_parser(usage=_('''\
176
 
any2lrf [options] myfile
177
 
 
178
 
Convert any ebook format into LRF. Supported formats are:
179
 
LIT, RTF, TXT, HTML, EPUB, MOBI, PRC and PDF. any2lrf will also process a RAR or
180
 
ZIP archive, looking for an ebook inside the archive.
181
 
    '''), gui_mode=gui_mode)
182
 
 
183
 
 
184
 
def main(args=sys.argv, logger=None, gui_mode=False):
185
 
    parser = option_parser(gui_mode) 
186
 
    options, args = parser.parse_args(args)
187
 
    if len(args) != 2:
188
 
        parser.print_help()
189
 
        print
190
 
        print _('No file to convert specified.')
191
 
        return 1
192
 
    
193
 
    src = args[1]
194
 
    if not isinstance(src, unicode):
195
 
        src = src.decode(sys.getfilesystemencoding())
196
 
    return process_file(src, options, logger)
197
 
 
198
 
if __name__ == '__main__':
199
 
    sys.exit(main())