diff --git a/colander/__init__.py b/colander/__init__.py index 05f7e82..16672da 100644 --- a/colander/__init__.py +++ b/colander/__init__.py @@ -2,11 +2,33 @@ import datetime import decimal import time import itertools -import iso8601 +from . import iso8601 import pprint import re import translationstring +import sys + +inPy3k = sys.version_info[0] == 3 + +try: + unicode +except NameError: + # Python 3 + basestring = unicode = str + +try: + next +except NameError: + # for Python 2.4 & 2.5 + def next(gen): + return gen.next() + +try: + xrange +except NameError: + xrange = range + _ = translationstring.TranslationStringFactory('colander') required = object() @@ -17,6 +39,9 @@ class _null(object): def __nonzero__(self): return False + def __bool__(self): + return False + def __repr__(self): return '' @@ -64,9 +89,12 @@ class Invalid(Exception): ``msg`` attribute is iterable, it is returned. If it is not iterable, a single-element list containing the ``msg`` value is returned.""" - if hasattr(self.msg, '__iter__'): - return self.msg - return [self.msg] + #if hasattr(self.msg, '__iter__'): + # return self.msg + #return [self.msg] + if isinstance(self.msg, basestring): + return [self.msg] + return self.msg def add(self, exc, pos=None): """ Add a child exception; ``exc`` must be an instance of @@ -169,7 +197,7 @@ class All(object): for validator in self.validators: try: validator(node, value) - except Invalid, e: + except Invalid as e: msgs.append(e.msg) if msgs: @@ -251,7 +279,7 @@ class Email(Regex): if msg is None: msg = _("Invalid email address") super(Email, self).__init__( - u'(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$', msg=msg) + unicode('(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$'), msg=msg) class Range(object): """ Validator which succeeds if the value it is passed is greater @@ -420,7 +448,7 @@ class Mapping(SchemaType): def _validate(self, node, value): try: return dict(value) - except Exception, e: + except Exception as e: raise Invalid(node, _('"${val}" is not a mapping type: ${err}', mapping = {'val':value, 'err':e}) @@ -437,7 +465,7 @@ class Mapping(SchemaType): subval = value.pop(name, null) try: result[name] = callback(subnode, subval) - except Invalid, e: + except Invalid as e: if error is None: error = Invalid(node) error.add(e, num) @@ -563,7 +591,7 @@ class Tuple(Positional, SchemaType): subval = value[num] try: result.append(callback(subnode, subval)) - except Invalid, e: + except Invalid as e: if error is None: error = Invalid(node) error.add(e, num) @@ -698,7 +726,7 @@ class Sequence(Positional, SchemaType): for num, subval in enumerate(value): try: result.append(callback(node.children[0], subval)) - except Invalid, e: + except Invalid as e: if error is None: error = Invalid(node) error.add(e, num) @@ -897,7 +925,7 @@ class String(SchemaType): else: result = unicode(appstruct) return result - except Exception, e: + except Exception as e: raise Invalid(node, _('"${val} cannot be serialized: ${err}', mapping={'val':appstruct, 'err':e}) @@ -910,10 +938,13 @@ class String(SchemaType): result = cstruct if not isinstance(result, unicode): if self.encoding: - result = unicode(str(cstruct), self.encoding) + if inPy3k: + result = unicode(bytes(cstruct), self.encoding) + else: + result = unicode(str(cstruct), self.encoding) else: result = unicode(cstruct) - except Exception, e: + except Exception as e: raise Invalid(node, _('${val} is not a string: %{err}', mapping={'val':cstruct, 'err':e})) @@ -1235,12 +1266,12 @@ class DateTime(SchemaType): try: result = iso8601.parse_date( cstruct, default_timezone=self.default_tzinfo) - except (iso8601.ParseError, TypeError), e: + except (iso8601.ParseError, TypeError) as e: try: year, month, day = map(int, cstruct.split('-', 2)) result = datetime.datetime(year, month, day, tzinfo=self.default_tzinfo) - except Exception, e: + except Exception as e: raise Invalid(node, _(self.err_template, mapping={'val':cstruct, 'err':e})) return result @@ -1312,7 +1343,7 @@ class Date(SchemaType): try: year, month, day = map(int, cstruct.split('-', 2)) result = datetime.date(year, month, day) - except Exception, e: + except Exception as e: raise Invalid(node, _(self.err_template, mapping={'val':cstruct, 'err':e}) @@ -1390,7 +1421,7 @@ class Time(SchemaType): except ValueError: try: result = timeparse(cstruct, '%H:%M') - except Exception, e: + except Exception as e: raise Invalid(node, _(self.err_template, mapping={'val':cstruct, 'err':e}) @@ -1470,7 +1501,8 @@ class SchemaNode(object): def __new__(cls, *arg, **kw): inst = object.__new__(cls) - inst._order = cls._counter.next() + #inst._order = cls._counter.next() + inst._order = next(cls._counter) return inst def __init__(self, typ, *children, **kw): @@ -1689,40 +1721,76 @@ class _SchemaMeta(type): extended.sort() cls.nodes = [x[1] for x in extended] -class Schema(object): - schema_type = Mapping - node_type = SchemaNode - __metaclass__ = _SchemaMeta +# class Schema(object): +# schema_type = Mapping +# node_type = SchemaNode +# __metaclass__ = _SchemaMeta +# +# def __new__(cls, *args, **kw): +# node = object.__new__(cls.node_type) +# node.name = None +# #node._order = SchemaNode._counter.next() +# node._order = next(SchemaNode._counter) +# typ = cls.schema_type() +# node.__init__(typ, *args, **kw) +# for n in cls.nodes: +# node.add(n) +# return node - def __new__(cls, *args, **kw): - node = object.__new__(cls.node_type) - node.name = None - node._order = SchemaNode._counter.next() - typ = cls.schema_type() - node.__init__(typ, *args, **kw) - for n in cls.nodes: - node.add(n) - return node +def _Schema__new__(cls, *args, **kw): + node = object.__new__(cls.node_type) + node.name = None + #node._order = SchemaNode._counter.next() + node._order = next(SchemaNode._counter) + typ = cls.schema_type() + node.__init__(typ, *args, **kw) + for n in cls.nodes: + node.add(n) + return node + +Schema = _SchemaMeta('Schema', (object,), + dict(schema_type=Mapping, + node_type=SchemaNode, + __new__=_Schema__new__)) MappingSchema = Schema -class SequenceSchema(object): - schema_type = Sequence - node_type = SchemaNode - __metaclass__ = _SchemaMeta +# class SequenceSchema(object): +# schema_type = Sequence +# node_type = SchemaNode +# __metaclass__ = _SchemaMeta +# +# def __new__(cls, *args, **kw): +# node = object.__new__(cls.node_type) +# node.name = None +# node._order = SchemaNode._counter.next() +# typ = cls.schema_type() +# node.__init__(typ, *args, **kw) +# if not len(cls.nodes) == 1: +# raise Invalid(node, +# 'Sequence schemas must have exactly one child node') +# for n in cls.nodes: +# node.add(n) +# return node - def __new__(cls, *args, **kw): - node = object.__new__(cls.node_type) - node.name = None - node._order = SchemaNode._counter.next() - typ = cls.schema_type() - node.__init__(typ, *args, **kw) - if not len(cls.nodes) == 1: - raise Invalid(node, - 'Sequence schemas must have exactly one child node') - for n in cls.nodes: - node.add(n) - return node +def _SequanceSchema__new__(cls, *args, **kw): + node = object.__new__(cls.node_type) + node.name = None + #node._order = SchemaNode._counter.next() + node._order = next(SchemaNode._counter) + typ = cls.schema_type() + node.__init__(typ, *args, **kw) + if not len(cls.nodes) == 1: + raise Invalid(node, + 'Sequence schemas must have exactly one child node') + for n in cls.nodes: + node.add(n) + return node + +SequenceSchema = _SchemaMeta('SequenceSchema', (object,), + dict(schema_type=Sequence, + node_type=SchemaNode, + __new__=_SequanceSchema__new__)) class TupleSchema(Schema): schema_type = Tuple diff --git a/colander/iso8601/__init__.py b/colander/iso8601/__init__.py new file mode 100755 index 0000000..3a002ac --- /dev/null +++ b/colander/iso8601/__init__.py @@ -0,0 +1,2 @@ +from .iso8601 import * +from . import iso8601 diff --git a/colander/iso8601/iso8601.py b/colander/iso8601/iso8601.py new file mode 100755 index 0000000..bcadc6b --- /dev/null +++ b/colander/iso8601/iso8601.py @@ -0,0 +1,108 @@ +"""ISO 8601 date time string parsing + +Basic usage: +>>> import iso8601 +>>> iso8601.parse_date("2007-01-25T12:00:00Z") +datetime.datetime(2007, 1, 25, 12, 0, tzinfo=) +>>> + +""" + +try: + unicode +except NameError: + # Python 3 + basestring = unicode = str + +from datetime import datetime, timedelta, tzinfo +import re + +__all__ = ["parse_date", "ParseError", "Utc", "FixedOffset"] + +# Adapted from http://delete.me.uk/2005/03/iso8601.html +ISO8601_REGEX = re.compile(r"(?P[0-9]{4})(-(?P[0-9]{1,2})(-(?P[0-9]{1,2})" + r"((?P.)(?P[0-9]{2}):(?P[0-9]{2})(:(?P[0-9]{2})(\.(?P[0-9]+))?)?" + r"(?PZ|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?" +) +TIMEZONE_REGEX = re.compile("(?P[+-])(?P[0-9]{2}).(?P[0-9]{2})") + +class ParseError(Exception): + """Raised when there is a problem parsing a date string""" + +# Yoinked from python docs +ZERO = timedelta(0) +class Utc(tzinfo): + """UTC + + """ + def utcoffset(self, dt): + return ZERO + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return ZERO +UTC = Utc() + +class FixedOffset(tzinfo): + """Fixed offset in hours and minutes from UTC + + """ + def __init__(self, offset_hours, offset_minutes, name): + self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) + self.__name = name + + def utcoffset(self, dt): + return self.__offset + + def tzname(self, dt): + return self.__name + + def dst(self, dt): + return ZERO + + def __repr__(self): + return "" % self.__name + +def parse_timezone(tzstring, default_timezone=UTC): + """Parses ISO 8601 time zone specs into tzinfo offsets + + """ + if tzstring == "Z": + return default_timezone + # This isn't strictly correct, but it's common to encounter dates without + # timezones so I'll assume the default (which defaults to UTC). + # Addresses issue 4. + if tzstring is None: + return default_timezone + m = TIMEZONE_REGEX.match(tzstring) + prefix, hours, minutes = m.groups() + hours, minutes = int(hours), int(minutes) + if prefix == "-": + hours = -hours + minutes = -minutes + return FixedOffset(hours, minutes, tzstring) + +def parse_date(datestring, default_timezone=UTC): + """Parses ISO 8601 dates into datetime objects + + The timezone is parsed from the date string. However it is quite common to + have dates without a timezone (not strictly correct). In this case the + default timezone specified in default_timezone is used. This is UTC by + default. + """ + if not isinstance(datestring, basestring): + raise ParseError("Expecting a string %r" % datestring) + m = ISO8601_REGEX.match(datestring) + if not m: + raise ParseError("Unable to parse date string %r" % datestring) + groups = m.groupdict() + tz = parse_timezone(groups["timezone"], default_timezone=default_timezone) + if groups["fraction"] is None: + groups["fraction"] = 0 + else: + groups["fraction"] = int(float("0.%s" % groups["fraction"]) * 1e6) + return datetime(int(groups["year"]), int(groups["month"]), int(groups["day"]), + int(groups["hour"]), int(groups["minute"]), int(groups["second"]), + int(groups["fraction"]), tz) diff --git a/colander/tests.py b/colander/tests.py index daf2e6e..31565ab 100644 --- a/colander/tests.py +++ b/colander/tests.py @@ -1,10 +1,17 @@ +# -*- coding:utf-8 -*- import unittest +try: + unicode +except NameError: + # Python 3 + basestring = unicode = str + def invalid_exc(func, *arg, **kw): from colander import Invalid try: func(*arg, **kw) - except Invalid, e: + except Invalid as e: return e else: raise AssertionError('Invalid not raised') # pragma: no cover @@ -26,7 +33,7 @@ class TestInvalid(unittest.TestCase): exc = self._makeOne(None, 'msg') other = Dummy() exc.add(other) - self.failIf(hasattr(other, 'positional')) + self.assertFalse(hasattr(other, 'positional')) self.assertEqual(exc.children, [other]) def test_add_positional(self): @@ -365,14 +372,14 @@ class TestMapping(unittest.TestCase): self._makeOne('ignore') self._makeOne('raise') self._makeOne('preserve') - except ValueError, e: # pragma: no cover + except ValueError as e: # pragma: no cover raise AssertionError(e) def test_deserialize_not_a_mapping(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, None) - self.failUnless( + self.assertTrue( e.msg.interpolate().startswith('"None" is not a mapping type')) def test_deserialize_null(self): @@ -445,7 +452,7 @@ class TestMapping(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, None) - self.failUnless( + self.assertTrue( e.msg.interpolate().startswith('"None" is not a mapping type')) def test_serialize_no_subnodes(self): @@ -950,10 +957,11 @@ class TestString(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, val) - self.failUnless(e.msg) + self.assertTrue(e.msg) def test_deserialize_unicode_from_None(self): - uni = u'\xf8' + #uni = unicode(b'\xf8') + uni = unicode(b'\xe3\x81\x82', encoding='utf-8') node = DummySchemaNode(None) typ = self._makeOne() result = typ.deserialize(node, uni) @@ -967,7 +975,8 @@ class TestString(unittest.TestCase): self.assertEqual(result, unicode(value)) def test_deserialize_from_utf8(self): - uni = u'\xf8' + #uni = unicode(b'\xf8') + uni = unicode(b'\xe3\x81\x82', encoding='utf-8') utf8 = uni.encode('utf-8') node = DummySchemaNode(None) typ = self._makeOne('utf-8') @@ -975,7 +984,8 @@ class TestString(unittest.TestCase): self.assertEqual(result, uni) def test_deserialize_from_utf16(self): - uni = u'\xf8' + #uni = unicode(b'\xf8') + uni = unicode(b'\xe3\x81\x82', encoding='utf-8') utf16 = uni.encode('utf-16') node = DummySchemaNode(None) typ = self._makeOne('utf-16') @@ -994,7 +1004,7 @@ class TestString(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, val) - self.failUnless(e.msg) + self.assertTrue(e.msg) def test_serialize_nonunicode_to_None(self): value = object() @@ -1004,14 +1014,15 @@ class TestString(unittest.TestCase): self.assertEqual(result, unicode(value)) def test_serialize_unicode_to_None(self): - value = u'abc' + value = unicode('abc') node = DummySchemaNode(None) typ = self._makeOne() result = typ.serialize(node, value) self.assertEqual(result, value) def test_serialize_to_utf8(self): - uni = u'\xf8' + #uni = unicode(b'\xf8') + uni = unicode(b'\xe3\x81\x82', encoding='utf-8') utf8 = uni.encode('utf-8') node = DummySchemaNode(None) typ = self._makeOne('utf-8') @@ -1019,7 +1030,8 @@ class TestString(unittest.TestCase): self.assertEqual(result, utf8) def test_serialize_to_utf16(self): - uni = u'\xf8' + #uni = unicode(b'\xf8') + uni = unicode(b'\xe3\x81\x82', encoding='utf-8') utf16 = uni.encode('utf-16') node = DummySchemaNode(None) typ = self._makeOne('utf-16') @@ -1027,11 +1039,11 @@ class TestString(unittest.TestCase): self.assertEqual(result, utf16) def test_serialize_string_with_high_unresolveable_high_order_chars(self): - not_utf8 = '\xff\xfe\xf8\x00' + not_utf8 = b'\xff\xfe\xf8\x00' node = DummySchemaNode(None) typ = self._makeOne('utf-8') e = invalid_exc(typ.serialize, node, not_utf8) - self.failUnless('cannot be serialized' in e.msg) + self.assertTrue('cannot be serialized' in e.msg) class TestInteger(unittest.TestCase): def _makeOne(self): @@ -1064,7 +1076,7 @@ class TestInteger(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, val) - self.failUnless(e.msg) + self.assertTrue(e.msg) def test_deserialize_ok(self): val = '1' @@ -1078,7 +1090,7 @@ class TestInteger(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, val) - self.failUnless(e.msg) + self.assertTrue(e.msg) def test_serialize_ok(self): val = 1 @@ -1113,7 +1125,7 @@ class TestFloat(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, val) - self.failUnless(e.msg) + self.assertTrue(e.msg) def test_deserialize_ok(self): val = '1.0' @@ -1127,7 +1139,7 @@ class TestFloat(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, val) - self.failUnless(e.msg) + self.assertTrue(e.msg) def test_serialize_ok(self): val = 1.0 @@ -1162,7 +1174,7 @@ class TestDecimal(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, val) - self.failUnless(e.msg) + self.assertTrue(e.msg) def test_deserialize_ok(self): import decimal @@ -1177,7 +1189,7 @@ class TestDecimal(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.serialize, node, val) - self.failUnless(e.msg) + self.assertTrue(e.msg) def test_serialize_ok(self): val = 1.0 @@ -1217,7 +1229,7 @@ class TestBoolean(unittest.TestCase): typ = self._makeOne() node = DummySchemaNode(None) e = invalid_exc(typ.deserialize, node, Uncooperative()) - self.failUnless(e.msg.endswith('not a string')) + self.assertTrue(e.msg.endswith('not a string')) def test_deserialize_null(self): import colander @@ -1423,12 +1435,12 @@ class TestDateTime(unittest.TestCase): return datetime.date.today() def test_ctor_default_tzinfo_None(self): - import iso8601 + from . import iso8601 typ = self._makeOne() self.assertEqual(typ.default_tzinfo.__class__, iso8601.iso8601.Utc) def test_ctor_default_tzinfo_non_None(self): - import iso8601 + from . import iso8601 tzinfo = iso8601.iso8601.FixedOffset(1, 0, 'myname') typ = self._makeOne(default_tzinfo=tzinfo) self.assertEqual(typ.default_tzinfo, tzinfo) @@ -1474,7 +1486,7 @@ class TestDateTime(unittest.TestCase): self.assertEqual(result, dt.isoformat()) def test_serialize_with_tzware_datetime(self): - import iso8601 + from . import iso8601 typ = self._makeOne() dt = self._dt() tzinfo = iso8601.iso8601.FixedOffset(1, 0, 'myname') @@ -1486,7 +1498,7 @@ class TestDateTime(unittest.TestCase): def test_deserialize_date(self): import datetime - import iso8601 + from . import iso8601 date = self._today() typ = self._makeOne() formatted = date.isoformat() @@ -1501,7 +1513,7 @@ class TestDateTime(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, 'garbage') - self.failUnless('Invalid' in e.msg) + self.assertTrue('Invalid' in e.msg) def test_deserialize_null(self): import colander @@ -1518,7 +1530,7 @@ class TestDateTime(unittest.TestCase): self.assertEqual(result, colander.null) def test_deserialize_success(self): - import iso8601 + from . import iso8601 typ = self._makeOne() dt = self._dt() tzinfo = iso8601.iso8601.FixedOffset(1, 0, 'myname') @@ -1529,7 +1541,7 @@ class TestDateTime(unittest.TestCase): self.assertEqual(result.isoformat(), iso) def test_deserialize_naive_with_default_tzinfo(self): - import iso8601 + from . import iso8601 tzinfo = iso8601.iso8601.FixedOffset(1, 0, 'myname') typ = self._makeOne(default_tzinfo=tzinfo) dt = self._dt() @@ -1594,13 +1606,13 @@ class TestDate(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, 'garbage') - self.failUnless('Invalid' in e.msg) + self.assertTrue('Invalid' in e.msg) def test_deserialize_invalid_weird(self): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, '10-10-10-10') - self.failUnless('Invalid' in e.msg) + self.assertTrue('Invalid' in e.msg) def test_deserialize_null(self): import colander @@ -1679,7 +1691,7 @@ class TestTime(unittest.TestCase): node = DummySchemaNode(None) typ = self._makeOne() e = invalid_exc(typ.deserialize, node, 'garbage') - self.failUnless('Invalid' in e.msg) + self.assertTrue('Invalid' in e.msg) def test_deserialize_three_digit_string(self): import datetime @@ -1739,7 +1751,7 @@ class TestSchemaNode(unittest.TestCase): def test_new_sets_order(self): node = self._makeOne(None) - self.failUnless(hasattr(node, '_order')) + self.assertTrue(hasattr(node, '_order')) def test_ctor_no_title(self): node = self._makeOne(None, 0, validator=1, default=2, name='name_a', @@ -1911,8 +1923,8 @@ class TestSchemaNode(unittest.TestCase): def test_repr(self): node = self._makeOne(None, name='flub') result = repr(node) - self.failUnless(result.startswith('")) + self.assertTrue(result.startswith('")) def test___getitem__success(self): node = self._makeOne(None) @@ -1958,8 +1970,8 @@ class TestSchemaNode(unittest.TestCase): node = self._makeOne(None) another = self._makeOne(None, name='another') node.add(another) - self.assertEquals('another' in node, True) - self.assertEquals('b' in node, False) + self.assertEqual('another' in node, True) + self.assertEqual('b' in node, False) def test_clone(self): inner_typ = DummyType() @@ -1970,13 +1982,13 @@ class TestSchemaNode(unittest.TestCase): inner_node.foo = 2 outer_node.children = [inner_node] outer_clone = outer_node.clone() - self.failIf(outer_clone is outer_node) + self.assertFalse(outer_clone is outer_node) self.assertEqual(outer_clone.typ, outer_typ) self.assertEqual(outer_clone.name, 'outer') self.assertEqual(outer_node.foo, 1) self.assertEqual(len(outer_clone.children), 1) inner_clone = outer_clone.children[0] - self.failIf(inner_clone is inner_node) + self.assertFalse(inner_clone is inner_node) self.assertEqual(inner_clone.typ, inner_typ) self.assertEqual(inner_clone.name, 'inner') self.assertEqual(inner_clone.foo, 2) @@ -1986,8 +1998,8 @@ class TestSchemaNode(unittest.TestCase): inner_typ = DummyType() outer_typ = DummyType() def dv(node, kw): - self.failUnless(node.name in ['outer', 'inner']) - self.failUnless('a' in kw) + self.assertTrue(node.name in ['outer', 'inner']) + self.assertTrue('a' in kw) return '123' dv = deferred(dv) outer_node = self._makeOne(outer_typ, name='outer', missing=dv) @@ -1995,10 +2007,10 @@ class TestSchemaNode(unittest.TestCase): missing=dv) outer_node.children = [inner_node] outer_clone = outer_node.bind(a=1) - self.failIf(outer_clone is outer_node) + self.assertFalse(outer_clone is outer_node) self.assertEqual(outer_clone.missing, '123') inner_clone = outer_clone.children[0] - self.failIf(inner_clone is inner_node) + self.assertFalse(inner_clone is inner_node) self.assertEqual(inner_clone.missing, '123') self.assertEqual(inner_clone.validator, '123') @@ -2007,8 +2019,8 @@ class TestSchemaNode(unittest.TestCase): inner_typ = DummyType() outer_typ = DummyType() def dv(node, kw): - self.failUnless(node.name in ['outer', 'inner']) - self.failUnless('a' in kw) + self.assertTrue(node.name in ['outer', 'inner']) + self.assertTrue('a' in kw) return '123' dv = deferred(dv) def remove_inner(node, kw): @@ -2020,7 +2032,7 @@ class TestSchemaNode(unittest.TestCase): missing=dv) outer_node.children = [inner_node] outer_clone = outer_node.bind(a=1) - self.failIf(outer_clone is outer_node) + self.assertFalse(outer_clone is outer_node) self.assertEqual(outer_clone.missing, '123') self.assertEqual(len(outer_clone.children), 0) self.assertEqual(len(outer_node.children), 1) @@ -2058,7 +2070,7 @@ class TestSchema(unittest.TestCase): thing_a = colander.SchemaNode(colander.String()) thing2 = colander.SchemaNode(colander.String(), title='bar') node = MySchema(default='abc') - self.failUnless(hasattr(node, '_order')) + self.assertTrue(hasattr(node, '_order')) self.assertEqual(node.default, 'abc') self.assertEqual(node.__class__, colander.SchemaNode) self.assertEqual(node.typ.__class__, colander.Mapping) @@ -2086,7 +2098,7 @@ class TestSequenceSchema(unittest.TestCase): class MySchema(colander.SequenceSchema): inner = _inner node = MySchema() - self.failUnless(hasattr(node, '_order')) + self.assertTrue(hasattr(node, '_order')) self.assertEqual(node.__class__, colander.SchemaNode) self.assertEqual(node.typ.__class__, colander.Sequence) self.assertEqual(node.children[0], _inner) @@ -2118,7 +2130,7 @@ class TestTupleSchema(unittest.TestCase): class MySchema(colander.TupleSchema): thing = colander.SchemaNode(colander.String()) node = MySchema() - self.failUnless(hasattr(node, '_order')) + self.assertTrue(hasattr(node, '_order')) self.assertEqual(node.__class__, colander.SchemaNode) self.assertEqual(node.typ.__class__, colander.Tuple) self.assertEqual(node.children[0].typ.__class__, colander.String) @@ -2378,7 +2390,7 @@ class TestDeclarative(unittest.TestCase, TestFunctional): class Test_null(unittest.TestCase): def test___nonzero__(self): from colander import null - self.failIf(null) + self.assertFalse(null) def test___repr__(self): from colander import null @@ -2386,8 +2398,8 @@ class Test_null(unittest.TestCase): def test_pickling(self): from colander import null - import cPickle - self.failUnless(cPickle.loads(cPickle.dumps(null)) is null) + import pickle + self.assertTrue(pickle.loads(pickle.dumps(null)) is null) class Dummy(object): pass diff --git a/setup.py b/setup.py index e29d8b2..151a074 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,8 @@ except: README = '' CHANGES = '' -requires = ['iso8601', 'translationstring'] +#requires = ['iso8601', 'translationstring'] +requires = ['translationstring'] setup(name='colander', version='0.9.5', diff --git a/tox.ini b/tox.ini index 45a8125..1f56528 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py24,py25,py26,py27,jython,pypy,cover + py26,py27,py32,jython,pypy,cover [testenv] commands =