def test_class(): class C1(object): pass schema = Schema(C1) schema(C1()) try: schema(None) except MultipleInvalid as e: assert_equal(str(e), "expected C1") assert_equal(len(e.errors), 1) assert_equal(type(e.errors[0]), TypeInvalid) else: assert False, "Did not raise Invalid" # In Python 2, this will be an old-style class (classobj instance) class C2: pass schema = Schema(C2) schema(C2()) try: schema(None) except MultipleInvalid as e: assert_equal(str(e), "expected C2") assert_equal(len(e.errors), 1) assert_equal(type(e.errors[0]), TypeInvalid) else: assert False, "Did not raise Invalid"
def test_unordered(): # Any order is OK s = Schema(Unordered([2, 1])) s([2, 1]) s([1, 2]) # Amount of errors is OK assert_raises(Invalid, s, [2, 0]) assert_raises(MultipleInvalid, s, [0, 0]) # Different length is NOK assert_raises(Invalid, s, [1]) assert_raises(Invalid, s, [1, 2, 0]) assert_raises(MultipleInvalid, s, [1, 2, 0, 0]) # Other type than list or tuple is NOK assert_raises(Invalid, s, 'foo') assert_raises(Invalid, s, 10) # Validators are evaluated through as schemas s = Schema(Unordered([int, str])) s([1, '2']) s(['1', 2]) s = Schema(Unordered([{'foo': int}, []])) s([{'foo': 3}, []]) # Most accurate validators must be positioned on left s = Schema(Unordered([int, 3])) assert_raises(Invalid, s, [3, 2]) s = Schema(Unordered([3, int])) s([3, 2])
def test_self_all(): schema = Schema( { "number": int, "follow": All(Self, Schema({"extra_number": int}, extra=ALLOW_EXTRA)) }, extra=ALLOW_EXTRA) try: schema({"number": "abc"}) except MultipleInvalid: pass else: assert False, "Did not raise Invalid" try: schema({"follow": {"number": '123456.712'}}) except MultipleInvalid: pass else: assert False, "Did not raise Invalid" schema({"follow": {"number": 123456}}) schema({"follow": {"follow": {"number": 123456}}}) schema({"follow": {"number": 123456, "extra_number": 123}}) try: schema({"follow": {"number": 123456, "extra_number": "123"}}) except MultipleInvalid: pass else: assert False, "Did not raise Invalid"
def test_named_tuples_validate_as_tuples(): NT = collections.namedtuple('NT', ['a', 'b']) nt = NT(1, 2) t = (1, 2) Schema((int, int))(nt) Schema((int, int))(t) Schema(NT(int, int))(nt) Schema(NT(int, int))(t)
def test_schema_infer_dict(): schema = Schema.infer({'a': {'b': {'c': 'foo'}}}) assert_equal( schema, Schema({Required('a'): { Required('b'): { Required('c'): str } }}))
def test_schema_extend_overrides(): """Verify that Schema.extend can override required/extra parameters.""" base = Schema({'a': int}, required=True) extended = base.extend({'b': str}, required=False, extra=ALLOW_EXTRA) assert base.required is True assert base.extra == PREVENT_EXTRA assert extended.required is False assert extended.extra == ALLOW_EXTRA
def test_maybe(): s = Schema(Maybe(int)) assert s(1) == 1 assert s(None) is None assert_raises(Invalid, s, 'foo') s = Schema(Maybe({str: Coerce(int)})) assert s({'foo': '100'}) == {'foo': 100} assert s(None) is None assert_raises(Invalid, s, {'foo': 'bar'})
def test_schema_extend_key_swap(): """Verify that Schema.extend can replace keys, even when different markers are used""" base = Schema({Optional('a'): int}) extension = {Required('a'): int} extended = base.extend(extension) assert_equal(len(base.schema), 1) assert_true(isinstance(list(base.schema)[0], Optional)) assert_equal(len(extended.schema), 1) assert_true((list(extended.schema)[0], Required))
def test_schema_extend(): """Verify that Schema.extend copies schema keys from both.""" base = Schema({'a': int}, required=True) extension = {'b': str} extended = base.extend(extension) assert base.schema == {'a': int} assert extension == {'b': str} assert extended.schema == {'a': int, 'b': str} assert extended.required == base.required assert extended.extra == base.extra
def test_equal(): s = Schema(Equal(1)) s(1) assert_raises(Invalid, s, 2) s = Schema(Equal('foo')) s('foo') assert_raises(Invalid, s, 'bar') s = Schema(Equal([1, 2])) s([1, 2]) assert_raises(Invalid, s, []) assert_raises(Invalid, s, [1, 2, 3]) # Evaluates exactly, not through validators s = Schema(Equal(str)) assert_raises(Invalid, s, 'foo')
def test_schema_infer(): schema = Schema.infer({ 'str': 'foo', 'bool': True, 'int': 42, 'float': 3.14 }) assert_equal( schema, Schema({ Required('str'): str, Required('bool'): bool, Required('int'): int, Required('float'): float }))
def test_unicode_as_key(): if sys.version_info >= (3, ): text_type = str else: text_type = unicode schema = Schema({text_type: int}) schema({u("foobar"): 1})
def test_extra_with_required(): """Verify that Required does not break Extra.""" schema = Schema({Required('toaster'): str, Extra: object}) r = schema({'toaster': 'blue', 'another_valid_key': 'another_valid_value'}) assert_equal(r, { 'toaster': 'blue', 'another_valid_key': 'another_valid_value' })
def test_subschema_extension(): """Verify that Schema.extend adds and replaces keys in a subschema""" base = Schema({'a': {'b': int, 'c': float}}) extension = {'d': str, 'a': {'b': str, 'e': int}} extended = base.extend(extension) assert_equal(base.schema, {'a': {'b': int, 'c': float}}) assert_equal(extension, {'d': str, 'a': {'b': str, 'e': int}}) assert_equal(extended.schema, { 'a': { 'b': str, 'c': float, 'e': int }, 'd': str })
def test_exact_sequence(): schema = Schema(ExactSequence([int, int])) try: schema([1, 2, 3]) except Invalid: assert True else: assert False, "Did not raise Invalid" assert_equal(schema([1, 2]), [1, 2])
def test_inequality(): assert_true(Schema('foo') != 'foo') assert_true(Schema(['foo', 'bar']) != "['foo', 'bar']") assert_true(Schema(['foo', 'bar']) != Schema("['foo', 'bar']")) assert_true(Schema({'foo': 1, 'bar': 2}) != "{'foo': 1, 'bar': 2}") assert_true(Schema({'foo': 1, 'bar': 2}) != Schema("{'foo': 1, 'bar': 2}"))
def test_contains(): """Verify contains validation method.""" schema = Schema({'color': Contains('red')}) schema({'color': ['blue', 'red', 'yellow']}) try: schema({'color': ['blue', 'yellow']}) except Invalid as e: assert_equal( str(e), "value is not allowed for dictionary value @ data['color']")
def test_email_validation_without_host(): """ test with empty host name in email """ schema = Schema({"email": Email()}) try: schema({"email": '[email protected]'}) except MultipleInvalid as e: assert_equal(str(e), "expected an Email for dictionary value @ data['email']") else: assert False, "Did not raise Invalid for empty string url"
def test_url_validation_with_none(): """ test with invalid None url""" schema = Schema({"url": Url()}) try: schema({"url": None}) except MultipleInvalid as e: assert_equal(str(e), "expected a URL for dictionary value @ data['url']") else: assert False, "Did not raise Invalid for None url"
def test_url_validation_without_host(): """ test with empty host URL """ schema = Schema({"url": Url()}) try: schema({"url": 'http://'}) except MultipleInvalid as e: assert_equal(str(e), "expected a URL for dictionary value @ data['url']") else: assert False, "Did not raise Invalid for empty string url"
def test_number_when_precision_none_n_invalid_scale_yield_decimal_true(): """ test with Number with no precision and invalid scale""" schema = Schema({"number": Number(scale=2, yield_decimal=True)}) try: schema({"number": '12345678901.234'}) except MultipleInvalid as e: assert_equal( str(e), "Scale must be equal to 2 for dictionary value @ data['number']") else: assert False, "Did not raise Invalid for String"
def test_required(): """Verify that Required works.""" schema = Schema({Required('q'): 1}) # Can't use nose's raises (because we need to access the raised # exception, nor assert_raises which fails with Python 2.6.9. try: schema({}) except Invalid as e: assert_equal(str(e), "required key not provided @ data['q']") else: assert False, "Did not raise Invalid"
def test_description(): marker = Marker(Schema(str), description='Hello') assert marker.description == 'Hello' optional = Optional('key', description='Hello') assert optional.description == 'Hello' exclusive = Exclusive('alpha', 'angles', description='Hello') assert exclusive.description == 'Hello' required = Required('key', description='Hello') assert required.description == 'Hello'
def test_fqdn_url_without_domain_name(): """ test with invalid fully qualified domain name url """ schema = Schema({"url": FqdnUrl()}) try: schema({"url": "http://localhost/"}) except MultipleInvalid as e: assert_equal( str(e), "expected a Fully qualified domain name URL for dictionary value @ data['url']" ) else: assert False, "Did not raise Invalid for None url"
def test_number_validation_with_invalid_precision_invalid_scale(): """ test with Number with invalid precision and scale""" schema = Schema({"number": Number(precision=6, scale=2)}) try: schema({"number": '123456.712'}) except MultipleInvalid as e: assert_equal( str(e), "Precision must be equal to 6, and Scale must be equal to 2 for dictionary value @ data['number']" ) else: assert False, "Did not raise Invalid for String"
def test_number_validation_with_string(): """ test with Number with string""" schema = Schema({"number": Number(precision=6, scale=2)}) try: schema({"number": 'teststr'}) except MultipleInvalid as e: assert_equal( str(e), "Value must be a number enclosed with string for dictionary value @ data['number']" ) else: assert False, "Did not raise Invalid for String"
def test_fqdnurl_validation_with_empty_string(): """ test with empty string FQDN URL """ schema = Schema({"url": FqdnUrl()}) try: schema({"url": ''}) except MultipleInvalid as e: assert_equal( str(e), "expected a Fully qualified domain name URL for dictionary value @ data['url']" ) else: assert False, "Did not raise Invalid for empty string url"
def test_not_in(): """Verify that NotIn works.""" schema = Schema({"color": NotIn(frozenset(["blue", "red", "yellow"]))}) schema({"color": "orange"}) try: schema({"color": "blue"}) except Invalid as e: assert_equal( str(e), "value is not allowed for dictionary value @ data['color']") else: assert False, "Did not raise NotInInvalid"
def test_humanize_error(): data = {'a': 'not an int', 'b': [123]} schema = Schema({'a': int, 'b': [str]}) try: schema(data) except MultipleInvalid as e: assert_equal( humanize_error(data, e), "expected int for dictionary value @ data['a']. Got 'not an int'\n" "expected str @ data['b'][0]. Got 123") else: assert False, 'Did not raise MultipleInvalid'
def test_ordered_dict(): if not hasattr(collections, 'OrderedDict'): # collections.OrderedDict was added in Python2.7; only run if present return schema = Schema({Number(): Number()}) # x, y pairs (for interpolation or something) data = collections.OrderedDict([(5.0, 3.7), (24.0, 8.7), (43.0, 1.5), (62.0, 2.1), (71.5, 6.7), (90.5, 4.1), (109.0, 3.9)]) out = schema(data) assert isinstance( out, collections.OrderedDict), 'Collection is no longer ordered' assert data.keys() == out.keys(), 'Order is not consistent'