Django

Code

Show
Ignore:
Timestamp:
08/05/08 12:15:33 (5 months ago)
Author:
jbronn
Message:

gis: Merged revisions 7981-8001,8003-8011,8013-8033,8035-8036,8038-8039,8041-8063,8065-8076,8078-8139,8141-8154,8156-8214 via svnmerge from trunk.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis

    • Property svnmerge-integrated changed from /django/trunk:1-7978 to /django/trunk:1-8214
  • django/branches/gis/django/test/testcases.py

    r7836 r8215  
    22import unittest 
    33from urlparse import urlsplit, urlunsplit 
    4  
    5 from django.http import QueryDict 
    6 from django.db import transaction 
     4from xml.dom.minidom import parseString, Node 
     5 
    76from django.conf import settings 
    87from django.core import mail 
    98from django.core.management import call_command 
     9from django.core.urlresolvers import clear_url_caches 
     10from django.db import transaction 
     11from django.http import QueryDict 
    1012from django.test import _doctest as doctest 
    1113from django.test.client import Client 
    12 from django.core.urlresolvers import clear_url_caches 
     14from django.utils import simplejson 
    1315 
    1416normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) 
     
    2830class OutputChecker(doctest.OutputChecker): 
    2931    def check_output(self, want, got, optionflags): 
    30         ok = doctest.OutputChecker.check_output(self, want, got, optionflags) 
    31  
    32         # Doctest does an exact string comparison of output, which means long 
    33         # integers aren't equal to normal integers ("22L" vs. "22"). The 
    34         # following code normalizes long integers so that they equal normal 
    35         # integers. 
    36         if not ok: 
    37             return normalize_long_ints(want) == normalize_long_ints(got) 
    38         return ok 
     32        "The entry method for doctest output checking. Defers to a sequence of child checkers" 
     33        checks = (self.check_output_default, 
     34                  self.check_output_long, 
     35                  self.check_output_xml, 
     36                  self.check_output_json) 
     37        for check in checks: 
     38            if check(want, got, optionflags): 
     39                return True 
     40        return False 
     41 
     42    def check_output_default(self, want, got, optionflags): 
     43        "The default comparator provided by doctest - not perfect, but good for most purposes" 
     44        return doctest.OutputChecker.check_output(self, want, got, optionflags) 
     45 
     46    def check_output_long(self, want, got, optionflags): 
     47        """Doctest does an exact string comparison of output, which means long 
     48        integers aren't equal to normal integers ("22L" vs. "22"). The 
     49        following code normalizes long integers so that they equal normal 
     50        integers. 
     51        """ 
     52        return normalize_long_ints(want) == normalize_long_ints(got) 
     53 
     54    def check_output_xml(self, want, got, optionsflags): 
     55        """Tries to do a 'xml-comparision' of want and got.  Plain string 
     56        comparision doesn't always work because, for example, attribute 
     57        ordering should not be important. 
     58         
     59        Based on http://codespeak.net/svn/lxml/trunk/src/lxml/doctestcompare.py 
     60        """ 
     61        _norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+') 
     62        def norm_whitespace(v): 
     63            return _norm_whitespace_re.sub(' ', v) 
     64 
     65        def child_text(element): 
     66            return ''.join([c.data for c in element.childNodes 
     67                            if c.nodeType == Node.TEXT_NODE]) 
     68 
     69        def children(element): 
     70            return [c for c in element.childNodes 
     71                    if c.nodeType == Node.ELEMENT_NODE] 
     72 
     73        def norm_child_text(element): 
     74            return norm_whitespace(child_text(element)) 
     75 
     76        def attrs_dict(element): 
     77            return dict(element.attributes.items()) 
     78 
     79        def check_element(want_element, got_element): 
     80            if want_element.tagName != got_element.tagName: 
     81                return False 
     82            if norm_child_text(want_element) != norm_child_text(got_element): 
     83                return False 
     84            if attrs_dict(want_element) != attrs_dict(got_element): 
     85                return False 
     86            want_children = children(want_element) 
     87            got_children = children(got_element) 
     88            if len(want_children) != len(got_children): 
     89                return False 
     90            for want, got in zip(want_children, got_children): 
     91                if not check_element(want, got): 
     92                    return False 
     93            return True 
     94 
     95        want, got = self._strip_quotes(want, got) 
     96        want = want.replace('\\n','\n') 
     97        got = got.replace('\\n','\n') 
     98 
     99        # If the string is not a complete xml document, we may need to add a 
     100        # root element. This allow us to compare fragments, like "<foo/><bar/>" 
     101        if not want.startswith('<?xml'): 
     102            wrapper = '<root>%s</root>' 
     103            want = wrapper % want 
     104            got = wrapper % got 
     105             
     106        # Parse the want and got strings, and compare the parsings. 
     107        try: 
     108            want_root = parseString(want).firstChild 
     109            got_root = parseString(got).firstChild 
     110        except: 
     111            return False 
     112        return check_element(want_root, got_root) 
     113 
     114    def check_output_json(self, want, got, optionsflags): 
     115        "Tries to compare want and got as if they were JSON-encoded data" 
     116        want, got = self._strip_quotes(want, got) 
     117        try: 
     118            want_json = simplejson.loads(want) 
     119            got_json = simplejson.loads(got) 
     120        except: 
     121            return False 
     122        return want_json == got_json 
     123 
     124    def _strip_quotes(self, want, got): 
     125        """ 
     126        Strip quotes of doctests output values: 
     127 
     128        >>> o = OutputChecker() 
     129        >>> o._strip_quotes("'foo'") 
     130        "foo" 
     131        >>> o._strip_quotes('"foo"') 
     132        "foo" 
     133        >>> o._strip_quotes("u'foo'") 
     134        "foo" 
     135        >>> o._strip_quotes('u"foo"') 
     136        "foo" 
     137        """ 
     138        def is_quoted_string(s): 
     139            s = s.strip() 
     140            return (len(s) >= 2 
     141                    and s[0] == s[-1] 
     142                    and s[0] in ('"', "'")) 
     143 
     144        def is_quoted_unicode(s): 
     145            s = s.strip() 
     146            return (len(s) >= 3 
     147                    and s[0] == 'u' 
     148                    and s[1] == s[-1] 
     149                    and s[1] in ('"', "'")) 
     150 
     151        if is_quoted_string(want) and is_quoted_string(got): 
     152            want = want.strip()[1:-1] 
     153            got = got.strip()[1:-1] 
     154        elif is_quoted_unicode(want) and is_quoted_unicode(got): 
     155            want = want.strip()[2:-1] 
     156            got = got.strip()[2:-1] 
     157        return want, got 
     158 
    39159 
    40160class DocTestRunner(doctest.DocTestRunner):