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

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import re
  5. import copy
  6. import htmlentitydefs
  7. import sgmllib
  8. import ClientForm
  9. import _request
  10. from _headersutil import split_header_words, is_html as _is_html
  11. import _rfc3986
  12. DEFAULT_ENCODING = 'latin-1'
  13. COMPRESS_RE = re.compile('\\s+')
  14.  
  15. class ParseError(ClientForm.ParseError):
  16.     pass
  17.  
  18.  
  19. class CachingGeneratorFunction(object):
  20.     
  21.     def __init__(self, iterable):
  22.         self._cache = []
  23.         self._iterator = iter(iterable)
  24.  
  25.     
  26.     def __call__(self):
  27.         cache = self._cache
  28.         for item in cache:
  29.             yield item
  30.         
  31.         for item in self._iterator:
  32.             cache.append(item)
  33.             yield item
  34.         
  35.  
  36.  
  37.  
  38. class EncodingFinder:
  39.     
  40.     def __init__(self, default_encoding):
  41.         self._default_encoding = default_encoding
  42.  
  43.     
  44.     def encoding(self, response):
  45.         for ct in response.info().getheaders('content-type'):
  46.             for k, v in split_header_words([
  47.                 ct])[0]:
  48.                 if k == 'charset':
  49.                     return v
  50.             
  51.         
  52.         return self._default_encoding
  53.  
  54.  
  55.  
  56. class ResponseTypeFinder:
  57.     
  58.     def __init__(self, allow_xhtml):
  59.         self._allow_xhtml = allow_xhtml
  60.  
  61.     
  62.     def is_html(self, response, encoding):
  63.         ct_hdrs = response.info().getheaders('content-type')
  64.         url = response.geturl()
  65.         return _is_html(ct_hdrs, url, self._allow_xhtml)
  66.  
  67.  
  68.  
  69. class Args:
  70.     
  71.     def __init__(self, args_map):
  72.         self.dictionary = dict(args_map)
  73.  
  74.     
  75.     def __getattr__(self, key):
  76.         
  77.         try:
  78.             return self.dictionary[key]
  79.         except KeyError:
  80.             return getattr(self.__class__, key)
  81.  
  82.  
  83.  
  84.  
  85. def form_parser_args(select_default = False, form_parser_class = None, request_class = None, backwards_compat = False):
  86.     return Args(locals())
  87.  
  88.  
  89. class Link:
  90.     
  91.     def __init__(self, base_url, url, text, tag, attrs):
  92.         self.base_url = base_url
  93.         self.absolute_url = _rfc3986.urljoin(base_url, url)
  94.         (self.url, self.text, self.tag, self.attrs) = (url, text, tag, attrs)
  95.  
  96.     
  97.     def __cmp__(self, other):
  98.         
  99.         try:
  100.             for name in ('url', 'text', 'tag', 'attrs'):
  101.                 if getattr(self, name) != getattr(other, name):
  102.                     return -1
  103.         except AttributeError:
  104.             return -1
  105.  
  106.         return 0
  107.  
  108.     
  109.     def __repr__(self):
  110.         return 'Link(base_url=%r, url=%r, text=%r, tag=%r, attrs=%r)' % (self.base_url, self.url, self.text, self.tag, self.attrs)
  111.  
  112.  
  113.  
  114. class LinksFactory:
  115.     
  116.     def __init__(self, link_parser_class = None, link_class = Link, urltags = None):
  117.         import _pullparser
  118.         if link_parser_class is None:
  119.             link_parser_class = _pullparser.TolerantPullParser
  120.         
  121.         self.link_parser_class = link_parser_class
  122.         self.link_class = link_class
  123.         if urltags is None:
  124.             urltags = {
  125.                 'a': 'href',
  126.                 'area': 'href',
  127.                 'frame': 'src',
  128.                 'iframe': 'src' }
  129.         
  130.         self.urltags = urltags
  131.         self._response = None
  132.         self._encoding = None
  133.  
  134.     
  135.     def set_response(self, response, base_url, encoding):
  136.         self._response = response
  137.         self._encoding = encoding
  138.         self._base_url = base_url
  139.  
  140.     
  141.     def links(self):
  142.         response = self._response
  143.         encoding = self._encoding
  144.         base_url = self._base_url
  145.         p = self.link_parser_class(response, encoding = encoding)
  146.         
  147.         try:
  148.             for token in p.tags(*self.urltags.keys() + [
  149.                 'base']):
  150.                 if token.type == 'endtag':
  151.                     continue
  152.                 
  153.                 if token.data == 'base':
  154.                     base_href = dict(token.attrs).get('href')
  155.                     if base_href is not None:
  156.                         base_url = base_href
  157.                         continue
  158.                     continue
  159.                 
  160.                 attrs = dict(token.attrs)
  161.                 tag = token.data
  162.                 name = attrs.get('name')
  163.                 text = None
  164.                 url = attrs.get(self.urltags[tag])
  165.                 if not url:
  166.                     continue
  167.                 
  168.                 url = _rfc3986.clean_url(url, encoding)
  169.                 if tag == 'a':
  170.                     if token.type != 'startendtag':
  171.                         text = p.get_compressed_text(('endtag', tag))
  172.                     
  173.                 
  174.                 yield Link(base_url, url, text, tag, token.attrs)
  175.         except sgmllib.SGMLParseError:
  176.             exc = None
  177.             raise ParseError(exc)
  178.  
  179.  
  180.  
  181.  
  182. class FormsFactory:
  183.     
  184.     def __init__(self, select_default = False, form_parser_class = None, request_class = None, backwards_compat = False):
  185.         import ClientForm
  186.         self.select_default = select_default
  187.         if form_parser_class is None:
  188.             form_parser_class = ClientForm.FormParser
  189.         
  190.         self.form_parser_class = form_parser_class
  191.         if request_class is None:
  192.             request_class = _request.Request
  193.         
  194.         self.request_class = request_class
  195.         self.backwards_compat = backwards_compat
  196.         self._response = None
  197.         self.encoding = None
  198.         self.global_form = None
  199.  
  200.     
  201.     def set_response(self, response, encoding):
  202.         self._response = response
  203.         self.encoding = encoding
  204.         self.global_form = None
  205.  
  206.     
  207.     def forms(self):
  208.         import ClientForm
  209.         encoding = self.encoding
  210.         
  211.         try:
  212.             forms = ClientForm.ParseResponseEx(self._response, select_default = self.select_default, form_parser_class = self.form_parser_class, request_class = self.request_class, encoding = encoding, _urljoin = _rfc3986.urljoin, _urlparse = _rfc3986.urlsplit, _urlunparse = _rfc3986.urlunsplit)
  213.         except ClientForm.ParseError:
  214.             exc = None
  215.             raise ParseError(exc)
  216.  
  217.         self.global_form = forms[0]
  218.         return forms[1:]
  219.  
  220.  
  221.  
  222. class TitleFactory:
  223.     
  224.     def __init__(self):
  225.         self._response = None
  226.         self._encoding = None
  227.  
  228.     
  229.     def set_response(self, response, encoding):
  230.         self._response = response
  231.         self._encoding = encoding
  232.  
  233.     
  234.     def _get_title_text(self, parser):
  235.         import _pullparser
  236.         text = []
  237.         tok = None
  238.         while None:
  239.             
  240.             try:
  241.                 tok = parser.get_token()
  242.             except _pullparser.NoMoreTokensError:
  243.                 break
  244.  
  245.             if tok.type == 'data':
  246.                 text.append(str(tok))
  247.                 continue
  248.             if tok.type == 'entityref':
  249.                 t = unescape('&%s;' % tok.data, parser._entitydefs, parser.encoding)
  250.                 text.append(t)
  251.                 continue
  252.             if tok.type == 'charref':
  253.                 t = unescape_charref(tok.data, parser.encoding)
  254.                 text.append(t)
  255.                 continue
  256.             if tok.type in ('starttag', 'endtag', 'startendtag'):
  257.                 tag_name = tok.data
  258.                 if tok.type == 'endtag' and tag_name == 'title':
  259.                     break
  260.                 
  261.                 text.append(str(tok))
  262.                 continue
  263.             continue
  264.             return COMPRESS_RE.sub(' ', ''.join(text).strip())
  265.  
  266.     
  267.     def title(self):
  268.         import _pullparser
  269.         p = _pullparser.TolerantPullParser(self._response, encoding = self._encoding)
  270.         
  271.         try:
  272.             
  273.             try:
  274.                 p.get_tag('title')
  275.             except _pullparser.NoMoreTokensError:
  276.                 return None
  277.  
  278.             return self._get_title_text(p)
  279.         except sgmllib.SGMLParseError:
  280.             exc = None
  281.             raise ParseError(exc)
  282.  
  283.  
  284.  
  285.  
  286. def unescape(data, entities, encoding):
  287.     if data is None or '&' not in data:
  288.         return data
  289.     
  290.     def replace_entities(match):
  291.         ent = match.group()
  292.         if ent[1] == '#':
  293.             return unescape_charref(ent[2:-1], encoding)
  294.         repl = entities.get(ent[1:-1])
  295.         return repl
  296.  
  297.     return re.sub('&#?[A-Za-z0-9]+?;', replace_entities, data)
  298.  
  299.  
  300. def unescape_charref(data, encoding):
  301.     name = data
  302.     base = 10
  303.     if name.startswith('x'):
  304.         name = name[1:]
  305.         base = 16
  306.     
  307.     uc = unichr(int(name, base))
  308.     if encoding is None:
  309.         return uc
  310.     
  311.     try:
  312.         repl = uc.encode(encoding)
  313.     except UnicodeError:
  314.         encoding is None
  315.         encoding is None
  316.         repl = '&#%s;' % data
  317.     except:
  318.         encoding is None
  319.  
  320.     return repl
  321.  
  322. import _beautifulsoup
  323. import ClientForm
  324. (RobustFormParser, NestingRobustFormParser) = ClientForm._create_bs_classes(_beautifulsoup.BeautifulSoup, _beautifulsoup.ICantBelieveItsBeautifulSoup)
  325. sgmllib.charref = re.compile('&#(x?[0-9a-fA-F]+)[^0-9a-fA-F]')
  326.  
  327. class MechanizeBs(_beautifulsoup.BeautifulSoup):
  328.     _entitydefs = htmlentitydefs.name2codepoint
  329.     PARSER_MASSAGE = [
  330.         (re.compile('(<[^<>]*)/>'), (lambda x: x.group(1) + ' />')),
  331.         (re.compile('<!\\s+([^<>]*)>'), (lambda x: '<!' + x.group(1) + '>'))]
  332.     
  333.     def __init__(self, encoding, text = None, avoidParserProblems = True, initialTextIsEverything = True):
  334.         self._encoding = encoding
  335.         _beautifulsoup.BeautifulSoup.__init__(self, text, avoidParserProblems, initialTextIsEverything)
  336.  
  337.     
  338.     def handle_charref(self, ref):
  339.         t = unescape('&#%s;' % ref, self._entitydefs, self._encoding)
  340.         self.handle_data(t)
  341.  
  342.     
  343.     def handle_entityref(self, ref):
  344.         t = unescape('&%s;' % ref, self._entitydefs, self._encoding)
  345.         self.handle_data(t)
  346.  
  347.     
  348.     def unescape_attrs(self, attrs):
  349.         escaped_attrs = []
  350.         for key, val in attrs:
  351.             val = unescape(val, self._entitydefs, self._encoding)
  352.             escaped_attrs.append((key, val))
  353.         
  354.         return escaped_attrs
  355.  
  356.  
  357.  
  358. class RobustLinksFactory:
  359.     compress_re = COMPRESS_RE
  360.     
  361.     def __init__(self, link_parser_class = None, link_class = Link, urltags = None):
  362.         if link_parser_class is None:
  363.             link_parser_class = MechanizeBs
  364.         
  365.         self.link_parser_class = link_parser_class
  366.         self.link_class = link_class
  367.         if urltags is None:
  368.             urltags = {
  369.                 'a': 'href',
  370.                 'area': 'href',
  371.                 'frame': 'src',
  372.                 'iframe': 'src' }
  373.         
  374.         self.urltags = urltags
  375.         self._bs = None
  376.         self._encoding = None
  377.         self._base_url = None
  378.  
  379.     
  380.     def set_soup(self, soup, base_url, encoding):
  381.         self._bs = soup
  382.         self._base_url = base_url
  383.         self._encoding = encoding
  384.  
  385.     
  386.     def links(self):
  387.         import _beautifulsoup
  388.         bs = self._bs
  389.         base_url = self._base_url
  390.         encoding = self._encoding
  391.         gen = bs.recursiveChildGenerator()
  392.         for ch in bs.recursiveChildGenerator():
  393.             if isinstance(ch, _beautifulsoup.Tag) and ch.name in self.urltags.keys() + [
  394.                 'base']:
  395.                 link = ch
  396.                 attrs = bs.unescape_attrs(link.attrs)
  397.                 attrs_dict = dict(attrs)
  398.                 if link.name == 'base':
  399.                     base_href = attrs_dict.get('href')
  400.                     if base_href is not None:
  401.                         base_url = base_href
  402.                         continue
  403.                     continue
  404.                 
  405.                 url_attr = self.urltags[link.name]
  406.                 url = attrs_dict.get(url_attr)
  407.                 if not url:
  408.                     continue
  409.                 
  410.                 url = _rfc3986.clean_url(url, encoding)
  411.                 text = link.fetchText((lambda t: True))
  412.                 if not text:
  413.                     if link.name == 'a':
  414.                         text = ''
  415.                     else:
  416.                         text = None
  417.                 else:
  418.                     text = self.compress_re.sub(' ', ' '.join(text).strip())
  419.                 yield Link(base_url, url, text, link.name, attrs)
  420.                 continue
  421.         
  422.  
  423.  
  424.  
  425. class RobustFormsFactory(FormsFactory):
  426.     
  427.     def __init__(self, *args, **kwds):
  428.         args = form_parser_args(*args, **kwds)
  429.         if args.form_parser_class is None:
  430.             args.form_parser_class = RobustFormParser
  431.         
  432.         FormsFactory.__init__(self, **args.dictionary)
  433.  
  434.     
  435.     def set_response(self, response, encoding):
  436.         self._response = response
  437.         self.encoding = encoding
  438.  
  439.  
  440.  
  441. class RobustTitleFactory:
  442.     
  443.     def __init__(self):
  444.         self._bs = None
  445.         self._encoding = None
  446.  
  447.     
  448.     def set_soup(self, soup, encoding):
  449.         self._bs = soup
  450.         self._encoding = encoding
  451.  
  452.     
  453.     def title(self):
  454.         import _beautifulsoup
  455.         title = self._bs.first('title')
  456.         if title == _beautifulsoup.Null:
  457.             return None
  458.         inner_html = []([ str(node) for node in title.contents ])
  459.         return COMPRESS_RE.sub(' ', inner_html.strip())
  460.  
  461.  
  462.  
  463. class Factory:
  464.     LAZY_ATTRS = [
  465.         'encoding',
  466.         'is_html',
  467.         'title',
  468.         'global_form']
  469.     
  470.     def __init__(self, forms_factory, links_factory, title_factory, encoding_finder = EncodingFinder(DEFAULT_ENCODING), response_type_finder = ResponseTypeFinder(allow_xhtml = False)):
  471.         self._forms_factory = forms_factory
  472.         self._links_factory = links_factory
  473.         self._title_factory = title_factory
  474.         self._encoding_finder = encoding_finder
  475.         self._response_type_finder = response_type_finder
  476.         self.set_response(None)
  477.  
  478.     
  479.     def set_request_class(self, request_class):
  480.         self._forms_factory.request_class = request_class
  481.  
  482.     
  483.     def set_response(self, response):
  484.         self._response = response
  485.         self._forms_genf = None
  486.         self._links_genf = None
  487.         self._get_title = None
  488.         for name in self.LAZY_ATTRS:
  489.             
  490.             try:
  491.                 delattr(self, name)
  492.             continue
  493.             except AttributeError:
  494.                 continue
  495.             
  496.  
  497.         
  498.  
  499.     
  500.     def __getattr__(self, name):
  501.         if name not in self.LAZY_ATTRS:
  502.             return getattr(self.__class__, name)
  503.         if name == 'encoding':
  504.             self.encoding = self._encoding_finder.encoding(copy.copy(self._response))
  505.             return self.encoding
  506.         if name == 'is_html':
  507.             self.is_html = self._response_type_finder.is_html(copy.copy(self._response), self.encoding)
  508.             return self.is_html
  509.         if name == 'title':
  510.             return self.title
  511.         if name == 'global_form':
  512.             self.forms()
  513.             return self.global_form
  514.  
  515.     
  516.     def forms(self):
  517.         if self._forms_genf is None:
  518.             
  519.             try:
  520.                 self._forms_genf = CachingGeneratorFunction(self._forms_factory.forms())
  521.             except:
  522.                 self.set_response(self._response)
  523.                 raise 
  524.  
  525.             self.global_form = getattr(self._forms_factory, 'global_form', None)
  526.         
  527.         return self._forms_genf()
  528.  
  529.     
  530.     def links(self):
  531.         if self._links_genf is None:
  532.             
  533.             try:
  534.                 self._links_genf = CachingGeneratorFunction(self._links_factory.links())
  535.             self.set_response(self._response)
  536.             raise 
  537.  
  538.         
  539.         return self._links_genf()
  540.  
  541.  
  542.  
  543. class DefaultFactory(Factory):
  544.     
  545.     def __init__(self, i_want_broken_xhtml_support = False):
  546.         Factory.__init__(self, forms_factory = FormsFactory(), links_factory = LinksFactory(), title_factory = TitleFactory(), response_type_finder = ResponseTypeFinder(allow_xhtml = i_want_broken_xhtml_support))
  547.  
  548.     
  549.     def set_response(self, response):
  550.         Factory.set_response(self, response)
  551.         if response is not None:
  552.             self._forms_factory.set_response(copy.copy(response), self.encoding)
  553.             self._links_factory.set_response(copy.copy(response), response.geturl(), self.encoding)
  554.             self._title_factory.set_response(copy.copy(response), self.encoding)
  555.         
  556.  
  557.  
  558.  
  559. class RobustFactory(Factory):
  560.     
  561.     def __init__(self, i_want_broken_xhtml_support = False, soup_class = None):
  562.         Factory.__init__(self, forms_factory = RobustFormsFactory(), links_factory = RobustLinksFactory(), title_factory = RobustTitleFactory(), response_type_finder = ResponseTypeFinder(allow_xhtml = i_want_broken_xhtml_support))
  563.         if soup_class is None:
  564.             soup_class = MechanizeBs
  565.         
  566.         self._soup_class = soup_class
  567.  
  568.     
  569.     def set_response(self, response):
  570.         Factory.set_response(self, response)
  571.         if response is not None:
  572.             data = response.read()
  573.             soup = self._soup_class(self.encoding, data)
  574.             self._forms_factory.set_response(copy.copy(response), self.encoding)
  575.             self._links_factory.set_soup(soup, response.geturl(), self.encoding)
  576.             self._title_factory.set_soup(soup, self.encoding)
  577.         
  578.  
  579.  
  580.