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
783 changes: 782 additions & 1 deletion pyenumerable/implementations/pure_python/__init__.py

Large diffs are not rendered by default.

742 changes: 0 additions & 742 deletions pyenumerable/implementations/pure_python/_enumerable.py

This file was deleted.

59 changes: 0 additions & 59 deletions pyenumerable/protocol/_supports_group_by.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,65 +9,6 @@


class SupportsGroupBy[TSource](Protocol):
@overload
def group_by[TKey: Comparable, TElement, TResult](
self,
key_selector: Callable[[TSource], TKey],
/,
*,
element_selector: Callable[[TSource], TElement],
result_selector: Callable[[TKey, "Enumerable[TElement]"], TResult],
) -> "Enumerable[TResult]": ...

@overload
def group_by[TKey, TElement, TResult](
self,
key_selector: Callable[[TSource], TKey],
/,
*,
element_selector: Callable[[TSource], TElement],
result_selector: Callable[[TKey, "Enumerable[TElement]"], TResult],
comparer: Comparer[TKey],
) -> "Enumerable[TResult]": ...

@overload
def group_by[TKey: Comparable, TElement](
self,
key_selector: Callable[[TSource], TKey],
/,
*,
element_selector: Callable[[TSource], TElement],
) -> "Enumerable[Associable[TKey, TElement]]": ...

@overload
def group_by[TKey, TElement](
self,
key_selector: Callable[[TSource], TKey],
/,
*,
element_selector: Callable[[TSource], TElement],
comparer: Comparer[TKey],
) -> "Enumerable[Associable[TKey, TElement]]": ...

@overload
def group_by[TKey: Comparable, TResult](
self,
key_selector: Callable[[TSource], TKey],
/,
*,
result_selector: Callable[[TKey, "Enumerable[TSource]"], TResult],
) -> "Enumerable[TResult]": ...

@overload
def group_by[TKey, TResult](
self,
key_selector: Callable[[TSource], TKey],
/,
*,
result_selector: Callable[[TKey, "Enumerable[TSource]"], TResult],
comparer: Comparer[TKey],
) -> "Enumerable[TResult]": ...

