Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4.0 #57

Closed
wants to merge 3 commits into from
Closed

v4.0 #57

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 22 additions & 21 deletions ordered_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,31 @@
An OrderedSet is a custom MutableSet that remembers its order, so that every
entry has an index that can be looked up.

Based on a recipe originally posted to ActiveState Recipes by Raymond Hettiger,
Based on a recipe originally posted to ActiveState by Raymond Hettinger,
and released under the MIT license.

http://code.activestate.com/recipes/576694-orderedset/
"""
import itertools as it
from collections import deque
from collections import OrderedDict

try:
# Python 3
from collections.abc import MutableSet, Sequence
dict_keys_view = type({}.keys())
dict_items_view = type({}.items())
odict_keys_view = type(OrderedDict().keys())
odict_items_view = type(OrderedDict().items())
except ImportError:
# Python 2.7
from collections import MutableSet, Sequence
dict_keys_view = type({}.viewkeys())
dict_items_view = type({}.viewitems())
odict_keys_view = type(OrderedDict().viewkeys())
odict_items_view = type(OrderedDict().viewitems())

SLICE_ALL = slice(None)
__version__ = "3.1"
__version__ = "4.0"


def is_iterable(obj):
Expand Down Expand Up @@ -279,33 +289,24 @@ def __repr__(self):

def __eq__(self, other):
"""
Returns true if the containers have the same items. If `other` is a
Sequence, then order is checked, otherwise it is ignored.
Returns true if the sets have the same members. If `other` is an
ordered set, then the same ordering is also checked, otherwise the
comparison is order agnostic.

Example:
>>> oset = OrderedSet([1, 3, 2])
>>> oset == [1, 3, 2]
True
>>> oset == [1, 2, 3]
False
>>> oset == [2, 3]
False
>>> oset == OrderedSet([3, 2, 1])
False
>>> oset == {3, 2, 1}
True
"""
# In Python 2 deque is not a Sequence, so treat it as one for
# consistent behavior with Python 3.
if isinstance(other, (Sequence, deque)):
if isinstance(other, (OrderedSet, odict_keys_view, odict_items_view)):
# Check that this OrderedSet contains the same elements, in the
# same order, as the other object.
return list(self) == list(other)
try:
other_as_set = set(other)
except TypeError:
# If `other` can't be converted into a set, it's not equal.
return False
else:
return set(self) == other_as_set
if isinstance(other, (set, frozenset, dict_keys_view, dict_items_view)):
return set(self) == other
return NotImplemented

def union(self, *sets):
"""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package_data={'': ['MIT-LICENSE']},
include_package_data=True,
tests_require=['pytest'],
python_requires='>=2.7',
python_requires='>=2.7.8',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
Expand Down
68 changes: 33 additions & 35 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def test_indexing():
assert set1[:] is not set1
assert set1.copy() is not set1

assert set1[[1, 2]] == OrderedSet(['b', 'r'])
assert set1[[1, 2]] == ['b', 'r']
assert set1[1:3] == OrderedSet(['b', 'r'])
assert set1.index('b') == 1
assert set1.index(['b', 'r']) == [1, 2]
Expand Down Expand Up @@ -156,7 +156,8 @@ def test_pop():

assert elem == 'a'

pytest.raises(KeyError, set1.pop)
with pytest.raises(KeyError):
set1.pop()


def test_getitem_type_error():
Expand All @@ -180,31 +181,15 @@ def test_empty_repr():
def test_eq_wrong_type():
set1 = OrderedSet()
assert set1 != 2
assert OrderedSet([1, 2]) != [1, 2]
assert OrderedSet([1, 2]) != (2, 1)


def test_ordered_equality():
# Ordered set checks order against sequences.
# Ordered set checks order against other Ordered set.
assert OrderedSet([1, 2]) == OrderedSet([1, 2])
assert OrderedSet([1, 2]) == [1, 2]
assert OrderedSet([1, 2]) == (1, 2)
assert OrderedSet([1, 2]) == collections.deque([1, 2])


def test_ordered_inequality():
# Ordered set checks order against sequences.
assert OrderedSet([1, 2]) != OrderedSet([2, 1])

