home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / sgmllib.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2008-10-29  |  15.0 KB  |  595 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. '''A parser for SGML, using the derived class as a static DTD.'''
  5. import markupbase
  6. import re
  7. __all__ = [
  8.     'SGMLParser',
  9.     'SGMLParseError']
  10. interesting = re.compile('[&<]')
  11. incomplete = re.compile('&([a-zA-Z][a-zA-Z0-9]*|#[0-9]*)?|<([a-zA-Z][^<>]*|/([a-zA-Z][^<>]*)?|![^<>]*)?')
  12. entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
  13. charref = re.compile('&#([0-9]+)[^0-9]')
  14. starttagopen = re.compile('<[>a-zA-Z]')
  15. shorttagopen = re.compile('<[a-zA-Z][-.a-zA-Z0-9]*/')
  16. shorttag = re.compile('<([a-zA-Z][-.a-zA-Z0-9]*)/([^/]*)/')
  17. piclose = re.compile('>')
  18. endbracket = re.compile('[<>]')
  19. tagfind = re.compile('[a-zA-Z][-_.a-zA-Z0-9]*')
  20. attrfind = re.compile('\\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)(\\s*=\\s*(\\\'[^\\\']*\\\'|"[^"]*"|[][\\-a-zA-Z0-9./,:;+*%?!&$\\(\\)_#=~\\\'"@]*))?')
  21.  
  22. class SGMLParseError(RuntimeError):
  23.     '''Exception raised for all parse errors.'''
  24.     pass
  25.  
  26.  
  27. class SGMLParser(markupbase.ParserBase):
  28.     entity_or_charref = re.compile('&(?:([a-zA-Z][-.a-zA-Z0-9]*)|#([0-9]+))(;?)')
  29.     
  30.     def __init__(self, verbose = 0):
  31.         '''Initialize and reset this instance.'''
  32.         self.verbose = verbose
  33.         self.reset()
  34.  
  35.     
  36.     def reset(self):
  37.         '''Reset this instance. Loses all unprocessed data.'''
  38.         self._SGMLParser__starttag_text = None
  39.         self.rawdata = ''
  40.         self.stack = []
  41.         self.lasttag = '???'
  42.         self.nomoretags = 0
  43.         self.literal = 0
  44.         markupbase.ParserBase.reset(self)
  45.  
  46.     
  47.     def setnomoretags(self):
  48.         '''Enter literal mode (CDATA) till EOF.
  49.  
  50.         Intended for derived classes only.
  51.         '''
  52.         self.nomoretags = self.literal = 1
  53.  
  54.     
  55.     def setliteral(self, *args):
  56.         '''Enter literal mode (CDATA).
  57.  
  58.         Intended for derived classes only.
  59.         '''
  60.         self.literal = 1
  61.  
  62.     
  63.     def feed(self, data):
  64.         """Feed some data to the parser.
  65.  
  66.         Call this as often as you want, with as little or as much text
  67.         as you want (may include '
  68. ').  (This just saves the text,
  69.         all the processing is done by goahead().)
  70.         """
  71.         self.rawdata = self.rawdata + data
  72.         self.goahead(0)
  73.  
  74.     
  75.     def close(self):
  76.         '''Handle the remaining data.'''
  77.         self.goahead(1)
  78.  
  79.     
  80.     def error(self, message):
  81.         raise SGMLParseError(message)
  82.  
  83.     
  84.     def goahead(self, end):
  85.         rawdata = self.rawdata
  86.         i = 0
  87.         n = len(rawdata)
  88.         while i < n:
  89.             if self.nomoretags:
  90.                 self.handle_data(rawdata[i:n])
  91.                 i = n
  92.                 break
  93.             
  94.             match = interesting.search(rawdata, i)
  95.             if match:
  96.                 j = match.start()
  97.             else:
  98.                 j = n
  99.             if i < j:
  100.                 self.handle_data(rawdata[i:j])
  101.             
  102.             i = j
  103.             if i == n:
  104.                 break
  105.             
  106.             if rawdata[i] == '<':
  107.                 if starttagopen.match(rawdata, i):
  108.                     if self.literal:
  109.                         self.handle_data(rawdata[i])
  110.                         i = i + 1
  111.                         continue
  112.                     
  113.                     k = self.parse_starttag(i)
  114.                     if k < 0:
  115.                         break
  116.                     
  117.                     i = k
  118.                     continue
  119.                 
  120.                 if rawdata.startswith('</', i):
  121.                     k = self.parse_endtag(i)
  122.                     if k < 0:
  123.                         break
  124.                     
  125.                     i = k
  126.                     self.literal = 0
  127.                     continue
  128.                 
  129.                 if self.literal:
  130.                     if n > i + 1:
  131.                         self.handle_data('<')
  132.                         i = i + 1
  133.                         continue
  134.                     break
  135.                     continue
  136.                 
  137.                 if rawdata.startswith('<!--', i):
  138.                     k = self.parse_comment(i)
  139.                     if k < 0:
  140.                         break
  141.                     
  142.                     i = k
  143.                     continue
  144.                 
  145.                 if rawdata.startswith('<?', i):
  146.                     k = self.parse_pi(i)
  147.                     if k < 0:
  148.                         break
  149.                     
  150.                     i = i + k
  151.                     continue
  152.                 
  153.                 if rawdata.startswith('<!', i):
  154.                     k = self.parse_declaration(i)
  155.                     if k < 0:
  156.                         break
  157.                     
  158.                     i = k
  159.                     continue
  160.                 
  161.             elif rawdata[i] == '&':
  162.                 if self.literal:
  163.                     self.handle_data(rawdata[i])
  164.                     i = i + 1
  165.                     continue
  166.                 
  167.                 match = charref.match(rawdata, i)
  168.                 if match:
  169.                     name = match.group(1)
  170.                     self.handle_charref(name)
  171.                     i = match.end(0)
  172.                     if rawdata[i - 1] != ';':
  173.                         i = i - 1
  174.                         continue
  175.                     continue
  176.                 
  177.                 match = entityref.match(rawdata, i)
  178.                 if match:
  179.                     name = match.group(1)
  180.                     self.handle_entityref(name)
  181.                     i = match.end(0)
  182.                     if rawdata[i - 1] != ';':
  183.                         i = i - 1
  184.                         continue
  185.                     continue
  186.                 
  187.             else:
  188.                 self.error('neither < nor & ??')
  189.             match = incomplete.match(rawdata, i)
  190.             if not match:
  191.                 self.handle_data(rawdata[i])
  192.                 i = i + 1
  193.                 continue
  194.             
  195.             j = match.end(0)
  196.             if j == n:
  197.                 break
  198.             
  199.             self.handle_data(rawdata[i:j])
  200.             i = j
  201.         if end and i < n:
  202.             self.handle_data(rawdata[i:n])
  203.             i = n
  204.         
  205.         self.rawdata = rawdata[i:]
  206.  
  207.     _decl_otherchars = '='
  208.     
  209.     def parse_pi(self, i):
  210.         rawdata = self.rawdata
  211.         if rawdata[i:i + 2] != '<?':
  212.             self.error('unexpected call to parse_pi()')
  213.         
  214.         match = piclose.search(rawdata, i + 2)
  215.         if not match:
  216.             return -1
  217.         
  218.         j = match.start(0)
  219.         self.handle_pi(rawdata[i + 2:j])
  220.         j = match.end(0)
  221.         return j - i
  222.  
  223.     
  224.     def get_starttag_text(self):
  225.         return self._SGMLParser__starttag_text
  226.  
  227.     
  228.     def parse_starttag(self, i):
  229.         self._SGMLParser__starttag_text = None
  230.         start_pos = i
  231.         rawdata = self.rawdata
  232.         if shorttagopen.match(rawdata, i):
  233.             match = shorttag.match(rawdata, i)
  234.             if not match:
  235.                 return -1
  236.             
  237.             (tag, data) = match.group(1, 2)
  238.             self._SGMLParser__starttag_text = '<%s/' % tag
  239.             tag = tag.lower()
  240.             k = match.end(0)
  241.             self.finish_shorttag(tag, data)
  242.             self._SGMLParser__starttag_text = rawdata[start_pos:match.end(1) + 1]
  243.             return k
  244.         
  245.         match = endbracket.search(rawdata, i + 1)
  246.         if not match:
  247.             return -1
  248.         
  249.         j = match.start(0)
  250.         attrs = []
  251.         if rawdata[i:i + 2] == '<>':
  252.             k = j
  253.             tag = self.lasttag
  254.         else:
  255.             match = tagfind.match(rawdata, i + 1)
  256.             if not match:
  257.                 self.error('unexpected call to parse_starttag')
  258.             
  259.             k = match.end(0)
  260.             tag = rawdata[i + 1:k].lower()
  261.             self.lasttag = tag
  262.         while k < j:
  263.             match = attrfind.match(rawdata, k)
  264.             if not match:
  265.                 break
  266.             
  267.             (attrname, rest, attrvalue) = match.group(1, 2, 3)
  268.             if not rest:
  269.                 attrvalue = attrname
  270.             elif "'" == "'":
  271.                 pass
  272.             elif not "'" == attrvalue[-1:]:
  273.                 if '"' == '"':
  274.                     pass
  275.                 elif '"' == attrvalue[-1:]:
  276.                     attrvalue = attrvalue[1:-1]
  277.                 
  278.             attrvalue = self.entity_or_charref.sub(self._convert_ref, attrvalue)
  279.             attrs.append((attrname.lower(), attrvalue))
  280.             k = match.end(0)
  281.             continue
  282.             attrvalue[:1]
  283.         if rawdata[j] == '>':
  284.             j = j + 1
  285.         
  286.         self._SGMLParser__starttag_text = rawdata[start_pos:j]
  287.         self.finish_starttag(tag, attrs)
  288.         return j
  289.  
  290.     
  291.     def _convert_ref(self, match):
  292.         if match.group(2):
  293.             if not self.convert_charref(match.group(2)):
  294.                 pass
  295.             return '&#%s%s' % match.groups()[1:]
  296.         elif match.group(3):
  297.             if not self.convert_entityref(match.group(1)):
  298.                 pass
  299.             return '&%s;' % match.group(1)
  300.         else:
  301.             return '&%s' % match.group(1)
  302.  
  303.     
  304.     def parse_endtag(self, i):
  305.         rawdata = self.rawdata
  306.         match = endbracket.search(rawdata, i + 1)
  307.         if not match:
  308.             return -1
  309.         
  310.         j = match.start(0)
  311.         tag = rawdata[i + 2:j].strip().lower()
  312.         if rawdata[j] == '>':
  313.             j = j + 1
  314.         
  315.         self.finish_endtag(tag)
  316.         return j
  317.  
  318.     
  319.     def finish_shorttag(self, tag, data):
  320.         self.finish_starttag(tag, [])
  321.         self.handle_data(data)
  322.         self.finish_endtag(tag)
  323.  
  324.     
  325.     def finish_starttag(self, tag, attrs):
  326.         
  327.         try:
  328.             method = getattr(self, 'start_' + tag)
  329.         except AttributeError:
  330.             
  331.             try:
  332.                 method = getattr(self, 'do_' + tag)
  333.             except AttributeError:
  334.                 self.unknown_starttag(tag, attrs)
  335.                 return -1
  336.  
  337.             self.handle_starttag(tag, method, attrs)
  338.             return 0
  339.  
  340.         self.stack.append(tag)
  341.         self.handle_starttag(tag, method, attrs)
  342.         return 1
  343.  
  344.     
  345.     def finish_endtag(self, tag):
  346.         if not tag:
  347.             found = len(self.stack) - 1
  348.             if found < 0:
  349.                 self.unknown_endtag(tag)
  350.                 return None
  351.             
  352.         elif tag not in self.stack:
  353.             
  354.             try:
  355.                 method = getattr(self, 'end_' + tag)
  356.             except AttributeError:
  357.                 self.unknown_endtag(tag)
  358.  
  359.             self.report_unbalanced(tag)
  360.             return None
  361.         
  362.         found = len(self.stack)
  363.         for i in range(found):
  364.             if self.stack[i] == tag:
  365.                 found = i
  366.                 continue
  367.         
  368.         while len(self.stack) > found:
  369.             tag = self.stack[-1]
  370.             
  371.             try:
  372.                 method = getattr(self, 'end_' + tag)
  373.             except AttributeError:
  374.                 method = None
  375.  
  376.             if method:
  377.                 self.handle_endtag(tag, method)
  378.             else:
  379.                 self.unknown_endtag(tag)
  380.             del self.stack[-1]
  381.  
  382.     
  383.     def handle_starttag(self, tag, method, attrs):
  384.         method(attrs)
  385.  
  386.     
  387.     def handle_endtag(self, tag, method):
  388.         method()
  389.  
  390.     
  391.     def report_unbalanced(self, tag):
  392.         if self.verbose:
  393.             print '*** Unbalanced </' + tag + '>'
  394.             print '*** Stack:', self.stack
  395.         
  396.  
  397.     
  398.     def convert_charref(self, name):
  399.         '''Convert character reference, may be overridden.'''
  400.         
  401.         try:
  402.             n = int(name)
  403.         except ValueError:
  404.             return None
  405.  
  406.         if n <= n:
  407.             pass
  408.         elif not n <= 255:
  409.             return None
  410.         
  411.         return self.convert_codepoint(n)
  412.  
  413.     
  414.     def convert_codepoint(self, codepoint):
  415.         return chr(codepoint)
  416.  
  417.     
  418.     def handle_charref(self, name):
  419.         '''Handle character reference, no need to override.'''
  420.         replacement = self.convert_charref(name)
  421.         if replacement is None:
  422.             self.unknown_charref(name)
  423.         else:
  424.             self.handle_data(replacement)
  425.  
  426.     entitydefs = {
  427.         'lt': '<',
  428.         'gt': '>',
  429.         'amp': '&',
  430.         'quot': '"',
  431.         'apos': "'" }
  432.     
  433.     def convert_entityref(self, name):
  434.         '''Convert entity references.
  435.  
  436.         As an alternative to overriding this method; one can tailor the
  437.         results by setting up the self.entitydefs mapping appropriately.
  438.         '''
  439.         table = self.entitydefs
  440.         if name in table:
  441.             return table[name]
  442.         else:
  443.             return None
  444.  
  445.     
  446.     def handle_entityref(self, name):
  447.         '''Handle entity references, no need to override.'''
  448.         replacement = self.convert_entityref(name)
  449.         if replacement is None:
  450.             self.unknown_entityref(name)
  451.         else:
  452.             self.handle_data(self.convert_entityref(name))
  453.  
  454.     
  455.     def handle_data(self, data):
  456.         pass
  457.  
  458.     
  459.     def handle_comment(self, data):
  460.         pass
  461.  
  462.     
  463.     def handle_decl(self, decl):
  464.         pass
  465.  
  466.     
  467.     def handle_pi(self, data):
  468.         pass
  469.  
  470.     
  471.     def unknown_starttag(self, tag, attrs):
  472.         pass
  473.  
  474.     
  475.     def unknown_endtag(self, tag):
  476.         pass
  477.  
  478.     
  479.     def unknown_charref(self, ref):
  480.         pass
  481.  
  482.     
  483.     def unknown_entityref(self, ref):
  484.         pass
  485.  
  486.  
  487.  
  488. class TestSGMLParser(SGMLParser):
  489.     
  490.     def __init__(self, verbose = 0):
  491.         self.testdata = ''
  492.         SGMLParser.__init__(self, verbose)
  493.  
  494.     
  495.     def handle_data(self, data):
  496.         self.testdata = self.testdata + data
  497.         if len(repr(self.testdata)) >= 70:
  498.             self.flush()
  499.         
  500.  
  501.     
  502.     def flush(self):
  503.         data = self.testdata
  504.         if data:
  505.             self.testdata = ''
  506.             print 'data:', repr(data)
  507.         
  508.  
  509.     
  510.     def handle_comment(self, data):
  511.         self.flush()
  512.         r = repr(data)
  513.         if len(r) > 68:
  514.             r = r[:32] + '...' + r[-32:]
  515.         
  516.         print 'comment:', r
  517.  
  518.     
  519.     def unknown_starttag(self, tag, attrs):
  520.         self.flush()
  521.         if not attrs:
  522.             print 'start tag: <' + tag + '>'
  523.         else:
  524.             print 'start tag: <' + tag,
  525.             for name, value in attrs:
  526.                 print name + '=' + '"' + value + '"',
  527.             
  528.             print '>'
  529.  
  530.     
  531.     def unknown_endtag(self, tag):
  532.         self.flush()
  533.         print 'end tag: </' + tag + '>'
  534.  
  535.     
  536.     def unknown_entityref(self, ref):
  537.         self.flush()
  538.         print '*** unknown entity ref: &' + ref + ';'
  539.  
  540.     
  541.     def unknown_charref(self, ref):
  542.         self.flush()
  543.         print '*** unknown char ref: &#' + ref + ';'
  544.  
  545.     
  546.     def unknown_decl(self, data):
  547.         self.flush()
  548.         print '*** unknown decl: [' + data + ']'
  549.  
  550.     
  551.     def close(self):
  552.         SGMLParser.close(self)
  553.         self.flush()
  554.  
  555.  
  556.  
  557. def test(args = None):
  558.     import sys
  559.     if args is None:
  560.         args = sys.argv[1:]
  561.     
  562.     if args and args[0] == '-s':
  563.         args = args[1:]
  564.         klass = SGMLParser
  565.     else:
  566.         klass = TestSGMLParser
  567.     if args:
  568.         file = args[0]
  569.     else:
  570.         file = 'test.html'
  571.     if file == '-':
  572.         f = sys.stdin
  573.     else:
  574.         
  575.         try:
  576.             f = open(file, 'r')
  577.         except IOError:
  578.             msg = None
  579.             print file, ':', msg
  580.             sys.exit(1)
  581.  
  582.     data = f.read()
  583.     if f is not sys.stdin:
  584.         f.close()
  585.     
  586.     x = klass()
  587.     for c in data:
  588.         x.feed(c)
  589.     
  590.     x.close()
  591.  
  592. if __name__ == '__main__':
  593.     test()
  594.  
  595.