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

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from lxml import etree
  5. import sys
  6. import re
  7. import doctest
  8. import cgi
  9. __all__ = [
  10.     'PARSE_HTML',
  11.     'PARSE_XML',
  12.     'NOPARSE_MARKUP',
  13.     'LXMLOutputChecker',
  14.     'LHTMLOutputChecker',
  15.     'install',
  16.     'temp_install']
  17.  
  18. try:
  19.     _basestring = basestring
  20. except NameError:
  21.     _basestring = (str, bytes)
  22.  
  23. _IS_PYTHON_3 = sys.version_info[0] >= 3
  24. PARSE_HTML = doctest.register_optionflag('PARSE_HTML')
  25. PARSE_XML = doctest.register_optionflag('PARSE_XML')
  26. NOPARSE_MARKUP = doctest.register_optionflag('NOPARSE_MARKUP')
  27. OutputChecker = doctest.OutputChecker
  28.  
  29. def strip(v):
  30.     if v is None:
  31.         return None
  32.     return v.strip()
  33.  
  34.  
  35. def norm_whitespace(v):
  36.     return _norm_whitespace_re.sub(' ', v)
  37.  
  38. _html_parser = etree.HTMLParser(recover = False, remove_blank_text = True)
  39.  
  40. def html_fromstring(html):
  41.     return etree.fromstring(html, _html_parser)
  42.  
  43. _repr_re = re.compile('^<[^>]+ (at|object) ')
  44. _norm_whitespace_re = re.compile('[ \\t\\n][ \\t\\n]+')
  45.  
  46. class LXMLOutputChecker(OutputChecker):
  47.     empty_tags = ('param', 'img', 'area', 'br', 'basefont', 'input', 'base', 'meta', 'link', 'col')
  48.     
  49.     def get_default_parser(self):
  50.         return etree.XML
  51.  
  52.     
  53.     def check_output(self, want, got, optionflags):
  54.         alt_self = getattr(self, '_temp_override_self', None)
  55.         if alt_self is not None:
  56.             super_method = self._temp_call_super_check_output
  57.             self = alt_self
  58.         else:
  59.             super_method = OutputChecker.check_output
  60.         parser = self.get_parser(want, got, optionflags)
  61.         if not parser:
  62.             return super_method(self, want, got, optionflags)
  63.         
  64.         try:
  65.             want_doc = parser(want)
  66.         except etree.XMLSyntaxError:
  67.             parser
  68.             parser
  69.             return False
  70.  
  71.         
  72.         try:
  73.             got_doc = parser(got)
  74.         except etree.XMLSyntaxError:
  75.             parser
  76.             parser
  77.             return False
  78.  
  79.         return self.compare_docs(want_doc, got_doc)
  80.  
  81.     
  82.     def get_parser(self, want, got, optionflags):
  83.         parser = None
  84.         if NOPARSE_MARKUP & optionflags:
  85.             return None
  86.         if PARSE_HTML & optionflags:
  87.             parser = html_fromstring
  88.         elif PARSE_XML & optionflags:
  89.             parser = etree.XML
  90.         elif want.strip().lower().startswith('<html') and got.strip().startswith('<html'):
  91.             parser = html_fromstring
  92.         elif self._looks_like_markup(want) and self._looks_like_markup(got):
  93.             parser = self.get_default_parser()
  94.         
  95.         return parser
  96.  
  97.     
  98.     def _looks_like_markup(self, s):
  99.         s = s.strip()
  100.         if s.startswith('<'):
  101.             pass
  102.         return not _repr_re.search(s)
  103.  
  104.     
  105.     def compare_docs(self, want, got):
  106.         if not self.tag_compare(want.tag, got.tag):
  107.             return False
  108.         if not self.text_compare(want.text, got.text, True):
  109.             return False
  110.         if not self.text_compare(want.tail, got.tail, True):
  111.             return False
  112.         return True
  113.  
  114.     
  115.     def text_compare(self, want, got, strip):
  116.         if not want:
  117.             pass
  118.         want = ''
  119.         if not got:
  120.             pass
  121.         got = ''
  122.         if strip:
  123.             want = norm_whitespace(want).strip()
  124.             got = norm_whitespace(got).strip()
  125.         
  126.         want = '^%s$' % re.escape(want)
  127.         want = want.replace('\\.\\.\\.', '.*')
  128.         if re.search(want, got):
  129.             return True
  130.         return False
  131.  
  132.     
  133.     def tag_compare(self, want, got):
  134.         if want == 'any':
  135.             return True
  136.         if not isinstance(want, _basestring) or not isinstance(got, _basestring):
  137.             return want == got
  138.         if not want:
  139.             pass
  140.         want = ''
  141.         if not got:
  142.             pass
  143.         got = ''
  144.         if want.startswith('{...}'):
  145.             return want.split('}')[-1] == got.split('}')[-1]
  146.         return want == got
  147.  
  148.     
  149.     def output_difference(self, example, got, optionflags):
  150.         want = example.want
  151.         parser = self.get_parser(want, got, optionflags)
  152.         errors = []
  153.         if parser is not None:
  154.             
  155.             try:
  156.                 want_doc = parser(want)
  157.             except etree.XMLSyntaxError:
  158.                 e = sys.exc_info()[1]
  159.                 errors.append('In example: %s' % e)
  160.  
  161.             
  162.             try:
  163.                 got_doc = parser(got)
  164.             except etree.XMLSyntaxError:
  165.                 e = sys.exc_info()[1]
  166.                 errors.append('In actual output: %s' % e)
  167.             except:
  168.                 None<EXCEPTION MATCH>etree.XMLSyntaxError
  169.             
  170.  
  171.         None<EXCEPTION MATCH>etree.XMLSyntaxError
  172.         if parser is None or errors:
  173.             value = OutputChecker.output_difference(self, example, got, optionflags)
  174.             if errors:
  175.                 errors.append(value)
  176.                 return '\n'.join(errors)
  177.             return value
  178.         errors
  179.         html = parser is html_fromstring
  180.         diff_parts = []
  181.         diff_parts.append('Expected:')
  182.         diff_parts.append(self.format_doc(want_doc, html, 2))
  183.         diff_parts.append('Got:')
  184.         diff_parts.append(self.format_doc(got_doc, html, 2))
  185.         diff_parts.append('Diff:')
  186.         diff_parts.append(self.collect_diff(want_doc, got_doc, html, 2))
  187.         return '\n'.join(diff_parts)
  188.  
  189.     
  190.     def html_empty_tag(self, el, html = True):
  191.         if not html:
  192.             return False
  193.         if el.tag not in self.empty_tags:
  194.             return False
  195.         if el.text or len(el):
  196.             return False
  197.         return True
  198.  
  199.     
  200.     def format_doc(self, doc, html, indent, prefix = ''):
  201.         parts = []
  202.         if not len(doc):
  203.             parts.append(' ' * indent)
  204.             parts.append(prefix)
  205.             parts.append(self.format_tag(doc))
  206.             if not self.html_empty_tag(doc, html):
  207.                 if strip(doc.text):
  208.                     parts.append(self.format_text(doc.text))
  209.                 
  210.                 parts.append(self.format_end_tag(doc))
  211.             
  212.             if strip(doc.tail):
  213.                 parts.append(self.format_text(doc.tail))
  214.             
  215.             parts.append('\n')
  216.             return ''.join(parts)
  217.         parts.append(' ' * indent)
  218.         parts.append(prefix)
  219.         parts.append(self.format_tag(doc))
  220.         if strip(doc.tail):
  221.             parts.append(' ' * indent)
  222.             parts.append(self.format_text(doc.tail))
  223.             parts.append('\n')
  224.         
  225.         return ''.join(parts)
  226.  
  227.     
  228.     def format_text(self, text, strip = True):
  229.         if text is None:
  230.             return ''
  231.         if strip:
  232.             text = text.strip()
  233.         
  234.         return cgi.escape(text, 1)
  235.  
  236.     
  237.     def format_tag(self, el):
  238.         attrs = []
  239.         if isinstance(el, etree.CommentBase):
  240.             return '<!--'
  241.         for name, value in sorted(el.attrib.items()):
  242.             attrs.append('%s="%s"' % (name, self.format_text(value, False)))
  243.         
  244.         if not attrs:
  245.             return '<%s>' % el.tag
  246.         return '<%s %s>' % (el.tag, ' '.join(attrs))
  247.  
  248.     
  249.     def format_end_tag(self, el):
  250.         if isinstance(el, etree.CommentBase):
  251.             return '-->'
  252.         return '</%s>' % el.tag
  253.  
  254.     
  255.     def collect_diff(self, want, got, html, indent):
  256.         parts = []
  257.         if not len(want) and not len(got):
  258.             parts.append(' ' * indent)
  259.             parts.append(self.collect_diff_tag(want, got))
  260.             if not self.html_empty_tag(got, html):
  261.                 parts.append(self.collect_diff_text(want.text, got.text))
  262.                 parts.append(self.collect_diff_end_tag(want, got))
  263.             
  264.             parts.append(self.collect_diff_text(want.tail, got.tail))
  265.             parts.append('\n')
  266.             return ''.join(parts)
  267.         parts.append(' ' * indent)
  268.         parts.append(self.collect_diff_tag(want, got))
  269.         parts.append('\n')
  270.         if strip(want.text) or strip(got.text):
  271.             parts.append(' ' * indent)
  272.             parts.append(self.collect_diff_text(want.text, got.text))
  273.             parts.append('\n')
  274.         
  275.         want_children = list(want)
  276.         got_children = list(got)
  277.         while want_children or got_children:
  278.             if not want_children:
  279.                 parts.append(self.format_doc(got_children.pop(0), html, indent + 2, '-'))
  280.                 continue
  281.             
  282.             if not got_children:
  283.                 parts.append(self.format_doc(want_children.pop(0), html, indent + 2, '+'))
  284.                 continue
  285.             
  286.             parts.append(self.collect_diff(want_children.pop(0), got_children.pop(0), html, indent + 2))
  287.         parts.append(' ' * indent)
  288.         parts.append(self.collect_diff_end_tag(want, got))
  289.         parts.append('\n')
  290.         if strip(want.tail) or strip(got.tail):
  291.             parts.append(' ' * indent)
  292.             parts.append(self.collect_diff_text(want.tail, got.tail))
  293.             parts.append('\n')
  294.         
  295.         return ''.join(parts)
  296.  
  297.     
  298.     def collect_diff_tag(self, want, got):
  299.         if not self.tag_compare(want.tag, got.tag):
  300.             tag = '%s (got: %s)' % (want.tag, got.tag)
  301.         else:
  302.             tag = got.tag
  303.         attrs = []
  304.         if not want.tag == 'any':
  305.             pass
  306.         any = 'any' in want.attrib
  307.         for name, value in sorted(got.attrib.items()):
  308.             if name not in want.attrib and not any:
  309.                 attrs.append('-%s="%s"' % (name, self.format_text(value, False)))
  310.                 continue
  311.             if name in want.attrib:
  312.                 text = self.collect_diff_text(value, want.attrib[name], False)
  313.             else:
  314.                 text = self.format_text(value, False)
  315.             attrs.append('%s="%s"' % (name, text))
  316.         
  317.         if not any:
  318.             for name, value in sorted(want.attrib.items()):
  319.                 if name in got.attrib:
  320.                     continue
  321.                 
  322.                 attrs.append('+%s="%s"' % (name, self.format_text(value, False)))
  323.             
  324.         
  325.         if attrs:
  326.             tag = '<%s %s>' % (tag, ' '.join(attrs))
  327.         else:
  328.             tag = '<%s>' % tag
  329.         return tag
  330.  
  331.     
  332.     def collect_diff_end_tag(self, want, got):
  333.         if want.tag != got.tag:
  334.             tag = '%s (got: %s)' % (want.tag, got.tag)
  335.         else:
  336.             tag = got.tag
  337.         return '</%s>' % tag
  338.  
  339.     
  340.     def collect_diff_text(self, want, got, strip = True):
  341.         if self.text_compare(want, got, strip):
  342.             if not got:
  343.                 return ''
  344.             return self.format_text(got, strip)
  345.         text = '%s (got: %s)' % (want, got)
  346.         return self.format_text(text, strip)
  347.  
  348.  
  349.  
  350. class LHTMLOutputChecker(LXMLOutputChecker):
  351.     
  352.     def get_default_parser(self):
  353.         return html_fromstring
  354.  
  355.  
  356.  
  357. def install(html = False):
  358.     if html:
  359.         doctest.OutputChecker = LHTMLOutputChecker
  360.     else:
  361.         doctest.OutputChecker = LXMLOutputChecker
  362.  
  363.  
  364. def temp_install(html = False, del_module = None):
  365.     if html:
  366.         Checker = LHTMLOutputChecker
  367.     else:
  368.         Checker = LXMLOutputChecker
  369.     frame = _find_doctest_frame()
  370.     dt_self = frame.f_locals['self']
  371.     checker = Checker()
  372.     old_checker = dt_self._checker
  373.     dt_self._checker = checker
  374.     if _IS_PYTHON_3:
  375.         check_func = frame.f_locals['check'].__func__
  376.         checker_check_func = checker.check_output.__func__
  377.     else:
  378.         check_func = frame.f_locals['check'].im_func
  379.         checker_check_func = checker.check_output.im_func
  380.     doctest.etree = etree
  381.     _RestoreChecker(dt_self, old_checker, checker, check_func, checker_check_func, del_module)
  382.  
  383.  
  384. class _RestoreChecker(object):
  385.     
  386.     def __init__(self, dt_self, old_checker, new_checker, check_func, clone_func, del_module):
  387.         self.dt_self = dt_self
  388.         self.checker = old_checker
  389.         self.checker._temp_call_super_check_output = self.call_super
  390.         self.checker._temp_override_self = new_checker
  391.         self.check_func = check_func
  392.         self.clone_func = clone_func
  393.         self.del_module = del_module
  394.         self.install_clone()
  395.         self.install_dt_self()
  396.  
  397.     
  398.     def install_clone(self):
  399.         if _IS_PYTHON_3:
  400.             self.func_code = self.check_func.__code__
  401.             self.func_globals = self.check_func.__globals__
  402.             self.check_func.__code__ = self.clone_func.__code__
  403.         else:
  404.             self.func_code = self.check_func.func_code
  405.             self.func_globals = self.check_func.func_globals
  406.             self.check_func.func_code = self.clone_func.func_code
  407.  
  408.     
  409.     def uninstall_clone(self):
  410.         if _IS_PYTHON_3:
  411.             self.check_func.__code__ = self.func_code
  412.         else:
  413.             self.check_func.func_code = self.func_code
  414.  
  415.     
  416.     def install_dt_self(self):
  417.         self.prev_func = self.dt_self._DocTestRunner__record_outcome
  418.         self.dt_self._DocTestRunner__record_outcome = self
  419.  
  420.     
  421.     def uninstall_dt_self(self):
  422.         self.dt_self._DocTestRunner__record_outcome = self.prev_func
  423.  
  424.     
  425.     def uninstall_module(self):
  426.         if self.del_module:
  427.             import sys
  428.             del sys.modules[self.del_module]
  429.             if '.' in self.del_module:
  430.                 (package, module) = self.del_module.rsplit('.', 1)
  431.                 package_mod = sys.modules[package]
  432.                 delattr(package_mod, module)
  433.             
  434.         
  435.  
  436.     
  437.     def __call__(self, *args, **kw):
  438.         self.uninstall_clone()
  439.         self.uninstall_dt_self()
  440.         del self.checker._temp_override_self
  441.         del self.checker._temp_call_super_check_output
  442.         result = self.prev_func(*args, **kw)
  443.         self.uninstall_module()
  444.         return result
  445.  
  446.     
  447.     def call_super(self, *args, **kw):
  448.         self.uninstall_clone()
  449.         
  450.         try:
  451.             return self.check_func(*args, **kw)
  452.         finally:
  453.             self.install_clone()
  454.  
  455.  
  456.  
  457.  
  458. def _find_doctest_frame():
  459.     import sys
  460.     frame = sys._getframe(1)
  461.     while frame:
  462.         l = frame.f_locals
  463.         if 'BOOM' in l:
  464.             return frame
  465.         frame = frame.f_back
  466.         continue
  467.         'BOOM' in l
  468.     raise LookupError('Could not find doctest (only use this function *inside* a doctest)')
  469.  
  470. __test__ = {
  471.     'basic': '\n    >>> temp_install()\n    >>> print """<xml a="1" b="2">stuff</xml>"""\n    <xml b="2" a="1">...</xml>\n    >>> print """<xml xmlns="http://example.com"><tag   attr="bar"   /></xml>"""\n    <xml xmlns="...">\n      <tag attr="..." />\n    </xml>\n    >>> print """<xml>blahblahblah<foo /></xml>""" # doctest: +NOPARSE_MARKUP, +ELLIPSIS\n    <xml>...foo /></xml>\n    ' }
  472. if __name__ == '__main__':
  473.     import doctest
  474.     doctest.testmod()
  475.  
  476.