home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / Calibre / calibre-0.8.18.msi / file_262 / HTMLParser.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-09-09  |  9.8 KB  |  315 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.7)
  3.  
  4. import markupbase
  5. import re
  6. interesting_normal = re.compile('[&<]')
  7. interesting_cdata = re.compile('<(/|\\Z)')
  8. incomplete = re.compile('&[a-zA-Z#]')
  9. entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
  10. charref = re.compile('&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]')
  11. starttagopen = re.compile('<[a-zA-Z]')
  12. piclose = re.compile('>')
  13. commentclose = re.compile('--\\s*>')
  14. tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*')
  15. attrfind = re.compile('\\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\\s*=\\s*(\\\'[^\\\']*\\\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\\(\\)_#=~@]*))?')
  16. locatestarttagend = re.compile('\n  <[a-zA-Z][-.a-zA-Z0-9:_]*          # tag name\n  (?:\\s+                             # whitespace before attribute name\n    (?:[a-zA-Z_][-.:a-zA-Z0-9_]*     # attribute name\n      (?:\\s*=\\s*                     # value indicator\n        (?:\'[^\']*\'                   # LITA-enclosed value\n          |\\"[^\\"]*\\"                # LIT-enclosed value\n          |[^\'\\">\\s]+                # bare value\n         )\n       )?\n     )\n   )*\n  \\s*                                # trailing whitespace\n', re.VERBOSE)
  17. endendtag = re.compile('>')
  18. endtagfind = re.compile('</\\s*([a-zA-Z][-.a-zA-Z0-9:_]*)\\s*>')
  19.  
  20. class HTMLParseError(Exception):
  21.     
  22.     def __init__(self, msg, position = (None, None)):
  23.         self.msg = msg
  24.         self.lineno = position[0]
  25.         self.offset = position[1]
  26.  
  27.     
  28.     def __str__(self):
  29.         result = self.msg
  30.         if self.lineno is not None:
  31.             result = result + ', at line %d' % self.lineno
  32.         if self.offset is not None:
  33.             result = result + ', column %d' % (self.offset + 1)
  34.         return result
  35.  
  36.  
  37.  
  38. class HTMLParser(markupbase.ParserBase):
  39.     CDATA_CONTENT_ELEMENTS = ('script', 'style')
  40.     
  41.     def __init__(self):
  42.         self.reset()
  43.  
  44.     
  45.     def reset(self):
  46.         self.rawdata = ''
  47.         self.lasttag = '???'
  48.         self.interesting = interesting_normal
  49.         markupbase.ParserBase.reset(self)
  50.  
  51.     
  52.     def feed(self, data):
  53.         self.rawdata = self.rawdata + data
  54.         self.goahead(0)
  55.  
  56.     
  57.     def close(self):
  58.         self.goahead(1)
  59.  
  60.     
  61.     def error(self, message):
  62.         raise HTMLParseError(message, self.getpos())
  63.  
  64.     __starttag_text = None
  65.     
  66.     def get_starttag_text(self):
  67.         return self._HTMLParser__starttag_text
  68.  
  69.     
  70.     def set_cdata_mode(self):
  71.         self.interesting = interesting_cdata
  72.  
  73.     
  74.     def clear_cdata_mode(self):
  75.         self.interesting = interesting_normal
  76.  
  77.     
  78.     def goahead(self, end):
  79.         rawdata = self.rawdata
  80.         i = 0
  81.         n = len(rawdata)
  82.         while i < n:
  83.             match = self.interesting.search(rawdata, i)
  84.             if match:
  85.                 j = match.start()
  86.             else:
  87.                 j = n
  88.             if i < j:
  89.                 self.handle_data(rawdata[i:j])
  90.             i = self.updatepos(i, j)
  91.             if i == n:
  92.                 break
  93.             startswith = rawdata.startswith
  94.             if startswith('<', i):
  95.                 if starttagopen.match(rawdata, i):
  96.                     k = self.parse_starttag(i)
  97.                 elif startswith('</', i):
  98.                     k = self.parse_endtag(i)
  99.                 elif startswith('<!--', i):
  100.                     k = self.parse_comment(i)
  101.                 elif startswith('<?', i):
  102.                     k = self.parse_pi(i)
  103.                 elif startswith('<!', i):
  104.                     k = self.parse_declaration(i)
  105.                 elif i + 1 < n:
  106.                     self.handle_data('<')
  107.                     k = i + 1
  108.                 else:
  109.                     break
  110.                 if k < 0:
  111.                     if end:
  112.                         self.error('EOF in middle of construct')
  113.                     break
  114.                 i = self.updatepos(i, k)
  115.                 continue
  116.             if startswith('&#', i):
  117.                 match = charref.match(rawdata, i)
  118.                 if match:
  119.                     name = match.group()[2:-1]
  120.                     self.handle_charref(name)
  121.                     k = match.end()
  122.                     if not startswith(';', k - 1):
  123.                         k = k - 1
  124.                     i = self.updatepos(i, k)
  125.                     continue
  126.                 elif ';' in rawdata[i:]:
  127.                     self.handle_data(rawdata[0:2])
  128.                     i = self.updatepos(i, 2)
  129.                 break
  130.                 continue
  131.             if startswith('&', i):
  132.                 match = entityref.match(rawdata, i)
  133.                 if match:
  134.                     name = match.group(1)
  135.                     self.handle_entityref(name)
  136.                     k = match.end()
  137.                     if not startswith(';', k - 1):
  138.                         k = k - 1
  139.                     i = self.updatepos(i, k)
  140.                     continue
  141.                 match = incomplete.match(rawdata, i)
  142.                 if match:
  143.                     if end and match.group() == rawdata[i:]:
  144.                         self.error('EOF in middle of entity or char ref')
  145.                     break
  146.                 elif i + 1 < n:
  147.                     self.handle_data('&')
  148.                     i = self.updatepos(i, i + 1)
  149.                 else:
  150.                     break
  151.             if end and i < n:
  152.                 self.handle_data(rawdata[i:n])
  153.                 i = self.updatepos(i, n)
  154.             self.rawdata = rawdata[i:]
  155.             return None
  156.  
  157.     
  158.     def parse_pi(self, i):
  159.         rawdata = self.rawdata
  160.         match = piclose.search(rawdata, i + 2)
  161.         if not match:
  162.             return -1
  163.         j = None.start()
  164.         self.handle_pi(rawdata[i + 2:j])
  165.         j = match.end()
  166.         return j
  167.  
  168.     
  169.     def parse_starttag(self, i):
  170.         self._HTMLParser__starttag_text = None
  171.         endpos = self.check_for_whole_start_tag(i)
  172.         if endpos < 0:
  173.             return endpos
  174.         rawdata = None.rawdata
  175.         self._HTMLParser__starttag_text = rawdata[i:endpos]
  176.         attrs = []
  177.         match = tagfind.match(rawdata, i + 1)
  178.         k = match.end()
  179.         self.lasttag = tag = rawdata[i + 1:k].lower()
  180.         while k < endpos:
  181.             m = attrfind.match(rawdata, k)
  182.             if not m:
  183.                 break
  184.             (attrname, rest, attrvalue) = m.group(1, 2, 3)
  185.             if not rest:
  186.                 attrvalue = None
  187.             elif "'" == "'":
  188.                 pass
  189.             elif not "'" == "'" == attrvalue[-1:]:
  190.                 if '"' == '"':
  191.                     pass
  192.                 elif '"' == attrvalue[-1:]:
  193.                     attrvalue = attrvalue[1:-1]
  194.                     attrvalue = self.unescape(attrvalue)
  195.                 attrs.append((attrname.lower(), attrvalue))
  196.                 k = m.end()
  197.             end = rawdata[k:endpos].strip()
  198.             if end not in ('>', '/>'):
  199.                 (lineno, offset) = self.getpos()
  200.                 self.error('junk characters in start tag: %r' % (rawdata[k:endpos][:20],))
  201.         return endpos
  202.  
  203.     
  204.     def check_for_whole_start_tag(self, i):
  205.         rawdata = self.rawdata
  206.         m = locatestarttagend.match(rawdata, i)
  207.         if m:
  208.             j = m.end()
  209.             next = rawdata[j:j + 1]
  210.             if next == '>':
  211.                 return j + 1
  212.             if None == '/':
  213.                 if rawdata.startswith('/>', j):
  214.                     return j + 2
  215.                 if None.startswith('/', j):
  216.                     return -1
  217.                 None.updatepos(i, j + 1)
  218.                 self.error('malformed empty start tag')
  219.             if next == '':
  220.                 return -1
  221.             if None in 'abcdefghijklmnopqrstuvwxyz=/ABCDEFGHIJKLMNOPQRSTUVWXYZ':
  222.                 return -1
  223.             None.updatepos(i, j)
  224.             self.error('malformed start tag')
  225.         raise AssertionError('we should not get here!')
  226.  
  227.     
  228.     def parse_endtag(self, i):
  229.         rawdata = self.rawdata
  230.         match = endendtag.search(rawdata, i + 1)
  231.         if not match:
  232.             return -1
  233.         j = None.end()
  234.         match = endtagfind.match(rawdata, i)
  235.         if not match:
  236.             self.error('bad end tag: %r' % (rawdata[i:j],))
  237.         tag = match.group(1)
  238.         self.handle_endtag(tag.lower())
  239.         self.clear_cdata_mode()
  240.         return j
  241.  
  242.     
  243.     def handle_startendtag(self, tag, attrs):
  244.         self.handle_starttag(tag, attrs)
  245.         self.handle_endtag(tag)
  246.  
  247.     
  248.     def handle_starttag(self, tag, attrs):
  249.         pass
  250.  
  251.     
  252.     def handle_endtag(self, tag):
  253.         pass
  254.  
  255.     
  256.     def handle_charref(self, name):
  257.         pass
  258.  
  259.     
  260.     def handle_entityref(self, name):
  261.         pass
  262.  
  263.     
  264.     def handle_data(self, data):
  265.         pass
  266.  
  267.     
  268.     def handle_comment(self, data):
  269.         pass
  270.  
  271.     
  272.     def handle_decl(self, decl):
  273.         pass
  274.  
  275.     
  276.     def handle_pi(self, data):
  277.         pass
  278.  
  279.     
  280.     def unknown_decl(self, data):
  281.         self.error('unknown declaration: %r' % (data,))
  282.  
  283.     entitydefs = None
  284.     
  285.     def unescape(self, s):
  286.         if '&' not in s:
  287.             return s
  288.         
  289.         def replaceEntities(s):
  290.             s = s.groups()[0]
  291.             if s[0] == '#':
  292.                 s = s[1:]
  293.                 if s[0] in ('x', 'X'):
  294.                     c = int(s[1:], 16)
  295.                 else:
  296.                     c = int(s)
  297.                 return unichr(c)
  298.             import htmlentitydefs
  299.             if HTMLParser.entitydefs is None:
  300.                 entitydefs = HTMLParser.entitydefs = {
  301.                     'apos': u"'" }
  302.                 for k, v in htmlentitydefs.name2codepoint.iteritems():
  303.                     entitydefs[k] = unichr(v)
  304.                 
  305.             
  306.             try:
  307.                 return self.entitydefs[s]
  308.             except KeyError:
  309.                 return '&' + s + ';'
  310.  
  311.  
  312.         return re.sub('&(#?[xX]?(?:[0-9a-fA-F]+|\\w{1,8}));', replaceEntities, s)
  313.  
  314.  
  315.