Skip to content
Open
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
9 changes: 9 additions & 0 deletions humanfriendly/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ def get(self, key, default=None):
"""Get the value of an existing item."""
return super(CaseInsensitiveDict, self).get(self.coerce_key(key), default)

def move_to_end(self, key, last=True):
"""Move an existing key to either end of the dictionary."""
return super(CaseInsensitiveDict, self).move_to_end(self.coerce_key(key), last=last)

def pop(self, key, default=None):
"""Remove an item from a case insensitive dictionary."""
return super(CaseInsensitiveDict, self).pop(self.coerce_key(key), default)
Expand Down Expand Up @@ -155,3 +159,8 @@ def __eq__(self, other):
return self._normalized == other.lower()
else:
return NotImplemented

def __ne__(self, other):
"""Compare inequality using the same lowercase values as equality."""
equal = self.__eq__(other)
return NotImplemented if equal is NotImplemented else not equal
25 changes: 25 additions & 0 deletions humanfriendly/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,31 @@ def test_case_insensitive_key(self):
mapping[rude] = 2
assert len(mapping) == 1

def test_case_insensitive_key_inequality(self):
"""Keep case-insensitive inequality consistent with equality."""
lower = CaseInsensitiveKey('content-type')
upper = CaseInsensitiveKey('CONTENT-TYPE')
assert lower == upper
assert not (lower != upper)
assert not (upper != 'content-type')
assert not ('content-type' != upper)
assert upper != 'other'
assert upper != 1
assert upper.__ne__(object()) is NotImplemented

def test_case_insensitive_move_to_end(self):
"""Coerce string keys before changing their insertion order."""
obj = CaseInsensitiveDict([('First', 1), ('Second', 2), (3, 3)])
assert obj.move_to_end('FIRST') is None
assert list(obj) == ['Second', 3, 'First']
obj.move_to_end('SECOND', last=False)
assert list(obj) == ['Second', 3, 'First']
obj.move_to_end(3, last=False)
assert list(obj) == [3, 'Second', 'First']
with self.assertRaises(KeyError):
obj.move_to_end('missing')
assert obj['first'] == 1

def test_capture_output(self):
"""Test the CaptureOutput class."""
with CaptureOutput() as capturer:
Expand Down