home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1618 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  10.4 KB  |  348 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __all__ = [
  5.     'buildlog',
  6.     'encodingByMediaType',
  7.     'getHTTPInfo',
  8.     'getMetaInfo',
  9.     'detectXMLEncoding',
  10.     'getEncodingInfo',
  11.     'tryEncodings',
  12.     'EncodingInfo']
  13. __docformat__ = 'restructuredtext'
  14. __author__ = 'Christof Hoeke, Robert Siemer'
  15. __version__ = '$Id: __init__.py 1712 2009-04-23 12:46:03Z cthedot $'
  16. import HTMLParser
  17. import StringIO
  18. import cgi
  19. import httplib
  20. import re
  21. import sys
  22. import types
  23. import urllib
  24. VERSION = '0.9'
  25.  
  26. class _MetaHTMLParser(HTMLParser.HTMLParser):
  27.     content_type = None
  28.     
  29.     def handle_starttag(self, tag, attrs):
  30.         pass
  31.  
  32.  
  33. _XML_APPLICATION_TYPE = 0
  34. _XML_TEXT_TYPE = 1
  35. _HTML_TEXT_TYPE = 2
  36. _TEXT_TYPE = 3
  37. _TEXT_UTF8 = 5
  38. _OTHER_TYPE = 4
  39.  
  40. class EncodingInfo(object):
  41.     
  42.     def __init__(self):
  43.         self.encoding = None
  44.         self.mismatch = None
  45.         self.logtext = None
  46.         self.http_encoding = None
  47.         self.http_media_type = None
  48.         self.meta_encoding = None
  49.         self.meta_media_type = None
  50.         self.xml_encoding = None
  51.  
  52.     
  53.     def __str__(self):
  54.         if self.encoding:
  55.             return self.encoding
  56.         return u''
  57.  
  58.     
  59.     def __repr__(self):
  60.         return '<%s.%s object encoding=%r mismatch=%s at 0x%x>' % (self.__class__.__module__, self.__class__.__name__, self.encoding, self.mismatch, id(self))
  61.  
  62.  
  63.  
  64. def buildlog(logname = 'encutils', level = 'INFO', stream = sys.stderr, filename = None, filemode = 'w', format = '%(levelname)s\t%(message)s'):
  65.     import logging
  66.     log = logging.getLogger(logname)
  67.     if filename:
  68.         hdlr = logging.FileHandler(filename, filemode)
  69.     else:
  70.         hdlr = logging.StreamHandler(stream)
  71.     formatter = logging.Formatter(format)
  72.     hdlr.setFormatter(formatter)
  73.     log.addHandler(hdlr)
  74.     log.setLevel(logging.__dict__.get(level, logging.INFO))
  75.     return log
  76.  
  77.  
  78. def _getTextTypeByMediaType(media_type, log = None):
  79.     if not media_type:
  80.         return _OTHER_TYPE
  81.     xml_application_types = [
  82.         u'application/.*?\\+xml',
  83.         u'application/xml',
  84.         u'application/xml-dtd',
  85.         u'application/xml-external-parsed-entity']
  86.     xml_text_types = [
  87.         u'text\\/.*?\\+xml',
  88.         u'text/xml',
  89.         u'text/xml-external-parsed-entity']
  90.     media_type = media_type.strip().lower()
  91.     if media_type in xml_application_types or re.match(xml_application_types[0], media_type, re.I | re.S | re.X):
  92.         return _XML_APPLICATION_TYPE
  93.     if media_type in xml_text_types or re.match(xml_text_types[0], media_type, re.I | re.S | re.X):
  94.         return _XML_TEXT_TYPE
  95.     if media_type == u'text/html':
  96.         return _HTML_TEXT_TYPE
  97.     if media_type == u'text/css':
  98.         return _TEXT_UTF8
  99.     if media_type.startswith(u'text/'):
  100.         return _TEXT_TYPE
  101.     return _OTHER_TYPE
  102.  
  103.  
  104. def _getTextType(text, log = None):
  105.     if text[:30].find(u'<?xml version=') != -1:
  106.         return _XML_APPLICATION_TYPE
  107.     return _OTHER_TYPE
  108.  
  109.  
  110. def encodingByMediaType(media_type, log = None):
  111.     defaultencodings = {
  112.         _XML_APPLICATION_TYPE: u'utf-8',
  113.         _XML_TEXT_TYPE: u'ascii',
  114.         _HTML_TEXT_TYPE: u'iso-8859-1',
  115.         _TEXT_TYPE: u'iso-8859-1',
  116.         _TEXT_UTF8: u'utf-8',
  117.         _OTHER_TYPE: None }
  118.     texttype = _getTextTypeByMediaType(media_type)
  119.     encoding = defaultencodings.get(texttype, None)
  120.     if log:
  121.         if not encoding:
  122.             log.debug(u'"%s" Media-Type has no default encoding', media_type)
  123.         else:
  124.             log.debug(u'Default encoding for Media Type "%s": %s', media_type, encoding)
  125.     
  126.     return encoding
  127.  
  128.  
  129. def getHTTPInfo(response, log = None):
  130.     info = response.info()
  131.     media_type = info.gettype()
  132.     encoding = info.getparam('charset')
  133.     if encoding:
  134.         encoding = encoding.lower()
  135.     
  136.     if log:
  137.         log.info(u'HTTP media_type: %s', media_type)
  138.         log.info(u'HTTP encoding: %s', encoding)
  139.     
  140.     return (media_type, encoding)
  141.  
  142.  
  143. def getMetaInfo(text, log = None):
  144.     p = _MetaHTMLParser()
  145.     
  146.     try:
  147.         p.feed(text)
  148.     except HTMLParser.HTMLParseError:
  149.         e = None
  150.  
  151.     if p.content_type:
  152.         (media_type, params) = cgi.parse_header(p.content_type)
  153.         encoding = params.get('charset')
  154.         if encoding:
  155.             encoding = encoding.lower()
  156.         
  157.         if log:
  158.             log.info(u'HTML META media_type: %s', media_type)
  159.             log.info(u'HTML META encoding: %s', encoding)
  160.         
  161.     else:
  162.         media_type = None
  163.         encoding = None
  164.     return (media_type, encoding)
  165.  
  166.  
  167. def detectXMLEncoding(fp, log = None, includeDefault = True):
  168.     if type(fp) in types.StringTypes:
  169.         fp = StringIO.StringIO(fp)
  170.     
  171.     bomDict = {
  172.         (0, 0, 254, 255): 'utf_32_be',
  173.         (255, 254, 0, 0): 'utf_32_le',
  174.         (254, 255, None, None): 'utf_16_be',
  175.         (255, 254, None, None): 'utf_16_le',
  176.         (239, 187, 191, None): 'utf-8' }
  177.     oldFP = fp.tell()
  178.     fp.seek(0)
  179.     (byte1, byte2, byte3, byte4) = tuple(map(ord, fp.read(4)))
  180.     bomDetection = bomDict.get((byte1, byte2, byte3, byte4))
  181.     if not bomDetection:
  182.         bomDetection = bomDict.get((byte1, byte2, byte3, None))
  183.         if not bomDetection:
  184.             bomDetection = bomDict.get((byte1, byte2, None, None))
  185.         
  186.     
  187.     if bomDetection:
  188.         if log:
  189.             log.info(u'XML BOM encoding: %s' % bomDetection)
  190.         
  191.         fp.seek(oldFP)
  192.         return bomDetection
  193.     fp.seek(0)
  194.     buffer = fp.read(2048)
  195.     xmlDeclPattern = '\n    ^<\\?xml             # w/o BOM, xmldecl starts with <?xml at the first byte\n    .+?                 # some chars (version info), matched minimal\n    encoding=           # encoding attribute begins\n    ["\']                # attribute start delimiter\n    (?P<encstr>         # what\'s matched in the brackets will be named encstr\n     [^"\']+              # every character not delimiter (not overly exact!)\n    )                   # closes the brackets pair for the named group\n    ["\']                # attribute end delimiter\n    .*?                 # some chars optionally (standalone decl or whitespace)\n    \\?>                 # xmldecl end\n    '
  196.     xmlDeclRE = re.compile(xmlDeclPattern, re.VERBOSE)
  197.     match = xmlDeclRE.search(buffer)
  198.     fp.seek(oldFP)
  199.     if match:
  200.         enc = match.group('encstr').lower()
  201.         if log:
  202.             log.info(u'XML encoding="%s"' % enc)
  203.         
  204.         return enc
  205.     if includeDefault:
  206.         return u'utf-8'
  207.     return None
  208.  
  209.  
  210. def tryEncodings(text, log = None):
  211.     
  212.     try:
  213.         import chardet
  214.         encoding = chardet.detect(text)['encoding']
  215.     except ImportError:
  216.         msg = 'Using simplified encoding detection, you might want to install chardet.'
  217.         if log:
  218.             log.warn(msg)
  219.         else:
  220.             print msg
  221.         encodings = ('ascii', 'iso-8859-1', 'utf-8')
  222.         encoding = None
  223.         for e in encodings:
  224.             
  225.             try:
  226.                 text.decode(e)
  227.             except UnicodeDecodeError:
  228.                 continue
  229.  
  230.             if 'iso-8859-1' == e:
  231.                 
  232.                 try:
  233.                     if u'Γé¼' in text.decode('windows-1252'):
  234.                         return 'windows-1252'
  235.                 except UnicodeDecodeError:
  236.                     pass
  237.                 except:
  238.                     None<EXCEPTION MATCH>UnicodeDecodeError
  239.                 
  240.  
  241.             None<EXCEPTION MATCH>UnicodeDecodeError
  242.             return e
  243.         
  244.  
  245.     return encoding
  246.  
  247.  
  248. def getEncodingInfo(response = None, text = u'', log = None, url = None):
  249.     if url:
  250.         response = urllib.urlopen(url)
  251.     
  252.     if text is None:
  253.         
  254.         try:
  255.             text = response.read()
  256.         except IOError:
  257.             e = None
  258.         except:
  259.             None<EXCEPTION MATCH>IOError
  260.         
  261.  
  262.     None<EXCEPTION MATCH>IOError
  263.     if text is None:
  264.         text = ''
  265.     
  266.     encinfo = EncodingInfo()
  267.     logstream = StringIO.StringIO()
  268.     if not log:
  269.         log = buildlog(stream = logstream, format = '%(message)s')
  270.     
  271.     if response:
  272.         (encinfo.http_media_type, encinfo.http_encoding) = getHTTPInfo(response, log)
  273.         texttype = _getTextTypeByMediaType(encinfo.http_media_type, log)
  274.     else:
  275.         texttype = _getTextType(text, log)
  276.     if texttype == _XML_APPLICATION_TYPE:
  277.         
  278.         try:
  279.             encinfo.xml_encoding = detectXMLEncoding(text, log)
  280.         except (AttributeError, ValueError):
  281.             e = None
  282.             encinfo.xml_encoding = None
  283.         except:
  284.             None<EXCEPTION MATCH>(AttributeError, ValueError)
  285.         
  286.  
  287.     None<EXCEPTION MATCH>(AttributeError, ValueError)
  288.     if texttype == _HTML_TEXT_TYPE:
  289.         
  290.         try:
  291.             encinfo.xml_encoding = detectXMLEncoding(text, log, includeDefault = False)
  292.         except (AttributeError, ValueError):
  293.             e = None
  294.             encinfo.xml_encoding = None
  295.         except:
  296.             None<EXCEPTION MATCH>(AttributeError, ValueError)
  297.         
  298.  
  299.     None<EXCEPTION MATCH>(AttributeError, ValueError)
  300.     if texttype == _HTML_TEXT_TYPE or texttype == _TEXT_TYPE:
  301.         (encinfo.meta_media_type, encinfo.meta_encoding) = getMetaInfo(text, log)
  302.     
  303.     encinfo.encoding = encinfo.http_encoding
  304.     encinfo.mismatch = False
  305.     if texttype == _XML_APPLICATION_TYPE:
  306.         if not encinfo.encoding:
  307.             encinfo.encoding = encinfo.xml_encoding
  308.         
  309.     elif texttype == _HTML_TEXT_TYPE:
  310.         if not encinfo.encoding:
  311.             encinfo.encoding = encinfo.meta_encoding
  312.         
  313.         if not encinfo.encoding:
  314.             encinfo.encoding = encodingByMediaType(encinfo.http_media_type)
  315.         
  316.         if not encinfo.encoding:
  317.             encinfo.encoding = tryEncodings(text)
  318.         
  319.     elif texttype == _XML_TEXT_TYPE or texttype == _TEXT_TYPE:
  320.         if not encinfo.encoding:
  321.             encinfo.encoding = encodingByMediaType(encinfo.http_media_type)
  322.         
  323.     elif texttype == _TEXT_UTF8:
  324.         if not encinfo.encoding:
  325.             encinfo.encoding = encodingByMediaType(encinfo.http_media_type)
  326.         
  327.     
  328.     if encinfo.http_encoding and encinfo.xml_encoding and encinfo.http_encoding != encinfo.xml_encoding:
  329.         encinfo.mismatch = True
  330.         log.warn(u'"%s" (HTTP) != "%s" (XML) encoding mismatch' % (encinfo.http_encoding, encinfo.xml_encoding))
  331.     
  332.     if encinfo.http_encoding and encinfo.meta_encoding and encinfo.http_encoding != encinfo.meta_encoding:
  333.         encinfo.mismatch = True
  334.         log.warn(u'"%s" (HTTP) != "%s" (HTML <meta>) encoding mismatch' % (encinfo.http_encoding, encinfo.meta_encoding))
  335.     
  336.     if encinfo.xml_encoding and encinfo.meta_encoding and encinfo.xml_encoding != encinfo.meta_encoding:
  337.         encinfo.mismatch = True
  338.         log.warn(u'"%s" (XML) != "%s" (HTML <meta>) encoding mismatch' % (encinfo.xml_encoding, encinfo.meta_encoding))
  339.     
  340.     log.info(u'Encoding (probably): %s (Mismatch: %s)', encinfo.encoding, encinfo.mismatch)
  341.     encinfo.logtext = logstream.getvalue()
  342.     return encinfo
  343.  
  344. if __name__ == '__main__':
  345.     import pydoc
  346.     pydoc.help(__name__)
  347.  
  348.