home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / calibre-0.7.26.msi / file_996 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-10-31  |  21.9 KB  |  696 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. __license__ = 'GPL v3'
  6. __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
  7. import sys
  8. import os
  9. import uuid
  10. import copy
  11. import re
  12. import cStringIO
  13. from itertools import izip
  14. from urlparse import urldefrag, urlparse
  15. from urllib import unquote as urlunquote
  16. from mimetypes import guess_type
  17. from collections import defaultdict
  18. from lxml import etree
  19. import cssutils
  20. from calibre.ebooks.oeb.base import OPF1_NS, OPF2_NS, OPF2_NSMAP, DC11_NS, DC_NSES, OPF
  21. from calibre.ebooks.oeb.base import OEB_DOCS, OEB_STYLES, OEB_IMAGES, PAGE_MAP_MIME, JPEG_MIME, NCX_MIME, SVG_MIME
  22. from calibre.ebooks.oeb.base import XMLDECL_RE, COLLAPSE_RE, ENTITY_RE, MS_COVER_TYPE, iterlinks
  23. from calibre.ebooks.oeb.base import namespace, barename, XPath, xpath, urlnormalize, BINARY_MIME, OEBError, OEBBook, DirContainer
  24. from calibre.ebooks.oeb.writer import OEBWriter
  25. from calibre.ebooks.oeb.entitydefs import ENTITYDEFS
  26. from calibre.utils.localization import get_lang
  27. from calibre.ptempfile import TemporaryDirectory
  28. from calibre.constants import __appname__, __version__
  29. __all__ = [
  30.     'OEBReader']
  31.  
  32. class OEBReader(object):
  33.     COVER_SVG_XP = XPath('h:body//svg:svg[position() = 1]')
  34.     COVER_OBJECT_XP = XPath('h:body//h:object[@data][position() = 1]')
  35.     Container = DirContainer
  36.     DEFAULT_PROFILE = 'PRS505'
  37.     TRANSFORMS = []
  38.     
  39.     def config(cls, cfg):
  40.         pass
  41.  
  42.     config = classmethod(config)
  43.     
  44.     def generate(cls, opts):
  45.         return cls()
  46.  
  47.     generate = classmethod(generate)
  48.     
  49.     def __call__(self, oeb, path):
  50.         self.oeb = oeb
  51.         self.logger = self.log = oeb.logger
  52.         oeb.container = self.Container(path, self.logger)
  53.         oeb.container.log = oeb.log
  54.         opf = self._read_opf()
  55.         self._all_from_opf(opf)
  56.         return oeb
  57.  
  58.     
  59.     def _clean_opf(self, opf):
  60.         nsmap = { }
  61.         for elem in opf.iter(tag = etree.Element):
  62.             nsmap.update(elem.nsmap)
  63.         
  64.         for elem in opf.iter(tag = etree.Element):
  65.             if namespace(elem.tag) in ('', OPF1_NS):
  66.                 elem.tag = OPF(barename(elem.tag))
  67.                 continue
  68.         
  69.         nsmap.update(OPF2_NSMAP)
  70.         attrib = dict(opf.attrib)
  71.         nroot = etree.Element(OPF('package'), nsmap = {
  72.             None: OPF2_NS }, attrib = attrib)
  73.         metadata = etree.SubElement(nroot, OPF('metadata'), nsmap = nsmap)
  74.         ignored = (OPF('dc-metadata'), OPF('x-metadata'))
  75.         for elem in xpath(opf, 'o2:metadata//*'):
  76.             if elem.tag in ignored:
  77.                 continue
  78.             
  79.             if namespace(elem.tag) in DC_NSES:
  80.                 tag = barename(elem.tag).lower()
  81.                 elem.tag = '{%s}%s' % (DC11_NS, tag)
  82.             
  83.             metadata.append(elem)
  84.         
  85.         for element in xpath(opf, 'o2:metadata//o2:meta'):
  86.             metadata.append(element)
  87.         
  88.         for tag in ('o2:manifest', 'o2:spine', 'o2:tours', 'o2:guide'):
  89.             for element in xpath(opf, tag):
  90.                 nroot.append(element)
  91.             
  92.         
  93.         return nroot
  94.  
  95.     
  96.     def _read_opf(self):
  97.         data = self.oeb.container.read(None)
  98.         data = self.oeb.decode(data)
  99.         data = XMLDECL_RE.sub('', data)
  100.         
  101.         try:
  102.             opf = etree.fromstring(data)
  103.         except etree.XMLSyntaxError:
  104.             
  105.             repl = lambda m: ENTITYDEFS.get(m.group(1), m.group(0))
  106.             data = ENTITY_RE.sub(repl, data)
  107.             
  108.             try:
  109.                 opf = etree.fromstring(data)
  110.                 self.logger.warn('OPF contains invalid HTML named entities')
  111.             except etree.XMLSyntaxError:
  112.                 data = re.sub('(?is)<tours>.+</tours>', '', data)
  113.                 self.logger.warn('OPF contains invalid tours section')
  114.                 data = data.replace('<dc-metadata>', '<dc-metadata xmlns:dc="http://purl.org/metadata/dublin_core">')
  115.                 opf = etree.fromstring(data)
  116.             except:
  117.                 None<EXCEPTION MATCH>etree.XMLSyntaxError
  118.             
  119.  
  120.             None<EXCEPTION MATCH>etree.XMLSyntaxError
  121.  
  122.         ns = namespace(opf.tag)
  123.         if ns not in ('', OPF1_NS, OPF2_NS):
  124.             raise OEBError('Invalid namespace %r for OPF document' % ns)
  125.         ns not in ('', OPF1_NS, OPF2_NS)
  126.         opf = self._clean_opf(opf)
  127.         return opf
  128.  
  129.     
  130.     def _metadata_from_opf(self, opf):
  131.         OPF = OPF
  132.         import calibre.ebooks.metadata.opf2
  133.         meta_info_to_oeb_metadata = meta_info_to_oeb_metadata
  134.         import calibre.ebooks.oeb.transforms.metadata
  135.         stream = cStringIO.StringIO(etree.tostring(opf))
  136.         mi = OPF(stream).to_book_metadata()
  137.         if not mi.language:
  138.             mi.language = get_lang().replace('_', '-')
  139.         
  140.         self.oeb.metadata.add('language', mi.language)
  141.         if not mi.book_producer:
  142.             mi.book_producer = '%(a)s (%(v)s) [http://%(a)s-ebook.com]' % dict(a = __appname__, v = __version__)
  143.         
  144.         meta_info_to_oeb_metadata(mi, self.oeb.metadata, self.logger)
  145.         m = self.oeb.metadata
  146.         m.add('identifier', str(uuid.uuid4()), id = 'uuid_id', scheme = 'uuid')
  147.         self.oeb.uid = self.oeb.metadata.identifier[-1]
  148.         if not m.title:
  149.             m.add('title', self.oeb.translate(__('Unknown')))
  150.         
  151.         has_aut = False
  152.         for x in m.creator:
  153.             if getattr(x, 'role', '').lower() in ('', 'aut'):
  154.                 has_aut = True
  155.                 break
  156.                 continue
  157.         
  158.         if not has_aut:
  159.             m.add('creator', self.oeb.translate(__('Unknown')), role = 'aut')
  160.         
  161.  
  162.     
  163.     def _manifest_prune_invalid(self):
  164.         bad = []
  165.         check = OEB_DOCS.union(OEB_STYLES)
  166.         for item in list(self.oeb.manifest.values()):
  167.             if item.media_type in check:
  168.                 
  169.                 try:
  170.                     item.data
  171.                 self.logger.exception('Failed to parse content in %s' % item.href)
  172.                 bad.append(item)
  173.                 self.oeb.manifest.remove(item)
  174.  
  175.                 continue
  176.         
  177.         return bad
  178.  
  179.     
  180.     def _manifest_add_missing(self, invalid):
  181.         manifest = self.oeb.manifest
  182.         known = set(manifest.hrefs)
  183.         unchecked = set(manifest.values())
  184.         while unchecked:
  185.             new = set()
  186.             for item in unchecked:
  187.                 if (item.media_type in OEB_DOCS or item.media_type[-4:] in ('/xml', '+xml')) and item.data is not None:
  188.                     hrefs = [ r[2] for r in iterlinks(item.data) ]
  189.                     for href in hrefs:
  190.                         (href, _) = urldefrag(href)
  191.                         href = item.abshref(urlnormalize(href))
  192.                         scheme = urlparse(href).scheme
  193.                         if not scheme and href not in known:
  194.                             new.add(href)
  195.                             continue
  196.                         None if not href else []
  197.                     
  198.                 if item.media_type in OEB_STYLES:
  199.                     for url in cssutils.getUrls(item.data):
  200.                         (href, _) = urldefrag(url)
  201.                         href = item.abshref(urlnormalize(href))
  202.                         scheme = urlparse(href).scheme
  203.                         if not scheme and href not in known:
  204.                             new.add(href)
  205.                             continue
  206.                     
  207.             
  208.             unchecked.clear()
  209.             warned = set([])
  210.             for href in new:
  211.                 known.add(href)
  212.                 is_invalid = False
  213.                 for item in invalid:
  214.                     if href == item.abshref(urlnormalize(href)):
  215.                         is_invalid = True
  216.                         break
  217.                         continue
  218.                 
  219.                 if is_invalid:
  220.                     continue
  221.                 
  222.                 if not self.oeb.container.exists(href):
  223.                     if href not in warned:
  224.                         self.logger.warn('Referenced file %r not found' % href)
  225.                         warned.add(href)
  226.                         continue
  227.                     continue
  228.                 
  229.                 if href not in warned:
  230.                     self.logger.warn('Referenced file %r not in manifest' % href)
  231.                     warned.add(href)
  232.                 
  233.                 (id, _) = manifest.generate(id = 'added')
  234.                 guessed = guess_type(href)[0]
  235.                 if not guessed:
  236.                     pass
  237.                 media_type = BINARY_MIME
  238.                 added = manifest.add(id, href, media_type)
  239.                 unchecked.add(added)
  240.             
  241.  
  242.     
  243.     def _manifest_from_opf(self, opf):
  244.         manifest = self.oeb.manifest
  245.         for elem in xpath(opf, '/o2:package/o2:manifest/o2:item'):
  246.             id = elem.get('id')
  247.             href = elem.get('href')
  248.             media_type = elem.get('media-type', None)
  249.             if media_type is None:
  250.                 media_type = elem.get('mediatype', None)
  251.             
  252.             if media_type is None or media_type == 'text/xml':
  253.                 guessed = guess_type(href)[0]
  254.                 if not guessed and media_type:
  255.                     pass
  256.                 media_type = BINARY_MIME
  257.             
  258.             if hasattr(media_type, 'lower'):
  259.                 media_type = media_type.lower()
  260.             
  261.             fallback = elem.get('fallback')
  262.             if href in manifest.hrefs:
  263.                 self.logger.warn(u'Duplicate manifest entry for %r' % href)
  264.                 continue
  265.             
  266.             if not self.oeb.container.exists(href):
  267.                 self.logger.warn(u'Manifest item %r not found' % href)
  268.                 continue
  269.             
  270.             if id in manifest.ids:
  271.                 self.logger.warn(u'Duplicate manifest id %r' % id)
  272.                 (id, href) = manifest.generate(id, href)
  273.             
  274.             manifest.add(id, href, media_type, fallback)
  275.         
  276.         invalid = self._manifest_prune_invalid()
  277.         self._manifest_add_missing(invalid)
  278.  
  279.     
  280.     def _spine_add_extra(self):
  281.         manifest = self.oeb.manifest
  282.         spine = self.oeb.spine
  283.         unchecked = set(spine)
  284.         selector = XPath('h:body//h:a/@href')
  285.         extras = set()
  286.         while unchecked:
  287.             new = set()
  288.             for item in unchecked:
  289.                 if item.media_type not in OEB_DOCS:
  290.                     continue
  291.                 
  292.                 for href in selector(item.data):
  293.                     (href, _) = urldefrag(href)
  294.                     if not href:
  295.                         continue
  296.                     
  297.                     href = item.abshref(urlnormalize(href))
  298.                     if href not in manifest.hrefs:
  299.                         continue
  300.                     
  301.                     found = manifest.hrefs[href]
  302.                     if found.media_type not in OEB_DOCS and found in spine or found in extras:
  303.                         continue
  304.                     
  305.                     new.add(found)
  306.                 
  307.             
  308.             extras.update(new)
  309.             unchecked = new
  310.         version = int(self.oeb.version[0])
  311.         for item in sorted(extras):
  312.             if version >= 2:
  313.                 self.logger.warn('Spine-referenced file %r not in spine' % item.href)
  314.             
  315.             spine.add(item, linear = False)
  316.         
  317.  
  318.     
  319.     def _spine_from_opf(self, opf):
  320.         spine = self.oeb.spine
  321.         manifest = self.oeb.manifest
  322.         for elem in xpath(opf, '/o2:package/o2:spine/o2:itemref'):
  323.             idref = elem.get('idref')
  324.             if idref not in manifest.ids:
  325.                 self.logger.warn(u'Spine item %r not found' % idref)
  326.                 continue
  327.             
  328.             item = manifest.ids[idref]
  329.             spine.add(item, elem.get('linear'))
  330.         
  331.         if len(spine) == 0:
  332.             raise OEBError('Spine is empty')
  333.         len(spine) == 0
  334.         self._spine_add_extra()
  335.  
  336.     
  337.     def _guide_from_opf(self, opf):
  338.         guide = self.oeb.guide
  339.         manifest = self.oeb.manifest
  340.         for elem in xpath(opf, '/o2:package/o2:guide/o2:reference'):
  341.             href = elem.get('href')
  342.             path = urldefrag(href)[0]
  343.             if path not in manifest.hrefs:
  344.                 self.logger.warn(u'Guide reference %r not found' % href)
  345.                 continue
  346.             
  347.             guide.add(elem.get('type'), elem.get('title'), href)
  348.         
  349.  
  350.     
  351.     def _find_ncx(self, opf):
  352.         result = xpath(opf, '/o2:package/o2:spine/@toc')
  353.         if result:
  354.             id = result[0]
  355.             if id not in self.oeb.manifest.ids:
  356.                 return None
  357.             item = self.oeb.manifest.ids[id]
  358.             self.oeb.manifest.remove(item)
  359.             return item
  360.         for item in self.oeb.manifest.values():
  361.             if item.media_type == NCX_MIME:
  362.                 self.oeb.manifest.remove(item)
  363.                 return item
  364.         
  365.  
  366.     
  367.     def _toc_from_navpoint(self, item, toc, navpoint):
  368.         children = xpath(navpoint, 'ncx:navPoint')
  369.         for child in children:
  370.             title = ''.join(xpath(child, 'ncx:navLabel/ncx:text/text()'))
  371.             title = COLLAPSE_RE.sub(' ', title.strip())
  372.             href = xpath(child, 'ncx:content/@src')
  373.             if not title or not href:
  374.                 continue
  375.             
  376.             href = item.abshref(urlnormalize(href[0]))
  377.             (path, _) = urldefrag(href)
  378.             if path not in self.oeb.manifest.hrefs:
  379.                 self.logger.warn('TOC reference %r not found' % href)
  380.                 continue
  381.             
  382.             id = child.get('id')
  383.             klass = child.get('class', 'chapter')
  384.             
  385.             try:
  386.                 po = int(child.get('playOrder', self.oeb.toc.next_play_order()))
  387.             except:
  388.                 po = self.oeb.toc.next_play_order()
  389.  
  390.             authorElement = xpath(child, 'descendant::calibre:meta[@name = "author"]')
  391.             if authorElement:
  392.                 author = authorElement[0].text
  393.             else:
  394.                 author = None
  395.             descriptionElement = xpath(child, 'descendant::calibre:meta[@name = "description"]')
  396.             if descriptionElement:
  397.                 description = etree.tostring(descriptionElement[0], method = 'text', encoding = unicode).strip()
  398.                 if not description:
  399.                     description = None
  400.                 
  401.             else:
  402.                 description = None
  403.             node = toc.add(title, href, id = id, klass = klass, play_order = po, description = description, author = author)
  404.             self._toc_from_navpoint(item, node, child)
  405.         
  406.  
  407.     
  408.     def _toc_from_ncx(self, item):
  409.         if item is None or item.data is None:
  410.             return False
  411.         self.log.debug('Reading TOC from NCX...')
  412.         ncx = item.data
  413.         title = ''.join(xpath(ncx, 'ncx:docTitle/ncx:text/text()'))
  414.         title = COLLAPSE_RE.sub(' ', title.strip())
  415.         if not title:
  416.             pass
  417.         title = unicode(self.oeb.metadata.title[0])
  418.         toc = self.oeb.toc
  419.         toc.title = title
  420.         navmaps = xpath(ncx, 'ncx:navMap')
  421.         for navmap in navmaps:
  422.             self._toc_from_navpoint(item, toc, navmap)
  423.         
  424.         return True
  425.  
  426.     
  427.     def _toc_from_tour(self, opf):
  428.         result = xpath(opf, 'o2:tours/o2:tour')
  429.         if not result:
  430.             return False
  431.         self.log.debug('Reading TOC from tour...')
  432.         tour = result[0]
  433.         toc = self.oeb.toc
  434.         toc.title = tour.get('title')
  435.         sites = xpath(tour, 'o2:site')
  436.         for site in sites:
  437.             title = site.get('title')
  438.             href = site.get('href')
  439.             if not title or not href:
  440.                 continue
  441.             
  442.             (path, _) = urldefrag(urlnormalize(href))
  443.             if path not in self.oeb.manifest.hrefs:
  444.                 self.logger.warn('TOC reference %r not found' % href)
  445.                 continue
  446.             
  447.             id = site.get('id')
  448.             toc.add(title, href, id = id)
  449.         
  450.         return True
  451.  
  452.     
  453.     def _toc_from_html(self, opf):
  454.         if 'toc' not in self.oeb.guide:
  455.             return False
  456.         self.log.debug('Reading TOC from HTML...')
  457.         (itempath, frag) = urldefrag(self.oeb.guide['toc'].href)
  458.         item = self.oeb.manifest.hrefs[itempath]
  459.         html = item.data
  460.         titles = defaultdict(list)
  461.         order = []
  462.         for anchor in xpath(html, './/h:a[@href]'):
  463.             href = anchor.attrib['href']
  464.             href = item.abshref(urlnormalize(href))
  465.             (path, frag) = urldefrag(href)
  466.             if path not in self.oeb.manifest.hrefs:
  467.                 continue
  468.             
  469.             title = ' '.join(xpath(anchor, './/text()'))
  470.             title = COLLAPSE_RE.sub(' ', title.strip())
  471.             if href not in titles:
  472.                 order.append(href)
  473.             
  474.             titles[href].append(title)
  475.         
  476.         toc = self.oeb.toc
  477.         for href in order:
  478.             toc.add(' '.join(titles[href]), href)
  479.         
  480.         return True
  481.  
  482.     
  483.     def _toc_from_spine(self, opf):
  484.         self.log.warn('Generating default TOC from spine...')
  485.         toc = self.oeb.toc
  486.         titles = []
  487.         headers = []
  488.         for item in self.oeb.spine:
  489.             if not item.linear:
  490.                 continue
  491.             
  492.             html = item.data
  493.             title = ''.join(xpath(html, '/h:html/h:head/h:title/text()'))
  494.             title = COLLAPSE_RE.sub(' ', title.strip())
  495.             if title:
  496.                 titles.append(title)
  497.             
  498.             headers.append('(unlabled)')
  499.             for tag in ('h1', 'h2', 'h3', 'h4', 'h5', 'strong'):
  500.                 expr = '/h:html/h:body//h:%s[position()=1]/text()'
  501.                 header = ''.join(xpath(html, expr % tag))
  502.                 header = COLLAPSE_RE.sub(' ', header.strip())
  503.                 if header:
  504.                     headers[-1] = header
  505.                     break
  506.                     continue
  507.             
  508.         
  509.         use = titles
  510.         if len(titles) > len(set(titles)):
  511.             use = headers
  512.         
  513.         for title, item in izip(use, self.oeb.spine):
  514.             if not item.linear:
  515.                 continue
  516.             
  517.             toc.add(title, item.href)
  518.         
  519.         return True
  520.  
  521.     
  522.     def _toc_from_opf(self, opf, item):
  523.         self.oeb.auto_generated_toc = False
  524.         if self._toc_from_ncx(item):
  525.             return None
  526.         if self._toc_from_html(opf):
  527.             return None
  528.         if self._toc_from_tour(opf):
  529.             return None
  530.         self._toc_from_spine(opf)
  531.         self.oeb.auto_generated_toc = True
  532.  
  533.     
  534.     def _pages_from_ncx(self, opf, item):
  535.         if item is None:
  536.             return False
  537.         ncx = item.data
  538.         if ncx is None:
  539.             return False
  540.         ptargets = xpath(ncx, 'ncx:pageList/ncx:pageTarget')
  541.         if not ptargets:
  542.             return False
  543.         pages = self.oeb.pages
  544.         for ptarget in ptargets:
  545.             name = ''.join(xpath(ptarget, 'ncx:navLabel/ncx:text/text()'))
  546.             name = COLLAPSE_RE.sub(' ', name.strip())
  547.             href = xpath(ptarget, 'ncx:content/@src')
  548.             href = item.abshref(urlnormalize(href[0]))
  549.             id = ptarget.get('id')
  550.             type = ptarget.get('type', 'normal')
  551.             klass = ptarget.get('class')
  552.             pages.add(name, href, type = type, id = id, klass = klass)
  553.         
  554.         return True
  555.  
  556.     
  557.     def _find_page_map(self, opf):
  558.         result = xpath(opf, '/o2:package/o2:spine/@page-map')
  559.         if result:
  560.             id = result[0]
  561.             if id not in self.oeb.manifest.ids:
  562.                 return None
  563.             item = self.oeb.manifest.ids[id]
  564.             self.oeb.manifest.remove(item)
  565.             return item
  566.         for item in self.oeb.manifest.values():
  567.             if item.media_type == PAGE_MAP_MIME:
  568.                 self.oeb.manifest.remove(item)
  569.                 return item
  570.         
  571.  
  572.     
  573.     def _pages_from_page_map(self, opf):
  574.         item = self._find_page_map(opf)
  575.         if item is None:
  576.             return False
  577.         pmap = item.data
  578.         pages = self.oeb.pages
  579.         for page in xpath(pmap, 'o2:page'):
  580.             name = page.get('name', '')
  581.             href = page.get('href')
  582.             if not href:
  583.                 continue
  584.             
  585.             name = COLLAPSE_RE.sub(' ', name.strip())
  586.             href = item.abshref(urlnormalize(href))
  587.             type = 'normal'
  588.             if not name:
  589.                 type = 'special'
  590.             elif name.lower().strip('ivxlcdm') == '':
  591.                 type = 'front'
  592.             
  593.             pages.add(name, href, type = type)
  594.         
  595.         return True
  596.  
  597.     
  598.     def _pages_from_opf(self, opf, item):
  599.         if self._pages_from_ncx(opf, item):
  600.             return None
  601.         if self._pages_from_page_map(opf):
  602.             return None
  603.  
  604.     
  605.     def _cover_from_html(self, hcover):
  606.         render_html_svg_workaround = render_html_svg_workaround
  607.         import calibre.ebooks
  608.         
  609.         try:
  610.             tdir = _[1]
  611.             writer = OEBWriter()
  612.             writer(self.oeb, tdir)
  613.             path = os.path.join(tdir, urlunquote(hcover.href))
  614.             data = render_html_svg_workaround(path, self.logger)
  615.             if not data:
  616.                 data = ''
  617.         finally:
  618.             pass
  619.  
  620.         (id, href) = self.oeb.manifest.generate('cover', 'cover.jpeg')
  621.         item = self.oeb.manifest.add(id, href, JPEG_MIME, data = data)
  622.         return item
  623.  
  624.     
  625.     def _locate_cover_image(self):
  626.         if self.oeb.metadata.cover:
  627.             id = unicode(self.oeb.metadata.cover[0])
  628.             item = self.oeb.manifest.ids.get(id, None)
  629.             if item is not None and item.media_type in OEB_IMAGES:
  630.                 return item
  631.             self.logger.warn('Invalid cover image @id %r' % id)
  632.         
  633.         hcover = self.oeb.spine[0]
  634.         if 'cover' in self.oeb.guide:
  635.             href = self.oeb.guide['cover'].href
  636.             item = self.oeb.manifest.hrefs[href]
  637.             media_type = item.media_type
  638.             if media_type in OEB_IMAGES:
  639.                 return item
  640.             if media_type in OEB_DOCS:
  641.                 hcover = item
  642.             
  643.         
  644.         html = hcover.data
  645.         if MS_COVER_TYPE in self.oeb.guide:
  646.             href = self.oeb.guide[MS_COVER_TYPE].href
  647.             item = self.oeb.manifest.hrefs.get(href, None)
  648.             if item is not None and item.media_type in OEB_IMAGES:
  649.                 return item
  650.         
  651.         if self.COVER_SVG_XP(html):
  652.             svg = copy.deepcopy(self.COVER_SVG_XP(html)[0])
  653.             href = os.path.splitext(hcover.href)[0] + '.svg'
  654.             (id, href) = self.oeb.manifest.generate(hcover.id, href)
  655.             item = self.oeb.manifest.add(id, href, SVG_MIME, data = svg)
  656.             return item
  657.         return self._cover_from_html(hcover)
  658.  
  659.     
  660.     def _ensure_cover_image(self):
  661.         cover = self._locate_cover_image()
  662.         if self.oeb.metadata.cover:
  663.             self.oeb.metadata.cover[0].value = cover.id
  664.             return None
  665.         self.oeb.metadata.add('cover', cover.id)
  666.  
  667.     
  668.     def _all_from_opf(self, opf):
  669.         self.oeb.version = opf.get('version', '1.2')
  670.         self._metadata_from_opf(opf)
  671.         self._manifest_from_opf(opf)
  672.         self._spine_from_opf(opf)
  673.         self._guide_from_opf(opf)
  674.         item = self._find_ncx(opf)
  675.         self._toc_from_opf(opf, item)
  676.         self._pages_from_opf(opf, item)
  677.  
  678.  
  679.  
  680. def main(argv = sys.argv):
  681.     reader = OEBReader()
  682.     for arg in argv[1:]:
  683.         oeb = reader(OEBBook(), arg)
  684.         for name, doc in oeb.to_opf1().values():
  685.             print etree.tostring(doc, pretty_print = True)
  686.         
  687.         for name, doc in oeb.to_opf2(page_map = True).values():
  688.             print etree.tostring(doc, pretty_print = True)
  689.         
  690.     
  691.     return 0
  692.  
  693. if __name__ == '__main__':
  694.     sys.exit(main())
  695.  
  696.