Skip to content
Draft
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
21 changes: 17 additions & 4 deletions orderedsets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
__version__ = importlib_metadata.version(__package__ or __name__)

from collections.abc import Iterator, Set
from typing import AbstractSet, Any, Iterable, Optional, Type, TypeVar, Union
from typing import AbstractSet, Any, Iterable, Optional, Type, TypeVar, Union, FrozenSet

T = TypeVar("T")

Expand All @@ -45,7 +45,7 @@ class _NotProvided:
pass


class OrderedSet(AbstractSet[T]):
class OrderedSet(set):
"""A set class that preserves insertion order.

It can be used as a drop-in replacement for :class:`set` where ordering is
Expand All @@ -55,19 +55,29 @@ class OrderedSet(AbstractSet[T]):
def __init__(self, items: Union[Iterable[T], Type[_NotProvided]] = _NotProvided)\
-> None:
"""Create a new :class:`OrderedSet`, optionally initialized with *items*."""
print("init", items)
if items is _NotProvided:
self._dict = {}
else:
# type-ignore-reason:
# mypy thinks 'items' can still be Type[_NotProvided] here.
self._dict = dict.fromkeys(items) # type: ignore[arg-type]

def __new__(cls, *args: Any, **kwargs: Any) -> OrderedSet[T]:
333/0

def __eq__(self, other: object) -> bool:
"""Return whether this set is equal to *other*."""
return (isinstance(other, Set)
print("eq", self, other)
return (isinstance(other, AbstractSet)
and len(self) == len(other)
and all(i in other for i in self))


def __ne__(self, other: object) -> bool:
"""Return whether this set is not equal to *other*."""
return not self.__eq__(other)

def __repr__(self) -> str:
"""Return a string representation of this set."""
if len(self) == 0:
Expand Down Expand Up @@ -156,6 +166,9 @@ def __contains__(self, o: object) -> bool:
"""Return whether *o* is in this set."""
return o in self._dict

def __getitem__(self, i: int) -> T:
444/0

def __iter__(self) -> Iterator[T]:
"""Return an iterator over the elements of this set."""
return iter(self._dict)
Expand Down Expand Up @@ -217,7 +230,7 @@ def __gt__(self, s: Set[T]) -> bool:
return len(self) > len(s) and set(self) > set(s)


class FrozenOrderedSet(AbstractSet[T]):
class FrozenOrderedSet(frozenset):
"""A frozen set class that preserves insertion order.

It can be used as a drop-in replacement for :class:`frozenset` where
Expand Down
61 changes: 38 additions & 23 deletions test/test_orderedsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,23 @@ def test_init(_cls: T_set[int]) -> None:
s = _cls(1, 2) # type: ignore[arg-type,call-overload,call-arg]


@all_set_types
def test_isinstance(_cls: T_ordered_set[int]) -> None:
assert isinstance(_cls(), AbstractSet)
if _cls in mutable_set_types:
assert isinstance(_cls(), Set)
assert isinstance(_cls(), set)
if _cls in ordered_set_types:
assert isinstance(_cls(), OrderedSet)
assert not isinstance(_cls(), FrozenOrderedSet)
else:
assert isinstance(_cls(), FrozenSet)
assert isinstance(_cls(), frozenset)
assert not isinstance(_cls(), OrderedSet)
if _cls in ordered_set_types:
assert isinstance(_cls(), FrozenOrderedSet)


@all_set_types
def test_call_abstractset(_cls: T_set[int]) -> None:
f(_cls([4, 1, 4, 1]))
Expand Down Expand Up @@ -120,15 +137,23 @@ def test_in(_cls: T_set[int]) -> None:
def test_eq(_cls: T_set[int]) -> None:
s1 = _cls([4, 1, 4, 1])
s2 = _cls([4, 4, 1])
s3 = set([4, 1, 4, 1]) # noqa: C405
assert s1 == s2
assert s1 == s3
assert s2 == s1
assert s3 == s1
assert s2 == s3 == s1
# s3 = set([4, 1, 4, 1]) # noqa: C405
# assert s1 == s2
# assert s1 == s3
# assert s2 == s1
# assert s3 == s1
# assert s2 == s3 == s1


s4 = _cls([4])
assert s1 != s4

# import pudb
# pu.db

# x =
# print(s1 == s4)

assert s1 != s4, (s1, s4)

assert s1 != [4, 1]
if _cls in ordered_set_types:
Expand Down Expand Up @@ -194,7 +219,12 @@ def test_clear_mutable(_cls: T_mutable_set[int]) -> None:

@all_set_types
def test_convert_to_set(_cls: T_set[int]) -> None:
assert {1, 2, 3} == set(_cls([3, 1, 2]))
import pudb
pu.db
x = _cls([3, 1, 2])
print(x)
s = set(x)
assert {1, 2, 3} == set(x)


@all_ordered_set_types
Expand Down Expand Up @@ -591,18 +621,3 @@ def test_ordering(_cls: T_set[int]) -> None:
assert not (oset3 >= oset4)
assert not (oset3 >= set(oset4))
# assert not (oset3 >= list(oset4))


@all_ordered_set_types
def test_isinstance(_cls: T_ordered_set[int]) -> None:
assert isinstance(_cls(), AbstractSet)
assert not isinstance(_cls(), Set)
assert not isinstance(_cls(), set)
assert not isinstance(_cls(), frozenset)

if _cls in mutable_set_types:
assert isinstance(_cls(), OrderedSet)
assert not isinstance(_cls(), FrozenOrderedSet)
else:
assert not isinstance(_cls(), OrderedSet)
assert isinstance(_cls(), FrozenOrderedSet)