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

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