diff --git a/setup.py b/setup.py index efaa50c..d615194 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ }, author='Alec Thomas', author_email='alec@swapoff.org', - python_requires=">=3.8", + python_requires='>=3.8', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', diff --git a/voluptuous/schema_builder.py b/voluptuous/schema_builder.py index 6ad8758..60842e4 100644 --- a/voluptuous/schema_builder.py +++ b/voluptuous/schema_builder.py @@ -138,7 +138,7 @@ def raises( if regex is not None: assert re.search(regex, str(e)), '%r does not match %r' % (str(e), regex) else: - raise AssertionError(f"Did not raise exception {exc.__name__}") + raise AssertionError(f'Did not raise exception {exc.__name__}') def Extra(_) -> None: @@ -268,7 +268,7 @@ def __str__(self): return str(self.schema) def __repr__(self): - return "" % ( + return '' % ( self.schema, self._extra_to_name.get(self.extra, '??'), self.required, @@ -290,7 +290,7 @@ def _compile(self, schema): return lambda _, v: v if schema is Self: return lambda p, v: self._compiled(p, v) - elif hasattr(schema, "__voluptuous_compile__"): + elif hasattr(schema, '__voluptuous_compile__'): return schema.__voluptuous_compile__(self) if isinstance(schema, Object): return self._compile_object(schema) @@ -983,7 +983,7 @@ def __init__( ) -> None: if cls and not issubclass(cls, er.Invalid): raise er.SchemaError( - "Msg can only use subclases of Invalid as custom class" + 'Msg can only use subclases of Invalid as custom class' ) self._schema = schema self.schema = Schema(schema) @@ -1127,7 +1127,7 @@ class Exclusive(Optional): ... } ... }) - >>> with raises(er.MultipleInvalid, "Please, use only one type of authentication at the same time. @ data[]"): + >>> with raises(er.MultipleInvalid, 'Please, use only one type of authentication at the same time. @ data[]'): ... schema({'classic': {'email': 'foo@example.com', 'password': 'bar'}, ... 'social': {'social_network': 'barfoo', 'token': 'tEMp'}}) """ @@ -1168,16 +1168,16 @@ class Inclusive(Optional): For example, API can return 'height' and 'width' together, but not separately. - >>> msg = "Height and width must exist together" + >>> msg = 'Height and width must exist together' >>> schema = Schema({ ... Inclusive('height', 'size', msg=msg): int, ... Inclusive('width', 'size', msg=msg): int ... }) - >>> with raises(er.MultipleInvalid, msg + " @ data[]"): + >>> with raises(er.MultipleInvalid, msg + ' @ data[]'): ... schema({'height': 100}) - >>> with raises(er.MultipleInvalid, msg + " @ data[]"): + >>> with raises(er.MultipleInvalid, msg + ' @ data[]'): ... schema({'width': 100}) >>> data = {'height': 100, 'width': 100} @@ -1231,7 +1231,7 @@ class Remove(Marker): keys will be treated as extras. >>> schema = Schema({str: int, Remove(int): str}) - >>> with raises(er.MultipleInvalid, "extra keys not allowed @ data[1]"): + >>> with raises(er.MultipleInvalid, 'extra keys not allowed @ data[1]'): ... schema({'keep': 1, 1: 1.0}) >>> schema({1: 'red', 'red': 1, 2: 'green'}) {'red': 1} @@ -1245,7 +1245,7 @@ def __call__(self, schema: Schemable): return self.__class__ def __repr__(self): - return "Remove(%r)" % (self.schema,) + return 'Remove(%r)' % (self.schema,) def __hash__(self): return object.__hash__(self) @@ -1284,7 +1284,7 @@ def message( """ if cls and not issubclass(cls, er.Invalid): raise er.SchemaError( - "message can only use subclases of Invalid as custom class" + 'message can only use subclases of Invalid as custom class' ) def decorator(f): diff --git a/voluptuous/tests/tests.py b/voluptuous/tests/tests.py index 05b7e8e..9a6ebb8 100644 --- a/voluptuous/tests/tests.py +++ b/voluptuous/tests/tests.py @@ -42,7 +42,7 @@ def test_exact_sequence(): def test_required(): """Verify that Required works.""" schema = Schema({Required('q'): int}) - schema({"q": 123}) + schema({'q': 123}) with raises(Invalid, "required key not provided @ data['q']"): schema({}) @@ -57,7 +57,7 @@ def test_extra_with_required(): def test_iterate_candidates(): """Verify that the order for iterating over mapping candidates is right.""" schema = { - "toaster": str, + 'toaster': str, Extra: object, } # toaster should be first. @@ -68,26 +68,26 @@ def test_iterate_candidates(): def test_in(): """Verify that In works.""" - schema = Schema({"color": In(frozenset(["red", "blue", "yellow"]))}) - schema({"color": "blue"}) + schema = Schema({'color': In(frozenset(['red', 'blue', 'yellow']))}) + schema({'color': 'blue'}) with pytest.raises( MultipleInvalid, match=r"value must be one of \['blue', 'red', 'yellow'\] for dictionary value @ data\['color'\]", ) as ctx: - schema({"color": "orange"}) + schema({'color': 'orange'}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], InInvalid) def test_not_in(): """Verify that NotIn works.""" - schema = Schema({"color": NotIn(frozenset(["red", "blue", "yellow"]))}) - schema({"color": "orange"}) + schema = Schema({'color': NotIn(frozenset(['red', 'blue', 'yellow']))}) + schema({'color': 'orange'}) with pytest.raises( MultipleInvalid, match=r"value must not be one of \['blue', 'red', 'yellow'\] for dictionary value @ data\['color'\]", ) as ctx: - schema({"color": "blue"}) + schema({'color': 'blue'}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], NotInInvalid) @@ -108,27 +108,27 @@ def test_contains(): 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_ + 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, + 'weight': float, + 'amount': int, # remove 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}) + 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_ + assert 'amount' in out_ and 'left' not in out_ # string keys with string values will stay - assert "condition" in out_ + assert 'condition' in out_ # remove value from list schema = Schema([Remove(1), int]) @@ -149,23 +149,23 @@ def test_extra_empty_errors(): 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}]) + schema = Schema([Literal({'a': 1}), Literal({'b': 1})]) + schema([{'a': 1}]) + schema([{'b': 1}]) + schema([{'a': 1}, {'b': 1}]) with pytest.raises( MultipleInvalid, match=r"\{'c': 1\} not match for \{'b': 1\} @ data\[0\]" ) as ctx: - schema([{"c": 1}]) + schema([{'c': 1}]) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], LiteralInvalid) - schema = Schema(Literal({"a": 1})) + schema = Schema(Literal({'a': 1})) with pytest.raises( MultipleInvalid, match=r"\{'b': 1\} not match for \{'a': 1\}" ) as ctx: - schema({"b": 1}) + schema({'b': 1}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], LiteralInvalid) @@ -177,7 +177,7 @@ class C1: schema = Schema(C1) schema(C1()) - with pytest.raises(MultipleInvalid, match=r"expected C1") as ctx: + with pytest.raises(MultipleInvalid, match=r'expected C1') as ctx: schema(None) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], TypeInvalid) @@ -185,44 +185,44 @@ class C1: def test_email_validation(): """Test with valid email address""" - schema = Schema({"email": Email()}) - out_ = schema({"email": "example@example.com"}) + schema = Schema({'email': Email()}) + out_ = schema({'email': 'example@example.com'}) - assert 'example@example.com"', out_.get("url") + assert 'example@example.com"', out_.get('url') def test_email_validation_with_none(): """Test with invalid None email address""" - schema = Schema({"email": Email()}) + schema = Schema({'email': Email()}) with pytest.raises( MultipleInvalid, match=r"expected an email address for dictionary value @ data\['email'\]", ) as ctx: - schema({"email": None}) + schema({'email': None}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], EmailInvalid) def test_email_validation_with_empty_string(): """Test with empty string email address""" - schema = Schema({"email": Email()}) + schema = Schema({'email': Email()}) with pytest.raises( MultipleInvalid, match=r"expected an email address for dictionary value @ data\['email'\]", ) as ctx: - schema({"email": ''}) + schema({'email': ''}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], EmailInvalid) def test_email_validation_without_host(): """Test with empty host name in email address""" - schema = Schema({"email": Email()}) + schema = Schema({'email': Email()}) with pytest.raises( MultipleInvalid, match=r"expected an email address for dictionary value @ data\['email'\]", ) as ctx: - schema({"email": 'a@.com'}) + schema({'email': 'a@.com'}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], EmailInvalid) @@ -232,73 +232,73 @@ def test_email_validation_without_host(): ) def test_email_validation_with_bad_data(input_value: str): """Test with bad data in email address""" - schema = Schema({"email": Email()}) + schema = Schema({'email': Email()}) with pytest.raises( MultipleInvalid, match=r"expected an email address for dictionary value @ data\['email'\]", ) as ctx: - schema({"email": input_value}) + schema({'email': input_value}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], EmailInvalid) def test_fqdn_url_validation(): """Test with valid fully qualified domain name URL""" - schema = Schema({"url": FqdnUrl()}) - out_ = schema({"url": "http://example.com/"}) + schema = Schema({'url': FqdnUrl()}) + out_ = schema({'url': 'http://example.com/'}) - assert 'http://example.com/', out_.get("url") + assert 'http://example.com/', out_.get('url') @pytest.mark.parametrize( 'input_value', [ - pytest.param("http://localhost/", id="without domain name"), - pytest.param(None, id="None"), - pytest.param("", id="empty string"), - pytest.param("http://", id="empty host"), + pytest.param('http://localhost/', id='without domain name'), + pytest.param(None, id='None'), + pytest.param('', id='empty string'), + pytest.param('http://', id='empty host'), ], ) def test_fqdn_url_validation_with_bad_data(input_value): - schema = Schema({"url": FqdnUrl()}) + schema = Schema({'url': FqdnUrl()}) with pytest.raises( MultipleInvalid, match=r"expected a fully qualified domain name URL for dictionary value @ data\['url'\]", ) as ctx: - schema({"url": input_value}) + schema({'url': input_value}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], UrlInvalid) def test_url_validation(): """Test with valid URL""" - schema = Schema({"url": Url()}) - out_ = schema({"url": "http://example.com/"}) + schema = Schema({'url': Url()}) + out_ = schema({'url': 'http://example.com/'}) - assert 'http://example.com/', out_.get("url") + assert 'http://example.com/', out_.get('url') @pytest.mark.parametrize( 'input_value', [ - pytest.param(None, id="None"), - pytest.param("", id="empty string"), - pytest.param("http://", id="empty host"), + pytest.param(None, id='None'), + pytest.param('', id='empty string'), + pytest.param('http://', id='empty host'), ], ) def test_url_validation_with_bad_data(input_value): - schema = Schema({"url": Url()}) + schema = Schema({'url': Url()}) with pytest.raises( MultipleInvalid, match=r"expected a URL for dictionary value @ data\['url'\]" ) as ctx: - schema({"url": input_value}) + schema({'url': input_value}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], UrlInvalid) def test_copy_dict_undefined(): """Test with a copied dictionary""" - fields = {Required("foo"): int} + fields = {Required('foo'): int} copied_fields = copy.deepcopy(fields) schema = Schema(copied_fields) @@ -306,7 +306,7 @@ def test_copy_dict_undefined(): # 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"}) + schema({'foo': 'bar'}) except Exception as e: assert isinstance(e, MultipleInvalid) @@ -453,7 +453,7 @@ def test_repr(): range_ = Range( min=0, max=42, min_included=False, max_included=False, msg='number not in range' ) - coerce_ = Coerce(int, msg="moo") + coerce_ = Coerce(int, msg='moo') all_ = All('10', Coerce(int), msg='all msg') maybe_int = Maybe(int) @@ -465,7 +465,7 @@ def test_repr(): ) assert repr(coerce_) == "Coerce(int, msg='moo')" assert repr(all_) == "All('10', Coerce(int, msg=None), msg='all msg')" - assert repr(maybe_int) == "Any(None, %s, msg=None)" % str(int) + assert repr(maybe_int) == 'Any(None, %s, msg=None)' % str(int) def test_list_validation_messages(): @@ -566,7 +566,7 @@ def test_range_excludes_none(): def test_range_excludes_string(): s = Schema(Range(min=0, max=10)) with pytest.raises(MultipleInvalid): - s("abc") + s('abc') def test_range_excludes_unordered_object(): @@ -598,7 +598,7 @@ def test_clamp_invalid(): with pytest.raises(MultipleInvalid): s(None) with pytest.raises(MultipleInvalid): - s("abc") + s('abc') else: assert 1 == s(None) @@ -607,7 +607,7 @@ def test_length_ok(): v1 = ['a', 'b', 'c'] s = Schema(Length(min=1, max=10)) assert v1 == s(v1) - v2 = "abcde" + v2 = 'abcde' assert v2 == s(v2) @@ -709,9 +709,9 @@ def test_maybe_returns_default_error(): # Should trigger a MultipleInvalid exception schema(3) except MultipleInvalid as e: - assert str(e) == "not a valid value" + assert str(e) == 'not a valid value' else: - assert False, "Did not raise correct Invalid" + assert False, 'Did not raise correct Invalid' def test_schema_empty_list(): @@ -721,16 +721,16 @@ def test_schema_empty_list(): try: s([123]) except MultipleInvalid as e: - assert str(e) == "not a valid value @ data[123]" + assert str(e) == 'not a valid value @ data[123]' else: - assert False, "Did not raise correct Invalid" + assert False, 'Did not raise correct Invalid' try: s({'var': 123}) except MultipleInvalid as e: - assert str(e) == "expected a list" + assert str(e) == 'expected a list' else: - assert False, "Did not raise correct Invalid" + assert False, 'Did not raise correct Invalid' def test_schema_empty_dict(): @@ -742,14 +742,14 @@ def test_schema_empty_dict(): except MultipleInvalid as e: assert str(e) == "extra keys not allowed @ data['var']" else: - assert False, "Did not raise correct Invalid" + assert False, 'Did not raise correct Invalid' try: s([123]) except MultipleInvalid as e: - assert str(e) == "expected a dictionary" + assert str(e) == 'expected a dictionary' else: - assert False, "Did not raise correct Invalid" + assert False, 'Did not raise correct Invalid' def test_schema_empty_dict_key(): @@ -762,7 +762,7 @@ def test_schema_empty_dict_key(): except MultipleInvalid as e: assert str(e) == "not a valid value for dictionary value @ data['var']" else: - assert False, "Did not raise correct Invalid" + assert False, 'Did not raise correct Invalid' def test_schema_decorator_match_with_args(): @@ -808,7 +808,7 @@ def fn(arg): def test_schema_decorator_unmatch_return_with_args(): @validate(int, __return__=int) def fn(arg): - return "hello" + return 'hello' pytest.raises(Invalid, fn, 1) @@ -824,7 +824,7 @@ def fn(arg): def test_schema_decorator_unmatch_return_with_kwargs(): @validate(arg=int, __return__=int) def fn(arg): - return "hello" + return 'hello' pytest.raises(Invalid, fn, 1) @@ -840,7 +840,7 @@ def fn(arg): def test_schema_decorator_return_only_unmatch(): @validate(__return__=int) def fn(arg): - return "hello" + return 'hello' pytest.raises(Invalid, fn, 1) @@ -850,7 +850,7 @@ def test_schema_decorator_partial_match_called_with_args(): def fn(arg1, arg2): return arg1 - fn(1, "foo") + fn(1, 'foo') def test_schema_decorator_partial_unmatch_called_with_args(): @@ -858,7 +858,7 @@ def test_schema_decorator_partial_unmatch_called_with_args(): def fn(arg1, arg2): return arg1 - pytest.raises(Invalid, fn, "bar", "foo") + pytest.raises(Invalid, fn, 'bar', 'foo') def test_schema_decorator_partial_match_called_with_kwargs(): @@ -866,7 +866,7 @@ def test_schema_decorator_partial_match_called_with_kwargs(): def fn(arg1, arg2): return arg1 - fn(arg1="foo", arg2=1) + fn(arg1='foo', arg2=1) def test_schema_decorator_partial_unmatch_called_with_kwargs(): @@ -874,104 +874,104 @@ def test_schema_decorator_partial_unmatch_called_with_kwargs(): def fn(arg1, arg2): return arg1 - pytest.raises(Invalid, fn, arg1=1, arg2="foo") + pytest.raises(Invalid, fn, arg1=1, arg2='foo') def test_number_validation_with_string(): """Test with Number with string""" - schema = Schema({"number": Number(precision=6, scale=2)}) + schema = Schema({'number': Number(precision=6, scale=2)}) try: - schema({"number": 'teststr'}) + schema({'number': 'teststr'}) except MultipleInvalid as e: assert ( str(e) == "Value must be a number enclosed with string for dictionary value @ data['number']" ) else: - assert False, "Did not raise Invalid for String" + assert False, 'Did not raise Invalid for String' 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)}) + schema = Schema({'number': Number(precision=6, scale=2)}) try: - schema({"number": '123456.712'}) + schema({'number': '123456.712'}) except MultipleInvalid as e: assert ( 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" + assert False, 'Did not raise Invalid for String' def test_number_validation_with_valid_precision_scale_yield_decimal_true(): """Test with Number with valid precision and scale""" - schema = Schema({"number": Number(precision=6, scale=2, yield_decimal=True)}) - out_ = schema({"number": '1234.00'}) - assert float(out_.get("number")) == 1234.00 + schema = Schema({'number': Number(precision=6, scale=2, yield_decimal=True)}) + out_ = schema({'number': '1234.00'}) + assert float(out_.get('number')) == 1234.00 def test_number_when_precision_scale_none_yield_decimal_true(): """Test with Number with no precision and scale""" - schema = Schema({"number": Number(yield_decimal=True)}) - out_ = schema({"number": '12345678901234'}) - assert out_.get("number") == 12345678901234 + schema = Schema({'number': Number(yield_decimal=True)}) + out_ = schema({'number': '12345678901234'}) + assert out_.get('number') == 12345678901234 def test_number_when_precision_none_n_valid_scale_case1_yield_decimal_true(): """Test with Number with no precision and valid scale case 1""" - schema = Schema({"number": Number(scale=2, yield_decimal=True)}) - out_ = schema({"number": '123456789.34'}) - assert float(out_.get("number")) == 123456789.34 + schema = Schema({'number': Number(scale=2, yield_decimal=True)}) + out_ = schema({'number': '123456789.34'}) + assert float(out_.get('number')) == 123456789.34 def test_number_when_precision_none_n_valid_scale_case2_yield_decimal_true(): """Test with Number with no precision and valid scale case 2 with zero in decimal part""" - schema = Schema({"number": Number(scale=2, yield_decimal=True)}) - out_ = schema({"number": '123456789012.00'}) - assert float(out_.get("number")) == 123456789012.00 + schema = Schema({'number': Number(scale=2, yield_decimal=True)}) + out_ = schema({'number': '123456789012.00'}) + assert float(out_.get('number')) == 123456789012.00 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)}) + schema = Schema({'number': Number(scale=2, yield_decimal=True)}) try: - schema({"number": '12345678901.234'}) + schema({'number': '12345678901.234'}) except MultipleInvalid as e: assert ( str(e) == "Scale must be equal to 2 for dictionary value @ data['number']" ) else: - assert False, "Did not raise Invalid for String" + assert False, 'Did not raise Invalid for String' def test_number_when_valid_precision_n_scale_none_yield_decimal_true(): """Test with Number with no precision and valid scale""" - schema = Schema({"number": Number(precision=14, yield_decimal=True)}) - out_ = schema({"number": '1234567.8901234'}) - assert float(out_.get("number")) == 1234567.8901234 + schema = Schema({'number': Number(precision=14, yield_decimal=True)}) + out_ = schema({'number': '1234567.8901234'}) + assert float(out_.get('number')) == 1234567.8901234 def test_number_when_invalid_precision_n_scale_none_yield_decimal_true(): """Test with Number with no precision and invalid scale""" - schema = Schema({"number": Number(precision=14, yield_decimal=True)}) + schema = Schema({'number': Number(precision=14, yield_decimal=True)}) try: - schema({"number": '12345674.8901234'}) + schema({'number': '12345674.8901234'}) except MultipleInvalid as e: assert ( str(e) == "Precision must be equal to 14 for dictionary value @ data['number']" ) else: - assert False, "Did not raise Invalid for String" + assert False, 'Did not raise Invalid for String' def test_number_validation_with_valid_precision_scale_yield_decimal_false(): """Test with Number with valid precision, scale and no yield_decimal""" - schema = Schema({"number": Number(precision=6, scale=2, yield_decimal=False)}) - out_ = schema({"number": '1234.00'}) - assert out_.get("number") == '1234.00' + schema = Schema({'number': Number(precision=6, scale=2, yield_decimal=False)}) + out_ = schema({'number': '1234.00'}) + assert out_.get('number') == '1234.00' def test_named_tuples_validate_as_tuples(): @@ -986,21 +986,21 @@ def test_named_tuples_validate_as_tuples(): def test_datetime(): - schema = Schema({"datetime": Datetime()}) - schema({"datetime": "2016-10-24T14:01:57.102152Z"}) - pytest.raises(MultipleInvalid, schema, {"datetime": "2016-10-24T14:01:57"}) + schema = Schema({'datetime': Datetime()}) + schema({'datetime': '2016-10-24T14:01:57.102152Z'}) + pytest.raises(MultipleInvalid, schema, {'datetime': '2016-10-24T14:01:57'}) def test_date(): - schema = Schema({"date": Date()}) - schema({"date": "2016-10-24"}) - pytest.raises(MultipleInvalid, schema, {"date": "2016-10-24Z"}) + schema = Schema({'date': Date()}) + schema({'date': '2016-10-24'}) + pytest.raises(MultipleInvalid, schema, {'date': '2016-10-24Z'}) def test_date_custom_format(): - schema = Schema({"date": Date("%Y%m%d")}) - schema({"date": "20161024"}) - pytest.raises(MultipleInvalid, schema, {"date": "2016-10-24"}) + schema = Schema({'date': Date('%Y%m%d')}) + schema({'date': '20161024'}) + pytest.raises(MultipleInvalid, schema, {'date': '2016-10-24'}) def test_ordered_dict(): @@ -1123,7 +1123,7 @@ def __call__(self, *args, **kwargs): schema(data) - assert counter[0] <= num_of_keys, "Validation complexity is not linear! %s > %s" % ( + assert counter[0] <= num_of_keys, 'Validation complexity is not linear! %s > %s' % ( counter[0], num_of_keys, ) @@ -1131,7 +1131,7 @@ def __call__(self, *args, **kwargs): counter[0] = 0 # reset counter schema(data_extra_keys) - assert counter[0] <= num_of_keys, "Validation complexity is not linear! %s > %s" % ( + assert counter[0] <= num_of_keys, 'Validation complexity is not linear! %s > %s' % ( counter[0], num_of_keys, ) @@ -1214,15 +1214,15 @@ def test_SomeOf_max_validation(): def test_self_validation(): - schema = Schema({"number": int, "follow": Self}) + schema = Schema({'number': int, 'follow': Self}) with raises(MultipleInvalid): - schema({"number": "abc"}) + schema({'number': 'abc'}) with raises(MultipleInvalid): - schema({"follow": {"number": '123456.712'}}) + schema({'follow': {'number': '123456.712'}}) - schema({"follow": {"number": 123456}}) - schema({"follow": {"follow": {"number": 123456}}}) + schema({'follow': {'number': 123456}}) + schema({'follow': {'follow': {'number': 123456}}}) def test_any_error_has_path(): @@ -1265,7 +1265,7 @@ def test_match_error_has_path(): """https://github.com/alecthomas/voluptuous/issues/347""" s = Schema( { - Required('q2'): Match("a"), + Required('q2'): Match('a'), } ) with pytest.raises(MultipleInvalid) as ctx: @@ -1346,44 +1346,44 @@ def __hash__(self): def test_self_any(): - schema = Schema({"number": int, "follow": Any(Self, "stop")}) + schema = Schema({'number': int, 'follow': Any(Self, 'stop')}) with pytest.raises(MultipleInvalid) as ctx: - schema({"number": "abc"}) + schema({'number': 'abc'}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], TypeInvalid) with raises(MultipleInvalid): - schema({"follow": {"number": '123456.712'}}) + schema({'follow': {'number': '123456.712'}}) - schema({"follow": {"number": 123456}}) - schema({"follow": {"follow": {"number": 123456}}}) - schema({"follow": {"follow": {"number": 123456, "follow": "stop"}}}) + schema({'follow': {'number': 123456}}) + schema({'follow': {'follow': {'number': 123456}}}) + schema({'follow': {'follow': {'number': 123456, 'follow': 'stop'}}}) def test_self_all(): schema = Schema( { - "number": int, - "follow": All(Self, Schema({"extra_number": int}, extra=ALLOW_EXTRA)), + 'number': int, + 'follow': All(Self, Schema({'extra_number': int}, extra=ALLOW_EXTRA)), }, extra=ALLOW_EXTRA, ) with pytest.raises(MultipleInvalid) as ctx: - schema({"number": "abc"}) + schema({'number': 'abc'}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], TypeInvalid) with pytest.raises(MultipleInvalid) as ctx: - schema({"follow": {"number": '123456.712'}}) + schema({'follow': {'number': '123456.712'}}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], TypeInvalid) - schema({"follow": {"number": 123456}}) - schema({"follow": {"follow": {"number": 123456}}}) - schema({"follow": {"number": 123456, "extra_number": 123}}) + schema({'follow': {'number': 123456}}) + schema({'follow': {'follow': {'number': 123456}}}) + schema({'follow': {'number': 123456, 'extra_number': 123}}) with pytest.raises(MultipleInvalid) as ctx: - schema({"follow": {"number": 123456, "extra_number": "123"}}) + schema({'follow': {'number': 123456, 'extra_number': '123'}}) assert len(ctx.value.errors) == 1 assert isinstance(ctx.value.errors[0], TypeInvalid) @@ -1410,7 +1410,7 @@ def test_set_of_integers(): schema(set()) schema(set([42])) schema(set([42, 43, 44])) - with pytest.raises(MultipleInvalid, match="invalid value in set") as ctx: + with pytest.raises(MultipleInvalid, match='invalid value in set') as ctx: schema(set(['abc'])) assert len(ctx.value.errors) == 1 @@ -1426,7 +1426,7 @@ def test_frozenset_of_integers(): schema(frozenset([42])) schema(frozenset([42, 43, 44])) - with pytest.raises(MultipleInvalid, match="invalid value in frozenset") as ctx: + with pytest.raises(MultipleInvalid, match='invalid value in frozenset') as ctx: schema(frozenset(['abc'])) assert len(ctx.value.errors) == 1 @@ -1441,7 +1441,7 @@ def test_set_of_integers_and_strings(): schema(set(['abc'])) schema(set([42, 'abc'])) - with pytest.raises(MultipleInvalid, match="invalid value in set") as ctx: + with pytest.raises(MultipleInvalid, match='invalid value in set') as ctx: schema(set([None])) assert len(ctx.value.errors) == 1 @@ -1456,46 +1456,46 @@ def test_frozenset_of_integers_and_strings(): schema(frozenset(['abc'])) schema(frozenset([42, 'abc'])) - with pytest.raises(MultipleInvalid, match="invalid value in frozenset") as ctx: + with pytest.raises(MultipleInvalid, match='invalid value in frozenset') as ctx: schema(frozenset([None])) assert len(ctx.value.errors) == 1 def test_lower_util_handles_various_inputs(): - assert Lower(3) == "3" - assert Lower(u"3") == u"3" - assert Lower(b'\xe2\x98\x83'.decode("UTF-8")) == b'\xe2\x98\x83'.decode("UTF-8") - assert Lower(u"A") == u"a" + assert Lower(3) == '3' + assert Lower(u'3') == u'3' + assert Lower(b'\xe2\x98\x83'.decode('UTF-8')) == b'\xe2\x98\x83'.decode('UTF-8') + assert Lower(u'A') == u'a' def test_upper_util_handles_various_inputs(): - assert Upper(3) == "3" - assert Upper(u"3") == u"3" - assert Upper(b'\xe2\x98\x83'.decode("UTF-8")) == b'\xe2\x98\x83'.decode("UTF-8") - assert Upper(u"a") == u"A" + assert Upper(3) == '3' + assert Upper(u'3') == u'3' + assert Upper(b'\xe2\x98\x83'.decode('UTF-8')) == b'\xe2\x98\x83'.decode('UTF-8') + assert Upper(u'a') == u'A' def test_capitalize_util_handles_various_inputs(): - assert Capitalize(3) == "3" - assert Capitalize(u"3") == u"3" - assert Capitalize(b'\xe2\x98\x83'.decode("UTF-8")) == b'\xe2\x98\x83'.decode( - "UTF-8" + assert Capitalize(3) == '3' + assert Capitalize(u'3') == u'3' + assert Capitalize(b'\xe2\x98\x83'.decode('UTF-8')) == b'\xe2\x98\x83'.decode( + 'UTF-8' ) - assert Capitalize(u"aaa aaa") == u"Aaa aaa" + assert Capitalize(u'aaa aaa') == u'Aaa aaa' def test_title_util_handles_various_inputs(): - assert Title(3) == "3" - assert Title(u"3") == u"3" - assert Title(b'\xe2\x98\x83'.decode("UTF-8")) == b'\xe2\x98\x83'.decode("UTF-8") - assert Title(u"aaa aaa") == u"Aaa Aaa" + assert Title(3) == '3' + assert Title(u'3') == u'3' + assert Title(b'\xe2\x98\x83'.decode('UTF-8')) == b'\xe2\x98\x83'.decode('UTF-8') + assert Title(u'aaa aaa') == u'Aaa Aaa' def test_strip_util_handles_various_inputs(): - assert Strip(3) == "3" - assert Strip(u"3") == u"3" - assert Strip(b'\xe2\x98\x83'.decode("UTF-8")) == b'\xe2\x98\x83'.decode("UTF-8") - assert Strip(u" aaa ") == u"aaa" + assert Strip(3) == '3' + assert Strip(u'3') == u'3' + assert Strip(b'\xe2\x98\x83'.decode('UTF-8')) == b'\xe2\x98\x83'.decode('UTF-8') + assert Strip(u' aaa ') == u'aaa' def test_any_required(): @@ -1654,23 +1654,23 @@ class Choice(Enum): Hard = 3 class StringChoice(str, Enum): - Easy = "easy" - Medium = "medium" - Hard = "hard" + Easy = 'easy' + Medium = 'medium' + Hard = 'hard' schema = Schema(Coerce(Choice)) string_schema = Schema(Coerce(StringChoice)) # Valid value assert schema(1) == Choice.Easy - assert string_schema("easy") == StringChoice.Easy + assert string_schema('easy') == StringChoice.Easy # Invalid value - with raises(Invalid, "expected Choice or one of 1, 2, 3"): + with raises(Invalid, 'expected Choice or one of 1, 2, 3'): schema(4) with raises(Invalid, "expected StringChoice or one of 'easy', 'medium', 'hard'"): - string_schema("hello") + string_schema('hello') class MyValueClass(object): @@ -1691,9 +1691,9 @@ def test_exception(): s(123) invalid_scalar_excp_repr = "ScalarInvalid('not a valid value')" - assert repr(ctx.value) == f"MultipleInvalid([{invalid_scalar_excp_repr}])" - assert str(ctx.value.msg) == "not a valid value" - assert str(ctx.value.error_message) == "not a valid value" - assert str(ctx.value.errors) == f"[{invalid_scalar_excp_repr}]" - ctx.value.add("Test Error") + assert repr(ctx.value) == f'MultipleInvalid([{invalid_scalar_excp_repr}])' + assert str(ctx.value.msg) == 'not a valid value' + assert str(ctx.value.error_message) == 'not a valid value' + assert str(ctx.value.errors) == f'[{invalid_scalar_excp_repr}]' + ctx.value.add('Test Error') assert str(ctx.value.errors) == f"[{invalid_scalar_excp_repr}, 'Test Error']" diff --git a/voluptuous/util.py b/voluptuous/util.py index 0bf9302..3b8efad 100644 --- a/voluptuous/util.py +++ b/voluptuous/util.py @@ -1,4 +1,4 @@ -# F401: "imported but unused" +# F401: 'imported but unused' # fmt: off import typing @@ -92,7 +92,7 @@ class SetTo(object): >>> s = Schema(validators.Any(int, SetTo(42))) >>> s(2) 2 - >>> s("foo") + >>> s('foo') 42 """ @@ -114,7 +114,7 @@ class Set(object): True >>> s([1, 2]) == set([1, 2]) True - >>> with raises(Invalid, regex="^cannot be presented as set: "): + >>> with raises(Invalid, regex='^cannot be presented as set: '): ... s([set([1, 2]), set([3, 4])]) """ diff --git a/voluptuous/validators.py b/voluptuous/validators.py index 348dc04..f0aa0ea 100644 --- a/voluptuous/validators.py +++ b/voluptuous/validators.py @@ -38,19 +38,19 @@ # Taken from https://github.com/kvesteri/validators/blob/master/validators/email.py USER_REGEX = re.compile( # start anchor, because fullmatch is not available in python 2.7 - "(?:" + '(?:' # dot-atom r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$" # quoted-string r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|' r"""\\[\001-\011\013\014\016-\177])*"$)""" # end anchor, because fullmatch is not available in python 2.7 - r")\Z", + r')\Z', re.IGNORECASE, ) DOMAIN_REGEX = re.compile( # start anchor, because fullmatch is not available in python 2.7 - "(?:" + '(?:' # domain r'(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+' # tld @@ -58,7 +58,7 @@ # literal form, ipv4 address (SMTP 4.1.3) r'|^\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$' # end anchor, because fullmatch is not available in python 2.7 - r")\Z", + r')\Z', re.IGNORECASE, ) @@ -104,7 +104,7 @@ class Coerce(object): With custom message: - >>> validate = Schema(Coerce(int, "moo")) + >>> validate = Schema(Coerce(int, 'moo')) >>> with raises(MultipleInvalid, 'moo'): ... validate('foo') """ @@ -124,7 +124,7 @@ def __call__(self, v): except (ValueError, TypeError, InvalidOperation): msg = self.msg or ('expected %s' % self.type_name) if not self.msg and Enum and issubclass(self.type, Enum): - msg += " or one of %s" % str([e.value for e in self.type])[1:-1] + msg += ' or one of %s' % str([e.value for e in self.type])[1:-1] raise CoerceInvalid(msg) def __repr__(self): @@ -141,11 +141,11 @@ def IsTrue(v): "In the Python sense" means that implicitly false values, such as empty lists, dictionaries, etc. are treated as "false": - >>> with raises(MultipleInvalid, "value was not true"): + >>> with raises(MultipleInvalid, 'value was not true'): ... validate([]) >>> validate([1]) [1] - >>> with raises(MultipleInvalid, "value was not true"): + >>> with raises(MultipleInvalid, 'value was not true'): ... validate(False) ...and so on. @@ -167,7 +167,7 @@ def IsFalse(v): >>> validate = Schema(IsFalse()) >>> validate([]) [] - >>> with raises(MultipleInvalid, "value was not false"): + >>> with raises(MultipleInvalid, 'value was not false'): ... validate(True) >>> try: @@ -190,11 +190,11 @@ def Boolean(v): >>> validate = Schema(Boolean()) >>> validate(True) True - >>> validate("1") + >>> validate('1') True - >>> validate("0") + >>> validate('0') False - >>> with raises(MultipleInvalid, "expected boolean"): + >>> with raises(MultipleInvalid, 'expected boolean'): ... validate('moo') >>> try: ... validate('moo') @@ -252,7 +252,7 @@ def __call__(self, v): def __repr__(self): return '%s(%s, msg=%r)' % ( self.__class__.__name__, - ", ".join(repr(v) for v in self.validators), + ', '.join(repr(v) for v in self.validators), self.msg, ) @@ -278,15 +278,15 @@ class Any(_WithSubValidators): 'true' >>> validate(1) True - >>> with raises(MultipleInvalid, "not a valid value"): + >>> with raises(MultipleInvalid, 'not a valid value'): ... validate('moo') msg argument is used - >>> validate = Schema(Any(1, 2, 3, msg="Expected 1 2 or 3")) + >>> validate = Schema(Any(1, 2, 3, msg='Expected 1 2 or 3')) >>> validate(1) 1 - >>> with raises(MultipleInvalid, "Expected 1 2 or 3"): + >>> with raises(MultipleInvalid, 'Expected 1 2 or 3'): ... validate(4) """ @@ -413,7 +413,7 @@ def __call__(self, v): try: match = self.pattern.match(v) except TypeError: - raise MatchInvalid("expected string or buffer") + raise MatchInvalid('expected string or buffer') if not match: raise MatchInvalid( self.msg @@ -460,7 +460,7 @@ def __repr__(self): def _url_validation(v: str) -> urlparse.ParseResult: parsed = urlparse.urlparse(v) if not parsed.scheme or not parsed.netloc: - raise UrlInvalid("must have a URL scheme and host") + raise UrlInvalid('must have a URL scheme and host') return parsed @@ -470,21 +470,21 @@ def Email(v): >>> s = Schema(Email()) >>> with raises(MultipleInvalid, 'expected an email address'): - ... s("a.com") + ... s('a.com') >>> with raises(MultipleInvalid, 'expected an email address'): - ... s("a@.com") + ... s('a@.com') >>> with raises(MultipleInvalid, 'expected an email address'): - ... s("a@.com") + ... s('a@.com') >>> s('t@x.com') 't@x.com' """ try: - if not v or "@" not in v: - raise EmailInvalid("Invalid email address") + if not v or '@' not in v: + raise EmailInvalid('Invalid email address') user_part, domain_part = v.rsplit('@', 1) if not (USER_REGEX.match(user_part) and DOMAIN_REGEX.match(domain_part)): - raise EmailInvalid("Invalid email address") + raise EmailInvalid('Invalid email address') return v except: # noqa: E722 raise ValueError @@ -496,14 +496,14 @@ def FqdnUrl(v): >>> s = Schema(FqdnUrl()) >>> with raises(MultipleInvalid, 'expected a fully qualified domain name URL'): - ... s("http://localhost/") + ... s('http://localhost/') >>> s('http://w3.org') 'http://w3.org' """ try: parsed_url = _url_validation(v) - if "." not in parsed_url.netloc: - raise UrlInvalid("must have a domain name in URL") + if '.' not in parsed_url.netloc: + raise UrlInvalid('must have a domain name in URL') return v except: # noqa: E722 raise ValueError @@ -534,7 +534,7 @@ def IsFile(v): >>> os.path.basename(IsFile()(__file__)).startswith('validators.py') True >>> with raises(FileInvalid, 'Not a file'): - ... IsFile()("random_filename_goes_here.py") + ... IsFile()('random_filename_goes_here.py') >>> with raises(FileInvalid, 'Not a file'): ... IsFile()(None) """ @@ -563,9 +563,9 @@ def IsDir(v): v = str(v) return os.path.isdir(v) else: - raise DirInvalid("Not a directory") + raise DirInvalid('Not a directory') except TypeError: - raise DirInvalid("Not a directory") + raise DirInvalid('Not a directory') @message('path does not exist', cls=PathInvalid) @@ -576,7 +576,7 @@ def PathExists(v): >>> os.path.basename(PathExists()(__file__)).startswith('validators.py') True >>> with raises(Invalid, 'path does not exist'): - ... PathExists()("random_filename_goes_here.py") + ... PathExists()('random_filename_goes_here.py') >>> with raises(PathInvalid, 'Not a Path'): ... PathExists()(None) """ @@ -585,9 +585,9 @@ def PathExists(v): v = str(v) return os.path.exists(v) else: - raise PathInvalid("Not a Path") + raise PathInvalid('Not a Path') except TypeError: - raise PathInvalid("Not a Path") + raise PathInvalid('Not a Path') def Maybe(validator: typing.Callable, msg: typing.Optional[str] = None): @@ -600,7 +600,7 @@ def Maybe(validator: typing.Callable, msg: typing.Optional[str] = None): >>> s(10) 10 >>> with raises(Invalid): - ... s("string") + ... s('string') """ return Any(None, validator, msg=msg) @@ -913,7 +913,7 @@ def __call__(self, v): return v def __repr__(self): - return 'ExactSequence([%s])' % ", ".join(repr(v) for v in self.validators) + return 'ExactSequence([%s])' % ', '.join(repr(v) for v in self.validators) class Unique(object): @@ -934,11 +934,11 @@ class Unique(object): ... s([1, 1, 2]) >>> with raises(Invalid, "contains duplicate items: ['one']"): ... s(['one', 'two', 'one']) - >>> with raises(Invalid, regex="^contains unhashable elements: "): + >>> with raises(Invalid, regex='^contains unhashable elements: '): ... s([set([1, 2]), set([3, 4])]) >>> s('abc') 'abc' - >>> with raises(Invalid, regex="^contains duplicate items: "): + >>> with raises(Invalid, regex='^contains duplicate items: '): ... s('aabbc') """ @@ -1070,7 +1070,7 @@ def __call__(self, v): return v def __repr__(self): - return 'Unordered([{}])'.format(", ".join(repr(v) for v in self.validators)) + return 'Unordered([{}])'.format(', '.join(repr(v) for v in self.validators)) class Number(object): @@ -1115,17 +1115,17 @@ def __call__(self, v): ): raise Invalid( self.msg - or "Precision must be equal to %s, and Scale must be equal to %s" + or 'Precision must be equal to %s, and Scale must be equal to %s' % (self.precision, self.scale) ) else: if self.precision is not None and precision != self.precision: raise Invalid( - self.msg or "Precision must be equal to %s" % self.precision + self.msg or 'Precision must be equal to %s' % self.precision ) if self.scale is not None and scale != self.scale: - raise Invalid(self.msg or "Scale must be equal to %s" % self.scale) + raise Invalid(self.msg or 'Scale must be equal to %s' % self.scale) if self.yield_decimal: return decimal_num @@ -1155,7 +1155,7 @@ def _get_precision_scale(self, number) -> typing.Tuple[int, int, Decimal]: else: # TODO: handle infinity and NaN # raise Invalid(self.msg or 'Value has no precision') - raise TypeError("infinity and NaN have no precision") + raise TypeError('infinity and NaN have no precision') class SomeOf(_WithSubValidators): @@ -1224,7 +1224,7 @@ def _exec(self, funcs, v, path=None): def __repr__(self): return 'SomeOf(min_valid=%s, validators=[%s], max_valid=%s, msg=%r)' % ( self.min_valid, - ", ".join(repr(v) for v in self.validators), + ', '.join(repr(v) for v in self.validators), self.max_valid, self.msg, )