@overload
def group_by[TKey: Comparable](
self,
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ lint.fixable = ["ALL"]
typeCheckingMode = "strict"
reportUnusedImport = false
reportUnusedVariable = false

[tool.pytest.ini_options]
pythonpath = ["."]
testpaths = ["test/unit"]
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Implementation of .NET's [IEnumerable](https://learn.microsoft.com/en-us/dotnet/
- [ ] Join
- [x] Intersect
- [ ] Group join
- [ ] Group by
- [x] Group by
- [x] Prepend
- [x] Order
- [x] Min
Expand Down
10 changes: 10 additions & 0 deletions test/unit/pure_python/associable/constructor/test_constructor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from pyenumerable.implementations.pure_python import PurePythonAssociable


class TestConstructor:
def test_initialization(self) -> None:
obj: PurePythonAssociable[str, int] = PurePythonAssociable(
key := "Key"
)

assert obj.key == key
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,7 @@


class TestContainsMethod:
def test_positive_without_comparer(self) -> None:
existing_item = "existing-item"
obj = PurePythonEnumerable(
"not-being-tested",
"also-not-being-tested",
existing_item,
)

assert obj.contains(existing_item) is True

def test_positive_with_comparer(self) -> None:
def test_positive(self) -> None:
obj = PurePythonEnumerable(
Person("john doe", 14),
Person("jane doe", 12),
Expand All @@ -28,15 +18,7 @@ def test_positive_with_comparer(self) -> None:
is True
)

def test_negative_without_comparer(self) -> None:
obj = PurePythonEnumerable(
"not-being-tested",
"also-not-being-tested",
)

assert obj.contains("non-existing-item") is False

def test_negative_with_comparer(self) -> None:
def test_negative(self) -> None:
obj = PurePythonEnumerable(
Person("john doe", 14),
Person("jane doe", 12),
Expand Down
19 changes: 19 additions & 0 deletions test/unit/pure_python/enumerable/except_/test_except_by_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from pyenumerable.implementations.pure_python import PurePythonEnumerable
from test.unit.pure_python.test_utility import Point


class TestExceptByMethod:
def test_except_by(self) -> None:
first_object = PurePythonEnumerable(
Point(0, 1),
first := Point(3, 2),
Point(4, 5),
second := Point(7, 6),
)
second_object = PurePythonEnumerable(
Point(3, 5), Point(8, 9), Point(-1, 1), Point(4, 7)
)

res = first_object.except_by(second_object, lambda point: point.y)

assert res.source == (first, second)
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@


class TestExceptMethod:
def test_without_comparer(self) -> None:
first_object = PurePythonEnumerable(*range(7))
second_object = PurePythonEnumerable(*range(start := 3, 9))

res = first_object.except_(second_object)

assert res.source == tuple(range(start))

def test_with_comparer(self) -> None:
def test_except(self) -> None:
first_object = PurePythonEnumerable(
Point(0, 1),
first := Point(1, 3),
Expand Down
40 changes: 40 additions & 0 deletions test/unit/pure_python/enumerable/group_by/test_group_by_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from pyenumerable.implementations.pure_python import PurePythonEnumerable
from test.unit.pure_python.test_utility import Point


class TestGroupByMethod:
def test_group_by(self) -> None:
number_of_groups = 2
first_group_key, number_of_first_group_members = 1, 3
second_group_key, number_of_second_group_members = 2, 2
obj = PurePythonEnumerable(
*(
Point(i, first_group_key)
for i in range(number_of_first_group_members)
),
*(
Point(i, second_group_key)
for i in range(number_of_second_group_members)
),
)

res = obj.group_by(lambda point: point.y)

first_group_index, second_group_index = 0, 1
assert len(res.source) == number_of_groups
assert (
len(res.source[first_group_index].source)
== number_of_first_group_members
)
assert (
len(res.source[second_group_index].source)
== number_of_second_group_members
)
assert all(
p.y == first_group_key
for p in res.source[first_group_index].source
)
assert all(
p.y == second_group_key
for p in res.source[second_group_index].source
)
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,7 @@ def test_when_second_empty(self) -> None:

assert res.source == ()

def test_without_comparer(self) -> None:
first_object = PurePythonEnumerable(
first := Person("john doe", 12, Person("marray doe", 27)),
Person("jane doe", 10, Person("larry doe", 31)),
Person("james doe", 11, None),
second := Person("jacob doe", 17, Person("harry doe", 41)),
third := Person(" doe", 14, Person("jerry doe", 34)),
)
second_object = PurePythonEnumerable(
Person("john doe", 12, Person("arry doe", 27)),
Person("jane doe", 10, Person("curry doe", 35)),
Person("jacob doe", 17, Person("harry doe", 41)),
Person(" doe", 14, Person("jerry doe", 34)),
)

res = first_object.intersect_by(
second_object,
lambda person: None
if person.parent is None
else person.parent.age,
)

assert res.source == (first, second, third)

def test_with_comparer(self) -> None:
def test_intersect_by(self) -> None:
first_object = PurePythonEnumerable(
first := Point(5, 1),
Point(3, 3),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,7 @@ def test_when_second_empty(self) -> None:

assert res.source == ()

def test_without_comparer(self) -> None:
first_object = PurePythonEnumerable(*range(end := 7))
second_object = PurePythonEnumerable(*range(start := 3, 9))

res = first_object.intersect(second_object)

assert res.source == tuple(range(start, end))

def test_with_comparer(self) -> None:
def test_intersect(self) -> None:
first_object = PurePythonEnumerable(
first := Point(0, 1),
Point(0, 3),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_exc_raise_when_uncomparable(self) -> None:
with pytest.raises(TypeError):
obj.max_by(lambda person: person.parent)

def test_with_comparer(self) -> None:
def test_max_by(self) -> None:
obj = PurePythonEnumerable(
Person("jane doe", 12, Person("james doe", 34)),
maximum := Person("john doe", 4, Person("jessie doe", 40)),
Expand All @@ -33,16 +33,6 @@ def test_with_comparer(self) -> None:

assert maximum is res

def test_without_comparer(self) -> None:
obj = PurePythonEnumerable(
maximum := Person("jane doe", 12, Person("james doe", 34)),
Person("john doe", 4, Person("jessie doe", 40)),
)

res = obj.max_by(lambda person: person.age)

assert res is maximum

@staticmethod
def age_comparer(
first: Person | None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,9 @@ def test_exc_raise_when_uncomparable(self) -> None:
with pytest.raises(TypeError):
obj.max_()

def test_with_comparer(self) -> None:
def test_max(self) -> None:
obj = PurePythonEnumerable(Point(4, 5), maximum := Point(6, 3))

res = obj.max_(comparer=lambda first, second: first.x > second.x)

assert res is maximum

def test_without_comparer(self) -> None:
obj = PurePythonEnumerable(6, 8, maximum := 10, 9, 7)

res = obj.max_()

assert res == maximum
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_exc_raise_when_uncomparable(self) -> None:
with pytest.raises(TypeError):
obj.min_by(lambda person: person.parent)

def test_with_comparer(self) -> None:
def test_min_by(self) -> None:
obj = PurePythonEnumerable(
Person("john doe", 4, Person("jessie doe", 40)),
minimum := Person("jane doe", 12, Person("james doe", 34)),
Expand All @@ -33,16 +33,6 @@ def test_with_comparer(self) -> None:

assert minimum is res

def test_without_comparer(self) -> None:
obj = PurePythonEnumerable(
Person("jane doe", 12, Person("james doe", 34)),
minimum := Person("john doe", 4, Person("jessie doe", 40)),
)

res = obj.min_by(lambda person: person.age)

assert res is minimum

@staticmethod
def age_comparer(
first: Person | None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,9 @@ def test_exc_raise_when_uncomparable(self) -> None:
with pytest.raises(TypeError):
obj.min_()

def test_with_comparer(self) -> None:
def test_min(self) -> None:
obj = PurePythonEnumerable(Point(6, 3), minimum := Point(4, 5))

res = obj.min_(comparer=lambda first, second: first.x < second.x)

assert res is minimum

def test_without_comparer(self) -> None:
obj = PurePythonEnumerable(minimum := 6, 8, 10, 9, 7)

res = obj.min_()

assert res == minimum
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,7 @@


class TestUnionByMethod:
def test_without_comparer(self) -> None:
first_object = PurePythonEnumerable(
*(
first_items := (
Point(0, 1),
Point(0, 2),
Point(0, 3),
)
)
)
second_object = PurePythonEnumerable(
*(
second_items := (
Point(0, 4),
Point(0, 5),
Point(0, 6),
)
)
)

res = first_object.union_by(second_object, lambda point: point.y)

assert res.source == first_items + second_items

def test_with_comparer(self) -> None:
def test_union_by(self) -> None:
first_object = PurePythonEnumerable(
*(
first_items := (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,7 @@ def test_exc_raise_when_unhashable(self) -> None:
with pytest.raises(TypeError):
first_object.union(second_object)

def test_without_comparer(self) -> None:
first_object = PurePythonEnumerable(*(first_items := tuple(range(3))))
second_object = PurePythonEnumerable(
*(second_items := tuple(range(7, 10)))
)

res = first_object.union(second_object)

assert res.source == first_items + second_items

def test_with_comparer(self) -> None:
def test_union(self) -> None:
first_object = PurePythonEnumerable(*(items := tuple(range(7))))
second_object = PurePythonEnumerable(*(-i for i in items))

Expand Down
Empty file.
Empty file.
Loading