Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
~~~~~~~~
Expand Down
12 changes: 12 additions & 0 deletions h2/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
129 changes: 129 additions & 0 deletions test/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]