assert OrderedSet([1, 2]) != [2, 1]
assert OrderedSet([1, 2]) != [2, 1, 1]

assert OrderedSet([1, 2]) != (2, 1)
assert OrderedSet([1, 2]) != (2, 1, 1)

# Note: in Python 2.7 deque does not inherit from Sequence, but __eq__
# contains an explicit check for this case for python 2/3 compatibility.
assert OrderedSet([1, 2]) != collections.deque([2, 1])
assert OrderedSet([1, 2]) != collections.deque([2, 2, 1])


def test_comparisons():
# Comparison operators on sets actually test for subset and superset.
Expand All @@ -219,21 +204,38 @@ def test_comparisons():
def test_unordered_equality():
# Unordered set checks order against non-sequences.
assert OrderedSet([1, 2]) == {1, 2}
assert OrderedSet([1, 2]) == {2, 1}
assert OrderedSet([1, 2]) == frozenset([2, 1])
assert OrderedSet([1, 2]) == frozenset([1, 2])


assert OrderedSet([1, 2]) == {1: 'a', 2: 'b'}
@pytest.mark.skipif(sys.version_info >= (3,), reason="requires Python 2.x")
@pytest.mark.xfail(sys.version_info < (2, 7, 8), reason="bug fixed in 2.7.8+")
def test_dict_views_py2():
assert OrderedSet([1, 2]) == {1: 1, 2: 2}.viewkeys()
assert OrderedSet([(1, 1), (2, 2)]) == {1: 1, 2: 2}.viewitems()
assert OrderedSet([1, 2]) != {1: 1, 2: 2}.viewvalues() # dict_values is not set-like
assert OrderedSet([1, 2]) == collections.OrderedDict([(1, 1), (2, 2)]).viewkeys()
assert OrderedSet([1, 2]) != collections.OrderedDict([(2, 2), (1, 1)]).viewkeys()


@pytest.mark.skipif(sys.version_info < (3,), reason="requires Python 3.x")
def test_dict_views_py3():
assert OrderedSet([1, 2]) == {1: 1, 2: 2}.keys()
assert OrderedSet([1, 2]) == {1: 1, 2: 2}.values()
assert OrderedSet([(1, 1), (2, 2)]) == {1: 1, 2: 2}.items()
assert OrderedSet([1, 2]) != {1: 1, 2: 2}.values() # dict_values is not set-like
assert OrderedSet([1, 2]) == collections.OrderedDict([(1, 1), (2, 2)]).keys()
assert OrderedSet([1, 2]) != collections.OrderedDict([(2, 2), (1, 1)]).keys()

# Corner case: OrderedDict is not a Sequence, so we don't check for order,
# even though it does have the concept of order.
assert OrderedSet([1, 2]) == collections.OrderedDict([(2, 2), (1, 1)])

# Corner case: We have to treat iterators as unordered because there
# is nothing to distinguish an ordered and unordered iterator
assert OrderedSet([1, 2]) == iter([1, 2])
assert OrderedSet([1, 2]) == iter([2, 1])
assert OrderedSet([1, 2]) == iter([2, 1, 1])
@pytest.mark.xfail(sys.version_info < (2, 7, 8), reason="bug fixed in 2.7.8+")
def test_unordered_equality_reflected():
# Expected failure on old versions of 2.7
# See https://bugs.python.org/issue8743
assert {1, 2} == OrderedSet([1, 2])
assert {2, 1} == OrderedSet([1, 2])
assert frozenset([2, 1]) == OrderedSet([1, 2])
assert frozenset([1, 2]) == OrderedSet([1, 2])


def test_unordered_inequality():
Expand All @@ -244,10 +246,6 @@ def test_unordered_inequality():
assert OrderedSet([1, 2]) != {1: 1, 4: 2}.keys()
assert OrderedSet([1, 2]) != {1: 1, 2: 3}.values()

# Corner case: OrderedDict is not a Sequence, so we don't check for order,
# even though it does have the concept of order.
assert OrderedSet([1, 2]) != collections.OrderedDict([(2, 2), (3, 1)])


def allsame_(iterable, eq=operator.eq):
""" returns True of all items in iterable equal each other """
Expand Down