home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_998 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  21.7 KB  |  691 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.         MetaInformation = MetaInformation
  134.         import calibre.ebooks.metadata
  135.         meta_info_to_oeb_metadata = meta_info_to_oeb_metadata
  136.         import calibre.ebooks.oeb.transforms.metadata
  137.         stream = cStringIO.StringIO(etree.tostring(opf))
  138.         mi = MetaInformation(OPF(stream))
  139.         if not mi.language:
  140.             mi.language = get_lang().replace('_', '-')
  141.         
  142.         self.oeb.metadata.add('language', mi.language)
  143.         if not mi.title:
  144.             mi.title = self.oeb.translate(__('Unknown'))
  145.         
  146.         if not mi.authors:
  147.             mi.authors = [
  148.                 self.oeb.translate(__('Unknown'))]
  149.         
  150.         if not mi.book_producer:
  151.             mi.book_producer = '%(a)s (%(v)s) [http://%(a)s.kovidgoyal.net]' % dict(a = __appname__, v = __version__)
  152.         
  153.         meta_info_to_oeb_metadata(mi, self.oeb.metadata, self.logger)
  154.         self.oeb.metadata.add('identifier', str(uuid.uuid4()), id = 'uuid_id', scheme = 'uuid')
  155.         self.oeb.uid = self.oeb.metadata.identifier[-1]
  156.  
  157.     
  158.     def _manifest_prune_invalid(self):
  159.         bad = []
  160.         check = OEB_DOCS.union(OEB_STYLES)
  161.         for item in list(self.oeb.manifest.values()):
  162.             if item.media_type in check:
  163.                 
  164.                 try:
  165.                     item.data
  166.                 self.logger.exception('Failed to parse content in %s' % item.href)
  167.                 bad.append(item)
  168.                 self.oeb.manifest.remove(item)
  169.  
  170.                 continue
  171.         
  172.         return bad
  173.  
  174.     
  175.     def _manifest_add_missing(self, invalid):
  176.         manifest = self.oeb.manifest
  177.         known = set(manifest.hrefs)
  178.         unchecked = set(manifest.values())
  179.         while unchecked:
  180.             new = set()
  181.             for item in unchecked:
  182.                 if (item.media_type in OEB_DOCS or item.media_type[-4:] in ('/xml', '+xml')) and item.data is not None:
  183.                     hrefs = [ r[2] for r in iterlinks(item.data) ]
  184.                     for href in hrefs:
  185.                         (href, _) = urldefrag(href)
  186.                         href = item.abshref(urlnormalize(href))
  187.                         scheme = urlparse(href).scheme
  188.                         if not scheme and href not in known:
  189.                             new.add(href)
  190.                             continue
  191.                         None if not href else []
  192.                     
  193.                 if item.media_type in OEB_STYLES:
  194.                     for url in cssutils.getUrls(item.data):
  195.                         (href, _) = urldefrag(url)
  196.                         href = item.abshref(urlnormalize(href))
  197.                         scheme = urlparse(href).scheme
  198.                         if not scheme and href not in known:
  199.                             new.add(href)
  200.                             continue
  201.                     
  202.             
  203.             unchecked.clear()
  204.             warned = set([])
  205.             for href in new:
  206.                 known.add(href)
  207.                 is_invalid = False
  208.                 for item in invalid:
  209.                     if href == item.abshref(urlnormalize(href)):
  210.                         is_invalid = True
  211.                         break
  212.                         continue
  213.                 
  214.                 if is_invalid:
  215.                     continue
  216.                 
  217.                 if not self.oeb.container.exists(href):
  218.                     if href not in warned:
  219.                         self.logger.warn('Referenced file %r not found' % href)
  220.                         warned.add(href)
  221.                         continue
  222.                     continue
  223.                 
  224.                 if href not in warned:
  225.                     self.logger.warn('Referenced file %r not in manifest' % href)
  226.                     warned.add(href)
  227.                 
  228.                 (id, _) = manifest.generate(id = 'added')
  229.                 guessed = guess_type(href)[0]
  230.                 if not guessed:
  231.                     pass
  232.                 media_type = BINARY_MIME
  233.                 added = manifest.add(id, href, media_type)
  234.                 unchecked.add(added)
  235.             
  236.  
  237.     
  238.     def _manifest_from_opf(self, opf):
  239.         manifest = self.oeb.manifest
  240.         for elem in xpath(opf, '/o2:package/o2:manifest/o2:item'):
  241.             id = elem.get('id')
  242.             href = elem.get('href')
  243.             media_type = elem.get('media-type', None)
  244.             if media_type is None:
  245.                 media_type = elem.get('mediatype', None)
  246.             
  247.             if media_type is None or media_type == 'text/xml':
  248.                 guessed = guess_type(href)[0]
  249.                 if not guessed and media_type:
  250.                     pass
  251.                 media_type = BINARY_MIME
  252.             
  253.             if hasattr(media_type, 'lower'):
  254.                 media_type = media_type.lower()
  255.             
  256.             fallback = elem.get('fallback')
  257.             if href in manifest.hrefs:
  258.                 self.logger.warn(u'Duplicate manifest entry for %r' % href)
  259.                 continue
  260.             
  261.             if not self.oeb.container.exists(href):
  262.                 self.logger.warn(u'Manifest item %r not found' % href)
  263.                 continue
  264.             
  265.             if id in manifest.ids:
  266.                 self.logger.warn(u'Duplicate manifest id %r' % id)
  267.                 (id, href) = manifest.generate(id, href)
  268.             
  269.             manifest.add(id, href, media_type, fallback)
  270.         
  271.         invalid = self._manifest_prune_invalid()
  272.         self._manifest_add_missing(invalid)
  273.  
  274.     
  275.     def _spine_add_extra(self):
  276.         manifest = self.oeb.manifest
  277.         spine = self.oeb.spine
  278.         unchecked = set(spine)
  279.         selector = XPath('h:body//h:a/@href')
  280.         extras = set()
  281.         while unchecked:
  282.             new = set()
  283.             for item in unchecked:
  284.                 if item.media_type not in OEB_DOCS:
  285.                     continue
  286.                 
  287.                 for href in selector(item.data):
  288.                     (href, _) = urldefrag(href)
  289.                     if not href:
  290.                         continue
  291.                     
  292.                     href = item.abshref(urlnormalize(href))
  293.                     if href not in manifest.hrefs:
  294.                         continue
  295.                     
  296.                     found = manifest.hrefs[href]
  297.                     if found.media_type not in OEB_DOCS and found in spine or found in extras:
  298.                         continue
  299.                     
  300.                     new.add(found)
  301.                 
  302.             
  303.             extras.update(new)
  304.             unchecked = new
  305.         version = int(self.oeb.version[0])
  306.         for item in sorted(extras):
  307.             if version >= 2:
  308.                 self.logger.warn('Spine-referenced file %r not in spine' % item.href)
  309.             
  310.             spine.add(item, linear = False)
  311.         
  312.  
  313.     
  314.     def _spine_from_opf(self, opf):
  315.         spine = self.oeb.spine
  316.         manifest = self.oeb.manifest
  317.         for elem in xpath(opf, '/o2:package/o2:spine/o2:itemref'):
  318.             idref = elem.get('idref')
  319.             if idref not in manifest.ids:
  320.                 self.logger.warn(u'Spine item %r not found' % idref)
  321.                 continue
  322.             
  323.             item = manifest.ids[idref]
  324.             spine.add(item, elem.get('linear'))
  325.         
  326.         if len(spine) == 0:
  327.             raise OEBError('Spine is empty')
  328.         len(spine) == 0
  329.         self._spine_add_extra()
  330.  
  331.     
  332.     def _guide_from_opf(self, opf):
  333.         guide = self.oeb.guide
  334.         manifest = self.oeb.manifest
  335.         for elem in xpath(opf, '/o2:package/o2:guide/o2:reference'):
  336.             href = elem.get('href')
  337.             path = urldefrag(href)[0]
  338.             if path not in manifest.hrefs:
  339.                 self.logger.warn(u'Guide reference %r not found' % href)
  340.                 continue
  341.             
  342.             guide.add(elem.get('type'), elem.get('title'), href)
  343.         
  344.  
  345.     
  346.     def _find_ncx(self, opf):
  347.         result = xpath(opf, '/o2:package/o2:spine/@toc')
  348.         if result:
  349.             id = result[0]
  350.             if id not in self.oeb.manifest.ids:
  351.                 return None
  352.             item = self.oeb.manifest.ids[id]
  353.             self.oeb.manifest.remove(item)
  354.             return item
  355.         for item in self.oeb.manifest.values():
  356.             if item.media_type == NCX_MIME:
  357.                 self.oeb.manifest.remove(item)
  358.                 return item
  359.         
  360.  
  361.     
  362.     def _toc_from_navpoint(self, item, toc, navpoint):
  363.         children = xpath(navpoint, 'ncx:navPoint')
  364.         for child in children:
  365.             title = ''.join(xpath(child, 'ncx:navLabel/ncx:text/text()'))
  366.             title = COLLAPSE_RE.sub(' ', title.strip())
  367.             href = xpath(child, 'ncx:content/@src')
  368.             if not title or not href:
  369.                 continue
  370.             
  371.             href = item.abshref(urlnormalize(href[0]))
  372.             (path, _) = urldefrag(href)
  373.             if path not in self.oeb.manifest.hrefs:
  374.                 self.logger.warn('TOC reference %r not found' % href)
  375.                 continue
  376.             
  377.             id = child.get('id')
  378.             klass = child.get('class', 'chapter')
  379.             
  380.             try:
  381.                 po = int(child.get('playOrder', self.oeb.toc.next_play_order()))
  382.             except:
  383.                 po = self.oeb.toc.next_play_order()
  384.  
  385.             authorElement = xpath(child, 'descendant::calibre:meta[@name = "author"]')
  386.             if authorElement:
  387.                 author = authorElement[0].text
  388.             else:
  389.                 author = None
  390.             descriptionElement = xpath(child, 'descendant::calibre:meta[@name = "description"]')
  391.             if descriptionElement:
  392.                 description = etree.tostring(descriptionElement[0], method = 'text', encoding = unicode).strip()
  393.                 if not description:
  394.                     description = None
  395.                 
  396.             else:
  397.                 description = None
  398.             node = toc.add(title, href, id = id, klass = klass, play_order = po, description = description, author = author)
  399.             self._toc_from_navpoint(item, node, child)
  400.         
  401.  
  402.     
  403.     def _toc_from_ncx(self, item):
  404.         if item is None or item.data is None:
  405.             return False
  406.         self.log.debug('Reading TOC from NCX...')
  407.         ncx = item.data
  408.         title = ''.join(xpath(ncx, 'ncx:docTitle/ncx:text/text()'))
  409.         title = COLLAPSE_RE.sub(' ', title.strip())
  410.         if not title:
  411.             pass
  412.         title = unicode(self.oeb.metadata.title[0])
  413.         toc = self.oeb.toc
  414.         toc.title = title
  415.         navmaps = xpath(ncx, 'ncx:navMap')
  416.         for navmap in navmaps:
  417.             self._toc_from_navpoint(item, toc, navmap)
  418.         
  419.         return True
  420.  
  421.     
  422.     def _toc_from_tour(self, opf):
  423.         result = xpath(opf, 'o2:tours/o2:tour')
  424.         if not result:
  425.             return False
  426.         self.log.debug('Reading TOC from tour...')
  427.         tour = result[0]
  428.         toc = self.oeb.toc
  429.         toc.title = tour.get('title')
  430.         sites = xpath(tour, 'o2:site')
  431.         for site in sites:
  432.             title = site.get('title')
  433.             href = site.get('href')
  434.             if not title or not href:
  435.                 continue
  436.             
  437.             (path, _) = urldefrag(urlnormalize(href))
  438.             if path not in self.oeb.manifest.hrefs:
  439.                 self.logger.warn('TOC reference %r not found' % href)
  440.                 continue
  441.             
  442.             id = site.get('id')
  443.             toc.add(title, href, id = id)
  444.         
  445.         return True
  446.  
  447.     
  448.     def _toc_from_html(self, opf):
  449.         if 'toc' not in self.oeb.guide:
  450.             return False
  451.         self.log.debug('Reading TOC from HTML...')
  452.         (itempath, frag) = urldefrag(self.oeb.guide['toc'].href)
  453.         item = self.oeb.manifest.hrefs[itempath]
  454.         html = item.data
  455.         titles = defaultdict(list)
  456.         order = []
  457.         for anchor in xpath(html, './/h:a[@href]'):
  458.             href = anchor.attrib['href']
  459.             href = item.abshref(urlnormalize(href))
  460.             (path, frag) = urldefrag(href)
  461.             if path not in self.oeb.manifest.hrefs:
  462.                 continue
  463.             
  464.             title = ' '.join(xpath(anchor, './/text()'))
  465.             title = COLLAPSE_RE.sub(' ', title.strip())
  466.             if href not in titles:
  467.                 order.append(href)
  468.             
  469.             titles[href].append(title)
  470.         
  471.         toc = self.oeb.toc
  472.         for href in order:
  473.             toc.add(' '.join(titles[href]), href)
  474.         
  475.         return True
  476.  
  477.     
  478.     def _toc_from_spine(self, opf):
  479.         self.log.warn('Generating default TOC from spine...')
  480.         toc = self.oeb.toc
  481.         titles = []
  482.         headers = []
  483.         for item in self.oeb.spine:
  484.             if not item.linear:
  485.                 continue
  486.             
  487.             html = item.data
  488.             title = ''.join(xpath(html, '/h:html/h:head/h:title/text()'))
  489.             title = COLLAPSE_RE.sub(' ', title.strip())
  490.             if title:
  491.                 titles.append(title)
  492.             
  493.             headers.append('(unlabled)')
  494.             for tag in ('h1', 'h2', 'h3', 'h4', 'h5', 'strong'):
  495.                 expr = '/h:html/h:body//h:%s[position()=1]/text()'
  496.                 header = ''.join(xpath(html, expr % tag))
  497.                 header = COLLAPSE_RE.sub(' ', header.strip())
  498.                 if header:
  499.                     headers[-1] = header
  500.                     break
  501.                     continue
  502.             
  503.         
  504.         use = titles
  505.         if len(titles) > len(set(titles)):
  506.             use = headers
  507.         
  508.         for title, item in izip(use, self.oeb.spine):
  509.             if not item.linear:
  510.                 continue
  511.             
  512.             toc.add(title, item.href)
  513.         
  514.         return True
  515.  
  516.     
  517.     def _toc_from_opf(self, opf, item):
  518.         self.oeb.auto_generated_toc = False
  519.         if self._toc_from_ncx(item):
  520.             return None
  521.         if self._toc_from_html(opf):
  522.             return None
  523.         if self._toc_from_tour(opf):
  524.             return None
  525.         self._toc_from_spine(opf)
  526.         self.oeb.auto_generated_toc = True
  527.  
  528.     
  529.     def _pages_from_ncx(self, opf, item):
  530.         if item is None:
  531.             return False
  532.         ncx = item.data
  533.         if ncx is None:
  534.             return False
  535.         ptargets = xpath(ncx, 'ncx:pageList/ncx:pageTarget')
  536.         if not ptargets:
  537.             return False
  538.         pages = self.oeb.pages
  539.         for ptarget in ptargets:
  540.             name = ''.join(xpath(ptarget, 'ncx:navLabel/ncx:text/text()'))
  541.             name = COLLAPSE_RE.sub(' ', name.strip())
  542.             href = xpath(ptarget, 'ncx:content/@src')
  543.             href = item.abshref(urlnormalize(href[0]))
  544.             id = ptarget.get('id')
  545.             type = ptarget.get('type', 'normal')
  546.             klass = ptarget.get('class')
  547.             pages.add(name, href, type = type, id = id, klass = klass)
  548.         
  549.         return True
  550.  
  551.     
  552.     def _find_page_map(self, opf):
  553.         result = xpath(opf, '/o2:package/o2:spine/@page-map')
  554.         if result:
  555.             id = result[0]
  556.             if id not in self.oeb.manifest.ids:
  557.                 return None
  558.             item = self.oeb.manifest.ids[id]
  559.             self.oeb.manifest.remove(item)
  560.             return item
  561.         for item in self.oeb.manifest.values():
  562.             if item.media_type == PAGE_MAP_MIME:
  563.                 self.oeb.manifest.remove(item)
  564.                 return item
  565.         
  566.  
  567.     
  568.     def _pages_from_page_map(self, opf):
  569.         item = self._find_page_map(opf)
  570.         if item is None:
  571.             return False
  572.         pmap = item.data
  573.         pages = self.oeb.pages
  574.         for page in xpath(pmap, 'o2:page'):
  575.             name = page.get('name', '')
  576.             href = page.get('href')
  577.             if not href:
  578.                 continue
  579.             
  580.             name = COLLAPSE_RE.sub(' ', name.strip())
  581.             href = item.abshref(urlnormalize(href))
  582.             type = 'normal'
  583.             if not name:
  584.                 type = 'special'
  585.             elif name.lower().strip('ivxlcdm') == '':
  586.                 type = 'front'
  587.             
  588.             pages.add(name, href, type = type)
  589.         
  590.         return True
  591.  
  592.     
  593.     def _pages_from_opf(self, opf, item):
  594.         if self._pages_from_ncx(opf, item):
  595.             return None
  596.         if self._pages_from_page_map(opf):
  597.             return None
  598.  
  599.     
  600.     def _cover_from_html(self, hcover):
  601.         render_html_svg_workaround = render_html_svg_workaround
  602.         import calibre.ebooks
  603.         
  604.         try:
  605.             tdir = _[1]
  606.             writer = OEBWriter()
  607.             writer(self.oeb, tdir)
  608.             path = os.path.join(tdir, urlunquote(hcover.href))
  609.             data = render_html_svg_workaround(path, self.logger)
  610.             if not data:
  611.                 data = ''
  612.         finally:
  613.             pass
  614.  
  615.         (id, href) = self.oeb.manifest.generate('cover', 'cover.jpeg')
  616.         item = self.oeb.manifest.add(id, href, JPEG_MIME, data = data)
  617.         return item
  618.  
  619.     
  620.     def _locate_cover_image(self):
  621.         if self.oeb.metadata.cover:
  622.             id = unicode(self.oeb.metadata.cover[0])
  623.             item = self.oeb.manifest.ids.get(id, None)
  624.             if item is not None and item.media_type in OEB_IMAGES:
  625.                 return item
  626.             self.logger.warn('Invalid cover image @id %r' % id)
  627.         
  628.         hcover = self.oeb.spine[0]
  629.         if 'cover' in self.oeb.guide:
  630.             href = self.oeb.guide['cover'].href
  631.             item = self.oeb.manifest.hrefs[href]
  632.             media_type = item.media_type
  633.             if media_type in OEB_IMAGES:
  634.                 return item
  635.             if media_type in OEB_DOCS:
  636.                 hcover = item
  637.             
  638.         
  639.         html = hcover.data
  640.         if MS_COVER_TYPE in self.oeb.guide:
  641.             href = self.oeb.guide[MS_COVER_TYPE].href
  642.             item = self.oeb.manifest.hrefs.get(href, None)
  643.             if item is not None and item.media_type in OEB_IMAGES:
  644.                 return item
  645.         
  646.         if self.COVER_SVG_XP(html):
  647.             svg = copy.deepcopy(self.COVER_SVG_XP(html)[0])
  648.             href = os.path.splitext(hcover.href)[0] + '.svg'
  649.             (id, href) = self.oeb.manifest.generate(hcover.id, href)
  650.             item = self.oeb.manifest.add(id, href, SVG_MIME, data = svg)
  651.             return item
  652.         return self._cover_from_html(hcover)
  653.  
  654.     
  655.     def _ensure_cover_image(self):
  656.         cover = self._locate_cover_image()
  657.         if self.oeb.metadata.cover:
  658.             self.oeb.metadata.cover[0].value = cover.id
  659.             return None
  660.         self.oeb.metadata.add('cover', cover.id)
  661.  
  662.     
  663.     def _all_from_opf(self, opf):
  664.         self.oeb.version = opf.get('version', '1.2')
  665.         self._metadata_from_opf(opf)
  666.         self._manifest_from_opf(opf)
  667.         self._spine_from_opf(opf)
  668.         self._guide_from_opf(opf)
  669.         item = self._find_ncx(opf)
  670.         self._toc_from_opf(opf, item)
  671.         self._pages_from_opf(opf, item)
  672.  
  673.  
  674.  
  675. def main(argv = sys.argv):
  676.     reader = OEBReader()
  677.     for arg in argv[1:]:
  678.         oeb = reader(OEBBook(), arg)
  679.         for name, doc in oeb.to_opf1().values():
  680.             print etree.tostring(doc, pretty_print = True)
  681.         
  682.         for name, doc in oeb.to_opf2(page_map = True).values():
  683.             print etree.tostring(doc, pretty_print = True)
  684.         
  685.     
  686.     return 0
  687.  
  688. if __name__ == '__main__':
  689.     sys.exit(main())
  690.  
  691.