From 52a3a71179b1c1bc01ce6cf75c8cc393c64c510f Mon Sep 17 00:00:00 2001 From: Dan Tao Date: Wed, 6 Dec 2017 09:10:43 -0600 Subject: [PATCH 1/4] add test for schema equality (see #315) --- voluptuous/tests/tests.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/voluptuous/tests/tests.py b/voluptuous/tests/tests.py index cc0ed61..db328a6 100644 --- a/voluptuous/tests/tests.py +++ b/voluptuous/tests/tests.py @@ -410,6 +410,27 @@ def test_subschema_extension(): assert_equal(extended.schema, {'a': {'b': str, 'c': float, 'e': int}, 'd': str}) +def test_equality(): + assert_equal(Schema('foo'), Schema('foo')) + + assert_equal(Schema(['foo', 'bar', 'baz']), + Schema(['foo', 'bar', 'baz'])) + + # Ensure two Schemas w/ two equivalent dicts initialized in a different + # order are considered equal. + dict_a = {} + dict_a['foo'] = 1 + dict_a['bar'] = 2 + dict_a['baz'] = 3 + + dict_b = {} + dict_b['baz'] = 3 + dict_b['bar'] = 2 + dict_b['foo'] = 1 + + assert_equal(Schema(dict_a), Schema(dict_b)) + + def test_repr(): """Verify that __repr__ returns valid Python expressions""" match = Match('a pattern', msg='message') From be867c5bf5c6dc9dde27d58352ea0f4f54c3d2c0 Mon Sep 17 00:00:00 2001 From: Dan Tao Date: Wed, 6 Dec 2017 09:12:33 -0600 Subject: [PATCH 2/4] fix Schema.__eq__ to deal with dicts properly (fixes #315) --- voluptuous/schema_builder.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/voluptuous/schema_builder.py b/voluptuous/schema_builder.py index f4244c8..7fb987d 100644 --- a/voluptuous/schema_builder.py +++ b/voluptuous/schema_builder.py @@ -242,10 +242,9 @@ def value_to_schema_type(value): return cls(value_to_schema_type(data), **kwargs) def __eq__(self, other): - if str(other) == str(self.schema): - # Because repr is combination mixture of object and schema - return True - return False + if not isinstance(other, Schema): + return False + return other.schema == self.schema def __str__(self): return str(self.schema) From 2c5c378f3552173d6fcba802045529b00d62c2ed Mon Sep 17 00:00:00 2001 From: Dan Tao Date: Wed, 6 Dec 2017 13:06:38 -0600 Subject: [PATCH 3/4] add negative equality tests This fills in missing test coverage to ensure the __eq__ method does not return True in some potentially unexpected cases (these tests would fail before be867c5). --- voluptuous/tests/tests.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/voluptuous/tests/tests.py b/voluptuous/tests/tests.py index db328a6..96452da 100644 --- a/voluptuous/tests/tests.py +++ b/voluptuous/tests/tests.py @@ -3,7 +3,7 @@ import os import sys -from nose.tools import assert_equal, assert_raises, assert_true +from nose.tools import assert_equal, assert_false, assert_raises, assert_true from voluptuous import ( Schema, Required, Exclusive, Optional, Extra, Invalid, In, Remove, Literal, @@ -431,6 +431,17 @@ def test_equality(): assert_equal(Schema(dict_a), Schema(dict_b)) +def test_equality_negative(): + """Verify that Schema objects are not equal to string representations""" + assert_false(Schema('foo') == 'foo') + + assert_false(Schema(['foo', 'bar']) == "['foo', 'bar']") + assert_false(Schema(['foo', 'bar']) == Schema("['foo', 'bar']")) + + assert_false(Schema({'foo': 1, 'bar': 2}) == "{'foo': 1, 'bar': 2}") + assert_false(Schema({'foo': 1, 'bar': 2}) == Schema("{'foo': 1, 'bar': 2}")) + + def test_repr(): """Verify that __repr__ returns valid Python expressions""" match = Match('a pattern', msg='message') From 04355117b9bd6792cf1250aba20452da1d608ec1 Mon Sep 17 00:00:00 2001 From: Dan Tao Date: Wed, 6 Dec 2017 13:18:22 -0600 Subject: [PATCH 4/4] implement Schema.__ne__ method to support != operator Previously only the __eq__ method was implemented, which could lead to surprising behavior e.g.: Schema('foo') == Schema('foo') # True Schema('foo') != Schema('foo') # True This adds the __ne__ method so that these operators are complementary as one might expect. --- voluptuous/schema_builder.py | 3 +++ voluptuous/tests/tests.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/voluptuous/schema_builder.py b/voluptuous/schema_builder.py index 7fb987d..724c504 100644 --- a/voluptuous/schema_builder.py +++ b/voluptuous/schema_builder.py @@ -246,6 +246,9 @@ def __eq__(self, other): return False return other.schema == self.schema + def __ne__(self, other): + return not (self == other) + def __str__(self): return str(self.schema) diff --git a/voluptuous/tests/tests.py b/voluptuous/tests/tests.py index 96452da..25a938c 100644 --- a/voluptuous/tests/tests.py +++ b/voluptuous/tests/tests.py @@ -442,6 +442,37 @@ def test_equality_negative(): assert_false(Schema({'foo': 1, 'bar': 2}) == Schema("{'foo': 1, 'bar': 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_inequality_negative(): + assert_false(Schema('foo') != Schema('foo')) + + assert_false(Schema(['foo', 'bar', 'baz']) != + Schema(['foo', 'bar', 'baz'])) + + # Ensure two Schemas w/ two equivalent dicts initialized in a different + # order are considered equal. + dict_a = {} + dict_a['foo'] = 1 + dict_a['bar'] = 2 + dict_a['baz'] = 3 + + dict_b = {} + dict_b['baz'] = 3 + dict_b['bar'] = 2 + dict_b['foo'] = 1 + + assert_false(Schema(dict_a) != Schema(dict_b)) + + def test_repr(): """Verify that __repr__ returns valid Python expressions""" match = Match('a pattern', msg='message')