home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / HTMLParser.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-11-11  |  11.8 KB  |  355 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''A parser for HTML and XHTML.'''
  5. import markupbase
  6. import re
  7. interesting_normal = re.compile('[&<]')
  8. interesting_cdata = re.compile('<(/|\\Z)')
  9. incomplete = re.compile('&[a-zA-Z#]')
  10. entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
  11. charref = re.compile('&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]')
  12. starttagopen = re.compile('<[a-zA-Z]')
  13. piclose = re.compile('>')
  14. commentclose = re.compile('--\\s*>')
  15. tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*')
  16. attrfind = re.compile('\\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\\s*=\\s*(\\\'[^\\\']*\\\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\\(\\)_#=~@]*))?')
  17. 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)
  18. endendtag = re.compile('>')
  19. endtagfind = re.compile('</\\s*([a-zA-Z][-.a-zA-Z0-9:_]*)\\s*>')
  20.  
  21. class HTMLParseError(Exception):
  22.     '''Exception raised for all parse errors.'''
  23.     
  24.     def __init__(self, msg, position = (None, None)):
  25.         if not msg:
  26.             raise AssertionError
  27.         self.msg = msg
  28.         self.lineno = position[0]
  29.         self.offset = position[1]
  30.  
  31.     
  32.     def __str__(self):
  33.         result = self.msg
  34.         if self.lineno is not None:
  35.             result = result + ', at line %d' % self.lineno
  36.         
  37.         if self.offset is not None:
  38.             result = result + ', column %d' % (self.offset + 1)
  39.         
  40.         return result
  41.  
  42.  
  43.  
  44. class HTMLParser(markupbase.ParserBase):
  45.     '''Find tags and other markup and call handler functions.
  46.  
  47.     Usage:
  48.         p = HTMLParser()
  49.         p.feed(data)
  50.         ...
  51.         p.close()
  52.  
  53.     Start tags are handled by calling self.handle_starttag() or
  54.     self.handle_startendtag(); end tags by self.handle_endtag().  The
  55.     data between tags is passed from the parser to the derived class
  56.     by calling self.handle_data() with the data as argument (the data
  57.     may be split up in arbitrary chunks).  Entity references are
  58.     passed by calling self.handle_entityref() with the entity
  59.     reference as the argument.  Numeric character references are
  60.     passed to self.handle_charref() with the string containing the
  61.     reference as the argument.
  62.     '''
  63.     CDATA_CONTENT_ELEMENTS = ('script', 'style')
  64.     
  65.     def __init__(self):
  66.         '''Initialize and reset this instance.'''
  67.         self.reset()
  68.  
  69.     
  70.     def reset(self):
  71.         '''Reset this instance.  Loses all unprocessed data.'''
  72.         self.rawdata = ''
  73.         self.lasttag = '???'
  74.         self.interesting = interesting_normal
  75.         markupbase.ParserBase.reset(self)
  76.  
  77.     
  78.     def feed(self, data):
  79.         """Feed data to the parser.
  80.  
  81.         Call this as often as you want, with as little or as much text
  82.         as you want (may include '
  83. ').
  84.         """
  85.         self.rawdata = self.rawdata + data
  86.         self.goahead(0)
  87.  
  88.     
  89.     def close(self):
  90.         '''Handle any buffered data.'''
  91.         self.goahead(1)
  92.  
  93.     
  94.     def error(self, message):
  95.         raise HTMLParseError(message, self.getpos())
  96.  
  97.     __starttag_text = None
  98.     
  99.     def get_starttag_text(self):
  100.         """Return full source of start tag: '<...>'."""
  101.         return self._HTMLParser__starttag_text
  102.  
  103.     
  104.     def set_cdata_mode(self):
  105.         self.interesting = interesting_cdata
  106.  
  107.     
  108.     def clear_cdata_mode(self):
  109.         self.interesting = interesting_normal
  110.  
  111.     
  112.     def goahead(self, end):
  113.         rawdata = self.rawdata
  114.         i = 0
  115.         n = len(rawdata)
  116.         while i < n:
  117.             match = self.interesting.search(rawdata, i)
  118.             if match:
  119.                 j = match.start()
  120.             else:
  121.                 j = n
  122.             if i < j:
  123.                 self.handle_data(rawdata[i:j])
  124.             
  125.             i = self.updatepos(i, j)
  126.             if i == n:
  127.                 break
  128.             
  129.             startswith = rawdata.startswith
  130.             if startswith('<', i):
  131.                 if starttagopen.match(rawdata, i):
  132.                     k = self.parse_starttag(i)
  133.                 elif startswith('</', i):
  134.                     k = self.parse_endtag(i)
  135.                 elif startswith('<!--', i):
  136.                     k = self.parse_comment(i)
  137.                 elif startswith('<?', i):
  138.                     k = self.parse_pi(i)
  139.                 elif startswith('<!', i):
  140.                     k = self.parse_declaration(i)
  141.                 elif i + 1 < n:
  142.                     self.handle_data('<')
  143.                     k = i + 1
  144.                 else:
  145.                     break
  146.                 if k < 0:
  147.                     if end:
  148.                         self.error('EOF in middle of construct')
  149.                     
  150.                     break
  151.                 
  152.                 i = self.updatepos(i, k)
  153.                 continue
  154.             if startswith('&#', i):
  155.                 match = charref.match(rawdata, i)
  156.                 if match:
  157.                     name = match.group()[2:-1]
  158.                     self.handle_charref(name)
  159.                     k = match.end()
  160.                     if not startswith(';', k - 1):
  161.                         k = k - 1
  162.                     
  163.                     i = self.updatepos(i, k)
  164.                     continue
  165.                 else:
  166.                     break
  167.             match
  168.             if startswith('&', i):
  169.                 match = entityref.match(rawdata, i)
  170.                 if match:
  171.                     name = match.group(1)
  172.                     self.handle_entityref(name)
  173.                     k = match.end()
  174.                     if not startswith(';', k - 1):
  175.                         k = k - 1
  176.                     
  177.                     i = self.updatepos(i, k)
  178.                     continue
  179.                 
  180.                 match = incomplete.match(rawdata, i)
  181.                 if match:
  182.                     if end and match.group() == rawdata[i:]:
  183.                         self.error('EOF in middle of entity or char ref')
  184.                     
  185.                     break
  186.                 elif i + 1 < n:
  187.                     self.handle_data('&')
  188.                     i = self.updatepos(i, i + 1)
  189.                 else:
  190.                     break
  191.             match
  192.             if not 0:
  193.                 raise AssertionError, 'interesting.search() lied'
  194.             continue
  195.             0
  196.         if end and i < n:
  197.             self.handle_data(rawdata[i:n])
  198.             i = self.updatepos(i, n)
  199.         
  200.         self.rawdata = rawdata[i:]
  201.  
  202.     
  203.     def parse_pi(self, i):
  204.         rawdata = self.rawdata
  205.         if not rawdata[i:i + 2] == '<?':
  206.             raise AssertionError, 'unexpected call to parse_pi()'
  207.         match = piclose.search(rawdata, i + 2)
  208.         if not match:
  209.             return -1
  210.         j = match.start()
  211.         self.handle_pi(rawdata[i + 2:j])
  212.         j = match.end()
  213.         return j
  214.  
  215.     
  216.     def parse_starttag(self, i):
  217.         self._HTMLParser__starttag_text = None
  218.         endpos = self.check_for_whole_start_tag(i)
  219.         if endpos < 0:
  220.             return endpos
  221.         rawdata = self.rawdata
  222.         self._HTMLParser__starttag_text = rawdata[i:endpos]
  223.         attrs = []
  224.         match = tagfind.match(rawdata, i + 1)
  225.         if not match:
  226.             raise AssertionError, 'unexpected call to parse_starttag()'
  227.         k = match.end()
  228.         while k < endpos:
  229.             m = attrfind.match(rawdata, k)
  230.             (attrname, rest, attrvalue) = m.group(1, 2, 3)
  231.             if not rest:
  232.                 attrvalue = None
  233.             elif "'" == "'":
  234.                 pass
  235.             elif not "'" == attrvalue[-1:]:
  236.                 if '"' == '"':
  237.                     pass
  238.                 elif '"' == attrvalue[-1:]:
  239.                     attrvalue = attrvalue[1:-1]
  240.                     attrvalue = self.unescape(attrvalue)
  241.                 
  242.             attrs.append((attrname.lower(), attrvalue))
  243.             k = m.end()
  244.             continue
  245.             attrvalue[:1]
  246.         end = rawdata[k:endpos].strip()
  247.         if end not in ('>', '/>'):
  248.             (lineno, offset) = self.getpos()
  249.             if '\n' in self._HTMLParser__starttag_text:
  250.                 lineno = lineno + self._HTMLParser__starttag_text.count('\n')
  251.                 offset = len(self._HTMLParser__starttag_text) - self._HTMLParser__starttag_text.rfind('\n')
  252.             else:
  253.                 offset = offset + len(self._HTMLParser__starttag_text)
  254.             self.error('junk characters in start tag: %r' % (rawdata[k:endpos][:20],))
  255.         
  256.         if end.endswith('/>'):
  257.             self.handle_startendtag(tag, attrs)
  258.         else:
  259.             self.handle_starttag(tag, attrs)
  260.             if tag in self.CDATA_CONTENT_ELEMENTS:
  261.                 self.set_cdata_mode()
  262.             
  263.         return endpos
  264.  
  265.     
  266.     def check_for_whole_start_tag(self, i):
  267.         rawdata = self.rawdata
  268.         m = locatestarttagend.match(rawdata, i)
  269.         raise AssertionError('we should not get here!')
  270.  
  271.     
  272.     def parse_endtag(self, i):
  273.         rawdata = self.rawdata
  274.         if not rawdata[i:i + 2] == '</':
  275.             raise AssertionError, 'unexpected call to parse_endtag'
  276.         match = endendtag.search(rawdata, i + 1)
  277.         if not match:
  278.             return -1
  279.         j = match.end()
  280.         match = endtagfind.match(rawdata, i)
  281.         tag = match.group(1)
  282.         self.handle_endtag(tag.lower())
  283.         self.clear_cdata_mode()
  284.         return j
  285.  
  286.     
  287.     def handle_startendtag(self, tag, attrs):
  288.         self.handle_starttag(tag, attrs)
  289.         self.handle_endtag(tag)
  290.  
  291.     
  292.     def handle_starttag(self, tag, attrs):
  293.         pass
  294.  
  295.     
  296.     def handle_endtag(self, tag):
  297.         pass
  298.  
  299.     
  300.     def handle_charref(self, name):
  301.         pass
  302.  
  303.     
  304.     def handle_entityref(self, name):
  305.         pass
  306.  
  307.     
  308.     def handle_data(self, data):
  309.         pass
  310.  
  311.     
  312.     def handle_comment(self, data):
  313.         pass
  314.  
  315.     
  316.     def handle_decl(self, decl):
  317.         pass
  318.  
  319.     
  320.     def handle_pi(self, data):
  321.         pass
  322.  
  323.     
  324.     def unknown_decl(self, data):
  325.         self.error('unknown declaration: %r' % (data,))
  326.  
  327.     entitydefs = None
  328.     
  329.     def unescape(self, s):
  330.         if '&' not in s:
  331.             return s
  332.         
  333.         def replaceEntities(s):
  334.             s = s.groups()[0]
  335.             if s[0] == '#':
  336.                 s = s[1:]
  337.                 if s[0] in ('x', 'X'):
  338.                     c = int(s[1:], 16)
  339.                 else:
  340.                     c = int(s)
  341.                 return unichr(c)
  342.             import htmlentitydefs
  343.             
  344.             try:
  345.                 return self.entitydefs[s]
  346.             except KeyError:
  347.                 None if HTMLParser.entitydefs is None else s[0] == '#'
  348.                 None if HTMLParser.entitydefs is None else s[0] == '#'
  349.                 return '&' + s + ';'
  350.  
  351.  
  352.         return re.sub('&(#?[xX]?(?:[0-9a-fA-F]+|\\w{1,8}));', replaceEntities, s)
  353.  
  354.  
  355.