From bba1e6aa6b5f0979982376e76db88e9771dcfbab Mon Sep 17 00:00:00 2001 From: bhavishya Date: Thu, 9 Feb 2017 20:51:54 +0530 Subject: [PATCH 1/2] Implementation of equality for the Settings class --- h2/settings.py | 12 ++++ test/test_settings.py | 129 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) diff --git a/h2/settings.py b/h2/settings.py index 9b325b00d..9b5332723 100644 --- a/h2/settings.py +++ b/h2/settings.py @@ -253,6 +253,18 @@ def __iter__(self): def __len__(self): return len(self._settings) + def __eq__(self, other): + if isinstance(other, Settings): + return self._settings == other._settings + else: + return NotImplemented + + def __ne__(self, other): + if isinstance(other, Settings): + return not self == other + else: + return NotImplemented + def _validate_setting(setting, value): """ diff --git a/test/test_settings.py b/test/test_settings.py index 1e853d1a4..ddc61213b 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -350,3 +350,132 @@ def test_cannot_set_invalid_values_for_max_header_list_size(self, val): with pytest.raises(KeyError): s[h2.settings.MAX_HEADER_LIST_SIZE] + + +class TestSettingsEquality(object): + """ + A class defining tests for the standard implementation of == and != . + """ + + def an_instance(self): + """ + Return an instance of the class under test. Each call to this method + must return a different object. All objects returned must be equal to + each other. + """ + overrides = { + h2.settings.HEADER_TABLE_SIZE: 0, + h2.settings.MAX_FRAME_SIZE: 16384, + h2.settings.MAX_CONCURRENT_STREAMS: 4, + h2.settings.MAX_HEADER_LIST_SIZE: 2**16, + } + return h2.settings.Settings(client=True, initial_values=overrides) + + def another_instance(self): + """ + Return an instance of the class under test. Each call to this method + must return a different object. The objects must not be equal to the + objects returned by an_instance. They may or may not be equal to + each other (they will not be compared against each other). + """ + overrides = { + h2.settings.HEADER_TABLE_SIZE: 8080, + h2.settings.MAX_FRAME_SIZE: 16388, + h2.settings.MAX_CONCURRENT_STREAMS: 100, + h2.settings.MAX_HEADER_LIST_SIZE: 2**16, + } + return h2.settings.Settings(client=False, initial_values=overrides) + + def test_identical_eq(self): + """ + An object compares equal to itself using the == operator. + """ + o = self.an_instance() + assert (o == o) + + def test_identical_ne(self): + """ + An object doesn't compare not equal to itself using the != operator. + """ + o = self.an_instance() + assert not (o != o) + + def test_same_eq(self): + """ + Two objects that are equal to each other compare equal to each other + using the == operator. + """ + a = self.an_instance() + b = self.an_instance() + assert (a == b) + + def test_same_ne(self): + """ + Two objects that are equal to each other do not compare not equal to + each other using the != operator. + """ + a = self.an_instance() + b = self.an_instance() + assert not (a != b) + + def test_different_eq(self): + """ + Two objects that are not equal to each other do not compare equal to + each other using the == operator. + """ + a = self.an_instance() + b = self.another_instance() + assert not (a == b) + + def test_different_ne(self): + """ + Two objects that are not equal to each other compare not equal to each + other using the != operator. + """ + a = self.an_instance() + b = self.another_instance() + assert (a != b) + + def test_another_type_eq(self): + """ + The object does not compare equal to an object of an unrelated type + (which does not implement the comparison) using the == operator. + """ + a = self.an_instance() + b = object() + assert not (a == b) + + def test_another_type_ne(self): + """ + The object compares not equal to an object of an unrelated type (which + does not implement the comparison) using the != operator. + """ + a = self.an_instance() + b = object() + assert (a != b) + + def test_delegated_eq(self): + """ + The result of comparison using == is delegated to the right-hand + operand if it is of an unrelated type. + """ + class Delegate(object): + def __eq__(self, other): + return [self] + + a = self.an_instance() + b = Delegate() + assert (a == b) == [b] + + def test_delegate_ne(self): + """ + The result of comparison using != is delegated to the right-hand + operand if it is of an unrelated type. + """ + class Delegate(object): + def __ne__(self, other): + return [self] + + a = self.an_instance() + b = Delegate() + assert (a != b) == [b] From bb3b7ea8288ee697e214700a133230971c329b65 Mon Sep 17 00:00:00 2001 From: Alex Chan Date: Mon, 13 Feb 2017 11:14:46 +0000 Subject: [PATCH 2/2] Add changelog entry for #465 --- HISTORY.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.rst b/HISTORY.rst index 51b7b3b67..dc8bae500 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -11,6 +11,7 @@ API Changes (Backward-Compatible) events. - Rather than reject outbound Connection-specific headers, h2 will now normalize the header block by removing them. +- Implement equality for the ``Settings`` class. Bugfixes ~~~~~~~~