From cd3c3c3130f8b067b27993a93fac0e0ffe5e59d2 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 6 Jul 2025 00:35:29 +0200 Subject: [PATCH] Various ruff fixes (#12821) --- DIRECTORY.md | 2 ++ ciphers/hill_cipher.py | 2 +- .../binary_tree/non_recursive_segment_tree.py | 4 ++-- data_structures/hashing/hash_map.py | 4 ++-- data_structures/heap/heap.py | 4 ++-- data_structures/heap/randomized_heap.py | 6 +++--- data_structures/heap/skew_heap.py | 6 +++--- data_structures/linked_list/skip_list.py | 6 +++--- data_structures/queues/queue_by_list.py | 15 ++++++--------- data_structures/queues/queue_by_two_stacks.py | 15 ++++++--------- data_structures/stacks/stack.py | 4 ++-- .../stacks/stack_with_doubly_linked_list.py | 6 +++--- .../stacks/stack_with_singly_linked_list.py | 6 +++--- graphs/graph_adjacency_list.py | 4 ++-- graphs/graph_adjacency_matrix.py | 4 ++-- graphs/graph_list.py | 4 ++-- graphs/minimum_spanning_tree_kruskal2.py | 8 ++++---- graphs/minimum_spanning_tree_prims2.py | 8 ++++---- matrix/matrix_class.py | 4 ++-- other/least_recently_used.py | 4 ++-- other/lfu_cache.py | 8 ++++---- other/lru_cache.py | 8 ++++---- pyproject.toml | 3 +++ sorts/insertion_sort.py | 2 +- sorts/tim_sort.py | 2 +- 25 files changed, 69 insertions(+), 70 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 00f4bb4ef..81d6f4c70 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -443,6 +443,7 @@ * [Present Value](financial/present_value.py) * [Price Plus Tax](financial/price_plus_tax.py) * [Simple Moving Average](financial/simple_moving_average.py) + * [Straight Line Depreciation](financial/straight_line_depreciation.py) * [Time And Half Pay](financial/time_and_half_pay.py) ## Fractals @@ -790,6 +791,7 @@ * [Sumset](maths/sumset.py) * [Sylvester Sequence](maths/sylvester_sequence.py) * [Tanh](maths/tanh.py) + * [Test Factorial](maths/test_factorial.py) * [Test Prime Check](maths/test_prime_check.py) * [Three Sum](maths/three_sum.py) * [Trapezoidal Rule](maths/trapezoidal_rule.py) diff --git a/ciphers/hill_cipher.py b/ciphers/hill_cipher.py index 33b2529f0..19422688c 100644 --- a/ciphers/hill_cipher.py +++ b/ciphers/hill_cipher.py @@ -79,7 +79,7 @@ class HillCipher: >>> hill_cipher.replace_digits(26) '0' """ - return self.key_string[round(num)] + return self.key_string[(num)] def check_determinant(self) -> None: """ diff --git a/data_structures/binary_tree/non_recursive_segment_tree.py b/data_structures/binary_tree/non_recursive_segment_tree.py index ca0d5c111..7d1c965fa 100644 --- a/data_structures/binary_tree/non_recursive_segment_tree.py +++ b/data_structures/binary_tree/non_recursive_segment_tree.py @@ -39,12 +39,12 @@ https://www.geeksforgeeks.org/segment-tree-efficient-implementation/ from __future__ import annotations from collections.abc import Callable -from typing import Any, Generic, TypeVar +from typing import Any, TypeVar T = TypeVar("T") -class SegmentTree(Generic[T]): +class SegmentTree[T]: def __init__(self, arr: list[T], fnc: Callable[[T, T], T]) -> None: """ Segment Tree constructor, it works just with commutative combiner. diff --git a/data_structures/hashing/hash_map.py b/data_structures/hashing/hash_map.py index 8c56c327a..0d99e578b 100644 --- a/data_structures/hashing/hash_map.py +++ b/data_structures/hashing/hash_map.py @@ -10,14 +10,14 @@ https://www.youtube.com/watch?v=p33CVV29OG8 from collections.abc import Iterator, MutableMapping from dataclasses import dataclass -from typing import Generic, TypeVar +from typing import TypeVar KEY = TypeVar("KEY") VAL = TypeVar("VAL") @dataclass(slots=True) -class _Item(Generic[KEY, VAL]): +class _Item[KEY, VAL]: key: KEY val: VAL diff --git a/data_structures/heap/heap.py b/data_structures/heap/heap.py index 7b15e69f1..41ef0ddd1 100644 --- a/data_structures/heap/heap.py +++ b/data_structures/heap/heap.py @@ -2,7 +2,7 @@ from __future__ import annotations from abc import abstractmethod from collections.abc import Iterable -from typing import Generic, Protocol, TypeVar +from typing import Protocol, TypeVar class Comparable(Protocol): @@ -22,7 +22,7 @@ class Comparable(Protocol): T = TypeVar("T", bound=Comparable) -class Heap(Generic[T]): +class Heap[T: Comparable]: """A Max Heap Implementation >>> unsorted = [103, 9, 1, 7, 11, 15, 25, 201, 209, 107, 5] diff --git a/data_structures/heap/randomized_heap.py b/data_structures/heap/randomized_heap.py index 12888c1f4..9668d3ac2 100644 --- a/data_structures/heap/randomized_heap.py +++ b/data_structures/heap/randomized_heap.py @@ -4,12 +4,12 @@ from __future__ import annotations import random from collections.abc import Iterable -from typing import Any, Generic, TypeVar +from typing import Any, TypeVar T = TypeVar("T", bound=bool) -class RandomizedHeapNode(Generic[T]): +class RandomizedHeapNode[T: bool]: """ One node of the randomized heap. Contains the value and references to two children. @@ -73,7 +73,7 @@ class RandomizedHeapNode(Generic[T]): return root1 -class RandomizedHeap(Generic[T]): +class RandomizedHeap[T: bool]: """ A data structure that allows inserting a new value and to pop the smallest values. Both operations take O(logN) time where N is the size of the diff --git a/data_structures/heap/skew_heap.py b/data_structures/heap/skew_heap.py index 0839db711..4e8256944 100644 --- a/data_structures/heap/skew_heap.py +++ b/data_structures/heap/skew_heap.py @@ -3,12 +3,12 @@ from __future__ import annotations from collections.abc import Iterable, Iterator -from typing import Any, Generic, TypeVar +from typing import Any, TypeVar T = TypeVar("T", bound=bool) -class SkewNode(Generic[T]): +class SkewNode[T: bool]: """ One node of the skew heap. Contains the value and references to two children. @@ -87,7 +87,7 @@ class SkewNode(Generic[T]): return result -class SkewHeap(Generic[T]): +class SkewHeap[T: bool]: """ A data structure that allows inserting a new value and to pop the smallest values. Both operations take O(logN) time where N is the size of the diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index 13e9a94a8..f21ca70bb 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -7,13 +7,13 @@ from __future__ import annotations from itertools import pairwise from random import random -from typing import Generic, TypeVar +from typing import TypeVar KT = TypeVar("KT") VT = TypeVar("VT") -class Node(Generic[KT, VT]): +class Node[KT, VT]: def __init__(self, key: KT | str = "root", value: VT | None = None): self.key = key self.value = value @@ -49,7 +49,7 @@ class Node(Generic[KT, VT]): return len(self.forward) -class SkipList(Generic[KT, VT]): +class SkipList[KT, VT]: def __init__(self, p: float = 0.5, max_level: int = 16): self.head: Node[KT, VT] = Node[KT, VT]() self.level = 0 diff --git a/data_structures/queues/queue_by_list.py b/data_structures/queues/queue_by_list.py index 4b05be9fd..182cc4147 100644 --- a/data_structures/queues/queue_by_list.py +++ b/data_structures/queues/queue_by_list.py @@ -1,13 +1,10 @@ """Queue represented by a Python list""" from collections.abc import Iterable -from typing import Generic, TypeVar - -_T = TypeVar("_T") -class QueueByList(Generic[_T]): - def __init__(self, iterable: Iterable[_T] | None = None) -> None: +class QueueByList[T]: + def __init__(self, iterable: Iterable[T] | None = None) -> None: """ >>> QueueByList() Queue(()) @@ -16,7 +13,7 @@ class QueueByList(Generic[_T]): >>> QueueByList((i**2 for i in range(1, 4))) Queue((1, 4, 9)) """ - self.entries: list[_T] = list(iterable or []) + self.entries: list[T] = list(iterable or []) def __len__(self) -> int: """ @@ -58,7 +55,7 @@ class QueueByList(Generic[_T]): return f"Queue({tuple(self.entries)})" - def put(self, item: _T) -> None: + def put(self, item: T) -> None: """Put `item` to the Queue >>> queue = QueueByList() @@ -72,7 +69,7 @@ class QueueByList(Generic[_T]): self.entries.append(item) - def get(self) -> _T: + def get(self) -> T: """ Get `item` from the Queue @@ -118,7 +115,7 @@ class QueueByList(Generic[_T]): for _ in range(rotation): put(get(0)) - def get_front(self) -> _T: + def get_front(self) -> T: """Get the front item from the Queue >>> queue = QueueByList((10, 20, 30)) diff --git a/data_structures/queues/queue_by_two_stacks.py b/data_structures/queues/queue_by_two_stacks.py index cd62f155a..f9e302ffc 100644 --- a/data_structures/queues/queue_by_two_stacks.py +++ b/data_structures/queues/queue_by_two_stacks.py @@ -1,13 +1,10 @@ """Queue implementation using two stacks""" from collections.abc import Iterable -from typing import Generic, TypeVar - -_T = TypeVar("_T") -class QueueByTwoStacks(Generic[_T]): - def __init__(self, iterable: Iterable[_T] | None = None) -> None: +class QueueByTwoStacks[T]: + def __init__(self, iterable: Iterable[T] | None = None) -> None: """ >>> QueueByTwoStacks() Queue(()) @@ -16,8 +13,8 @@ class QueueByTwoStacks(Generic[_T]): >>> QueueByTwoStacks((i**2 for i in range(1, 4))) Queue((1, 4, 9)) """ - self._stack1: list[_T] = list(iterable or []) - self._stack2: list[_T] = [] + self._stack1: list[T] = list(iterable or []) + self._stack2: list[T] = [] def __len__(self) -> int: """ @@ -59,7 +56,7 @@ class QueueByTwoStacks(Generic[_T]): """ return f"Queue({tuple(self._stack2[::-1] + self._stack1)})" - def put(self, item: _T) -> None: + def put(self, item: T) -> None: """ Put `item` into the Queue @@ -74,7 +71,7 @@ class QueueByTwoStacks(Generic[_T]): self._stack1.append(item) - def get(self) -> _T: + def get(self) -> T: """ Get `item` from the Queue diff --git a/data_structures/stacks/stack.py b/data_structures/stacks/stack.py index 93698f5aa..3ffa32d41 100644 --- a/data_structures/stacks/stack.py +++ b/data_structures/stacks/stack.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") @@ -13,7 +13,7 @@ class StackUnderflowError(BaseException): pass -class Stack(Generic[T]): +class Stack[T]: """A stack is an abstract data type that serves as a collection of elements with two principal operations: push() and pop(). push() adds an element to the top of the stack, and pop() removes an element from the top diff --git a/data_structures/stacks/stack_with_doubly_linked_list.py b/data_structures/stacks/stack_with_doubly_linked_list.py index 50c5236e0..ad01cd7eb 100644 --- a/data_structures/stacks/stack_with_doubly_linked_list.py +++ b/data_structures/stacks/stack_with_doubly_linked_list.py @@ -3,19 +3,19 @@ from __future__ import annotations -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") -class Node(Generic[T]): +class Node[T]: def __init__(self, data: T): self.data = data # Assign data self.next: Node[T] | None = None # Initialize next as null self.prev: Node[T] | None = None # Initialize prev as null -class Stack(Generic[T]): +class Stack[T]: """ >>> stack = Stack() >>> stack.is_empty() diff --git a/data_structures/stacks/stack_with_singly_linked_list.py b/data_structures/stacks/stack_with_singly_linked_list.py index 8e77c2b96..57a68679e 100644 --- a/data_structures/stacks/stack_with_singly_linked_list.py +++ b/data_structures/stacks/stack_with_singly_linked_list.py @@ -3,12 +3,12 @@ from __future__ import annotations from collections.abc import Iterator -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") -class Node(Generic[T]): +class Node[T]: def __init__(self, data: T): self.data = data self.next: Node[T] | None = None @@ -17,7 +17,7 @@ class Node(Generic[T]): return f"{self.data}" -class LinkedStack(Generic[T]): +class LinkedStack[T]: """ Linked List Stack implementing push (to top), pop (from top) and is_empty diff --git a/graphs/graph_adjacency_list.py b/graphs/graph_adjacency_list.py index abc75311c..244e59e0e 100644 --- a/graphs/graph_adjacency_list.py +++ b/graphs/graph_adjacency_list.py @@ -21,14 +21,14 @@ from __future__ import annotations import random import unittest from pprint import pformat -from typing import Generic, TypeVar +from typing import TypeVar import pytest T = TypeVar("T") -class GraphAdjacencyList(Generic[T]): +class GraphAdjacencyList[T]: def __init__( self, vertices: list[T], edges: list[list[T]], directed: bool = True ) -> None: diff --git a/graphs/graph_adjacency_matrix.py b/graphs/graph_adjacency_matrix.py index 568c84166..8eeeae786 100644 --- a/graphs/graph_adjacency_matrix.py +++ b/graphs/graph_adjacency_matrix.py @@ -21,14 +21,14 @@ from __future__ import annotations import random import unittest from pprint import pformat -from typing import Generic, TypeVar +from typing import TypeVar import pytest T = TypeVar("T") -class GraphAdjacencyMatrix(Generic[T]): +class GraphAdjacencyMatrix[T]: def __init__( self, vertices: list[T], edges: list[list[T]], directed: bool = True ) -> None: diff --git a/graphs/graph_list.py b/graphs/graph_list.py index 6563cbb76..6b63590bf 100644 --- a/graphs/graph_list.py +++ b/graphs/graph_list.py @@ -6,12 +6,12 @@ from __future__ import annotations from pprint import pformat -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") -class GraphAdjacencyList(Generic[T]): +class GraphAdjacencyList[T]: """ Adjacency List type Graph Data Structure that accounts for directed and undirected Graphs. Initialize graph object indicating whether it's directed or undirected. diff --git a/graphs/minimum_spanning_tree_kruskal2.py b/graphs/minimum_spanning_tree_kruskal2.py index 0ddb43ce8..1f6d72556 100644 --- a/graphs/minimum_spanning_tree_kruskal2.py +++ b/graphs/minimum_spanning_tree_kruskal2.py @@ -1,11 +1,11 @@ from __future__ import annotations -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") -class DisjointSetTreeNode(Generic[T]): +class DisjointSetTreeNode[T]: # Disjoint Set Node to store the parent and rank def __init__(self, data: T) -> None: self.data = data @@ -13,7 +13,7 @@ class DisjointSetTreeNode(Generic[T]): self.rank = 0 -class DisjointSetTree(Generic[T]): +class DisjointSetTree[T]: # Disjoint Set DataStructure def __init__(self) -> None: # map from node name to the node object @@ -46,7 +46,7 @@ class DisjointSetTree(Generic[T]): self.link(self.find_set(data1), self.find_set(data2)) -class GraphUndirectedWeighted(Generic[T]): +class GraphUndirectedWeighted[T]: def __init__(self) -> None: # connections: map from the node to the neighbouring nodes (with weights) self.connections: dict[T, dict[T, int]] = {} diff --git a/graphs/minimum_spanning_tree_prims2.py b/graphs/minimum_spanning_tree_prims2.py index 6870cc80f..d22111289 100644 --- a/graphs/minimum_spanning_tree_prims2.py +++ b/graphs/minimum_spanning_tree_prims2.py @@ -10,7 +10,7 @@ connection from the tree to another vertex. from __future__ import annotations from sys import maxsize -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") @@ -47,7 +47,7 @@ def get_child_right_position(position: int) -> int: return (2 * position) + 2 -class MinPriorityQueue(Generic[T]): +class MinPriorityQueue[T]: """ Minimum Priority Queue Class @@ -184,7 +184,7 @@ class MinPriorityQueue(Generic[T]): self.position_map[node2_elem] = node1_pos -class GraphUndirectedWeighted(Generic[T]): +class GraphUndirectedWeighted[T]: """ Graph Undirected Weighted Class @@ -217,7 +217,7 @@ class GraphUndirectedWeighted(Generic[T]): self.connections[node2][node1] = weight -def prims_algo( +def prims_algo[T]( graph: GraphUndirectedWeighted[T], ) -> tuple[dict[T, int], dict[T, T | None]]: """ diff --git a/matrix/matrix_class.py b/matrix/matrix_class.py index a5940a38e..dee924728 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -260,7 +260,7 @@ class Matrix: if position is None: self.rows.append(row) else: - self.rows = self.rows[0:position] + [row] + self.rows[position:] + self.rows = [*self.rows[0:position], row, *self.rows[position:]] def add_column(self, column: list[int], position: int | None = None) -> None: type_error = TypeError( @@ -279,7 +279,7 @@ class Matrix: self.rows = [self.rows[i] + [column[i]] for i in range(self.num_rows)] else: self.rows = [ - self.rows[i][0:position] + [column[i]] + self.rows[i][position:] + [*self.rows[i][0:position], column[i], *self.rows[i][position:]] for i in range(self.num_rows) ] diff --git a/other/least_recently_used.py b/other/least_recently_used.py index cb692bb1b..d96960868 100644 --- a/other/least_recently_used.py +++ b/other/least_recently_used.py @@ -2,12 +2,12 @@ from __future__ import annotations import sys from collections import deque -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") -class LRUCache(Generic[T]): +class LRUCache[T]: """ Page Replacement Algorithm, Least Recently Used (LRU) Caching. diff --git a/other/lfu_cache.py b/other/lfu_cache.py index 5a143c739..6eaacff29 100644 --- a/other/lfu_cache.py +++ b/other/lfu_cache.py @@ -1,13 +1,13 @@ from __future__ import annotations from collections.abc import Callable -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") U = TypeVar("U") -class DoubleLinkedListNode(Generic[T, U]): +class DoubleLinkedListNode[T, U]: """ Double Linked List Node built specifically for LFU Cache @@ -30,7 +30,7 @@ class DoubleLinkedListNode(Generic[T, U]): ) -class DoubleLinkedList(Generic[T, U]): +class DoubleLinkedList[T, U]: """ Double Linked List built specifically for LFU Cache @@ -161,7 +161,7 @@ class DoubleLinkedList(Generic[T, U]): return node -class LFUCache(Generic[T, U]): +class LFUCache[T, U]: """ LFU Cache to store a given capacity of data. Can be used as a stand-alone object or as a function decorator. diff --git a/other/lru_cache.py b/other/lru_cache.py index 4f0c843c8..058b03b02 100644 --- a/other/lru_cache.py +++ b/other/lru_cache.py @@ -1,13 +1,13 @@ from __future__ import annotations from collections.abc import Callable -from typing import Generic, TypeVar +from typing import TypeVar T = TypeVar("T") U = TypeVar("U") -class DoubleLinkedListNode(Generic[T, U]): +class DoubleLinkedListNode[T, U]: """ Double Linked List Node built specifically for LRU Cache @@ -28,7 +28,7 @@ class DoubleLinkedListNode(Generic[T, U]): ) -class DoubleLinkedList(Generic[T, U]): +class DoubleLinkedList[T, U]: """ Double Linked List built specifically for LRU Cache @@ -143,7 +143,7 @@ class DoubleLinkedList(Generic[T, U]): return node -class LRUCache(Generic[T, U]): +class LRUCache[T, U]: """ LRU Cache to store a given capacity of data. Can be used as a stand-alone object or as a function decorator. diff --git a/pyproject.toml b/pyproject.toml index 2ead5cd51..b680cc0d4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -112,11 +112,14 @@ lint.ignore = [ "EXE001", # Shebang is present but file is not executable -- DO NOT FIX "G004", # Logging statement uses f-string "ISC001", # Conflicts with ruff format -- DO NOT FIX + "PLC0415", # import-outside-top-level -- DO NOT FIX "PLC1901", # `{}` can be simplified to `{}` as an empty string is falsey "PLW060", # Using global for `{name}` but no assignment is done -- DO NOT FIX + "PLW1641", # eq-without-hash "PLW2901", # PLW2901: Redefined loop variable -- FIX ME "PT011", # `pytest.raises(Exception)` is too broad, set the `match` parameter or use a more specific exception "PT018", # Assertion should be broken down into multiple parts + "PT028", # pytest-parameter-with-default-argument "S101", # Use of `assert` detected -- DO NOT FIX "S311", # Standard pseudo-random generators are not suitable for cryptographic purposes -- FIX ME "SIM905", # Consider using a list literal instead of `str.split` -- DO NOT FIX diff --git a/sorts/insertion_sort.py b/sorts/insertion_sort.py index 46b263d84..2e39be255 100644 --- a/sorts/insertion_sort.py +++ b/sorts/insertion_sort.py @@ -24,7 +24,7 @@ class Comparable(Protocol): T = TypeVar("T", bound=Comparable) -def insertion_sort(collection: MutableSequence[T]) -> MutableSequence[T]: +def insertion_sort[T: Comparable](collection: MutableSequence[T]) -> MutableSequence[T]: """A pure Python implementation of the insertion sort algorithm :param collection: some mutable ordered collection with heterogeneous diff --git a/sorts/tim_sort.py b/sorts/tim_sort.py index 138f11c71..41ab4a10a 100644 --- a/sorts/tim_sort.py +++ b/sorts/tim_sort.py @@ -19,7 +19,7 @@ def insertion_sort(lst): for index in range(1, length): value = lst[index] pos = binary_search(lst, value, 0, index - 1) - lst = lst[:pos] + [value] + lst[pos:index] + lst[index + 1 :] + lst = [*lst[:pos], value, *lst[pos:index], *lst[index + 1 :]] return lst