diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 91e05fb..e74de20 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: pip install --upgrade pip pip install nox - name: Test '${{ matrix.nox_env }}' with nox - run: nox -e ${{ matrix.nox_env }} + run: nox -s ${{ matrix.nox_env }} tests: name: Unit tests @@ -48,7 +48,7 @@ jobs: pip install nox pip install coverage - name: Test with nox - run: nox -e pytest + run: nox -s pytest - name: Upload coverage report uses: codecov/codecov-action@v5.1.2 with: diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 2b51d78..b9399a0 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -59,8 +59,7 @@ representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -. +reported to the community leaders responsible for enforcement. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the diff --git a/pyproject.toml b/pyproject.toml index fa36d8d..974832e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,10 +45,9 @@ lint.per-file-ignores."__init__.py" = [ "F401", # {name} imported but unused ] lint.per-file-ignores."tests/*" = [ - "D103", # Missing docstring in public function - "D104", # Missing docstring in public package - "PT011", # pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception - "S101", # Use of assert detected + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "S101", # Use of assert detected ] [tool.mypy] diff --git a/pysortlib/__init__.py b/pysortlib/__init__.py index 22cae71..0e8c122 100644 --- a/pysortlib/__init__.py +++ b/pysortlib/__init__.py @@ -1,6 +1,6 @@ """Library containing various sorting algorithms.""" -from .sorting import ( +from pysortlib.sorting import ( bubble_sort, heap_sort, insert_sort, @@ -9,4 +9,4 @@ selection_sort, shell_sort, ) -from .sorting_extra import counting_sort, radix_sort, sleep_sort +from pysortlib.sorting_extra import counting_sort, radix_sort, sleep_sort diff --git a/pysortlib/sorting.py b/pysortlib/sorting.py index 04bc506..47fd8d4 100644 --- a/pysortlib/sorting.py +++ b/pysortlib/sorting.py @@ -96,8 +96,8 @@ def heap_sort(array: list[int]) -> None: """ Sorts an array of integers using the heap sort algorithm. - Time complexity: O(n*log(n)), where n is the length of the array. - Extra space complexity: O(1). + Time complexity: O(n log(n)), where n is the length of the array. + Extra space complexity: O(1) Stable: No (the relative order of equal elements is not preserved). In-place: Yes (the input array is modified). @@ -157,7 +157,7 @@ def merge_sort(array: list[int]) -> list[int]: """ Sorts an array of integers using the merge sort algorithm. - Time complexity: O(n*log(n)), where n is the length of the array. + Time complexity: O(n log(n)), where n is the length of the array. Extra space complexity: O(n), where n is the length of the array. Stable: Yes (the relative order of equal elements is preserved). @@ -181,23 +181,23 @@ def merge_sort(array: list[int]) -> list[int]: def _partition(array: list[int], start: int, end: int) -> int: - pivot = array[end] - pivot_index = start - 1 + partition = array[end] + partition_index = start - 1 for i in range(start, end): - if array[i] <= pivot: - pivot_index += 1 - swap(array, pivot_index, i) + if array[i] <= partition: + partition_index += 1 + swap(array, partition_index, i) - swap(array, pivot_index + 1, end) - return pivot_index + 1 + swap(array, partition_index + 1, end) + return partition_index + 1 def quick_sort(array: list[int], left: int, right: int) -> None: """ Sorts an array of integers using the quick sort algorithm. - Time complexity: O(n*log(n)), where n is the length of the array. + Time complexity: O(n log(n)), where n is the length of the array. Extra space complexity: O(1) Stable: No (the relative order of equal elements is not preserved). @@ -242,7 +242,7 @@ def shell_sort(array: list[int]) -> None: Sorts an array of integers using the shell sort algorithm. Time complexity: O(n^2), where n is the length of the array. - Extra space complexity: O(1). + Extra space complexity: O(1) Stable: No (the relative order of equal elements is not preserved). In-place: Yes (the input array is modified). @@ -272,7 +272,7 @@ def pancake_sort(array: list[int]) -> None: Sorts an array of integers using the pancake sort algorithm. Time complexity: O(n^2), where n is the length of the array. - Extra space complexity: O(1). + Extra space complexity: O(1) Stable: No (the relative order of equal elements is not preserved). In-place: Yes (the input array is modified). diff --git a/pysortlib/sorting_extra.py b/pysortlib/sorting_extra.py index 89d807b..d67a10b 100644 --- a/pysortlib/sorting_extra.py +++ b/pysortlib/sorting_extra.py @@ -4,7 +4,7 @@ import time from itertools import chain, repeat -from .utils import check_negative_integers +from pysortlib.utils import check_negative_integers def counting_sort(array: list[int], *, max_value: int) -> list[int]: @@ -48,7 +48,7 @@ def radix_sort(array: list[int], *, max_digits: int, base: int = 10) -> list[int """ Sorts an array of integers using the radix sort algorithm. - Time complexity: O(d*(n+k)), where: + Time complexity: O(d (n+k)), where: - d is the number of digits in the largest number - n is the length of the array - k is the number of possible digits (the base) @@ -62,7 +62,7 @@ def radix_sort(array: list[int], *, max_digits: int, base: int = 10) -> list[int :param array: array of integers :param max_digits: number of digits in the largest number - :param base: base of the numbers, default is 10 + :param base: base of the numbers :raises: ValueError: if the array contains negative integers :return: sorted array of integers """ @@ -79,9 +79,9 @@ def radix_sort(array: list[int], *, max_digits: int, base: int = 10) -> list[int return array -def _shut_up_for(secs: int) -> int: - time.sleep(secs) - return secs +def _shut_up_for(seconds: int) -> int: + time.sleep(seconds) + return seconds def sleep_sort(array: list[int]) -> list[int]: @@ -92,8 +92,11 @@ def sleep_sort(array: list[int]) -> list[int]: Extra space complexity: O(n), where n is the length of the array. :param array: array of integers + :raises: ValueError: if the array contains negative integers :return: sorted array of integers """ + check_negative_integers(array) + with concurrent.futures.ThreadPoolExecutor() as executor: futures = [executor.submit(_shut_up_for, num) for num in array] iterator = concurrent.futures.as_completed(futures) diff --git a/pysortlib/utils.py b/pysortlib/utils.py index 139304c..d4d5a11 100644 --- a/pysortlib/utils.py +++ b/pysortlib/utils.py @@ -9,5 +9,5 @@ def swap(array: list[int], index_1: int, index_2: int) -> None: def check_negative_integers(array: list[int]) -> None: """Check if the array contains only non-negative integers.""" if any(num < 0 for num in array): - msg = "The array should contain only non-negative integers" + msg = "The array must contain only non-negative integers" raise ValueError(msg) diff --git a/tests/test_sorting_extra.py b/tests/test_sorting_extra.py index 2e00aa0..782dc5d 100644 --- a/tests/test_sorting_extra.py +++ b/tests/test_sorting_extra.py @@ -23,9 +23,9 @@ def test_counting_sort(array: list[int]) -> None: ], ) def test_counting_sort_with_negative_integers(array: list[int]) -> None: - with pytest.raises(ValueError) as exc: + pattern = "The array must contain only non-negative integers" + with pytest.raises(ValueError, match=pattern): counting_sort(array, max_value=1) - assert str(exc.value) == "The array should contain only non-negative integers" @given(lists(integers(min_value=0, max_value=999))) @@ -42,9 +42,9 @@ def test_radix_sort(array: list[int]) -> None: ], ) def test_radix_sort_with_negative_integers(array: list[int]) -> None: - with pytest.raises(ValueError) as exc: + pattern = "The array must contain only non-negative integers" + with pytest.raises(ValueError, match=pattern): radix_sort(array, max_digits=1) - assert str(exc.value) == "The array should contain only non-negative integers" @pytest.mark.parametrize( @@ -65,3 +65,16 @@ def test_sleep_sort(array: list[int]) -> None: assert (end - start) < timeout assert result == sorted(array) + + +@pytest.mark.parametrize( + "array", + [ + [-1, 0], + [0, -1], + ], +) +def test_sleep_sort_with_negative_integers(array: list[int]) -> None: + pattern = "The array must contain only non-negative integers" + with pytest.raises(ValueError, match=pattern): + radix_sort(array, max_digits=1)