Skip to content

Commit f240475

Browse files
author
Harsh Raj Singhania
committed
sorts: type bubble sort for any comparable items
Bound bubble_sort_iterative and bubble_sort_recursive to a Comparable protocol instead of Any, add TypeError doctests, and cover the mixed-type failure in tests/test_sorts.py. Refs #15234
1 parent d0f9b6e commit f240475

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

sorts/bubble_sort.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
from typing import Any
1+
from typing import Any, Protocol, TypeVar
22

33

4-
def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
4+
class Comparable(Protocol):
5+
def __lt__(self, other: Any, /) -> bool: ...
6+
7+
8+
T = TypeVar("T", bound=Comparable)
9+
10+
11+
def bubble_sort_iterative[T: Comparable](collection: list[T]) -> list[T]:
512
"""Pure implementation of the bubble sort algorithm in Python (iterative).
613
714
Bubble sort works by repeatedly stepping through the collection,
@@ -58,6 +65,10 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
5865
>>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100)
5966
>>> bubble_sort_iterative(collection_arg) == sorted(collection_arg)
6067
True
68+
>>> bubble_sort_iterative([1, "a"]) # doctest: +IGNORE_EXCEPTION_DETAIL
69+
Traceback (most recent call last):
70+
...
71+
TypeError: '<' not supported between instances of 'str' and 'int'
6172
"""
6273
length = len(collection)
6374
for i in reversed(range(length)):
@@ -71,7 +82,7 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
7182
return collection
7283

7384

74-
def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
85+
def bubble_sort_recursive[T: Comparable](collection: list[T]) -> list[T]:
7586
"""Pure implementation of the bubble sort algorithm in Python (recursive).
7687
7788
Functionally identical to the iterative version: each call makes a
@@ -124,6 +135,10 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
124135
>>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100)
125136
>>> bubble_sort_recursive(collection_arg) == sorted(collection_arg)
126137
True
138+
>>> bubble_sort_recursive([1, "a"]) # doctest: +IGNORE_EXCEPTION_DETAIL
139+
Traceback (most recent call last):
140+
...
141+
TypeError: '<' not supported between instances of 'str' and 'int'
127142
"""
128143
length = len(collection)
129144
swapped = False

tests/test_sorts.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import pytest
1818

1919
from sorts.binary_insertion_sort import binary_insertion_sort
20-
from sorts.bubble_sort import bubble_sort_iterative
20+
from sorts.bubble_sort import bubble_sort_iterative, bubble_sort_recursive
2121
from sorts.circle_sort import circle_sort
2222
from sorts.cocktail_shaker_sort import cocktail_shaker_sort
2323
from sorts.comb_sort import comb_sort
@@ -92,3 +92,13 @@ def test_sort_matches_builtin(sort, case):
9292
def test_binary_insertion_sort_rejects_non_comparable_items():
9393
with pytest.raises(TypeError):
9494
binary_insertion_sort([1, "a"])
95+
96+
97+
@pytest.mark.parametrize(
98+
"sort",
99+
(bubble_sort_iterative, bubble_sort_recursive),
100+
ids=lambda f: f.__name__,
101+
)
102+
def test_bubble_sort_rejects_non_comparable_items(sort):
103+
with pytest.raises(TypeError):
104+
sort([1, "a"])

0 commit comments

Comments
 (0)