Commit f642e9e3 authored by wbond's avatar wbond

Python 2.6 compat fixes for tests

parent b91c4495
# Copyright (c) 2009 Raymond Hettinger
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
from UserDict import DictMixin
class OrderedDict(dict, DictMixin):
def __init__(self, *args, **kwds):
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
try:
self.__end
except AttributeError:
self.clear()
self.update(*args, **kwds)
def clear(self):
self.__end = end = []
end += [None, end, end] # sentinel node for doubly linked list
self.__map = {} # key --> [key, prev, next]
dict.clear(self)
def __setitem__(self, key, value):
if key not in self:
end = self.__end
curr = end[1]
curr[2] = end[1] = self.__map[key] = [key, curr, end]
dict.__setitem__(self, key, value)
def __delitem__(self, key):
dict.__delitem__(self, key)
key, prev, next = self.__map.pop(key)
prev[2] = next
next[1] = prev
def __iter__(self):
end = self.__end
curr = end[2]
while curr is not end:
yield curr[0]
curr = curr[2]
def __reversed__(self):
end = self.__end
curr = end[1]
while curr is not end:
yield curr[0]
curr = curr[1]
def popitem(self, last=True):
if not self:
raise KeyError('dictionary is empty')
if last:
key = reversed(self).next()
else:
key = iter(self).next()
value = self.pop(key)
return key, value
def __reduce__(self):
items = [[k, self[k]] for k in self]
tmp = self.__map, self.__end
del self.__map, self.__end
inst_dict = vars(self).copy()
self.__map, self.__end = tmp
if inst_dict:
return (self.__class__, (items,), inst_dict)
return self.__class__, (items,)
def keys(self):
return list(self)
setdefault = DictMixin.setdefault
update = DictMixin.update
pop = DictMixin.pop
values = DictMixin.values
items = DictMixin.items
iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems
def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, self.items())
def copy(self):
return self.__class__(self)
@classmethod
def fromkeys(cls, iterable, value=None):
d = cls()
for key in iterable:
d[key] = value
return d
def __eq__(self, other):
if isinstance(other, OrderedDict):
if len(self) != len(other):
return False
for p, q in zip(self.items(), other.items()):
if p != q:
return False
return True
return dict.__eq__(self, other)
def __ne__(self, other):
return not self == other
...@@ -21,14 +21,17 @@ import unittest ...@@ -21,14 +21,17 @@ import unittest
from functools import wraps from functools import wraps
if sys.version_info >= (3,): if sys.version_info >= (3,):
from collections import OrderedDict
from urllib.request import urlopen from urllib.request import urlopen
from urllib.error import HTTPError from urllib.error import HTTPError
from urllib.parse import urljoin from urllib.parse import urljoin
generator_method_type = 'method'
str_cls = str
else: else:
from .ordereddict import OrderedDict from . import unittest_compat
from urlparse import urljoin from urlparse import urljoin
from urllib2 import HTTPError, urlopen from urllib2 import HTTPError, urlopen
generator_method_type = 'instancemethod'
str_cls = unicode
if hasattr(sys, 'argv'): if hasattr(sys, 'argv'):
...@@ -51,16 +54,7 @@ def _open(filepath, *args, **kwargs): ...@@ -51,16 +54,7 @@ def _open(filepath, *args, **kwargs):
if not os.path.exists(filepath): if not os.path.exists(filepath):
filepath = os.path.join("..", filepath) filepath = os.path.join("..", filepath)
if sys.version_info >= (3,): return open(filepath, 'rb', *args, **kwargs)
encoding = 'utf-8'
errors = 'replace'
if args and args[0] in ['rb', 'wb', 'ab']:
encoding = None
errors = None
kwargs['encoding'] = encoding
kwargs['errors'] = errors
return open(filepath, *args, **kwargs)
def generate_test_methods(cls, stream): def generate_test_methods(cls, stream):
...@@ -79,7 +73,7 @@ def generate_test_methods(cls, stream): ...@@ -79,7 +73,7 @@ def generate_test_methods(cls, stream):
if not name.startswith("generate_") or not callable(generator): if not name.startswith("generate_") or not callable(generator):
continue continue
if not generator.__class__.__name__ == 'method': if not generator.__class__.__name__ == generator_method_type:
raise TypeError("Generator methods must be classmethods") raise TypeError("Generator methods must be classmethods")
# Create new methods for each `yield` # Create new methods for each `yield`
...@@ -137,16 +131,16 @@ class TestContainer(object): ...@@ -137,16 +131,16 @@ class TestContainer(object):
""" """
package_key_types_map = { package_key_types_map = {
'name': str, 'name': str_cls,
'details': str, 'details': str_cls,
'description': str, 'description': str_cls,
'releases': list, 'releases': list,
'homepage': str, 'homepage': str_cls,
'author': str, 'author': str_cls,
'readme': str, 'readme': str_cls,
'issues': str, 'issues': str_cls,
'donate': (str, type(None)), 'donate': (str_cls, type(None)),
'buy': str, 'buy': str_cls,
'previous_names': list, 'previous_names': list,
'labels': list 'labels': list
} }
...@@ -208,7 +202,7 @@ class TestContainer(object): ...@@ -208,7 +202,7 @@ class TestContainer(object):
"Package inserted in wrong file") "Package inserted in wrong file")
# Check package order # Check package order
self.assertEqual(packages, sorted(packages, key=str.lower), self.assertEqual(packages, sorted(packages, key=str_cls.lower),
"Packages must be sorted alphabetically (by name)") "Packages must be sorted alphabetically (by name)")
def _test_repository_indents(self, include, contents): def _test_repository_indents(self, include, contents):
...@@ -295,8 +289,8 @@ class TestContainer(object): ...@@ -295,8 +289,8 @@ class TestContainer(object):
'and <version> is a 4 digit number') 'and <version> is a 4 digit number')
if k == 'platforms': if k == 'platforms':
self.assertIsInstance(v, (str, list)) self.assertIsInstance(v, (str_cls, list))
if isinstance(v, str): if isinstance(v, str_cls):
v = [v] v = [v]
for plat in v: for plat in v:
self.assertRegex(plat, self.assertRegex(plat,
...@@ -345,18 +339,20 @@ class TestContainer(object): ...@@ -345,18 +339,20 @@ class TestContainer(object):
if re.match('https?://', path, re.I) is not None: if re.match('https?://', path, re.I) is not None:
# Download the repository # Download the repository
try: try:
with urlopen(path) as f: f = urlopen(path)
source = f.read().decode("utf-8") source = f.read().decode("utf-8", 'replace')
except Exception as e: except Exception as e:
cls._write(stream, 'failed (%s)\n' % str(e)) cls._write(stream, 'failed (%s)\n' % str_cls(e))
yield cls._fail("Downloading %s failed" % path, e) yield cls._fail("Downloading %s failed" % path, e)
return return
finally:
f.close()
else: else:
try: try:
with _open(path, 'rb') as f: with _open(path) as f:
source = f.read().decode('utf-8') source = f.read().decode('utf-8', 'replace')
except Exception as e: except Exception as e:
cls._write(stream, 'failed (%s)\n' % str(e)) cls._write(stream, 'failed (%s)\n' % str_cls(e))
yield cls._fail("Opening %s failed" % path, e) yield cls._fail("Opening %s failed" % path, e)
return return
...@@ -405,7 +401,8 @@ class TestContainer(object): ...@@ -405,7 +401,8 @@ class TestContainer(object):
if 'includes' in data: if 'includes' in data:
for include in data['includes']: for include in data['includes']:
i_url = urljoin(path, include) i_url = urljoin(path, include)
yield from cls._include_tests(i_url, stream) for test in cls._include_tests(i_url, stream):
yield test
@classmethod @classmethod
def _fail(cls, *args): def _fail(cls, *args):
...@@ -436,7 +433,8 @@ class DefaultChannelTests(TestContainer, unittest.TestCase): ...@@ -436,7 +433,8 @@ class DefaultChannelTests(TestContainer, unittest.TestCase):
maxDiff = None maxDiff = None
with _open('channel.json') as f: with _open('channel.json') as f:
j = json.load(f) source = f.read().decode('utf-8', 'replace')
j = json.loads(source)
def test_channel_keys(self): def test_channel_keys(self):
keys = sorted(self.j.keys()) keys = sorted(self.j.keys())
...@@ -446,11 +444,11 @@ class DefaultChannelTests(TestContainer, unittest.TestCase): ...@@ -446,11 +444,11 @@ class DefaultChannelTests(TestContainer, unittest.TestCase):
self.assertIsInstance(self.j['repositories'], list) self.assertIsInstance(self.j['repositories'], list)
for repo in self.j['repositories']: for repo in self.j['repositories']:
self.assertIsInstance(repo, str) self.assertIsInstance(repo, str_cls)
def test_channel_repo_order(self): def test_channel_repo_order(self):
repos = self.j['repositories'] repos = self.j['repositories']
self.assertEqual(repos, sorted(repos, key=str.lower), self.assertEqual(repos, sorted(repos, key=str_cls.lower),
"Repositories must be sorted alphabetically") "Repositories must be sorted alphabetically")
@classmethod @classmethod
...@@ -468,7 +466,8 @@ class DefaultChannelTests(TestContainer, unittest.TestCase): ...@@ -468,7 +466,8 @@ class DefaultChannelTests(TestContainer, unittest.TestCase):
if not repository.startswith("http"): if not repository.startswith("http"):
cls._fail("Unexpected repository url: %s" % repository) cls._fail("Unexpected repository url: %s" % repository)
yield from cls._include_tests(repository, stream) for test in cls._include_tests(repository, stream):
yield test
cls._write(stream, '\n') cls._write(stream, '\n')
...@@ -477,7 +476,8 @@ class DefaultRepositoryTests(TestContainer, unittest.TestCase): ...@@ -477,7 +476,8 @@ class DefaultRepositoryTests(TestContainer, unittest.TestCase):
maxDiff = None maxDiff = None
with _open('repository.json') as f: with _open('repository.json') as f:
j = json.load(f, object_pairs_hook=OrderedDict) source = f.read().decode('utf-8', 'replace')
j = json.loads(source)
def test_repository_keys(self): def test_repository_keys(self):
keys = sorted(self.j.keys()) keys = sorted(self.j.keys())
...@@ -488,15 +488,15 @@ class DefaultRepositoryTests(TestContainer, unittest.TestCase): ...@@ -488,15 +488,15 @@ class DefaultRepositoryTests(TestContainer, unittest.TestCase):
self.assertIsInstance(self.j['includes'], list) self.assertIsInstance(self.j['includes'], list)
for include in self.j['includes']: for include in self.j['includes']:
self.assertIsInstance(include, str) self.assertIsInstance(include, str_cls)
@classmethod @classmethod
def generate_include_tests(cls, stream): def generate_include_tests(cls, stream):
for include in cls.j['includes']: for include in cls.j['includes']:
try: try:
with _open(include) as f: with _open(include) as f:
contents = f.read() contents = f.read().decode('utf-8', 'replace')
data = json.loads(contents, object_pairs_hook=OrderedDict) data = json.loads(contents)
except Exception as e: except Exception as e:
yield cls._test_error, ("Error while reading %r" % include, e) yield cls._test_error, ("Error while reading %r" % include, e)
continue continue
......
import re
import unittest
def assertIn(self, member, container, msg=None):
"""Just like self.assertTrue(a in b), but with a nicer default message."""
if member not in container:
if not msg:
msg = '%r not found in %r' % (member, container)
self.fail(msg)
unittest.TestCase.assertIn = assertIn
def assertNotIn(self, member, container, msg=None):
"""Just like self.assertTrue(a not in b), but with a nicer default message."""
if member in container:
if not msg:
msg = '%s unexpectedly found in %s' % (member,
container)
self.fail(msg)
unittest.TestCase.assertNotIn = assertNotIn
def assertGreater(self, a, b, msg=None):
"""Just like self.assertTrue(a > b), but with a nicer default message."""
if not a > b:
if not msg:
msg = '%s not greater than %s' % (a, b)
self.fail(msg)
unittest.TestCase.assertGreater = assertGreater
def assertRegexpMatches(self, text, expected_regexp, msg=None):
"""Fail the test unless the text matches the regular expression."""
if isinstance(expected_regexp, basestring):
expected_regexp = re.compile(expected_regexp)
if not expected_regexp.search(text):
msg = msg or "Regexp didn't match"
msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
raise self.failureException(msg)
unittest.TestCase.assertRegex = assertRegexpMatches
def assertNotRegexpMatches(self, text, unexpected_regexp, msg=None):
"""Fail the test if the text matches the regular expression."""
if isinstance(unexpected_regexp, basestring):
unexpected_regexp = re.compile(unexpected_regexp)
match = unexpected_regexp.search(text)
if match:
msg = msg or "Regexp matched"
msg = '%s: %r matches %r in %r' % (msg,
text[match.start():match.end()],
unexpected_regexp.pattern,
text)
raise self.failureException(msg)
unittest.TestCase.assertNotRegex = assertNotRegexpMatches
def assertIsInstance(self, obj, cls, msg=None):
"""Same as self.assertTrue(isinstance(obj, cls)), with a nicer
default message."""
if not isinstance(obj, cls):
if not msg:
msg = '%s is not an instance of %r' % (obj, cls)
self.fail(msg)
unittest.TestCase.assertIsInstance = assertIsInstance
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment