diff -Nru voluptuous-0.9.2/debian/changelog voluptuous-0.9.3/debian/changelog --- voluptuous-0.9.2/debian/changelog 2016-08-02 22:22:12.000000000 +0000 +++ voluptuous-0.9.3/debian/changelog 2016-08-03 14:34:27.000000000 +0000 @@ -1,3 +1,13 @@ +voluptuous (0.9.3-1) unstable; urgency=medium + + * New upstream release. + * d/patches: + - restore-tests.patch: Removed; fixed upstream. + - add-voluptuous-tests.patch: Added so nose can find the tests during + package build. + + -- Barry Warsaw Wed, 03 Aug 2016 10:34:27 -0400 + voluptuous (0.9.2-1) unstable; urgency=medium [ Ondřej Nový ] diff -Nru voluptuous-0.9.2/debian/.git-dpm voluptuous-0.9.3/debian/.git-dpm --- voluptuous-0.9.2/debian/.git-dpm 2016-08-02 22:22:12.000000000 +0000 +++ voluptuous-0.9.3/debian/.git-dpm 2016-08-03 14:34:27.000000000 +0000 @@ -1,11 +1,11 @@ # see git-dpm(1) from git-dpm package -466520f320160206832e09b2e67990e4c2a1393b -466520f320160206832e09b2e67990e4c2a1393b -96e09f6d760c570a65be150fa542abdad75f8d71 -96e09f6d760c570a65be150fa542abdad75f8d71 -voluptuous_0.9.2.orig.tar.gz -bb4924485f70be72a2c28a1a24f007108f8b8da1 -29857 +6bb916e353ee49059e3d0830838d320013f7c80f +6bb916e353ee49059e3d0830838d320013f7c80f +e76887bc2aae782c4533fcf696cc280ba2589996 +e76887bc2aae782c4533fcf696cc280ba2589996 +voluptuous_0.9.3.orig.tar.gz +315dd79c372380799d0d2e21ae711aa4097efb81 +34097 debianTag="debian/%e%v" patchedTag="patched/%e%v" upstreamTag="upstream/%e%u" diff -Nru voluptuous-0.9.2/debian/patches/add-voluptuous-tests.patch voluptuous-0.9.3/debian/patches/add-voluptuous-tests.patch --- voluptuous-0.9.2/debian/patches/add-voluptuous-tests.patch 1970-01-01 00:00:00.000000000 +0000 +++ voluptuous-0.9.3/debian/patches/add-voluptuous-tests.patch 2016-08-03 14:34:27.000000000 +0000 @@ -0,0 +1,23 @@ +From 6bb916e353ee49059e3d0830838d320013f7c80f Mon Sep 17 00:00:00 2001 +From: Barry Warsaw +Date: Wed, 3 Aug 2016 10:27:23 -0400 +Subject: Add tests package so nose will find them. + +Patch-Name: add-voluptuous-tests.patch +--- + setup.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/setup.py b/setup.py +index 6140253..4d6275d 100644 +--- a/setup.py ++++ b/setup.py +@@ -32,7 +32,7 @@ setup( + long_description=long_description, + license='BSD', + platforms=['any'], +- packages=['voluptuous'], ++ packages=['voluptuous', 'voluptuous.tests'], + author='Alec Thomas', + author_email='alec@swapoff.org', + classifiers=[ diff -Nru voluptuous-0.9.2/debian/patches/restore-tests.patch voluptuous-0.9.3/debian/patches/restore-tests.patch --- voluptuous-0.9.2/debian/patches/restore-tests.patch 2016-08-02 22:22:12.000000000 +0000 +++ voluptuous-0.9.3/debian/patches/restore-tests.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,740 +0,0 @@ -From 466520f320160206832e09b2e67990e4c2a1393b Mon Sep 17 00:00:00 2001 -From: Barry Warsaw -Date: Tue, 2 Aug 2016 14:05:07 -0400 -Subject: Add the tests which are missing from PyPI tarball. - -Bug: https://github.com/alecthomas/voluptuous/issues/188 -Forwarded: not-needed - -Patch-Name: restore-tests.patch ---- - setup.py | 2 +- - voluptuous/tests/__init__.py | 1 + - voluptuous/tests/tests.md | 268 +++++++++++++++++++++++++++ - voluptuous/tests/tests.py | 421 +++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 691 insertions(+), 1 deletion(-) - create mode 100644 voluptuous/tests/__init__.py - create mode 100644 voluptuous/tests/tests.md - create mode 100644 voluptuous/tests/tests.py - -diff --git a/setup.py b/setup.py -index 6140253..4d6275d 100644 ---- a/setup.py -+++ b/setup.py -@@ -32,7 +32,7 @@ setup( - long_description=long_description, - license='BSD', - platforms=['any'], -- packages=['voluptuous'], -+ packages=['voluptuous', 'voluptuous.tests'], - author='Alec Thomas', - author_email='alec@swapoff.org', - classifiers=[ -diff --git a/voluptuous/tests/__init__.py b/voluptuous/tests/__init__.py -new file mode 100644 -index 0000000..f29719c ---- /dev/null -+++ b/voluptuous/tests/__init__.py -@@ -0,0 +1 @@ -+__author__ = 'tusharmakkar08' -diff --git a/voluptuous/tests/tests.md b/voluptuous/tests/tests.md -new file mode 100644 -index 0000000..18f6fba ---- /dev/null -+++ b/voluptuous/tests/tests.md -@@ -0,0 +1,268 @@ -+Error reporting should be accurate: -+ -+ >>> from voluptuous import * -+ >>> schema = Schema(['one', {'two': 'three', 'four': ['five'], -+ ... 'six': {'seven': 'eight'}}]) -+ >>> schema(['one']) -+ ['one'] -+ >>> schema([{'two': 'three'}]) -+ [{'two': 'three'}] -+ -+It should show the exact index and container type, in this case a list -+value: -+ -+ >>> try: -+ ... schema(['one', 'two']) -+ ... raise AssertionError('MultipleInvalid not raised') -+ ... except MultipleInvalid as e: -+ ... exc = e -+ >>> str(exc) == 'expected a dictionary @ data[1]' -+ True -+ -+It should also be accurate for nested values: -+ -+ >>> try: -+ ... schema([{'two': 'nine'}]) -+ ... raise AssertionError('MultipleInvalid not raised') -+ ... except MultipleInvalid as e: -+ ... exc = e -+ >>> str(exc) -+ "not a valid value for dictionary value @ data[0]['two']" -+ -+ >>> try: -+ ... schema([{'four': ['nine']}]) -+ ... raise AssertionError('MultipleInvalid not raised') -+ ... except MultipleInvalid as e: -+ ... exc = e -+ >>> str(exc) -+ "not a valid value @ data[0]['four'][0]" -+ -+ >>> try: -+ ... schema([{'six': {'seven': 'nine'}}]) -+ ... raise AssertionError('MultipleInvalid not raised') -+ ... except MultipleInvalid as e: -+ ... exc = e -+ >>> str(exc) -+ "not a valid value for dictionary value @ data[0]['six']['seven']" -+ -+Errors should be reported depth-first: -+ -+ >>> validate = Schema({'one': {'two': 'three', 'four': 'five'}}) -+ >>> try: -+ ... validate({'one': {'four': 'six'}}) -+ ... except Invalid as e: -+ ... print(e) -+ ... print(e.path) -+ not a valid value for dictionary value @ data['one']['four'] -+ ['one', 'four'] -+ -+Voluptuous supports validation when extra fields are present in the -+data: -+ -+ >>> schema = Schema({'one': 1, Extra: object}) -+ >>> schema({'two': 'two', 'one': 1}) == {'two': 'two', 'one': 1} -+ True -+ >>> schema = Schema({'one': 1}) -+ >>> try: -+ ... schema({'two': 2}) -+ ... raise AssertionError('MultipleInvalid not raised') -+ ... except MultipleInvalid as e: -+ ... exc = e -+ >>> str(exc) -+ "extra keys not allowed @ data['two']" -+ -+dict, list, and tuple should be available as type validators: -+ -+ >>> Schema(dict)({'a': 1, 'b': 2}) == {'a': 1, 'b': 2} -+ True -+ >>> Schema(list)([1,2,3]) -+ [1, 2, 3] -+ >>> Schema(tuple)((1,2,3)) -+ (1, 2, 3) -+ -+Validation should return instances of the right types when the types are -+subclasses of dict or list: -+ -+ >>> class Dict(dict): -+ ... pass -+ >>> -+ >>> d = Schema(dict)(Dict(a=1, b=2)) -+ >>> d == {'a': 1, 'b': 2} -+ True -+ >>> type(d) is Dict -+ True -+ >>> class List(list): -+ ... pass -+ >>> -+ >>> l = Schema(list)(List([1,2,3])) -+ >>> l -+ [1, 2, 3] -+ >>> type(l) is List -+ True -+ -+Multiple errors are reported: -+ -+ >>> schema = Schema({'one': 1, 'two': 2}) -+ >>> try: -+ ... schema({'one': 2, 'two': 3, 'three': 4}) -+ ... except MultipleInvalid as e: -+ ... errors = sorted(e.errors, key=lambda k: str(k)) -+ ... print([str(i) for i in errors]) # doctest: +NORMALIZE_WHITESPACE -+ ["extra keys not allowed @ data['three']", -+ "not a valid value for dictionary value @ data['one']", -+ "not a valid value for dictionary value @ data['two']"] -+ >>> schema = Schema([[1], [2], [3]]) -+ >>> try: -+ ... schema([1, 2, 3]) -+ ... except MultipleInvalid as e: -+ ... print([str(i) for i in e.errors]) # doctest: +NORMALIZE_WHITESPACE -+ ['expected a list @ data[0]', -+ 'expected a list @ data[1]', -+ 'expected a list @ data[2]'] -+ -+Required fields in dictionary which are invalid should not have required : -+ -+ >>> from voluptuous import * -+ >>> schema = Schema({'one': {'two': 3}}, required=True) -+ >>> try: -+ ... schema({'one': {'two': 2}}) -+ ... except MultipleInvalid as e: -+ ... errors = e.errors -+ >>> 'required' in ' '.join([x.msg for x in errors]) -+ False -+ -+Multiple errors for nested fields in dicts and objects: -+ -+> \>\>\> from collections import namedtuple \>\>\> validate = Schema({ -+> ... 'anobject': Object({ ... 'strfield': str, ... 'intfield': int ... -+> }) ... }) \>\>\> try: ... SomeObj = namedtuple('SomeObj', ('strfield', -+> 'intfield')) ... validate({'anobject': SomeObj(strfield=123, -+> intfield='one')}) ... except MultipleInvalid as e: ... -+> print(sorted(str(i) for i in e.errors)) \# doctest: -+> +NORMALIZE\_WHITESPACE ["expected int for object value @ -+> data['anobject']['intfield']", "expected str for object value @ -+> data['anobject']['strfield']"] -+ -+Custom classes validate as schemas: -+ -+ >>> class Thing(object): -+ ... pass -+ >>> schema = Schema(Thing) -+ >>> t = schema(Thing()) -+ >>> type(t) is Thing -+ True -+ -+Classes with custom metaclasses should validate as schemas: -+ -+ >>> class MyMeta(type): -+ ... pass -+ >>> class Thing(object): -+ ... __metaclass__ = MyMeta -+ >>> schema = Schema(Thing) -+ >>> t = schema(Thing()) -+ >>> type(t) is Thing -+ True -+ -+Schemas built with All() should give the same error as the original -+validator (Issue \#26): -+ -+ >>> schema = Schema({ -+ ... Required('items'): All([{ -+ ... Required('foo'): str -+ ... }]) -+ ... }) -+ -+ >>> try: -+ ... schema({'items': [{}]}) -+ ... raise AssertionError('MultipleInvalid not raised') -+ ... except MultipleInvalid as e: -+ ... exc = e -+ >>> str(exc) -+ "required key not provided @ data['items'][0]['foo']" -+ -+Validator should return same instance of the same type for object: -+ -+ >>> class Structure(object): -+ ... def __init__(self, q=None): -+ ... self.q = q -+ ... def __repr__(self): -+ ... return '{0.__name__}(q={1.q!r})'.format(type(self), self) -+ ... -+ >>> schema = Schema(Object({'q': 'one'}, cls=Structure)) -+ >>> type(schema(Structure(q='one'))) is Structure -+ True -+ -+Object validator should treat cls argument as optional. In this case it -+shouldn't check object type: -+ -+ >>> from collections import namedtuple -+ >>> NamedTuple = namedtuple('NamedTuple', ('q',)) -+ >>> schema = Schema(Object({'q': 'one'})) -+ >>> named = NamedTuple(q='one') -+ >>> schema(named) == named -+ True -+ >>> schema(named) -+ NamedTuple(q='one') -+ -+If cls argument passed to object validator we should check object type: -+ -+ >>> schema = Schema(Object({'q': 'one'}, cls=Structure)) -+ >>> schema(NamedTuple(q='one')) # doctest: +IGNORE_EXCEPTION_DETAIL -+ Traceback (most recent call last): -+ ... -+ MultipleInvalid: expected a -+ >>> schema = Schema(Object({'q': 'one'}, cls=NamedTuple)) -+ >>> schema(NamedTuple(q='one')) -+ NamedTuple(q='one') -+ -+Ensure that objects with \_\_slots\_\_ supported properly: -+ -+ >>> class SlotsStructure(Structure): -+ ... __slots__ = ['q'] -+ ... -+ >>> schema = Schema(Object({'q': 'one'})) -+ >>> schema(SlotsStructure(q='one')) -+ SlotsStructure(q='one') -+ >>> class DictStructure(object): -+ ... __slots__ = ['q', '__dict__'] -+ ... def __init__(self, q=None, page=None): -+ ... self.q = q -+ ... self.page = page -+ ... def __repr__(self): -+ ... return '{0.__name__}(q={1.q!r}, page={1.page!r})'.format(type(self), self) -+ ... -+ >>> structure = DictStructure(q='one') -+ >>> structure.page = 1 -+ >>> try: -+ ... schema(structure) -+ ... raise AssertionError('MultipleInvalid not raised') -+ ... except MultipleInvalid as e: -+ ... exc = e -+ >>> str(exc) -+ "extra keys not allowed @ data['page']" -+ -+ >>> schema = Schema(Object({'q': 'one', Extra: object})) -+ >>> schema(structure) -+ DictStructure(q='one', page=1) -+ -+Ensure that objects can be used with other validators: -+ -+ >>> schema = Schema({'meta': Object({'q': 'one'})}) -+ >>> schema({'meta': Structure(q='one')}) -+ {'meta': Structure(q='one')} -+ -+Ensure that subclasses of Invalid of are raised as is. -+ -+ >>> class SpecialInvalid(Invalid): -+ ... pass -+ ... -+ >>> def custom_validator(value): -+ ... raise SpecialInvalid('boom') -+ ... -+ >>> schema = Schema({'thing': custom_validator}) -+ >>> try: -+ ... schema({'thing': 'not an int'}) -+ ... except MultipleInvalid as e: -+ ... exc = e -+ >>> exc.errors[0].__class__.__name__ -+ 'SpecialInvalid' -diff --git a/voluptuous/tests/tests.py b/voluptuous/tests/tests.py -new file mode 100644 -index 0000000..2b77272 ---- /dev/null -+++ b/voluptuous/tests/tests.py -@@ -0,0 +1,421 @@ -+import copy -+from nose.tools import assert_equal, assert_raises -+ -+from voluptuous import ( -+ Schema, Required, Extra, Invalid, In, Remove, Literal, -+ Url, MultipleInvalid, LiteralInvalid, NotIn, Match, Email, -+ Replace, Range, Coerce, All, Any, Length, FqdnUrl, ALLOW_EXTRA, PREVENT_EXTRA, -+ validate_schema, -+) -+from voluptuous.humanize import humanize_error -+ -+ -+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_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_iterate_candidates(): -+ """Verify that the order for iterating over mapping candidates is right.""" -+ schema = { -+ "toaster": str, -+ Extra: object, -+ } -+ # toaster should be first. -+ from voluptuous.schema_builder import _iterate_mapping_candidates -+ assert_equal(_iterate_mapping_candidates(schema)[0][0], 'toaster') -+ -+ -+def test_in(): -+ """Verify that In works.""" -+ schema = Schema({"color": In(frozenset(["blue", "red", "yellow"]))}) -+ schema({"color": "blue"}) -+ -+ -+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_remove(): -+ """Verify that Remove works.""" -+ # remove dict keys -+ schema = Schema({"weight": int, -+ Remove("color"): str, -+ Remove("amount"): int}) -+ out_ = schema({"weight": 10, "color": "red", "amount": 1}) -+ assert "color" not in out_ and "amount" not in out_ -+ -+ # remove keys by type -+ schema = Schema({"weight": float, -+ "amount": int, -+ # remvove str keys with int values -+ Remove(str): int, -+ # keep str keys with str values -+ str: str}) -+ out_ = schema({"weight": 73.4, -+ "condition": "new", -+ "amount": 5, -+ "left": 2}) -+ # amount should stay since it's defined -+ # other string keys with int values will be removed -+ assert "amount" in out_ and "left" not in out_ -+ # string keys with string values will stay -+ assert "condition" in out_ -+ -+ # remove value from list -+ schema = Schema([Remove(1), int]) -+ out_ = schema([1, 2, 3, 4, 1, 5, 6, 1, 1, 1]) -+ assert_equal(out_, [2, 3, 4, 5, 6]) -+ -+ # remove values from list by type -+ schema = Schema([1.0, Remove(float), int]) -+ out_ = schema([1, 2, 1.0, 2.0, 3.0, 4]) -+ assert_equal(out_, [1, 2, 1.0, 4]) -+ -+ -+def test_extra_empty_errors(): -+ schema = Schema({'a': {Extra: object}}, required=True) -+ schema({'a': {}}) -+ -+ -+def test_literal(): -+ """ test with Literal """ -+ -+ schema = Schema([Literal({"a": 1}), Literal({"b": 1})]) -+ schema([{"a": 1}]) -+ schema([{"b": 1}]) -+ schema([{"a": 1}, {"b": 1}]) -+ -+ try: -+ schema([{"c": 1}]) -+ except Invalid as e: -+ assert_equal(str(e), "{'c': 1} not match for {'b': 1} @ data[0]") -+ else: -+ assert False, "Did not raise Invalid" -+ -+ schema = Schema(Literal({"a": 1})) -+ try: -+ schema({"b": 1}) -+ except MultipleInvalid as e: -+ assert_equal(str(e), "{'b': 1} not match for {'a': 1}") -+ assert_equal(len(e.errors), 1) -+ assert_equal(type(e.errors[0]), LiteralInvalid) -+ else: -+ assert False, "Did not raise Invalid" -+ -+ -+def test_email_validation(): -+ """ test with valid email """ -+ schema = Schema({"email": Email()}) -+ out_ = schema({"email": "example@example.com"}) -+ -+ assert 'example@example.com"', out_.get("url") -+ -+ -+def test_email_validation_with_none(): -+ """ test with invalid None Email""" -+ schema = Schema({"email": Email()}) -+ try: -+ schema({"email": None}) -+ except MultipleInvalid as e: -+ assert_equal(str(e), -+ "expected an Email for dictionary value @ data['email']") -+ else: -+ assert False, "Did not raise Invalid for None url" -+ -+ -+def test_email_validation_with_empty_string(): -+ """ test with empty string Email""" -+ schema = Schema({"email": Email()}) -+ try: -+ schema({"email": ''}) -+ 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_email_validation_without_host(): -+ """ test with empty host name in email """ -+ schema = Schema({"email": Email()}) -+ try: -+ schema({"email": 'a@.com'}) -+ 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_fqdn_url_validation(): -+ """ test with valid fully qualified domain name url """ -+ schema = Schema({"url": FqdnUrl()}) -+ out_ = schema({"url": "http://example.com/"}) -+ -+ assert 'http://example.com/', out_.get("url") -+ -+ -+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_fqdnurl_validation_with_none(): -+ """ test with invalid None FQDN url""" -+ schema = Schema({"url": FqdnUrl()}) -+ try: -+ schema({"url": None}) -+ 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_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_fqdnurl_validation_without_host(): -+ """ test with empty host FQDN URL """ -+ schema = Schema({"url": FqdnUrl()}) -+ try: -+ schema({"url": 'http://'}) -+ 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_url_validation(): -+ """ test with valid URL """ -+ schema = Schema({"url": Url()}) -+ out_ = schema({"url": "http://example.com/"}) -+ -+ assert 'http://example.com/', out_.get("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_with_empty_string(): -+ """ test with empty string URL """ -+ schema = Schema({"url": Url()}) -+ try: -+ schema({"url": ''}) -+ 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_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_copy_dict_undefined(): -+ """ test with a copied dictionary """ -+ fields = { -+ Required("foo"): int -+ } -+ copied_fields = copy.deepcopy(fields) -+ -+ schema = Schema(copied_fields) -+ -+ # This used to raise a `TypeError` because the instance of `Undefined` -+ # was a copy, so object comparison would not work correctly. -+ try: -+ schema({"foo": "bar"}) -+ except Exception as e: -+ assert isinstance(e, MultipleInvalid) -+ -+ -+def test_sorting(): -+ """ Expect alphabetic sorting """ -+ foo = Required('foo') -+ bar = Required('bar') -+ items = [foo, bar] -+ expected = [bar, foo] -+ result = sorted(items) -+ assert result == expected -+ -+ -+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_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_repr(): -+ """Verify that __repr__ returns valid Python expressions""" -+ match = Match('a pattern', msg='message') -+ replace = Replace('you', 'I', msg='you and I') -+ range_ = Range(min=0, max=42, min_included=False, -+ max_included=False, msg='number not in range') -+ coerce_ = Coerce(int, msg="moo") -+ all_ = All('10', Coerce(int), msg='all msg') -+ -+ assert_equal(repr(match), "Match('a pattern', msg='message')") -+ assert_equal(repr(replace), "Replace('you', 'I', msg='you and I')") -+ assert_equal( -+ repr(range_), -+ "Range(min=0, max=42, min_included=False, max_included=False, msg='number not in range')" -+ ) -+ assert_equal(repr(coerce_), "Coerce(int, msg='moo')") -+ assert_equal(repr(all_), "All('10', Coerce(int, msg=None), msg='all msg')") -+ -+ -+def test_list_validation_messages(): -+ """ Make sure useful error messages are available """ -+ -+ def is_even(value): -+ if value % 2: -+ raise Invalid('%i is not even' % value) -+ return value -+ -+ schema = Schema(dict(even_numbers=[All(int, is_even)])) -+ -+ try: -+ schema(dict(even_numbers=[3])) -+ except Invalid as e: -+ assert_equal(len(e.errors), 1, e.errors) -+ assert_equal(str(e.errors[0]), "3 is not even @ data['even_numbers'][0]") -+ assert_equal(str(e), "3 is not even @ data['even_numbers'][0]") -+ else: -+ assert False, "Did not raise Invalid" -+ -+ -+def test_nested_multiple_validation_errors(): -+ """ Make sure useful error messages are available """ -+ -+ def is_even(value): -+ if value % 2: -+ raise Invalid('%i is not even' % value) -+ return value -+ -+ schema = Schema(dict(even_numbers=All([All(int, is_even)], -+ Length(min=1)))) -+ -+ try: -+ schema(dict(even_numbers=[3])) -+ except Invalid as e: -+ assert_equal(len(e.errors), 1, e.errors) -+ assert_equal(str(e.errors[0]), "3 is not even @ data['even_numbers'][0]") -+ assert_equal(str(e), "3 is not even @ data['even_numbers'][0]") -+ else: -+ assert False, "Did not raise Invalid" -+ -+ -+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_fix_157(): -+ s = Schema(All([Any('one', 'two', 'three')]), Length(min=1)) -+ assert_equal(['one'], s(['one'])) -+ assert_raises(MultipleInvalid, s, ['four']) -+ -+ -+def test_schema_decorator(): -+ @validate_schema(int) -+ def fn(arg): -+ return arg -+ -+ fn(1) -+ assert_raises(Invalid, fn, 1.0) diff -Nru voluptuous-0.9.2/debian/patches/series voluptuous-0.9.3/debian/patches/series --- voluptuous-0.9.2/debian/patches/series 2016-08-02 22:22:12.000000000 +0000 +++ voluptuous-0.9.3/debian/patches/series 2016-08-03 14:34:27.000000000 +0000 @@ -1 +1 @@ -restore-tests.patch +add-voluptuous-tests.patch diff -Nru voluptuous-0.9.2/MANIFEST.in voluptuous-0.9.3/MANIFEST.in --- voluptuous-0.9.2/MANIFEST.in 2014-08-08 23:20:46.000000000 +0000 +++ voluptuous-0.9.3/MANIFEST.in 2016-08-02 23:03:16.000000000 +0000 @@ -1,2 +1,4 @@ include *.md include COPYING +include voluptuous/tests/*.py +include voluptuous/tests/*.md diff -Nru voluptuous-0.9.2/PKG-INFO voluptuous-0.9.3/PKG-INFO --- voluptuous-0.9.2/PKG-INFO 2016-08-01 03:21:09.000000000 +0000 +++ voluptuous-0.9.3/PKG-INFO 2016-08-02 23:04:26.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: voluptuous -Version: 0.9.2 +Version: 0.9.3 Summary: Voluptuous is a Python data validation library Home-page: https://github.com/alecthomas/voluptuous Author: Alec Thomas diff -Nru voluptuous-0.9.2/voluptuous/__init__.py voluptuous-0.9.3/voluptuous/__init__.py --- voluptuous-0.9.2/voluptuous/__init__.py 2016-08-01 03:20:50.000000000 +0000 +++ voluptuous-0.9.3/voluptuous/__init__.py 2016-08-02 23:03:44.000000000 +0000 @@ -11,5 +11,5 @@ from .util import * from .error import * -__version__ = '0.9.2' +__version__ = '0.9.3' __author__ = 'tusharmakkar08' diff -Nru voluptuous-0.9.2/voluptuous/tests/__init__.py voluptuous-0.9.3/voluptuous/tests/__init__.py --- voluptuous-0.9.2/voluptuous/tests/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ voluptuous-0.9.3/voluptuous/tests/__init__.py 2016-04-22 23:05:13.000000000 +0000 @@ -0,0 +1 @@ +__author__ = 'tusharmakkar08' diff -Nru voluptuous-0.9.2/voluptuous/tests/tests.md voluptuous-0.9.3/voluptuous/tests/tests.md --- voluptuous-0.9.2/voluptuous/tests/tests.md 1970-01-01 00:00:00.000000000 +0000 +++ voluptuous-0.9.3/voluptuous/tests/tests.md 2016-04-22 23:05:13.000000000 +0000 @@ -0,0 +1,268 @@ +Error reporting should be accurate: + + >>> from voluptuous import * + >>> schema = Schema(['one', {'two': 'three', 'four': ['five'], + ... 'six': {'seven': 'eight'}}]) + >>> schema(['one']) + ['one'] + >>> schema([{'two': 'three'}]) + [{'two': 'three'}] + +It should show the exact index and container type, in this case a list +value: + + >>> try: + ... schema(['one', 'two']) + ... raise AssertionError('MultipleInvalid not raised') + ... except MultipleInvalid as e: + ... exc = e + >>> str(exc) == 'expected a dictionary @ data[1]' + True + +It should also be accurate for nested values: + + >>> try: + ... schema([{'two': 'nine'}]) + ... raise AssertionError('MultipleInvalid not raised') + ... except MultipleInvalid as e: + ... exc = e + >>> str(exc) + "not a valid value for dictionary value @ data[0]['two']" + + >>> try: + ... schema([{'four': ['nine']}]) + ... raise AssertionError('MultipleInvalid not raised') + ... except MultipleInvalid as e: + ... exc = e + >>> str(exc) + "not a valid value @ data[0]['four'][0]" + + >>> try: + ... schema([{'six': {'seven': 'nine'}}]) + ... raise AssertionError('MultipleInvalid not raised') + ... except MultipleInvalid as e: + ... exc = e + >>> str(exc) + "not a valid value for dictionary value @ data[0]['six']['seven']" + +Errors should be reported depth-first: + + >>> validate = Schema({'one': {'two': 'three', 'four': 'five'}}) + >>> try: + ... validate({'one': {'four': 'six'}}) + ... except Invalid as e: + ... print(e) + ... print(e.path) + not a valid value for dictionary value @ data['one']['four'] + ['one', 'four'] + +Voluptuous supports validation when extra fields are present in the +data: + + >>> schema = Schema({'one': 1, Extra: object}) + >>> schema({'two': 'two', 'one': 1}) == {'two': 'two', 'one': 1} + True + >>> schema = Schema({'one': 1}) + >>> try: + ... schema({'two': 2}) + ... raise AssertionError('MultipleInvalid not raised') + ... except MultipleInvalid as e: + ... exc = e + >>> str(exc) + "extra keys not allowed @ data['two']" + +dict, list, and tuple should be available as type validators: + + >>> Schema(dict)({'a': 1, 'b': 2}) == {'a': 1, 'b': 2} + True + >>> Schema(list)([1,2,3]) + [1, 2, 3] + >>> Schema(tuple)((1,2,3)) + (1, 2, 3) + +Validation should return instances of the right types when the types are +subclasses of dict or list: + + >>> class Dict(dict): + ... pass + >>> + >>> d = Schema(dict)(Dict(a=1, b=2)) + >>> d == {'a': 1, 'b': 2} + True + >>> type(d) is Dict + True + >>> class List(list): + ... pass + >>> + >>> l = Schema(list)(List([1,2,3])) + >>> l + [1, 2, 3] + >>> type(l) is List + True + +Multiple errors are reported: + + >>> schema = Schema({'one': 1, 'two': 2}) + >>> try: + ... schema({'one': 2, 'two': 3, 'three': 4}) + ... except MultipleInvalid as e: + ... errors = sorted(e.errors, key=lambda k: str(k)) + ... print([str(i) for i in errors]) # doctest: +NORMALIZE_WHITESPACE + ["extra keys not allowed @ data['three']", + "not a valid value for dictionary value @ data['one']", + "not a valid value for dictionary value @ data['two']"] + >>> schema = Schema([[1], [2], [3]]) + >>> try: + ... schema([1, 2, 3]) + ... except MultipleInvalid as e: + ... print([str(i) for i in e.errors]) # doctest: +NORMALIZE_WHITESPACE + ['expected a list @ data[0]', + 'expected a list @ data[1]', + 'expected a list @ data[2]'] + +Required fields in dictionary which are invalid should not have required : + + >>> from voluptuous import * + >>> schema = Schema({'one': {'two': 3}}, required=True) + >>> try: + ... schema({'one': {'two': 2}}) + ... except MultipleInvalid as e: + ... errors = e.errors + >>> 'required' in ' '.join([x.msg for x in errors]) + False + +Multiple errors for nested fields in dicts and objects: + +> \>\>\> from collections import namedtuple \>\>\> validate = Schema({ +> ... 'anobject': Object({ ... 'strfield': str, ... 'intfield': int ... +> }) ... }) \>\>\> try: ... SomeObj = namedtuple('SomeObj', ('strfield', +> 'intfield')) ... validate({'anobject': SomeObj(strfield=123, +> intfield='one')}) ... except MultipleInvalid as e: ... +> print(sorted(str(i) for i in e.errors)) \# doctest: +> +NORMALIZE\_WHITESPACE ["expected int for object value @ +> data['anobject']['intfield']", "expected str for object value @ +> data['anobject']['strfield']"] + +Custom classes validate as schemas: + + >>> class Thing(object): + ... pass + >>> schema = Schema(Thing) + >>> t = schema(Thing()) + >>> type(t) is Thing + True + +Classes with custom metaclasses should validate as schemas: + + >>> class MyMeta(type): + ... pass + >>> class Thing(object): + ... __metaclass__ = MyMeta + >>> schema = Schema(Thing) + >>> t = schema(Thing()) + >>> type(t) is Thing + True + +Schemas built with All() should give the same error as the original +validator (Issue \#26): + + >>> schema = Schema({ + ... Required('items'): All([{ + ... Required('foo'): str + ... }]) + ... }) + + >>> try: + ... schema({'items': [{}]}) + ... raise AssertionError('MultipleInvalid not raised') + ... except MultipleInvalid as e: + ... exc = e + >>> str(exc) + "required key not provided @ data['items'][0]['foo']" + +Validator should return same instance of the same type for object: + + >>> class Structure(object): + ... def __init__(self, q=None): + ... self.q = q + ... def __repr__(self): + ... return '{0.__name__}(q={1.q!r})'.format(type(self), self) + ... + >>> schema = Schema(Object({'q': 'one'}, cls=Structure)) + >>> type(schema(Structure(q='one'))) is Structure + True + +Object validator should treat cls argument as optional. In this case it +shouldn't check object type: + + >>> from collections import namedtuple + >>> NamedTuple = namedtuple('NamedTuple', ('q',)) + >>> schema = Schema(Object({'q': 'one'})) + >>> named = NamedTuple(q='one') + >>> schema(named) == named + True + >>> schema(named) + NamedTuple(q='one') + +If cls argument passed to object validator we should check object type: + + >>> schema = Schema(Object({'q': 'one'}, cls=Structure)) + >>> schema(NamedTuple(q='one')) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + MultipleInvalid: expected a + >>> schema = Schema(Object({'q': 'one'}, cls=NamedTuple)) + >>> schema(NamedTuple(q='one')) + NamedTuple(q='one') + +Ensure that objects with \_\_slots\_\_ supported properly: + + >>> class SlotsStructure(Structure): + ... __slots__ = ['q'] + ... + >>> schema = Schema(Object({'q': 'one'})) + >>> schema(SlotsStructure(q='one')) + SlotsStructure(q='one') + >>> class DictStructure(object): + ... __slots__ = ['q', '__dict__'] + ... def __init__(self, q=None, page=None): + ... self.q = q + ... self.page = page + ... def __repr__(self): + ... return '{0.__name__}(q={1.q!r}, page={1.page!r})'.format(type(self), self) + ... + >>> structure = DictStructure(q='one') + >>> structure.page = 1 + >>> try: + ... schema(structure) + ... raise AssertionError('MultipleInvalid not raised') + ... except MultipleInvalid as e: + ... exc = e + >>> str(exc) + "extra keys not allowed @ data['page']" + + >>> schema = Schema(Object({'q': 'one', Extra: object})) + >>> schema(structure) + DictStructure(q='one', page=1) + +Ensure that objects can be used with other validators: + + >>> schema = Schema({'meta': Object({'q': 'one'})}) + >>> schema({'meta': Structure(q='one')}) + {'meta': Structure(q='one')} + +Ensure that subclasses of Invalid of are raised as is. + + >>> class SpecialInvalid(Invalid): + ... pass + ... + >>> def custom_validator(value): + ... raise SpecialInvalid('boom') + ... + >>> schema = Schema({'thing': custom_validator}) + >>> try: + ... schema({'thing': 'not an int'}) + ... except MultipleInvalid as e: + ... exc = e + >>> exc.errors[0].__class__.__name__ + 'SpecialInvalid' diff -Nru voluptuous-0.9.2/voluptuous/tests/tests.py voluptuous-0.9.3/voluptuous/tests/tests.py --- voluptuous-0.9.2/voluptuous/tests/tests.py 1970-01-01 00:00:00.000000000 +0000 +++ voluptuous-0.9.3/voluptuous/tests/tests.py 2016-07-22 08:23:22.000000000 +0000 @@ -0,0 +1,421 @@ +import copy +from nose.tools import assert_equal, assert_raises + +from voluptuous import ( + Schema, Required, Extra, Invalid, In, Remove, Literal, + Url, MultipleInvalid, LiteralInvalid, NotIn, Match, Email, + Replace, Range, Coerce, All, Any, Length, FqdnUrl, ALLOW_EXTRA, PREVENT_EXTRA, + validate_schema, +) +from voluptuous.humanize import humanize_error + + +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_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_iterate_candidates(): + """Verify that the order for iterating over mapping candidates is right.""" + schema = { + "toaster": str, + Extra: object, + } + # toaster should be first. + from voluptuous.schema_builder import _iterate_mapping_candidates + assert_equal(_iterate_mapping_candidates(schema)[0][0], 'toaster') + + +def test_in(): + """Verify that In works.""" + schema = Schema({"color": In(frozenset(["blue", "red", "yellow"]))}) + schema({"color": "blue"}) + + +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_remove(): + """Verify that Remove works.""" + # remove dict keys + schema = Schema({"weight": int, + Remove("color"): str, + Remove("amount"): int}) + out_ = schema({"weight": 10, "color": "red", "amount": 1}) + assert "color" not in out_ and "amount" not in out_ + + # remove keys by type + schema = Schema({"weight": float, + "amount": int, + # remvove str keys with int values + Remove(str): int, + # keep str keys with str values + str: str}) + out_ = schema({"weight": 73.4, + "condition": "new", + "amount": 5, + "left": 2}) + # amount should stay since it's defined + # other string keys with int values will be removed + assert "amount" in out_ and "left" not in out_ + # string keys with string values will stay + assert "condition" in out_ + + # remove value from list + schema = Schema([Remove(1), int]) + out_ = schema([1, 2, 3, 4, 1, 5, 6, 1, 1, 1]) + assert_equal(out_, [2, 3, 4, 5, 6]) + + # remove values from list by type + schema = Schema([1.0, Remove(float), int]) + out_ = schema([1, 2, 1.0, 2.0, 3.0, 4]) + assert_equal(out_, [1, 2, 1.0, 4]) + + +def test_extra_empty_errors(): + schema = Schema({'a': {Extra: object}}, required=True) + schema({'a': {}}) + + +def test_literal(): + """ test with Literal """ + + schema = Schema([Literal({"a": 1}), Literal({"b": 1})]) + schema([{"a": 1}]) + schema([{"b": 1}]) + schema([{"a": 1}, {"b": 1}]) + + try: + schema([{"c": 1}]) + except Invalid as e: + assert_equal(str(e), "{'c': 1} not match for {'b': 1} @ data[0]") + else: + assert False, "Did not raise Invalid" + + schema = Schema(Literal({"a": 1})) + try: + schema({"b": 1}) + except MultipleInvalid as e: + assert_equal(str(e), "{'b': 1} not match for {'a': 1}") + assert_equal(len(e.errors), 1) + assert_equal(type(e.errors[0]), LiteralInvalid) + else: + assert False, "Did not raise Invalid" + + +def test_email_validation(): + """ test with valid email """ + schema = Schema({"email": Email()}) + out_ = schema({"email": "example@example.com"}) + + assert 'example@example.com"', out_.get("url") + + +def test_email_validation_with_none(): + """ test with invalid None Email""" + schema = Schema({"email": Email()}) + try: + schema({"email": None}) + except MultipleInvalid as e: + assert_equal(str(e), + "expected an Email for dictionary value @ data['email']") + else: + assert False, "Did not raise Invalid for None url" + + +def test_email_validation_with_empty_string(): + """ test with empty string Email""" + schema = Schema({"email": Email()}) + try: + schema({"email": ''}) + 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_email_validation_without_host(): + """ test with empty host name in email """ + schema = Schema({"email": Email()}) + try: + schema({"email": 'a@.com'}) + 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_fqdn_url_validation(): + """ test with valid fully qualified domain name url """ + schema = Schema({"url": FqdnUrl()}) + out_ = schema({"url": "http://example.com/"}) + + assert 'http://example.com/', out_.get("url") + + +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_fqdnurl_validation_with_none(): + """ test with invalid None FQDN url""" + schema = Schema({"url": FqdnUrl()}) + try: + schema({"url": None}) + 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_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_fqdnurl_validation_without_host(): + """ test with empty host FQDN URL """ + schema = Schema({"url": FqdnUrl()}) + try: + schema({"url": 'http://'}) + 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_url_validation(): + """ test with valid URL """ + schema = Schema({"url": Url()}) + out_ = schema({"url": "http://example.com/"}) + + assert 'http://example.com/', out_.get("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_with_empty_string(): + """ test with empty string URL """ + schema = Schema({"url": Url()}) + try: + schema({"url": ''}) + 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_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_copy_dict_undefined(): + """ test with a copied dictionary """ + fields = { + Required("foo"): int + } + copied_fields = copy.deepcopy(fields) + + schema = Schema(copied_fields) + + # This used to raise a `TypeError` because the instance of `Undefined` + # was a copy, so object comparison would not work correctly. + try: + schema({"foo": "bar"}) + except Exception as e: + assert isinstance(e, MultipleInvalid) + + +def test_sorting(): + """ Expect alphabetic sorting """ + foo = Required('foo') + bar = Required('bar') + items = [foo, bar] + expected = [bar, foo] + result = sorted(items) + assert result == expected + + +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_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_repr(): + """Verify that __repr__ returns valid Python expressions""" + match = Match('a pattern', msg='message') + replace = Replace('you', 'I', msg='you and I') + range_ = Range(min=0, max=42, min_included=False, + max_included=False, msg='number not in range') + coerce_ = Coerce(int, msg="moo") + all_ = All('10', Coerce(int), msg='all msg') + + assert_equal(repr(match), "Match('a pattern', msg='message')") + assert_equal(repr(replace), "Replace('you', 'I', msg='you and I')") + assert_equal( + repr(range_), + "Range(min=0, max=42, min_included=False, max_included=False, msg='number not in range')" + ) + assert_equal(repr(coerce_), "Coerce(int, msg='moo')") + assert_equal(repr(all_), "All('10', Coerce(int, msg=None), msg='all msg')") + + +def test_list_validation_messages(): + """ Make sure useful error messages are available """ + + def is_even(value): + if value % 2: + raise Invalid('%i is not even' % value) + return value + + schema = Schema(dict(even_numbers=[All(int, is_even)])) + + try: + schema(dict(even_numbers=[3])) + except Invalid as e: + assert_equal(len(e.errors), 1, e.errors) + assert_equal(str(e.errors[0]), "3 is not even @ data['even_numbers'][0]") + assert_equal(str(e), "3 is not even @ data['even_numbers'][0]") + else: + assert False, "Did not raise Invalid" + + +def test_nested_multiple_validation_errors(): + """ Make sure useful error messages are available """ + + def is_even(value): + if value % 2: + raise Invalid('%i is not even' % value) + return value + + schema = Schema(dict(even_numbers=All([All(int, is_even)], + Length(min=1)))) + + try: + schema(dict(even_numbers=[3])) + except Invalid as e: + assert_equal(len(e.errors), 1, e.errors) + assert_equal(str(e.errors[0]), "3 is not even @ data['even_numbers'][0]") + assert_equal(str(e), "3 is not even @ data['even_numbers'][0]") + else: + assert False, "Did not raise Invalid" + + +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_fix_157(): + s = Schema(All([Any('one', 'two', 'three')]), Length(min=1)) + assert_equal(['one'], s(['one'])) + assert_raises(MultipleInvalid, s, ['four']) + + +def test_schema_decorator(): + @validate_schema(int) + def fn(arg): + return arg + + fn(1) + assert_raises(Invalid, fn, 1.0) diff -Nru voluptuous-0.9.2/voluptuous.egg-info/PKG-INFO voluptuous-0.9.3/voluptuous.egg-info/PKG-INFO --- voluptuous-0.9.2/voluptuous.egg-info/PKG-INFO 2016-08-01 03:21:07.000000000 +0000 +++ voluptuous-0.9.3/voluptuous.egg-info/PKG-INFO 2016-08-02 23:04:26.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: voluptuous -Version: 0.9.2 +Version: 0.9.3 Summary: Voluptuous is a Python data validation library Home-page: https://github.com/alecthomas/voluptuous Author: Alec Thomas diff -Nru voluptuous-0.9.2/voluptuous.egg-info/SOURCES.txt voluptuous-0.9.3/voluptuous.egg-info/SOURCES.txt --- voluptuous-0.9.2/voluptuous.egg-info/SOURCES.txt 2016-08-01 03:21:09.000000000 +0000 +++ voluptuous-0.9.3/voluptuous.egg-info/SOURCES.txt 2016-08-02 23:04:26.000000000 +0000 @@ -14,4 +14,7 @@ voluptuous.egg-info/SOURCES.txt voluptuous.egg-info/dependency_links.txt voluptuous.egg-info/requires.txt -voluptuous.egg-info/top_level.txt \ No newline at end of file +voluptuous.egg-info/top_level.txt +voluptuous/tests/__init__.py +voluptuous/tests/tests.md +voluptuous/tests/tests.py \ No newline at end of file