From 74b540ad73bd3b1187ed6e3c89bb8f309ef543fd Mon Sep 17 00:00:00 2001 From: Tony Dang <62843153+Dang-Hoang-Tung@users.noreply.github.com> Date: Sat, 29 Mar 2025 08:13:47 +0000 Subject: [PATCH 001/113] Genetic Algorithm: Fix bug in multi-threading (#12644) * Fix bug in multi-threading - Multi-threading (despite being commented out) had a tiny bug: missing target argument (2nd argument). - Commented out code was also slightly hard to understand, added (Option 1/2) in comments to clarify where a user may choose between 2 implementations. * Update basic_string.py --------- Co-authored-by: Maxim Smolskiy --- genetic_algorithm/basic_string.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index a906ce85a779..b75491d9a949 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -144,18 +144,18 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, # Random population created. Now it's time to evaluate. - # Adding a bit of concurrency can make everything faster, + # (Option 1) Adding a bit of concurrency can make everything faster, # # import concurrent.futures # population_score: list[tuple[str, float]] = [] # with concurrent.futures.ThreadPoolExecutor( # max_workers=NUM_WORKERS) as executor: - # futures = {executor.submit(evaluate, item) for item in population} + # futures = {executor.submit(evaluate, item, target) for item in population} # concurrent.futures.wait(futures) # population_score = [item.result() for item in futures] # # but with a simple algorithm like this, it will probably be slower. - # We just need to call evaluate for every item inside the population. + # (Option 2) We just need to call evaluate for every item inside the population. population_score = [evaluate(item, target) for item in population] # Check if there is a matching evolution. From f10a5cbfccc5ee9ddb5ddd9906591ecaad58f672 Mon Sep 17 00:00:00 2001 From: Isidro Date: Mon, 31 Mar 2025 23:09:14 +0200 Subject: [PATCH 002/113] prefix_evaluation: Add alternative recursive implementation (#12646) * prefix_evaluation: Add alternative recursive implementation * improve doc * better variable name calc->operators * Update prefix_evaluation.py * Update prefix_evaluation.py * Update prefix_evaluation.py * Update prefix_evaluation.py --------- Co-authored-by: Maxim Smolskiy --- data_structures/stacks/prefix_evaluation.py | 39 +++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/data_structures/stacks/prefix_evaluation.py b/data_structures/stacks/prefix_evaluation.py index f48eca23d7b5..03a70d884725 100644 --- a/data_structures/stacks/prefix_evaluation.py +++ b/data_structures/stacks/prefix_evaluation.py @@ -1,8 +1,9 @@ """ -Python3 program to evaluate a prefix expression. +Program to evaluate a prefix expression. +https://en.wikipedia.org/wiki/Polish_notation """ -calc = { +operators = { "+": lambda x, y: x + y, "-": lambda x, y: x - y, "*": lambda x, y: x * y, @@ -31,6 +32,10 @@ def evaluate(expression): 21 >>> evaluate("/ * 10 2 + 4 1 ") 4.0 + >>> evaluate("2") + 2 + >>> evaluate("+ * 2 3 / 8 4") + 8.0 """ stack = [] @@ -45,11 +50,39 @@ def evaluate(expression): # push the result onto the stack again o1 = stack.pop() o2 = stack.pop() - stack.append(calc[c](o1, o2)) + stack.append(operators[c](o1, o2)) return stack.pop() +def evaluate_recursive(expression: list[str]): + """ + Alternative recursive implementation + + >>> evaluate_recursive(['2']) + 2 + >>> expression = ['+', '*', '2', '3', '/', '8', '4'] + >>> evaluate_recursive(expression) + 8.0 + >>> expression + [] + >>> evaluate_recursive(['+', '9', '*', '2', '6']) + 21 + >>> evaluate_recursive(['/', '*', '10', '2', '+', '4', '1']) + 4.0 + """ + + op = expression.pop(0) + if is_operand(op): + return int(op) + + operation = operators[op] + + a = evaluate_recursive(expression) + b = evaluate_recursive(expression) + return operation(a, b) + + # Driver code if __name__ == "__main__": test_expression = "+ 9 * 2 6" From baab802965c37fa1740054a559cad8c119b2ee35 Mon Sep 17 00:00:00 2001 From: Isidro Date: Tue, 1 Apr 2025 20:55:14 +0200 Subject: [PATCH 003/113] doubly linked list: add dataclass and typing (#12647) * Node is a dataclass * fix mypy errors * LinkedList is a dataclass * fix mypy errors * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py --------- Co-authored-by: Maxim Smolskiy --- .../linked_list/doubly_linked_list_two.py | 62 +++++++++---------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/data_structures/linked_list/doubly_linked_list_two.py b/data_structures/linked_list/doubly_linked_list_two.py index e993cc5a20af..3d3bfb0cde30 100644 --- a/data_structures/linked_list/doubly_linked_list_two.py +++ b/data_structures/linked_list/doubly_linked_list_two.py @@ -9,25 +9,19 @@ Delete operation is more efficient """ +from dataclasses import dataclass +from typing import Self + +@dataclass class Node: - def __init__(self, data: int, previous=None, next_node=None): - self.data = data - self.previous = previous - self.next = next_node + data: int + previous: Self | None = None + next: Self | None = None def __str__(self) -> str: return f"{self.data}" - def get_data(self) -> int: - return self.data - - def get_next(self): - return self.next - - def get_previous(self): - return self.previous - class LinkedListIterator: def __init__(self, head): @@ -40,30 +34,30 @@ def __next__(self): if not self.current: raise StopIteration else: - value = self.current.get_data() - self.current = self.current.get_next() + value = self.current.data + self.current = self.current.next return value +@dataclass class LinkedList: - def __init__(self): - self.head = None # First node in list - self.tail = None # Last node in list + head: Node | None = None # First node in list + tail: Node | None = None # Last node in list def __str__(self): current = self.head nodes = [] while current is not None: - nodes.append(current.get_data()) - current = current.get_next() + nodes.append(current.data) + current = current.next return " ".join(str(node) for node in nodes) def __contains__(self, value: int): current = self.head while current: - if current.get_data() == value: + if current.data == value: return True - current = current.get_next() + current = current.next return False def __iter__(self): @@ -71,12 +65,12 @@ def __iter__(self): def get_head_data(self): if self.head: - return self.head.get_data() + return self.head.data return None def get_tail_data(self): if self.tail: - return self.tail.get_data() + return self.tail.data return None def set_head(self, node: Node) -> None: @@ -103,18 +97,20 @@ def insert_before_node(self, node: Node, node_to_insert: Node) -> None: node_to_insert.next = node node_to_insert.previous = node.previous - if node.get_previous() is None: + if node.previous is None: self.head = node_to_insert else: node.previous.next = node_to_insert node.previous = node_to_insert - def insert_after_node(self, node: Node, node_to_insert: Node) -> None: + def insert_after_node(self, node: Node | None, node_to_insert: Node) -> None: + assert node is not None + node_to_insert.previous = node node_to_insert.next = node.next - if node.get_next() is None: + if node.next is None: self.tail = node_to_insert else: node.next.previous = node_to_insert @@ -136,27 +132,27 @@ def insert_at_position(self, position: int, value: int) -> None: def get_node(self, item: int) -> Node: node = self.head while node: - if node.get_data() == item: + if node.data == item: return node - node = node.get_next() + node = node.next raise Exception("Node not found") def delete_value(self, value): if (node := self.get_node(value)) is not None: if node == self.head: - self.head = self.head.get_next() + self.head = self.head.next if node == self.tail: - self.tail = self.tail.get_previous() + self.tail = self.tail.previous self.remove_node_pointers(node) @staticmethod def remove_node_pointers(node: Node) -> None: - if node.get_next(): + if node.next: node.next.previous = node.previous - if node.get_previous(): + if node.previous: node.previous.next = node.next node.next = None From 0c8cf8e9871a5f91182d767adf173dccf87c2c0f Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Wed, 2 Apr 2025 10:23:55 +0300 Subject: [PATCH 004/113] Fix bug for data_structures/linked_list/doubly_linked_list_two.py (#12651) * Fix bug for data_structures/linked_list/doubly_linked_list_two.py * Fix * Fix * Fix * Fix * Fix * Fix * Fix * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py --- .../linked_list/doubly_linked_list_two.py | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/data_structures/linked_list/doubly_linked_list_two.py b/data_structures/linked_list/doubly_linked_list_two.py index 3d3bfb0cde30..8c93cddd5d31 100644 --- a/data_structures/linked_list/doubly_linked_list_two.py +++ b/data_structures/linked_list/doubly_linked_list_two.py @@ -81,8 +81,9 @@ def set_head(self, node: Node) -> None: self.insert_before_node(self.head, node) def set_tail(self, node: Node) -> None: - if self.head is None: - self.set_head(node) + if self.tail is None: + self.head = node + self.tail = node else: self.insert_after_node(self.tail, node) @@ -104,9 +105,7 @@ def insert_before_node(self, node: Node, node_to_insert: Node) -> None: node.previous = node_to_insert - def insert_after_node(self, node: Node | None, node_to_insert: Node) -> None: - assert node is not None - + def insert_after_node(self, node: Node, node_to_insert: Node) -> None: node_to_insert.previous = node node_to_insert.next = node.next @@ -127,7 +126,7 @@ def insert_at_position(self, position: int, value: int) -> None: return current_position += 1 node = node.next - self.insert_after_node(self.tail, new_node) + self.set_tail(new_node) def get_node(self, item: int) -> Node: node = self.head @@ -237,6 +236,22 @@ def create_linked_list() -> None: 7 8 9 + >>> linked_list = LinkedList() + >>> linked_list.insert_at_position(position=1, value=10) + >>> str(linked_list) + '10' + >>> linked_list.insert_at_position(position=2, value=20) + >>> str(linked_list) + '10 20' + >>> linked_list.insert_at_position(position=1, value=30) + >>> str(linked_list) + '30 10 20' + >>> linked_list.insert_at_position(position=3, value=40) + >>> str(linked_list) + '30 10 40 20' + >>> linked_list.insert_at_position(position=5, value=50) + >>> str(linked_list) + '30 10 40 20 50' """ From 5afe02994eb0aafb0b462fec32fe5f6ecedf7305 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 23:20:19 +0200 Subject: [PATCH 005/113] [pre-commit.ci] pre-commit autoupdate (#12661) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.2 → v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.2...v0.11.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0fc8b2b14e07..20065c433062 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.2 + rev: v0.11.4 hooks: - id: ruff - id: ruff-format From a4576dc2a42cbfc7585a7ce6f28917cb97f83c45 Mon Sep 17 00:00:00 2001 From: Kim Date: Wed, 9 Apr 2025 15:24:37 +0900 Subject: [PATCH 006/113] fix: correct typo "util" to "until" (#12653) --- dynamic_programming/bitmask.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dynamic_programming/bitmask.py b/dynamic_programming/bitmask.py index a6e6a0cda7bf..4737a3419e8e 100644 --- a/dynamic_programming/bitmask.py +++ b/dynamic_programming/bitmask.py @@ -42,7 +42,7 @@ def count_ways_until(self, mask, task_no): return self.dp[mask][task_no] # Number of ways when we don't this task in the arrangement - total_ways_util = self.count_ways_until(mask, task_no + 1) + total_ways_until = self.count_ways_until(mask, task_no + 1) # now assign the tasks one by one to all possible persons and recursively # assign for the remaining tasks. @@ -54,10 +54,10 @@ def count_ways_until(self, mask, task_no): # assign this task to p and change the mask value. And recursively # assign tasks with the new mask value. - total_ways_util += self.count_ways_until(mask | (1 << p), task_no + 1) + total_ways_until += self.count_ways_until(mask | (1 << p), task_no + 1) # save the value. - self.dp[mask][task_no] = total_ways_util + self.dp[mask][task_no] = total_ways_until return self.dp[mask][task_no] From 4ed61418a8fef5a0fe3c5a05a49c7cbc5ac8298c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 19:55:55 +0200 Subject: [PATCH 007/113] [pre-commit.ci] pre-commit autoupdate (#12671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.4 → v0.11.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.4...v0.11.5) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 20065c433062..8a8697ca778a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.4 + rev: v0.11.5 hooks: - id: ruff - id: ruff-format From cc621f1fddac7391389270d7bc38326507b4b495 Mon Sep 17 00:00:00 2001 From: parth-6945 <140963864+parth-6945@users.noreply.github.com> Date: Mon, 14 Apr 2025 23:31:29 +0530 Subject: [PATCH 008/113] Add find_unique_number algorithm to bit manipulation (#12654) * Add find_unique_number algorithm to bit manipulation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- bit_manipulation/find_unique_number.py | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 bit_manipulation/find_unique_number.py diff --git a/bit_manipulation/find_unique_number.py b/bit_manipulation/find_unique_number.py new file mode 100644 index 000000000000..77970b4865d1 --- /dev/null +++ b/bit_manipulation/find_unique_number.py @@ -0,0 +1,37 @@ +def find_unique_number(arr: list[int]) -> int: + """ + Given a list of integers where every element appears twice except for one, + this function returns the element that appears only once using bitwise XOR. + + >>> find_unique_number([1, 1, 2, 2, 3]) + 3 + >>> find_unique_number([4, 5, 4, 6, 6]) + 5 + >>> find_unique_number([7]) + 7 + >>> find_unique_number([10, 20, 10]) + 20 + >>> find_unique_number([]) + Traceback (most recent call last): + ... + ValueError: input list must not be empty + >>> find_unique_number([1, 'a', 1]) + Traceback (most recent call last): + ... + TypeError: all elements must be integers + """ + if not arr: + raise ValueError("input list must not be empty") + if not all(isinstance(x, int) for x in arr): + raise TypeError("all elements must be integers") + + result = 0 + for num in arr: + result ^= num + return result + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From d123cbc649e0777717b02dc74b4466872941a8d5 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Tue, 15 Apr 2025 02:30:25 +0800 Subject: [PATCH 009/113] Solution for the Euler Project Problem 122 (#12655) * Add initial version for euler project problem 122. * Add doctests and documentation for the project euler problem 122. * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py --------- Co-authored-by: Maxim Smolskiy --- project_euler/problem_122/__init__.py | 0 project_euler/problem_122/sol1.py | 89 +++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 project_euler/problem_122/__init__.py create mode 100644 project_euler/problem_122/sol1.py diff --git a/project_euler/problem_122/__init__.py b/project_euler/problem_122/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/project_euler/problem_122/sol1.py b/project_euler/problem_122/sol1.py new file mode 100644 index 000000000000..cd8b1e67708c --- /dev/null +++ b/project_euler/problem_122/sol1.py @@ -0,0 +1,89 @@ +""" +Project Euler Problem 122: https://projecteuler.net/problem=122 + +Efficient Exponentiation + +The most naive way of computing n^15 requires fourteen multiplications: + + n x n x ... x n = n^15. + +But using a "binary" method you can compute it in six multiplications: + + n x n = n^2 + n^2 x n^2 = n^4 + n^4 x n^4 = n^8 + n^8 x n^4 = n^12 + n^12 x n^2 = n^14 + n^14 x n = n^15 + +However it is yet possible to compute it in only five multiplications: + + n x n = n^2 + n^2 x n = n^3 + n^3 x n^3 = n^6 + n^6 x n^6 = n^12 + n^12 x n^3 = n^15 + +We shall define m(k) to be the minimum number of multiplications to compute n^k; +for example m(15) = 5. + +Find sum_{k = 1}^200 m(k). + +It uses the fact that for rather small n, applicable for this problem, the solution +for each number can be formed by increasing the largest element. + +References: +- https://en.wikipedia.org/wiki/Addition_chain +""" + + +def solve(nums: list[int], goal: int, depth: int) -> bool: + """ + Checks if nums can have a sum equal to goal, given that length of nums does + not exceed depth. + + >>> solve([1], 2, 2) + True + >>> solve([1], 2, 0) + False + """ + if len(nums) > depth: + return False + for el in nums: + if el + nums[-1] == goal: + return True + nums.append(el + nums[-1]) + if solve(nums=nums, goal=goal, depth=depth): + return True + del nums[-1] + return False + + +def solution(n: int = 200) -> int: + """ + Calculates sum of smallest number of multiplactions for each number up to + and including n. + + >>> solution(1) + 0 + >>> solution(2) + 1 + >>> solution(14) + 45 + >>> solution(15) + 50 + """ + total = 0 + for i in range(2, n + 1): + max_length = 0 + while True: + nums = [1] + max_length += 1 + if solve(nums=nums, goal=i, depth=max_length): + break + total += max_length + return total + + +if __name__ == "__main__": + print(f"{solution() = }") From 42820634f3795e7d7397ad2e688d091a79c1eb83 Mon Sep 17 00:00:00 2001 From: Naitik Dwivedi Date: Tue, 15 Apr 2025 00:27:13 +0530 Subject: [PATCH 010/113] Add matrix inversion algorithm using NumPy (#12657) * Create matrix_inversion.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update matrix_inversion.py * Update matrix_inversion.py * Update matrix_inversion.py * Update matrix_inversion.py * Update matrix_inversion.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- linear_algebra/matrix_inversion.py | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 linear_algebra/matrix_inversion.py diff --git a/linear_algebra/matrix_inversion.py b/linear_algebra/matrix_inversion.py new file mode 100644 index 000000000000..50dae1c2e825 --- /dev/null +++ b/linear_algebra/matrix_inversion.py @@ -0,0 +1,36 @@ +import numpy as np + + +def invert_matrix(matrix: list[list[float]]) -> list[list[float]]: + """ + Returns the inverse of a square matrix using NumPy. + + Parameters: + matrix (list[list[float]]): A square matrix. + + Returns: + list[list[float]]: Inverted matrix if invertible, else raises error. + + >>> invert_matrix([[4.0, 7.0], [2.0, 6.0]]) + [[0.6000000000000001, -0.7000000000000001], [-0.2, 0.4]] + >>> invert_matrix([[1.0, 2.0], [0.0, 0.0]]) + Traceback (most recent call last): + ... + ValueError: Matrix is not invertible + """ + np_matrix = np.array(matrix) + + try: + inv_matrix = np.linalg.inv(np_matrix) + except np.linalg.LinAlgError: + raise ValueError("Matrix is not invertible") + + return inv_matrix.tolist() + + +if __name__ == "__main__": + mat = [[4.0, 7.0], [2.0, 6.0]] + print("Original Matrix:") + print(mat) + print("Inverted Matrix:") + print(invert_matrix(mat)) From c585cb122718e219870ea7a2af110939b55e52f9 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Fri, 18 Apr 2025 07:16:15 +0800 Subject: [PATCH 011/113] Solution for the Euler Project problem 136 (#12658) * Add initial version of file for the Euler project problem 136 solution. * Add documentation and tests for the Euler project problem 136 solution. * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- project_euler/problem_136/__init__.py | 0 project_euler/problem_136/sol1.py | 63 +++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 project_euler/problem_136/__init__.py create mode 100644 project_euler/problem_136/sol1.py diff --git a/project_euler/problem_136/__init__.py b/project_euler/problem_136/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/project_euler/problem_136/sol1.py b/project_euler/problem_136/sol1.py new file mode 100644 index 000000000000..688a9a5d7f24 --- /dev/null +++ b/project_euler/problem_136/sol1.py @@ -0,0 +1,63 @@ +""" +Project Euler Problem 136: https://projecteuler.net/problem=136 + +Singleton Difference + +The positive integers, x, y, and z, are consecutive terms of an arithmetic progression. +Given that n is a positive integer, the equation, x^2 - y^2 - z^2 = n, +has exactly one solution when n = 20: + 13^2 - 10^2 - 7^2 = 20. + +In fact there are twenty-five values of n below one hundred for which +the equation has a unique solution. + +How many values of n less than fifty million have exactly one solution? + +By change of variables + +x = y + delta +z = y - delta + +The expression can be rewritten: + +x^2 - y^2 - z^2 = y * (4 * delta - y) = n + +The algorithm loops over delta and y, which is restricted in upper and lower limits, +to count how many solutions each n has. +In the end it is counted how many n's have one solution. +""" + + +def solution(n_limit: int = 50 * 10**6) -> int: + """ + Define n count list and loop over delta, y to get the counts, then check + which n has count == 1. + + >>> solution(3) + 0 + >>> solution(10) + 3 + >>> solution(100) + 25 + >>> solution(110) + 27 + """ + n_sol = [0] * n_limit + + for delta in range(1, (n_limit + 1) // 4 + 1): + for y in range(4 * delta - 1, delta, -1): + n = y * (4 * delta - y) + if n >= n_limit: + break + n_sol[n] += 1 + + ans = 0 + for i in range(n_limit): + if n_sol[i] == 1: + ans += 1 + + return ans + + +if __name__ == "__main__": + print(f"{solution() = }") From a1aa6313e08657f0e9ae337afa81d6b6f95357c9 Mon Sep 17 00:00:00 2001 From: Samuel Willis <109305646+konsoleSam@users.noreply.github.com> Date: Thu, 17 Apr 2025 17:33:08 -0600 Subject: [PATCH 012/113] Adding time and a half pay calculator algorithm to financial folder (#12662) * Create time&half-pay.py * Update time&half-pay.py * Update time&half-pay.py * Rename time&half-pay.py to time_and_half_pay.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update time_and_half_pay.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update time_and_half_pay.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update time_and_half_pay.py * Update time_and_half_pay.py * Update time_and_half_pay.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- financial/time_and_half_pay.py | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 financial/time_and_half_pay.py diff --git a/financial/time_and_half_pay.py b/financial/time_and_half_pay.py new file mode 100644 index 000000000000..c5dff1bc1ce1 --- /dev/null +++ b/financial/time_and_half_pay.py @@ -0,0 +1,40 @@ +""" +Calculate time and a half pay +""" + + +def pay(hours_worked: float, pay_rate: float, hours: float = 40) -> float: + """ + hours_worked = The total hours worked + pay_rate = Amount of money per hour + hours = Number of hours that must be worked before you receive time and a half + + >>> pay(41, 1) + 41.5 + >>> pay(65, 19) + 1472.5 + >>> pay(10, 1) + 10.0 + """ + # Check that all input parameters are float or integer + assert isinstance(hours_worked, (float, int)), ( + "Parameter 'hours_worked' must be of type 'int' or 'float'" + ) + assert isinstance(pay_rate, (float, int)), ( + "Parameter 'pay_rate' must be of type 'int' or 'float'" + ) + assert isinstance(hours, (float, int)), ( + "Parameter 'hours' must be of type 'int' or 'float'" + ) + + normal_pay = hours_worked * pay_rate + over_time = max(0, hours_worked - hours) + over_time_pay = over_time * pay_rate / 2 + return normal_pay + over_time_pay + + +if __name__ == "__main__": + # Test + import doctest + + doctest.testmod() From 9891d2bc3051ab4242ed041ea30edd10b94925bd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Apr 2025 19:54:11 +0200 Subject: [PATCH 013/113] [pre-commit.ci] pre-commit autoupdate (#12680) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.5 → v0.11.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.5...v0.11.6) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] --- .pre-commit-config.yaml | 2 +- DIRECTORY.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8a8697ca778a..8474deebb7ba 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.5 + rev: v0.11.6 hooks: - id: ruff - id: ruff-format diff --git a/DIRECTORY.md b/DIRECTORY.md index 1c02c191bd14..fa731e32ff23 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -40,6 +40,7 @@ * [Count Number Of One Bits](bit_manipulation/count_number_of_one_bits.py) * [Excess 3 Code](bit_manipulation/excess_3_code.py) * [Find Previous Power Of Two](bit_manipulation/find_previous_power_of_two.py) + * [Find Unique Number](bit_manipulation/find_unique_number.py) * [Gray Code Sequence](bit_manipulation/gray_code_sequence.py) * [Highest Set Bit](bit_manipulation/highest_set_bit.py) * [Index Of Rightmost Set Bit](bit_manipulation/index_of_rightmost_set_bit.py) @@ -442,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) + * [Time And Half Pay](financial/time_and_half_pay.py) ## Fractals * [Julia Sets](fractals/julia_sets.py) @@ -570,6 +572,7 @@ * [Gaussian Elimination](linear_algebra/gaussian_elimination.py) * [Jacobi Iteration Method](linear_algebra/jacobi_iteration_method.py) * [Lu Decomposition](linear_algebra/lu_decomposition.py) + * [Matrix Inversion](linear_algebra/matrix_inversion.py) * Src * [Conjugate Gradient](linear_algebra/src/conjugate_gradient.py) * [Gaussian Elimination Pivoting](linear_algebra/src/gaussian_elimination_pivoting.py) @@ -1153,6 +1156,8 @@ * [Sol1](project_euler/problem_120/sol1.py) * Problem 121 * [Sol1](project_euler/problem_121/sol1.py) + * Problem 122 + * [Sol1](project_euler/problem_122/sol1.py) * Problem 123 * [Sol1](project_euler/problem_123/sol1.py) * Problem 125 @@ -1163,6 +1168,8 @@ * [Sol1](project_euler/problem_131/sol1.py) * Problem 135 * [Sol1](project_euler/problem_135/sol1.py) + * Problem 136 + * [Sol1](project_euler/problem_136/sol1.py) * Problem 144 * [Sol1](project_euler/problem_144/sol1.py) * Problem 145 From 11a61d15dc3aebc69f153adca8568076a25f7110 Mon Sep 17 00:00:00 2001 From: Isidro Date: Mon, 21 Apr 2025 21:04:39 +0200 Subject: [PATCH 014/113] Generic type hint in DDL (#12677) * Generic type hint in DDL Instead of forcing int * Update doubly_linked_list_two.py * Update doubly_linked_list_two.py --------- Co-authored-by: Maxim Smolskiy --- .../linked_list/doubly_linked_list_two.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/data_structures/linked_list/doubly_linked_list_two.py b/data_structures/linked_list/doubly_linked_list_two.py index 8c93cddd5d31..a7f639a6e289 100644 --- a/data_structures/linked_list/doubly_linked_list_two.py +++ b/data_structures/linked_list/doubly_linked_list_two.py @@ -10,12 +10,14 @@ """ from dataclasses import dataclass -from typing import Self +from typing import Self, TypeVar + +DataType = TypeVar("DataType") @dataclass -class Node: - data: int +class Node[DataType]: + data: DataType previous: Self | None = None next: Self | None = None @@ -52,7 +54,7 @@ def __str__(self): current = current.next return " ".join(str(node) for node in nodes) - def __contains__(self, value: int): + def __contains__(self, value: DataType): current = self.head while current: if current.data == value: @@ -87,7 +89,7 @@ def set_tail(self, node: Node) -> None: else: self.insert_after_node(self.tail, node) - def insert(self, value: int) -> None: + def insert(self, value: DataType) -> None: node = Node(value) if self.head is None: self.set_head(node) @@ -116,7 +118,7 @@ def insert_after_node(self, node: Node, node_to_insert: Node) -> None: node.next = node_to_insert - def insert_at_position(self, position: int, value: int) -> None: + def insert_at_position(self, position: int, value: DataType) -> None: current_position = 1 new_node = Node(value) node = self.head @@ -128,7 +130,7 @@ def insert_at_position(self, position: int, value: int) -> None: node = node.next self.set_tail(new_node) - def get_node(self, item: int) -> Node: + def get_node(self, item: DataType) -> Node: node = self.head while node: if node.data == item: From 29afed0df65fd84f53ad697ff1dbfc86c6e83631 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Apr 2025 08:30:42 +0200 Subject: [PATCH 015/113] Bump astral-sh/setup-uv from 5 to 6 (#12683) * Bump astral-sh/setup-uv from 5 to 6 Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5 to 6. - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/v5...v6) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * uv run pytest --ignore=web_programming/fetch_anime_and_play.py --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .github/workflows/build.yml | 3 ++- .github/workflows/project_euler.yml | 4 ++-- .github/workflows/ruff.yml | 2 +- .github/workflows/sphinx.yml | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 62829b2b45a5..8b83cb41c79a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@v6 with: enable-cache: true cache-dependency-glob: uv.lock @@ -30,6 +30,7 @@ jobs: --ignore=project_euler/ --ignore=quantum/q_fourier_transform.py --ignore=scripts/validate_solutions.py + --ignore=web_programming/fetch_anime_and_play.py --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} diff --git a/.github/workflows/project_euler.yml b/.github/workflows/project_euler.yml index 8d51ad8850cf..eaf4150e4eaa 100644 --- a/.github/workflows/project_euler.yml +++ b/.github/workflows/project_euler.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v5 with: python-version: 3.x @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v5 with: python-version: 3.x diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml index cfe127b3521f..ec9f0202bd7e 100644 --- a/.github/workflows/ruff.yml +++ b/.github/workflows/ruff.yml @@ -12,5 +12,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@v6 - run: uvx ruff check --output-format=github . diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index 16ff284a74f2..2010041d80c5 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-24.04-arm steps: - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v5 with: python-version: 3.13 From 0a3a96534767c37a0f1561d0f5148b5d1d5e0272 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 19:55:57 +0200 Subject: [PATCH 016/113] [pre-commit.ci] pre-commit autoupdate (#12692) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.6 → v0.11.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.6...v0.11.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8474deebb7ba..034493b10912 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.6 + rev: v0.11.7 hooks: - id: ruff - id: ruff-format From 145879b8b2546c74fc51446ac607823876a0f601 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Mon, 5 May 2025 15:00:32 +0800 Subject: [PATCH 017/113] Add solution for the Euler project problem 164. (#12663) * Add solution for the Euler project problem 164. * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- project_euler/problem_164/__init__.py | 0 project_euler/problem_164/sol1.py | 65 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 project_euler/problem_164/__init__.py create mode 100644 project_euler/problem_164/sol1.py diff --git a/project_euler/problem_164/__init__.py b/project_euler/problem_164/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/project_euler/problem_164/sol1.py b/project_euler/problem_164/sol1.py new file mode 100644 index 000000000000..5387c89bd757 --- /dev/null +++ b/project_euler/problem_164/sol1.py @@ -0,0 +1,65 @@ +""" +Project Euler Problem 164: https://projecteuler.net/problem=164 + +Three Consecutive Digital Sum Limit + +How many 20 digit numbers n (without any leading zero) exist such that no three +consecutive digits of n have a sum greater than 9? + +Brute-force recursive solution with caching of intermediate results. +""" + + +def solve( + digit: int, prev1: int, prev2: int, sum_max: int, first: bool, cache: dict[str, int] +) -> int: + """ + Solve for remaining 'digit' digits, with previous 'prev1' digit, and + previous-previous 'prev2' digit, total sum of 'sum_max'. + Pass around 'cache' to store/reuse intermediate results. + + >>> solve(digit=1, prev1=0, prev2=0, sum_max=9, first=True, cache={}) + 9 + >>> solve(digit=1, prev1=0, prev2=0, sum_max=9, first=False, cache={}) + 10 + """ + if digit == 0: + return 1 + + cache_str = f"{digit},{prev1},{prev2}" + if cache_str in cache: + return cache[cache_str] + + comb = 0 + for curr in range(sum_max - prev1 - prev2 + 1): + if first and curr == 0: + continue + + comb += solve( + digit=digit - 1, + prev1=curr, + prev2=prev1, + sum_max=sum_max, + first=False, + cache=cache, + ) + + cache[cache_str] = comb + return comb + + +def solution(n_digits: int = 20) -> int: + """ + Solves the problem for n_digits number of digits. + + >>> solution(2) + 45 + >>> solution(10) + 21838806 + """ + cache: dict[str, int] = {} + return solve(digit=n_digits, prev1=0, prev2=0, sum_max=9, first=True, cache=cache) + + +if __name__ == "__main__": + print(f"{solution(10) = }") From 40f4c510b6047d95d07f03c9915a53bbf84789e4 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Mon, 5 May 2025 15:14:56 +0800 Subject: [PATCH 018/113] Add solution for the Euler problem 190 (#12664) * Add solution for the Euler project problem 164. * Add solution for the Euler project problem 190. * Delete project_euler/problem_164/sol1.py * Delete project_euler/problem_164/__init__.py * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- project_euler/problem_190/__init__.py | 0 project_euler/problem_190/sol1.py | 48 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 project_euler/problem_190/__init__.py create mode 100644 project_euler/problem_190/sol1.py diff --git a/project_euler/problem_190/__init__.py b/project_euler/problem_190/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/project_euler/problem_190/sol1.py b/project_euler/problem_190/sol1.py new file mode 100644 index 000000000000..b18d45be16b4 --- /dev/null +++ b/project_euler/problem_190/sol1.py @@ -0,0 +1,48 @@ +""" +Project Euler Problem 190: https://projecteuler.net/problem=190 + +Maximising a Weighted Product + +Let S_m = (x_1, x_2, ..., x_m) be the m-tuple of positive real numbers with +x_1 + x_2 + ... + x_m = m for which P_m = x_1 * x_2^2 * ... * x_m^m is maximised. + +For example, it can be verified that |_ P_10 _| = 4112 +(|_ _| is the integer part function). + +Find Sum_{m=2}^15 = |_ P_m _|. + +Solution: +- Fix x_1 = m - x_2 - ... - x_m. +- Calculate partial derivatives of P_m wrt the x_2, ..., x_m. This gives that + x_2 = 2 * x_1, x_3 = 3 * x_1, ..., x_m = m * x_1. +- Calculate partial second order derivatives of P_m wrt the x_2, ..., x_m. + By plugging in the values from the previous step, can verify that solution is maximum. +""" + + +def solution(n: int = 15) -> int: + """ + Calculate sum of |_ P_m _| for m from 2 to n. + + >>> solution(2) + 1 + >>> solution(3) + 2 + >>> solution(4) + 4 + >>> solution(5) + 10 + """ + total = 0 + for m in range(2, n + 1): + x1 = 2 / (m + 1) + p = 1.0 + for i in range(1, m + 1): + xi = i * x1 + p *= xi**i + total += int(p) + return total + + +if __name__ == "__main__": + print(f"{solution() = }") From 7ed7f042feeb3567ace384a00707d83c327310ab Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 19:23:31 +0100 Subject: [PATCH 019/113] [pre-commit.ci] pre-commit autoupdate (#12708) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.7 → v0.11.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.7...v0.11.8) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] --- .pre-commit-config.yaml | 2 +- DIRECTORY.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 034493b10912..9e13416dc78d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.7 + rev: v0.11.8 hooks: - id: ruff - id: ruff-format diff --git a/DIRECTORY.md b/DIRECTORY.md index fa731e32ff23..04e09c29de97 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1174,6 +1174,8 @@ * [Sol1](project_euler/problem_144/sol1.py) * Problem 145 * [Sol1](project_euler/problem_145/sol1.py) + * Problem 164 + * [Sol1](project_euler/problem_164/sol1.py) * Problem 173 * [Sol1](project_euler/problem_173/sol1.py) * Problem 174 @@ -1184,6 +1186,8 @@ * [Sol1](project_euler/problem_187/sol1.py) * Problem 188 * [Sol1](project_euler/problem_188/sol1.py) + * Problem 190 + * [Sol1](project_euler/problem_190/sol1.py) * Problem 191 * [Sol1](project_euler/problem_191/sol1.py) * Problem 203 From d9d56b10464f6825dc762c1665716e76b70c5fa2 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Wed, 7 May 2025 03:49:59 +0800 Subject: [PATCH 020/113] Add solution for the Euler project problem 345 (#12666) * Add solution for the Euler project problem 345. * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- project_euler/problem_345/__init__.py | 0 project_euler/problem_345/sol1.py | 117 ++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 project_euler/problem_345/__init__.py create mode 100644 project_euler/problem_345/sol1.py diff --git a/project_euler/problem_345/__init__.py b/project_euler/problem_345/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/project_euler/problem_345/sol1.py b/project_euler/problem_345/sol1.py new file mode 100644 index 000000000000..4234458c5ad5 --- /dev/null +++ b/project_euler/problem_345/sol1.py @@ -0,0 +1,117 @@ +""" +Project Euler Problem 345: https://projecteuler.net/problem=345 + +Matrix Sum + +We define the Matrix Sum of a matrix as the maximum possible sum of +matrix elements such that none of the selected elements share the same row or column. + +For example, the Matrix Sum of the matrix below equals +3315 ( = 863 + 383 + 343 + 959 + 767): + 7 53 183 439 863 + 497 383 563 79 973 + 287 63 343 169 583 + 627 343 773 959 943 + 767 473 103 699 303 + +Find the Matrix Sum of: + 7 53 183 439 863 497 383 563 79 973 287 63 343 169 583 + 627 343 773 959 943 767 473 103 699 303 957 703 583 639 913 + 447 283 463 29 23 487 463 993 119 883 327 493 423 159 743 + 217 623 3 399 853 407 103 983 89 463 290 516 212 462 350 + 960 376 682 962 300 780 486 502 912 800 250 346 172 812 350 + 870 456 192 162 593 473 915 45 989 873 823 965 425 329 803 + 973 965 905 919 133 673 665 235 509 613 673 815 165 992 326 + 322 148 972 962 286 255 941 541 265 323 925 281 601 95 973 + 445 721 11 525 473 65 511 164 138 672 18 428 154 448 848 + 414 456 310 312 798 104 566 520 302 248 694 976 430 392 198 + 184 829 373 181 631 101 969 613 840 740 778 458 284 760 390 + 821 461 843 513 17 901 711 993 293 157 274 94 192 156 574 + 34 124 4 878 450 476 712 914 838 669 875 299 823 329 699 + 815 559 813 459 522 788 168 586 966 232 308 833 251 631 107 + 813 883 451 509 615 77 281 613 459 205 380 274 302 35 805 + +Brute force solution, with caching intermediate steps to speed up the calculation. +""" + +import numpy as np +from numpy.typing import NDArray + +MATRIX_1 = [ + "7 53 183 439 863", + "497 383 563 79 973", + "287 63 343 169 583", + "627 343 773 959 943", + "767 473 103 699 303", +] + +MATRIX_2 = [ + "7 53 183 439 863 497 383 563 79 973 287 63 343 169 583", + "627 343 773 959 943 767 473 103 699 303 957 703 583 639 913", + "447 283 463 29 23 487 463 993 119 883 327 493 423 159 743", + "217 623 3 399 853 407 103 983 89 463 290 516 212 462 350", + "960 376 682 962 300 780 486 502 912 800 250 346 172 812 350", + "870 456 192 162 593 473 915 45 989 873 823 965 425 329 803", + "973 965 905 919 133 673 665 235 509 613 673 815 165 992 326", + "322 148 972 962 286 255 941 541 265 323 925 281 601 95 973", + "445 721 11 525 473 65 511 164 138 672 18 428 154 448 848", + "414 456 310 312 798 104 566 520 302 248 694 976 430 392 198", + "184 829 373 181 631 101 969 613 840 740 778 458 284 760 390", + "821 461 843 513 17 901 711 993 293 157 274 94 192 156 574", + "34 124 4 878 450 476 712 914 838 669 875 299 823 329 699", + "815 559 813 459 522 788 168 586 966 232 308 833 251 631 107", + "813 883 451 509 615 77 281 613 459 205 380 274 302 35 805", +] + + +def solve(arr: NDArray, row: int, cols: set[int], cache: dict[str, int]) -> int: + """ + Finds the max sum for array `arr` starting with row index `row`, and with columns + included in `cols`. `cache` is used for caching intermediate results. + + >>> solve(arr=np.array([[1, 2], [3, 4]]), row=0, cols={0, 1}, cache={}) + 5 + """ + + cache_id = f"{row}, {sorted(cols)}" + if cache_id in cache: + return cache[cache_id] + + if row == len(arr): + return 0 + + max_sum = 0 + for col in cols: + new_cols = cols - {col} + max_sum = max( + max_sum, + int(arr[row, col]) + + solve(arr=arr, row=row + 1, cols=new_cols, cache=cache), + ) + cache[cache_id] = max_sum + return max_sum + + +def solution(matrix_str: list[str] = MATRIX_2) -> int: + """ + Takes list of strings `matrix_str` to parse the matrix and calculates the max sum. + + >>> solution(["1 2", "3 4"]) + 5 + >>> solution(MATRIX_1) + 3315 + """ + + n = len(matrix_str) + arr = np.empty(shape=(n, n), dtype=int) + for row, matrix_row_str in enumerate(matrix_str): + matrix_row_list_str = matrix_row_str.split() + for col, elem_str in enumerate(matrix_row_list_str): + arr[row, col] = int(elem_str) + + cache: dict[str, int] = {} + return solve(arr=arr, row=0, cols=set(range(n)), cache=cache) + + +if __name__ == "__main__": + print(f"{solution() = }") From b720f24b89c328944f8a0d6c18db0e09d9bcffba Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Sat, 10 May 2025 19:13:07 +0800 Subject: [PATCH 021/113] Add solution for the Euler project problem 95. (#12669) * Add documentation and tests for the Euler project problem 95 solution. * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py * Update sol1.py --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- project_euler/problem_095/__init__.py | 0 project_euler/problem_095/sol1.py | 164 ++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 project_euler/problem_095/__init__.py create mode 100644 project_euler/problem_095/sol1.py diff --git a/project_euler/problem_095/__init__.py b/project_euler/problem_095/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/project_euler/problem_095/sol1.py b/project_euler/problem_095/sol1.py new file mode 100644 index 000000000000..82d84c5544de --- /dev/null +++ b/project_euler/problem_095/sol1.py @@ -0,0 +1,164 @@ +""" +Project Euler Problem 95: https://projecteuler.net/problem=95 + +Amicable Chains + +The proper divisors of a number are all the divisors excluding the number itself. +For example, the proper divisors of 28 are 1, 2, 4, 7, and 14. +As the sum of these divisors is equal to 28, we call it a perfect number. + +Interestingly the sum of the proper divisors of 220 is 284 and +the sum of the proper divisors of 284 is 220, forming a chain of two numbers. +For this reason, 220 and 284 are called an amicable pair. + +Perhaps less well known are longer chains. +For example, starting with 12496, we form a chain of five numbers: + 12496 -> 14288 -> 15472 -> 14536 -> 14264 (-> 12496 -> ...) + +Since this chain returns to its starting point, it is called an amicable chain. + +Find the smallest member of the longest amicable chain with +no element exceeding one million. + +Solution is doing the following: +- Get relevant prime numbers +- Iterate over product combination of prime numbers to generate all non-prime + numbers up to max number, by keeping track of prime factors +- Calculate the sum of factors for each number +- Iterate over found some factors to find longest chain +""" + +from math import isqrt + + +def generate_primes(max_num: int) -> list[int]: + """ + Calculates the list of primes up to and including `max_num`. + + >>> generate_primes(6) + [2, 3, 5] + """ + are_primes = [True] * (max_num + 1) + are_primes[0] = are_primes[1] = False + for i in range(2, isqrt(max_num) + 1): + if are_primes[i]: + for j in range(i * i, max_num + 1, i): + are_primes[j] = False + + return [prime for prime, is_prime in enumerate(are_primes) if is_prime] + + +def multiply( + chain: list[int], + primes: list[int], + min_prime_idx: int, + prev_num: int, + max_num: int, + prev_sum: int, + primes_degrees: dict[int, int], +) -> None: + """ + Run over all prime combinations to generate non-prime numbers. + + >>> chain = [0] * 3 + >>> primes_degrees = {} + >>> multiply( + ... chain=chain, + ... primes=[2], + ... min_prime_idx=0, + ... prev_num=1, + ... max_num=2, + ... prev_sum=0, + ... primes_degrees=primes_degrees, + ... ) + >>> chain + [0, 0, 1] + >>> primes_degrees + {2: 1} + """ + + min_prime = primes[min_prime_idx] + num = prev_num * min_prime + + min_prime_degree = primes_degrees.get(min_prime, 0) + min_prime_degree += 1 + primes_degrees[min_prime] = min_prime_degree + + new_sum = prev_sum * min_prime + (prev_sum + prev_num) * (min_prime - 1) // ( + min_prime**min_prime_degree - 1 + ) + chain[num] = new_sum + + for prime_idx in range(min_prime_idx, len(primes)): + if primes[prime_idx] * num > max_num: + break + + multiply( + chain=chain, + primes=primes, + min_prime_idx=prime_idx, + prev_num=num, + max_num=max_num, + prev_sum=new_sum, + primes_degrees=primes_degrees.copy(), + ) + + +def find_longest_chain(chain: list[int], max_num: int) -> int: + """ + Finds the smallest element of longest chain + + >>> find_longest_chain(chain=[0, 0, 0, 0, 0, 0, 6], max_num=6) + 6 + """ + + max_len = 0 + min_elem = 0 + for start in range(2, len(chain)): + visited = {start} + elem = chain[start] + length = 1 + + while elem > 1 and elem <= max_num and elem not in visited: + visited.add(elem) + elem = chain[elem] + length += 1 + + if elem == start and length > max_len: + max_len = length + min_elem = start + + return min_elem + + +def solution(max_num: int = 1000000) -> int: + """ + Runs the calculation for numbers <= `max_num`. + + >>> solution(10) + 6 + >>> solution(200000) + 12496 + """ + + primes = generate_primes(max_num) + chain = [0] * (max_num + 1) + for prime_idx, prime in enumerate(primes): + if prime**2 > max_num: + break + + multiply( + chain=chain, + primes=primes, + min_prime_idx=prime_idx, + prev_num=1, + max_num=max_num, + prev_sum=0, + primes_degrees={}, + ) + + return find_longest_chain(chain=chain, max_num=max_num) + + +if __name__ == "__main__": + print(f"{solution() = }") From a728cc96ab4f05248ac3389365a26f01dfaf6f8e Mon Sep 17 00:00:00 2001 From: NidhaNureen <165757787+NidhaNureen@users.noreply.github.com> Date: Sat, 10 May 2025 23:32:45 +1200 Subject: [PATCH 022/113] Added/Improved doctests for lowest_common_ancestor.py (#12673) * added doctests to functions in lowest_common_ancestor.py * fixed doctests to be less excessive * Update lowest_common_ancestor.py * Update lowest_common_ancestor.py * Update lowest_common_ancestor.py * Update lowest_common_ancestor.py * Update lowest_common_ancestor.py * Update lowest_common_ancestor.py --------- Co-authored-by: Maxim Smolskiy --- .../binary_tree/lowest_common_ancestor.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 651037703b95..ea0e31256903 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -15,6 +15,8 @@ def swap(a: int, b: int) -> tuple[int, int]: (4, 3) >>> swap(67, 12) (12, 67) + >>> swap(3,-4) + (-4, 3) """ a ^= b b ^= a @@ -25,6 +27,23 @@ def swap(a: int, b: int) -> tuple[int, int]: def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: """ creating sparse table which saves each nodes 2^i-th parent + >>> max_node = 6 + >>> parent = [[0, 0, 1, 1, 2, 2, 3]] + [[0] * 7 for _ in range(19)] + >>> parent = create_sparse(max_node=max_node, parent=parent) + >>> parent[0] + [0, 0, 1, 1, 2, 2, 3] + >>> parent[1] + [0, 0, 0, 0, 1, 1, 1] + >>> parent[2] + [0, 0, 0, 0, 0, 0, 0] + + >>> max_node = 1 + >>> parent = [[0, 0]] + [[0] * 2 for _ in range(19)] + >>> parent = create_sparse(max_node=max_node, parent=parent) + >>> parent[0] + [0, 0] + >>> parent[1] + [0, 0] """ j = 1 while (1 << j) < max_node: @@ -38,6 +57,21 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: def lowest_common_ancestor( u: int, v: int, level: list[int], parent: list[list[int]] ) -> int: + """ + Return the lowest common ancestor between u and v + + >>> level = [-1, 0, 1, 1, 2, 2, 2] + >>> parent = [[0, 0, 1, 1, 2, 2, 3],[0, 0, 0, 0, 1, 1, 1]] + \ + [[0] * 7 for _ in range(17)] + >>> lowest_common_ancestor(u=4, v=5, level=level, parent=parent) + 2 + >>> lowest_common_ancestor(u=4, v=6, level=level, parent=parent) + 1 + >>> lowest_common_ancestor(u=2, v=3, level=level, parent=parent) + 1 + >>> lowest_common_ancestor(u=6, v=6, level=level, parent=parent) + 6 + """ # u must be deeper in the tree than v if level[u] < level[v]: u, v = swap(u, v) @@ -68,6 +102,26 @@ def breadth_first_search( sets every nodes direct parent parent of root node is set to 0 calculates depth of each node from root node + >>> level = [-1] * 7 + >>> parent = [[0] * 7 for _ in range(20)] + >>> graph = {1: [2, 3], 2: [4, 5], 3: [6], 4: [], 5: [], 6: []} + >>> level, parent = breadth_first_search( + ... level=level, parent=parent, max_node=6, graph=graph, root=1) + >>> level + [-1, 0, 1, 1, 2, 2, 2] + >>> parent[0] + [0, 0, 1, 1, 2, 2, 3] + + + >>> level = [-1] * 2 + >>> parent = [[0] * 2 for _ in range(20)] + >>> graph = {1: []} + >>> level, parent = breadth_first_search( + ... level=level, parent=parent, max_node=1, graph=graph, root=1) + >>> level + [-1, 0] + >>> parent[0] + [0, 0] """ level[root] = 0 q: Queue[int] = Queue(maxsize=max_node) From 59c3c8bbf384ef05d3cb9862a41bba39bb098fe9 Mon Sep 17 00:00:00 2001 From: robohie Date: Sat, 10 May 2025 12:47:22 +0100 Subject: [PATCH 023/113] Add N Input AND Gate (#12717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update and_gate.py J'ai nourri ce programme en ajoutant une porte And à n entrées. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and_gate.py Commentaires en anglais * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and_gate.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- boolean_algebra/and_gate.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/boolean_algebra/and_gate.py b/boolean_algebra/and_gate.py index 6ae66b5b0a77..650017b7ae10 100644 --- a/boolean_algebra/and_gate.py +++ b/boolean_algebra/and_gate.py @@ -1,8 +1,8 @@ """ -An AND Gate is a logic gate in boolean algebra which results to 1 (True) if both the -inputs are 1, and 0 (False) otherwise. +An AND Gate is a logic gate in boolean algebra which results to 1 (True) if all the +inputs are 1 (True), and 0 (False) otherwise. -Following is the truth table of an AND Gate: +Following is the truth table of a Two Input AND Gate: ------------------------------ | Input 1 | Input 2 | Output | ------------------------------ @@ -12,7 +12,7 @@ | 1 | 1 | 1 | ------------------------------ -Refer - https://www.geeksforgeeks.org/logic-gates-in-python/ +Refer - https://www.geeksforgeeks.org/logic-gates/ """ @@ -32,6 +32,18 @@ def and_gate(input_1: int, input_2: int) -> int: return int(input_1 and input_2) +def n_input_and_gate(inputs: list[int]) -> int: + """ + Calculate AND of a list of input values + + >>> n_input_and_gate([1, 0, 1, 1, 0]) + 0 + >>> n_input_and_gate([1, 1, 1, 1, 1]) + 1 + """ + return int(all(inputs)) + + if __name__ == "__main__": import doctest From 47a44abe23870ca0f7c8062601278645039b1c70 Mon Sep 17 00:00:00 2001 From: Alfredo Hernandez Baeza Date: Sat, 10 May 2025 07:57:43 -0400 Subject: [PATCH 024/113] Improve longest_common_substring.py (#12705) * Update longest_common_substring.py - Combined the ans_index and ans_length into a single tuple to track the best match (position + length) more cleanly. - Early exit for empty strings. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update longest_common_substring.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- dynamic_programming/longest_common_substring.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dynamic_programming/longest_common_substring.py b/dynamic_programming/longest_common_substring.py index ea5233eb2d17..3ba83f3d9f03 100644 --- a/dynamic_programming/longest_common_substring.py +++ b/dynamic_programming/longest_common_substring.py @@ -43,22 +43,25 @@ def longest_common_substring(text1: str, text2: str) -> str: if not (isinstance(text1, str) and isinstance(text2, str)): raise ValueError("longest_common_substring() takes two strings for inputs") + if not text1 or not text2: + return "" + text1_length = len(text1) text2_length = len(text2) dp = [[0] * (text2_length + 1) for _ in range(text1_length + 1)] - ans_index = 0 - ans_length = 0 + end_pos = 0 + max_length = 0 for i in range(1, text1_length + 1): for j in range(1, text2_length + 1): if text1[i - 1] == text2[j - 1]: dp[i][j] = 1 + dp[i - 1][j - 1] - if dp[i][j] > ans_length: - ans_index = i - ans_length = dp[i][j] + if dp[i][j] > max_length: + end_pos = i + max_length = dp[i][j] - return text1[ans_index - ans_length : ans_index] + return text1[end_pos - max_length : end_pos] if __name__ == "__main__": From 131765574f5ccfaff4214a6f848412ce2fe4ab20 Mon Sep 17 00:00:00 2001 From: robohie Date: Sat, 10 May 2025 21:18:02 +0100 Subject: [PATCH 025/113] Fix error messages for horizontal_projectile_motion.py (#12722) * Update horizontal_projectile_motion.py This commit is about logic of this program. Changes made aim to allow a good understanding of what is done. * Update horizontal_projectile_motion.py --------- Co-authored-by: Maxim Smolskiy --- physics/horizontal_projectile_motion.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/physics/horizontal_projectile_motion.py b/physics/horizontal_projectile_motion.py index 60f21c2b39c4..32dc5eb36f35 100644 --- a/physics/horizontal_projectile_motion.py +++ b/physics/horizontal_projectile_motion.py @@ -17,7 +17,7 @@ """ # Importing packages -from math import radians as angle_to_radians +from math import radians as deg_to_rad from math import sin # Acceleration Constant on Earth (unit m/s^2) @@ -31,10 +31,10 @@ def check_args(init_velocity: float, angle: float) -> None: # Ensure valid instance if not isinstance(init_velocity, (int, float)): - raise TypeError("Invalid velocity. Should be a positive number.") + raise TypeError("Invalid velocity. Should be an integer or float.") if not isinstance(angle, (int, float)): - raise TypeError("Invalid angle. Range is 1-90 degrees.") + raise TypeError("Invalid angle. Should be an integer or float.") # Ensure valid angle if angle > 90 or angle < 1: @@ -71,7 +71,7 @@ def horizontal_distance(init_velocity: float, angle: float) -> float: ValueError: Invalid angle. Range is 1-90 degrees. """ check_args(init_velocity, angle) - radians = angle_to_radians(2 * angle) + radians = deg_to_rad(2 * angle) return round(init_velocity**2 * sin(radians) / g, 2) @@ -94,14 +94,14 @@ def max_height(init_velocity: float, angle: float) -> float: >>> max_height("a", 20) Traceback (most recent call last): ... - TypeError: Invalid velocity. Should be a positive number. + TypeError: Invalid velocity. Should be an integer or float. >>> horizontal_distance(30, "b") Traceback (most recent call last): ... - TypeError: Invalid angle. Range is 1-90 degrees. + TypeError: Invalid angle. Should be an integer or float. """ check_args(init_velocity, angle) - radians = angle_to_radians(angle) + radians = deg_to_rad(angle) return round(init_velocity**2 * sin(radians) ** 2 / (2 * g), 2) @@ -128,10 +128,10 @@ def total_time(init_velocity: float, angle: float) -> float: >>> total_time(30, "b") Traceback (most recent call last): ... - TypeError: Invalid angle. Range is 1-90 degrees. + TypeError: Invalid angle. Should be an integer or float. """ check_args(init_velocity, angle) - radians = angle_to_radians(angle) + radians = deg_to_rad(angle) return round(2 * init_velocity * sin(radians) / g, 2) From 95fb181f5a944427fdbc5766cbf4e1cb699d4a6d Mon Sep 17 00:00:00 2001 From: S Sajeev <167018420+SajeevSenthil@users.noreply.github.com> Date: Sun, 11 May 2025 02:13:39 +0530 Subject: [PATCH 026/113] Add escape velocity calculator using standard physics formula (#12721) * Added iterative solution for power calculation * Added iterative solution for power calculation * Added iterative solution for power calculation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added iterative solution for power calculation fixes #12709 * Added iterative solution for power calculation FIXES NUMBER 12709 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Escape velocity is the minimum speed an object must have to break free from a celestial body's gravitational pull without further propulsion. Takes input as the Mass of the Celestial body (M) and Radius fron the center of mass (M) * Fix: added header comment to escape_velocity.py * Trigger re-PR with a minor change * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix: resolve Ruff linter errors and add Wikipedia reference * Delete maths/power_using_iteration.py * Test doctests * Update escape_velocity.py * Update escape_velocity.py * Update escape_velocity.py * Update escape_velocity.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- physics/escape_velocity.py | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 physics/escape_velocity.py diff --git a/physics/escape_velocity.py b/physics/escape_velocity.py new file mode 100644 index 000000000000..e54ed5e50798 --- /dev/null +++ b/physics/escape_velocity.py @@ -0,0 +1,67 @@ +import math + + +def escape_velocity(mass: float, radius: float) -> float: + """ + Calculates the escape velocity needed to break free from a celestial body's + gravitational field. + + The formula used is: + v = sqrt(2 * G * M / R) + + where: + v = escape velocity (m/s) + G = gravitational constant (6.67430 * 10^-11 m^3 kg^-1 s^-2) + M = mass of the celestial body (kg) + R = radius from the center of mass (m) + + Source: + https://en.wikipedia.org/wiki/Escape_velocity + + Args: + mass (float): Mass of the celestial body in kilograms. + radius (float): Radius from the center of mass in meters. + + Returns: + float: Escape velocity in meters per second, rounded to 3 decimal places. + + Examples: + >>> escape_velocity(mass=5.972e24, radius=6.371e6) # Earth + 11185.978 + >>> escape_velocity(mass=7.348e22, radius=1.737e6) # Moon + 2376.307 + >>> escape_velocity(mass=1.898e27, radius=6.9911e7) # Jupiter + 60199.545 + >>> escape_velocity(mass=0, radius=1.0) + 0.0 + >>> escape_velocity(mass=1.0, radius=0) + Traceback (most recent call last): + ... + ZeroDivisionError: Radius cannot be zero. + """ + gravitational_constant = 6.67430e-11 # m^3 kg^-1 s^-2 + + if radius == 0: + raise ZeroDivisionError("Radius cannot be zero.") + + velocity = math.sqrt(2 * gravitational_constant * mass / radius) + return round(velocity, 3) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + print("Calculate escape velocity of a celestial body...\n") + + try: + mass = float(input("Enter mass of the celestial body (in kgs): ").strip()) + radius = float(input("Enter radius from the center of mass (in ms): ").strip()) + + velocity = escape_velocity(mass=mass, radius=radius) + print(f"Escape velocity is {velocity} m/s") + + except ValueError: + print("Invalid input. Please enter valid numeric values.") + except ZeroDivisionError as e: + print(e) From 1ea05feffec48250a3d6d0ccbd1378242d680cbc Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 12 May 2025 11:59:19 +0200 Subject: [PATCH 027/113] Prep for Python 3.14: Rename compression to data_compression (#12725) * Prep for Python 3.14: Rename compression to data_compression * updating DIRECTORY.md --------- Co-authored-by: cclauss --- DIRECTORY.md | 23 +++++++++++------- compression/image_data/__init__.py | 0 {compression => data_compression}/README.md | 0 {compression => data_compression}/__init__.py | 0 .../burrows_wheeler.py | 0 {compression => data_compression}/huffman.py | 0 .../image_data/PSNR-example-base.png | Bin .../image_data/PSNR-example-comp-10.jpg | Bin .../image_data/compressed_image.png | Bin .../image_data/example_image.jpg | Bin .../image_data/example_wikipedia_image.jpg | Bin .../image_data/original_image.png | Bin .../lempel_ziv.py | 0 .../lempel_ziv_decompress.py | 0 {compression => data_compression}/lz77.py | 0 .../peak_signal_to_noise_ratio.py | 0 .../run_length_encoding.py | 0 pyproject.toml | 2 +- 18 files changed, 15 insertions(+), 10 deletions(-) delete mode 100644 compression/image_data/__init__.py rename {compression => data_compression}/README.md (100%) rename {compression => data_compression}/__init__.py (100%) rename {compression => data_compression}/burrows_wheeler.py (100%) rename {compression => data_compression}/huffman.py (100%) rename {compression => data_compression}/image_data/PSNR-example-base.png (100%) rename {compression => data_compression}/image_data/PSNR-example-comp-10.jpg (100%) rename {compression => data_compression}/image_data/compressed_image.png (100%) rename {compression => data_compression}/image_data/example_image.jpg (100%) rename {compression => data_compression}/image_data/example_wikipedia_image.jpg (100%) rename {compression => data_compression}/image_data/original_image.png (100%) rename {compression => data_compression}/lempel_ziv.py (100%) rename {compression => data_compression}/lempel_ziv_decompress.py (100%) rename {compression => data_compression}/lz77.py (100%) rename {compression => data_compression}/peak_signal_to_noise_ratio.py (100%) rename {compression => data_compression}/run_length_encoding.py (100%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 04e09c29de97..85dcc243462e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -128,15 +128,6 @@ * [Vigenere Cipher](ciphers/vigenere_cipher.py) * [Xor Cipher](ciphers/xor_cipher.py) -## Compression - * [Burrows Wheeler](compression/burrows_wheeler.py) - * [Huffman](compression/huffman.py) - * [Lempel Ziv](compression/lempel_ziv.py) - * [Lempel Ziv Decompress](compression/lempel_ziv_decompress.py) - * [Lz77](compression/lz77.py) - * [Peak Signal To Noise Ratio](compression/peak_signal_to_noise_ratio.py) - * [Run Length Encoding](compression/run_length_encoding.py) - ## Computer Vision * [Cnn Classification](computer_vision/cnn_classification.py) * [Flip Augmentation](computer_vision/flip_augmentation.py) @@ -181,6 +172,15 @@ * [Volume Conversions](conversions/volume_conversions.py) * [Weight Conversion](conversions/weight_conversion.py) +## Data Compression + * [Burrows Wheeler](data_compression/burrows_wheeler.py) + * [Huffman](data_compression/huffman.py) + * [Lempel Ziv](data_compression/lempel_ziv.py) + * [Lempel Ziv Decompress](data_compression/lempel_ziv_decompress.py) + * [Lz77](data_compression/lz77.py) + * [Peak Signal To Noise Ratio](data_compression/peak_signal_to_noise_ratio.py) + * [Run Length Encoding](data_compression/run_length_encoding.py) + ## Data Structures * Arrays * [Equilibrium Index In Array](data_structures/arrays/equilibrium_index_in_array.py) @@ -884,6 +884,7 @@ * [Centripetal Force](physics/centripetal_force.py) * [Coulombs Law](physics/coulombs_law.py) * [Doppler Frequency](physics/doppler_frequency.py) + * [Escape Velocity](physics/escape_velocity.py) * [Grahams Law](physics/grahams_law.py) * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) * [Hubble Parameter](physics/hubble_parameter.py) @@ -1122,6 +1123,8 @@ * [Sol1](project_euler/problem_092/sol1.py) * Problem 094 * [Sol1](project_euler/problem_094/sol1.py) + * Problem 095 + * [Sol1](project_euler/problem_095/sol1.py) * Problem 097 * [Sol1](project_euler/problem_097/sol1.py) * Problem 099 @@ -1202,6 +1205,8 @@ * [Sol1](project_euler/problem_234/sol1.py) * Problem 301 * [Sol1](project_euler/problem_301/sol1.py) + * Problem 345 + * [Sol1](project_euler/problem_345/sol1.py) * Problem 493 * [Sol1](project_euler/problem_493/sol1.py) * Problem 551 diff --git a/compression/image_data/__init__.py b/compression/image_data/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/compression/README.md b/data_compression/README.md similarity index 100% rename from compression/README.md rename to data_compression/README.md diff --git a/compression/__init__.py b/data_compression/__init__.py similarity index 100% rename from compression/__init__.py rename to data_compression/__init__.py diff --git a/compression/burrows_wheeler.py b/data_compression/burrows_wheeler.py similarity index 100% rename from compression/burrows_wheeler.py rename to data_compression/burrows_wheeler.py diff --git a/compression/huffman.py b/data_compression/huffman.py similarity index 100% rename from compression/huffman.py rename to data_compression/huffman.py diff --git a/compression/image_data/PSNR-example-base.png b/data_compression/image_data/PSNR-example-base.png similarity index 100% rename from compression/image_data/PSNR-example-base.png rename to data_compression/image_data/PSNR-example-base.png diff --git a/compression/image_data/PSNR-example-comp-10.jpg b/data_compression/image_data/PSNR-example-comp-10.jpg similarity index 100% rename from compression/image_data/PSNR-example-comp-10.jpg rename to data_compression/image_data/PSNR-example-comp-10.jpg diff --git a/compression/image_data/compressed_image.png b/data_compression/image_data/compressed_image.png similarity index 100% rename from compression/image_data/compressed_image.png rename to data_compression/image_data/compressed_image.png diff --git a/compression/image_data/example_image.jpg b/data_compression/image_data/example_image.jpg similarity index 100% rename from compression/image_data/example_image.jpg rename to data_compression/image_data/example_image.jpg diff --git a/compression/image_data/example_wikipedia_image.jpg b/data_compression/image_data/example_wikipedia_image.jpg similarity index 100% rename from compression/image_data/example_wikipedia_image.jpg rename to data_compression/image_data/example_wikipedia_image.jpg diff --git a/compression/image_data/original_image.png b/data_compression/image_data/original_image.png similarity index 100% rename from compression/image_data/original_image.png rename to data_compression/image_data/original_image.png diff --git a/compression/lempel_ziv.py b/data_compression/lempel_ziv.py similarity index 100% rename from compression/lempel_ziv.py rename to data_compression/lempel_ziv.py diff --git a/compression/lempel_ziv_decompress.py b/data_compression/lempel_ziv_decompress.py similarity index 100% rename from compression/lempel_ziv_decompress.py rename to data_compression/lempel_ziv_decompress.py diff --git a/compression/lz77.py b/data_compression/lz77.py similarity index 100% rename from compression/lz77.py rename to data_compression/lz77.py diff --git a/compression/peak_signal_to_noise_ratio.py b/data_compression/peak_signal_to_noise_ratio.py similarity index 100% rename from compression/peak_signal_to_noise_ratio.py rename to data_compression/peak_signal_to_noise_ratio.py diff --git a/compression/run_length_encoding.py b/data_compression/run_length_encoding.py similarity index 100% rename from compression/run_length_encoding.py rename to data_compression/run_length_encoding.py diff --git a/pyproject.toml b/pyproject.toml index 60f8d4ffc96f..c320a2f2bbfe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -187,9 +187,9 @@ autoapi_dirs = [ "boolean_algebra", "cellular_automata", "ciphers", - "compression", "computer_vision", "conversions", + "data_compression", "data_structures", "digital_image_processing", "divide_and_conquer", From 088c74e84026fcb77b3e3e0c15c83111a6979ae7 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 12 May 2025 12:45:53 +0200 Subject: [PATCH 028/113] Delete empty source directory (#12730) --- source/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 source/__init__.py diff --git a/source/__init__.py b/source/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 From 485f688d0683ca026959e1b68f12e5d221724860 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 12 May 2025 12:52:27 +0200 Subject: [PATCH 029/113] Add PEP723 header to scripts/validate_solutions.py (#12731) Enable `uv run scripts/validate_solutions.py` or `pipx run scripts/validate_solutions.py` * https://peps.python.org/pep-0723 * https://docs.astral.sh/uv/guides/scripts/#declaring-script-dependencies --- scripts/validate_solutions.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/validate_solutions.py b/scripts/validate_solutions.py index df5d01086bbe..c3f872203591 100755 --- a/scripts/validate_solutions.py +++ b/scripts/validate_solutions.py @@ -1,4 +1,13 @@ #!/usr/bin/env python3 + +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "pytest", +# "requests", +# ] +# /// + import hashlib import importlib.util import json From f721e598e5677ed368b7dbd119092eb409ab2fb0 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 12 May 2025 13:33:33 +0200 Subject: [PATCH 030/113] Add a proper shebang line to scripts/validate_filenames.py (#12733) --- scripts/validate_filenames.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/validate_filenames.py b/scripts/validate_filenames.py index 80399673cced..a7328e099dde 100755 --- a/scripts/validate_filenames.py +++ b/scripts/validate_filenames.py @@ -1,4 +1,5 @@ -#!python +#!/usr/bin/env python3 + import os try: From ee3a1732e007d32b5835635ac7c7fbb2b5464f53 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 19:59:33 +0200 Subject: [PATCH 031/113] [pre-commit.ci] pre-commit autoupdate (#12736) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.8 → v0.11.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.8...v0.11.9) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e13416dc78d..288e3f591403 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.8 + rev: v0.11.9 hooks: - id: ruff - id: ruff-format From 6e4d1b376546cdf347b6513ff5f493510b956309 Mon Sep 17 00:00:00 2001 From: S Sajeev <167018420+SajeevSenthil@users.noreply.github.com> Date: Tue, 13 May 2025 14:44:05 +0530 Subject: [PATCH 032/113] Physics orbital_transfer_work (#12728) * Added iterative solution for power calculation * Added iterative solution for power calculation * Added iterative solution for power calculation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added iterative solution for power calculation fixes #12709 * Added iterative solution for power calculation FIXES NUMBER 12709 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Escape velocity is the minimum speed an object must have to break free from a celestial body's gravitational pull without further propulsion. Takes input as the Mass of the Celestial body (M) and Radius fron the center of mass (M) * Fix: added header comment to escape_velocity.py * Trigger re-PR with a minor change * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix: resolve Ruff linter errors and add Wikipedia reference * Add: work done calculation for orbital transfer between orbits * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update escape_velocity.py * Delete maths/power_using_iteration.py * Update and rename workdone.py to orbital_transfer_work.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- physics/orbital_transfer_work.py | 73 ++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 physics/orbital_transfer_work.py diff --git a/physics/orbital_transfer_work.py b/physics/orbital_transfer_work.py new file mode 100644 index 000000000000..7fb90fe9be0e --- /dev/null +++ b/physics/orbital_transfer_work.py @@ -0,0 +1,73 @@ +def orbital_transfer_work( + mass_central: float, mass_object: float, r_initial: float, r_final: float +) -> str: + """ + Calculates the work required to move an object from one orbit to another in a + gravitational field based on the change in total mechanical energy. + + The formula used is: + W = (G * M * m / 2) * (1/r_initial - 1/r_final) + + where: + W = work done (Joules) + G = gravitational constant (6.67430 * 10^-11 m^3 kg^-1 s^-2) + M = mass of the central body (kg) + m = mass of the orbiting object (kg) + r_initial = initial orbit radius (m) + r_final = final orbit radius (m) + + Args: + mass_central (float): Mass of the central body (kg) + mass_object (float): Mass of the object being moved (kg) + r_initial (float): Initial orbital radius (m) + r_final (float): Final orbital radius (m) + + Returns: + str: Work done in Joules as a string in scientific notation (3 decimals) + + Examples: + >>> orbital_transfer_work(5.972e24, 1000, 6.371e6, 7e6) + '2.811e+09' + >>> orbital_transfer_work(5.972e24, 500, 7e6, 6.371e6) + '-1.405e+09' + >>> orbital_transfer_work(1.989e30, 1000, 1.5e11, 2.28e11) + '1.514e+11' + """ + gravitational_constant = 6.67430e-11 + + if r_initial <= 0 or r_final <= 0: + raise ValueError("Orbital radii must be greater than zero.") + + work = (gravitational_constant * mass_central * mass_object / 2) * ( + 1 / r_initial - 1 / r_final + ) + return f"{work:.3e}" + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + print("Orbital transfer work calculator\n") + + try: + M = float(input("Enter mass of central body (kg): ").strip()) + if M <= 0: + r1 = float(input("Enter initial orbit radius (m): ").strip()) + if r1 <= 0: + raise ValueError("Initial orbit radius must be greater than zero.") + + r2 = float(input("Enter final orbit radius (m): ").strip()) + if r2 <= 0: + raise ValueError("Final orbit radius must be greater than zero.") + m = float(input("Enter mass of orbiting object (kg): ").strip()) + if m <= 0: + raise ValueError("Mass of the orbiting object must be greater than zero.") + r1 = float(input("Enter initial orbit radius (m): ").strip()) + r2 = float(input("Enter final orbit radius (m): ").strip()) + + result = orbital_transfer_work(M, m, r1, r2) + print(f"Work done in orbital transfer: {result} Joules") + + except ValueError as e: + print(f"Input error: {e}") From a2fa32c7ad8085c49021b28578440fc167627e8e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 14 May 2025 03:42:11 +0200 Subject: [PATCH 033/113] Lukazlim: Replace dependency `requests` with `httpx` (#12744) * Replace dependency `requests` with `httpx` Fixes #12742 Signed-off-by: Lim, Lukaz Wei Hwang * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Signed-off-by: Lim, Lukaz Wei Hwang Co-authored-by: Lim, Lukaz Wei Hwang Co-authored-by: cclauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 1 + machine_learning/linear_regression.py | 12 +- physics/speeds_of_gas_molecules.py | 8 +- pyproject.toml | 4 +- requirements.txt | 2 +- scripts/validate_solutions.py | 6 +- uv.lock | 1108 +++++++++-------- web_programming/co2_emission.py | 13 +- web_programming/covid_stats_via_xpath.py | 12 +- web_programming/crawl_google_results.py | 18 +- .../crawl_google_scholar_citation.py | 12 +- web_programming/currency_converter.py | 11 +- web_programming/current_stock_price.py | 14 +- web_programming/current_weather.py | 13 +- web_programming/daily_horoscope.py | 12 +- .../download_images_from_google_query.py | 12 +- web_programming/emails_from_url.py | 21 +- web_programming/fetch_anime_and_play.py | 21 +- web_programming/fetch_bbc_news.py | 11 +- web_programming/fetch_github_info.py | 13 +- web_programming/fetch_jobs.py | 14 +- web_programming/fetch_quotes.py | 13 +- web_programming/get_amazon_product_data.py | 13 +- .../get_imdb_top_250_movies_csv.py | 16 +- web_programming/get_ip_geolocation.py | 13 +- web_programming/get_top_billionaires.py | 12 +- web_programming/get_top_hn_posts.py | 13 +- web_programming/giphy.py | 12 +- web_programming/instagram_crawler.py | 14 +- web_programming/instagram_pic.py | 20 +- web_programming/instagram_video.py | 15 +- web_programming/nasa_data.py | 17 +- web_programming/open_google_results.py | 25 +- web_programming/random_anime_character.py | 15 +- web_programming/recaptcha_verification.py | 11 +- web_programming/reddit.py | 16 +- web_programming/search_books_by_isbn.py | 21 +- web_programming/slack_message.py | 11 +- web_programming/test_fetch_github_info.py | 4 +- web_programming/world_covid19_stats.py | 26 +- 40 files changed, 971 insertions(+), 654 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 85dcc243462e..4129f9c1a5e2 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -899,6 +899,7 @@ * [N Body Simulation](physics/n_body_simulation.py) * [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py) * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) + * [Orbital Transfer Work](physics/orbital_transfer_work.py) * [Period Of Pendulum](physics/period_of_pendulum.py) * [Photoelectric Effect](physics/photoelectric_effect.py) * [Potential Energy](physics/potential_energy.py) diff --git a/machine_learning/linear_regression.py b/machine_learning/linear_regression.py index 1d11e5a9cc2b..5b1e663116cc 100644 --- a/machine_learning/linear_regression.py +++ b/machine_learning/linear_regression.py @@ -8,8 +8,16 @@ Rating). We try to best fit a line through dataset and estimate the parameters. """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# "numpy", +# ] +# /// + +import httpx import numpy as np -import requests def collect_dataset(): @@ -17,7 +25,7 @@ def collect_dataset(): The dataset contains ADR vs Rating of a Player :return : dataset obtained from the link, as matrix """ - response = requests.get( + response = httpx.get( "https://raw.githubusercontent.com/yashLadha/The_Math_of_Intelligence/" "master/Week1/ADRvsRating.csv", timeout=10, diff --git a/physics/speeds_of_gas_molecules.py b/physics/speeds_of_gas_molecules.py index 42f90a9fd6f3..3f50ffa5b45d 100644 --- a/physics/speeds_of_gas_molecules.py +++ b/physics/speeds_of_gas_molecules.py @@ -59,9 +59,9 @@ def avg_speed_of_molecule(temperature: float, molar_mass: float) -> float: Examples: >>> avg_speed_of_molecule(273, 0.028) # nitrogen at 273 K - 454.3488755020387 + 454.3488755062257 >>> avg_speed_of_molecule(300, 0.032) # oxygen at 300 K - 445.52572733919885 + 445.5257273433045 >>> avg_speed_of_molecule(-273, 0.028) # invalid temperature Traceback (most recent call last): ... @@ -87,9 +87,9 @@ def mps_speed_of_molecule(temperature: float, molar_mass: float) -> float: Examples: >>> mps_speed_of_molecule(273, 0.028) # nitrogen at 273 K - 402.65620701908966 + 402.65620702280023 >>> mps_speed_of_molecule(300, 0.032) # oxygen at 300 K - 394.836895549922 + 394.8368955535605 >>> mps_speed_of_molecule(-273, 0.028) # invalid temperature Traceback (most recent call last): ... diff --git a/pyproject.toml b/pyproject.toml index c320a2f2bbfe..2ead5cd51ae8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,7 @@ classifiers = [ dependencies = [ "beautifulsoup4>=4.12.3", "fake-useragent>=1.5.1", + "httpx>=0.28.1", "imageio>=2.36.1", "keras>=3.7", "lxml>=5.3", @@ -19,7 +20,6 @@ dependencies = [ "opencv-python>=4.10.0.84", "pandas>=2.2.3", "pillow>=11", - "requests>=2.32.3", "rich>=13.9.4", "scikit-learn>=1.5.2", "sphinx-pyproject>=0.3", @@ -42,8 +42,8 @@ docs = [ "sphinx-pyproject>=0.3", ] euler-validate = [ + "httpx>=0.28.1", "numpy>=2.1.3", - "requests>=2.32.3", ] [tool.ruff] diff --git a/requirements.txt b/requirements.txt index b104505e01bc..66b5d8a6b94e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ beautifulsoup4 fake-useragent +httpx imageio keras lxml @@ -8,7 +9,6 @@ numpy opencv-python pandas pillow -requests rich scikit-learn sphinx-pyproject diff --git a/scripts/validate_solutions.py b/scripts/validate_solutions.py index c3f872203591..f426153b5683 100755 --- a/scripts/validate_solutions.py +++ b/scripts/validate_solutions.py @@ -3,8 +3,8 @@ # /// script # requires-python = ">=3.13" # dependencies = [ +# "httpx", # "pytest", -# "requests", # ] # /// @@ -15,8 +15,8 @@ import pathlib from types import ModuleType +import httpx import pytest -import requests PROJECT_EULER_DIR_PATH = pathlib.Path.cwd().joinpath("project_euler") PROJECT_EULER_ANSWERS_PATH = pathlib.Path.cwd().joinpath( @@ -66,7 +66,7 @@ def added_solution_file_path() -> list[pathlib.Path]: "Accept": "application/vnd.github.v3+json", "Authorization": "token " + os.environ["GITHUB_TOKEN"], } - files = requests.get(get_files_url(), headers=headers, timeout=10).json() + files = httpx.get(get_files_url(), headers=headers, timeout=10).json() for file in files: filepath = pathlib.Path.cwd().joinpath(file["filename"]) if ( diff --git a/uv.lock b/uv.lock index 077288f041a1..c75a1070745b 100644 --- a/uv.lock +++ b/uv.lock @@ -1,319 +1,361 @@ version = 1 +revision = 2 requires-python = ">=3.13" resolution-markers = [ - "platform_system == 'Darwin'", - "platform_machine == 'aarch64' and platform_system == 'Linux'", - "(platform_machine != 'aarch64' and platform_system != 'Darwin') or (platform_system != 'Darwin' and platform_system != 'Linux')", + "sys_platform == 'darwin'", + "platform_machine == 'aarch64' and sys_platform == 'linux'", + "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')", ] [[package]] name = "absl-py" -version = "2.1.0" +version = "2.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7a/8f/fc001b92ecc467cc32ab38398bd0bfb45df46e7523bf33c2ad22a505f06e/absl-py-2.1.0.tar.gz", hash = "sha256:7820790efbb316739cde8b4e19357243fc3608a152024288513dd968d7d959ff", size = 118055 } +sdist = { url = "https://files.pythonhosted.org/packages/b5/f0/e6342091061ed3a46aadc116b13edd7bb5249c3ab1b3ef07f24b0c248fc3/absl_py-2.2.2.tar.gz", hash = "sha256:bf25b2c2eed013ca456918c453d687eab4e8309fba81ee2f4c1a6aa2494175eb", size = 119982, upload-time = "2025-04-03T12:41:04.55Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/ad/e0d3c824784ff121c03cc031f944bc7e139a8f1870ffd2845cc2dd76f6c4/absl_py-2.1.0-py3-none-any.whl", hash = "sha256:526a04eadab8b4ee719ce68f204172ead1027549089702d99b9059f129ff1308", size = 133706 }, + { url = "https://files.pythonhosted.org/packages/f6/d4/349f7f4bd5ea92dab34f5bb0fe31775ef6c311427a14d5a5b31ecb442341/absl_py-2.2.2-py3-none-any.whl", hash = "sha256:e5797bc6abe45f64fd95dc06394ca3f2bedf3b5d895e9da691c9ee3397d70092", size = 135565, upload-time = "2025-04-03T12:41:03.172Z" }, ] [[package]] name = "alabaster" version = "1.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210 } +sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, +] + +[[package]] +name = "anyio" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929 }, + { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" }, ] [[package]] name = "astroid" -version = "3.3.5" +version = "3.3.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/38/1e/326fb1d3d83a3bb77c9f9be29d31f2901e35acb94b0605c3f2e5085047f9/astroid-3.3.5.tar.gz", hash = "sha256:5cfc40ae9f68311075d27ef68a4841bdc5cc7f6cf86671b49f00607d30188e2d", size = 397229 } +sdist = { url = "https://files.pythonhosted.org/packages/00/c2/9b2de9ed027f9fe5734a6c0c0a601289d796b3caaf1e372e23fa88a73047/astroid-3.3.10.tar.gz", hash = "sha256:c332157953060c6deb9caa57303ae0d20b0fbdb2e59b4a4f2a6ba49d0a7961ce", size = 398941, upload-time = "2025-05-10T13:33:10.405Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/41/30/624365383fa4a40329c0f0bbbc151abc4a64e30dfc110fc8f6e2afcd02bb/astroid-3.3.5-py3-none-any.whl", hash = "sha256:a9d1c946ada25098d790e079ba2a1b112157278f3fb7e718ae6a9252f5835dc8", size = 274586 }, + { url = "https://files.pythonhosted.org/packages/15/58/5260205b9968c20b6457ed82f48f9e3d6edf2f1f95103161798b73aeccf0/astroid-3.3.10-py3-none-any.whl", hash = "sha256:104fb9cb9b27ea95e847a94c003be03a9e039334a8ebca5ee27dafaf5c5711eb", size = 275388, upload-time = "2025-05-10T13:33:08.391Z" }, ] [[package]] name = "babel" -version = "2.16.0" +version = "2.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2a/74/f1bc80f23eeba13393b7222b11d95ca3af2c1e28edca18af487137eefed9/babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316", size = 9348104 } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", size = 9587599 }, + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, ] [[package]] name = "beautifulsoup4" -version = "4.12.3" +version = "4.13.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "soupsieve" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b3/ca/824b1195773ce6166d388573fc106ce56d4a805bd7427b624e063596ec58/beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", size = 581181 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/e4/0c4c39e18fd76d6a628d4dd8da40543d136ce2d1752bd6eeeab0791f4d6b/beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195", size = 621067, upload-time = "2025-04-15T17:05:13.836Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed", size = 147925 }, + { url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285, upload-time = "2025-04-15T17:05:12.221Z" }, ] [[package]] name = "certifi" -version = "2024.8.30" +version = "2025.4.26" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", size = 168507 } +sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 }, + { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, ] [[package]] name = "charset-normalizer" -version = "3.4.0" +version = "3.4.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", size = 106620 } +sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/89/68a4c86f1a0002810a27f12e9a7b22feb198c59b2f05231349fbce5c06f4/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114", size = 194617 }, - { url = "https://files.pythonhosted.org/packages/4f/cd/8947fe425e2ab0aa57aceb7807af13a0e4162cd21eee42ef5b053447edf5/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed", size = 125310 }, - { url = "https://files.pythonhosted.org/packages/5b/f0/b5263e8668a4ee9becc2b451ed909e9c27058337fda5b8c49588183c267a/charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250", size = 119126 }, - { url = "https://files.pythonhosted.org/packages/ff/6e/e445afe4f7fda27a533f3234b627b3e515a1b9429bc981c9a5e2aa5d97b6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920", size = 139342 }, - { url = "https://files.pythonhosted.org/packages/a1/b2/4af9993b532d93270538ad4926c8e37dc29f2111c36f9c629840c57cd9b3/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64", size = 149383 }, - { url = "https://files.pythonhosted.org/packages/fb/6f/4e78c3b97686b871db9be6f31d64e9264e889f8c9d7ab33c771f847f79b7/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23", size = 142214 }, - { url = "https://files.pythonhosted.org/packages/2b/c9/1c8fe3ce05d30c87eff498592c89015b19fade13df42850aafae09e94f35/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc", size = 144104 }, - { url = "https://files.pythonhosted.org/packages/ee/68/efad5dcb306bf37db7db338338e7bb8ebd8cf38ee5bbd5ceaaaa46f257e6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d", size = 146255 }, - { url = "https://files.pythonhosted.org/packages/0c/75/1ed813c3ffd200b1f3e71121c95da3f79e6d2a96120163443b3ad1057505/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88", size = 140251 }, - { url = "https://files.pythonhosted.org/packages/7d/0d/6f32255c1979653b448d3c709583557a4d24ff97ac4f3a5be156b2e6a210/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90", size = 148474 }, - { url = "https://files.pythonhosted.org/packages/ac/a0/c1b5298de4670d997101fef95b97ac440e8c8d8b4efa5a4d1ef44af82f0d/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b", size = 151849 }, - { url = "https://files.pythonhosted.org/packages/04/4f/b3961ba0c664989ba63e30595a3ed0875d6790ff26671e2aae2fdc28a399/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d", size = 149781 }, - { url = "https://files.pythonhosted.org/packages/d8/90/6af4cd042066a4adad58ae25648a12c09c879efa4849c705719ba1b23d8c/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482", size = 144970 }, - { url = "https://files.pythonhosted.org/packages/cc/67/e5e7e0cbfefc4ca79025238b43cdf8a2037854195b37d6417f3d0895c4c2/charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", size = 94973 }, - { url = "https://files.pythonhosted.org/packages/65/97/fc9bbc54ee13d33dc54a7fcf17b26368b18505500fc01e228c27b5222d80/charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", size = 102308 }, - { url = "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", size = 49446 }, -] - -[[package]] -name = "codespell" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a0/a9/98353dfc7afcdf18cffd2dd3e959a25eaaf2728cf450caa59af89648a8e4/codespell-2.3.0.tar.gz", hash = "sha256:360c7d10f75e65f67bad720af7007e1060a5d395670ec11a7ed1fed9dd17471f", size = 329791 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/20/b6019add11e84f821184234cea0ad91442373489ef7ccfa3d73a71b908fa/codespell-2.3.0-py3-none-any.whl", hash = "sha256:a9c7cef2501c9cfede2110fd6d4e5e62296920efe9abfb84648df866e47f58d1", size = 329167 }, + { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" }, + { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" }, + { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" }, + { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" }, + { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" }, + { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" }, + { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" }, + { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" }, + { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" }, + { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" }, + { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" }, + { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" }, + { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] [[package]] name = "contourpy" -version = "1.3.1" +version = "1.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/c2/fc7193cc5383637ff390a712e88e4ded0452c9fbcf84abe3de5ea3df1866/contourpy-1.3.1.tar.gz", hash = "sha256:dfd97abd83335045a913e3bcc4a09c0ceadbe66580cf573fe961f4a825efa699", size = 13465753 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/e7/de62050dce687c5e96f946a93546910bc67e483fe05324439e329ff36105/contourpy-1.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a761d9ccfc5e2ecd1bf05534eda382aa14c3e4f9205ba5b1684ecfe400716ef2", size = 271548 }, - { url = "https://files.pythonhosted.org/packages/78/4d/c2a09ae014ae984c6bdd29c11e74d3121b25eaa117eca0bb76340efd7e1c/contourpy-1.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:523a8ee12edfa36f6d2a49407f705a6ef4c5098de4f498619787e272de93f2d5", size = 255576 }, - { url = "https://files.pythonhosted.org/packages/ab/8a/915380ee96a5638bda80cd061ccb8e666bfdccea38d5741cb69e6dbd61fc/contourpy-1.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece6df05e2c41bd46776fbc712e0996f7c94e0d0543af1656956d150c4ca7c81", size = 306635 }, - { url = "https://files.pythonhosted.org/packages/29/5c/c83ce09375428298acd4e6582aeb68b1e0d1447f877fa993d9bf6cd3b0a0/contourpy-1.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:573abb30e0e05bf31ed067d2f82500ecfdaec15627a59d63ea2d95714790f5c2", size = 345925 }, - { url = "https://files.pythonhosted.org/packages/29/63/5b52f4a15e80c66c8078a641a3bfacd6e07106835682454647aca1afc852/contourpy-1.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fa36448e6a3a1a9a2ba23c02012c43ed88905ec80163f2ffe2421c7192a5d7", size = 318000 }, - { url = "https://files.pythonhosted.org/packages/9a/e2/30ca086c692691129849198659bf0556d72a757fe2769eb9620a27169296/contourpy-1.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ea9924d28fc5586bf0b42d15f590b10c224117e74409dd7a0be3b62b74a501c", size = 322689 }, - { url = "https://files.pythonhosted.org/packages/6b/77/f37812ef700f1f185d348394debf33f22d531e714cf6a35d13d68a7003c7/contourpy-1.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b75aa69cb4d6f137b36f7eb2ace9280cfb60c55dc5f61c731fdf6f037f958a3", size = 1268413 }, - { url = "https://files.pythonhosted.org/packages/3f/6d/ce84e79cdd128542ebeb268f84abb4b093af78e7f8ec504676673d2675bc/contourpy-1.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:041b640d4ec01922083645a94bb3b2e777e6b626788f4095cf21abbe266413c1", size = 1326530 }, - { url = "https://files.pythonhosted.org/packages/72/22/8282f4eae20c73c89bee7a82a19c4e27af9b57bb602ecaa00713d5bdb54d/contourpy-1.3.1-cp313-cp313-win32.whl", hash = "sha256:36987a15e8ace5f58d4d5da9dca82d498c2bbb28dff6e5d04fbfcc35a9cb3a82", size = 175315 }, - { url = "https://files.pythonhosted.org/packages/e3/d5/28bca491f65312b438fbf076589dcde7f6f966b196d900777f5811b9c4e2/contourpy-1.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:a7895f46d47671fa7ceec40f31fae721da51ad34bdca0bee83e38870b1f47ffd", size = 220987 }, - { url = "https://files.pythonhosted.org/packages/2f/24/a4b285d6adaaf9746e4700932f579f1a7b6f9681109f694cfa233ae75c4e/contourpy-1.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9ddeb796389dadcd884c7eb07bd14ef12408aaae358f0e2ae24114d797eede30", size = 285001 }, - { url = "https://files.pythonhosted.org/packages/48/1d/fb49a401b5ca4f06ccf467cd6c4f1fd65767e63c21322b29b04ec40b40b9/contourpy-1.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:19c1555a6801c2f084c7ddc1c6e11f02eb6a6016ca1318dd5452ba3f613a1751", size = 268553 }, - { url = "https://files.pythonhosted.org/packages/79/1e/4aef9470d13fd029087388fae750dccb49a50c012a6c8d1d634295caa644/contourpy-1.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:841ad858cff65c2c04bf93875e384ccb82b654574a6d7f30453a04f04af71342", size = 310386 }, - { url = "https://files.pythonhosted.org/packages/b0/34/910dc706ed70153b60392b5305c708c9810d425bde12499c9184a1100888/contourpy-1.3.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4318af1c925fb9a4fb190559ef3eec206845f63e80fb603d47f2d6d67683901c", size = 349806 }, - { url = "https://files.pythonhosted.org/packages/31/3c/faee6a40d66d7f2a87f7102236bf4780c57990dd7f98e5ff29881b1b1344/contourpy-1.3.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:14c102b0eab282427b662cb590f2e9340a9d91a1c297f48729431f2dcd16e14f", size = 321108 }, - { url = "https://files.pythonhosted.org/packages/17/69/390dc9b20dd4bb20585651d7316cc3054b7d4a7b4f8b710b2b698e08968d/contourpy-1.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05e806338bfeaa006acbdeba0ad681a10be63b26e1b17317bfac3c5d98f36cda", size = 327291 }, - { url = "https://files.pythonhosted.org/packages/ef/74/7030b67c4e941fe1e5424a3d988080e83568030ce0355f7c9fc556455b01/contourpy-1.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4d76d5993a34ef3df5181ba3c92fabb93f1eaa5729504fb03423fcd9f3177242", size = 1263752 }, - { url = "https://files.pythonhosted.org/packages/f0/ed/92d86f183a8615f13f6b9cbfc5d4298a509d6ce433432e21da838b4b63f4/contourpy-1.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:89785bb2a1980c1bd87f0cb1517a71cde374776a5f150936b82580ae6ead44a1", size = 1318403 }, - { url = "https://files.pythonhosted.org/packages/b3/0e/c8e4950c77dcfc897c71d61e56690a0a9df39543d2164040301b5df8e67b/contourpy-1.3.1-cp313-cp313t-win32.whl", hash = "sha256:8eb96e79b9f3dcadbad2a3891672f81cdcab7f95b27f28f1c67d75f045b6b4f1", size = 185117 }, - { url = "https://files.pythonhosted.org/packages/c1/31/1ae946f11dfbd229222e6d6ad8e7bd1891d3d48bde5fbf7a0beb9491f8e3/contourpy-1.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:287ccc248c9e0d0566934e7d606201abd74761b5703d804ff3df8935f523d546", size = 236668 }, +sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/61/5673f7e364b31e4e7ef6f61a4b5121c5f170f941895912f773d95270f3a2/contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb", size = 271630, upload-time = "2025-04-15T17:38:19.142Z" }, + { url = "https://files.pythonhosted.org/packages/ff/66/a40badddd1223822c95798c55292844b7e871e50f6bfd9f158cb25e0bd39/contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08", size = 255670, upload-time = "2025-04-15T17:38:23.688Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c7/cf9fdee8200805c9bc3b148f49cb9482a4e3ea2719e772602a425c9b09f8/contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c", size = 306694, upload-time = "2025-04-15T17:38:28.238Z" }, + { url = "https://files.pythonhosted.org/packages/dd/e7/ccb9bec80e1ba121efbffad7f38021021cda5be87532ec16fd96533bb2e0/contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f", size = 345986, upload-time = "2025-04-15T17:38:33.502Z" }, + { url = "https://files.pythonhosted.org/packages/dc/49/ca13bb2da90391fa4219fdb23b078d6065ada886658ac7818e5441448b78/contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85", size = 318060, upload-time = "2025-04-15T17:38:38.672Z" }, + { url = "https://files.pythonhosted.org/packages/c8/65/5245ce8c548a8422236c13ffcdcdada6a2a812c361e9e0c70548bb40b661/contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841", size = 322747, upload-time = "2025-04-15T17:38:43.712Z" }, + { url = "https://files.pythonhosted.org/packages/72/30/669b8eb48e0a01c660ead3752a25b44fdb2e5ebc13a55782f639170772f9/contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422", size = 1308895, upload-time = "2025-04-15T17:39:00.224Z" }, + { url = "https://files.pythonhosted.org/packages/05/5a/b569f4250decee6e8d54498be7bdf29021a4c256e77fe8138c8319ef8eb3/contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef", size = 1379098, upload-time = "2025-04-15T17:43:29.649Z" }, + { url = "https://files.pythonhosted.org/packages/19/ba/b227c3886d120e60e41b28740ac3617b2f2b971b9f601c835661194579f1/contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f", size = 178535, upload-time = "2025-04-15T17:44:44.532Z" }, + { url = "https://files.pythonhosted.org/packages/12/6e/2fed56cd47ca739b43e892707ae9a13790a486a3173be063681ca67d2262/contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9", size = 223096, upload-time = "2025-04-15T17:44:48.194Z" }, + { url = "https://files.pythonhosted.org/packages/54/4c/e76fe2a03014a7c767d79ea35c86a747e9325537a8b7627e0e5b3ba266b4/contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f", size = 285090, upload-time = "2025-04-15T17:43:34.084Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e2/5aba47debd55d668e00baf9651b721e7733975dc9fc27264a62b0dd26eb8/contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739", size = 268643, upload-time = "2025-04-15T17:43:38.626Z" }, + { url = "https://files.pythonhosted.org/packages/a1/37/cd45f1f051fe6230f751cc5cdd2728bb3a203f5619510ef11e732109593c/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823", size = 310443, upload-time = "2025-04-15T17:43:44.522Z" }, + { url = "https://files.pythonhosted.org/packages/8b/a2/36ea6140c306c9ff6dd38e3bcec80b3b018474ef4d17eb68ceecd26675f4/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5", size = 349865, upload-time = "2025-04-15T17:43:49.545Z" }, + { url = "https://files.pythonhosted.org/packages/95/b7/2fc76bc539693180488f7b6cc518da7acbbb9e3b931fd9280504128bf956/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532", size = 321162, upload-time = "2025-04-15T17:43:54.203Z" }, + { url = "https://files.pythonhosted.org/packages/f4/10/76d4f778458b0aa83f96e59d65ece72a060bacb20cfbee46cf6cd5ceba41/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b", size = 327355, upload-time = "2025-04-15T17:44:01.025Z" }, + { url = "https://files.pythonhosted.org/packages/43/a3/10cf483ea683f9f8ab096c24bad3cce20e0d1dd9a4baa0e2093c1c962d9d/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52", size = 1307935, upload-time = "2025-04-15T17:44:17.322Z" }, + { url = "https://files.pythonhosted.org/packages/78/73/69dd9a024444489e22d86108e7b913f3528f56cfc312b5c5727a44188471/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd", size = 1372168, upload-time = "2025-04-15T17:44:33.43Z" }, + { url = "https://files.pythonhosted.org/packages/0f/1b/96d586ccf1b1a9d2004dd519b25fbf104a11589abfd05484ff12199cca21/contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1", size = 189550, upload-time = "2025-04-15T17:44:37.092Z" }, + { url = "https://files.pythonhosted.org/packages/b0/e6/6000d0094e8a5e32ad62591c8609e269febb6e4db83a1c75ff8868b42731/contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69", size = 238214, upload-time = "2025-04-15T17:44:40.827Z" }, ] [[package]] name = "coverage" -version = "7.6.8" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ab/75/aecfd0a3adbec6e45753976bc2a9fed62b42cea9a206d10fd29244a77953/coverage-7.6.8.tar.gz", hash = "sha256:8b2b8503edb06822c86d82fa64a4a5cb0760bb8f31f26e138ec743f422f37cfc", size = 801425 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/84/6f0ccf94a098ac3d6d6f236bd3905eeac049a9e0efcd9a63d4feca37ac4b/coverage-7.6.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0b0c69f4f724c64dfbfe79f5dfb503b42fe6127b8d479b2677f2b227478db2eb", size = 207313 }, - { url = "https://files.pythonhosted.org/packages/db/2b/e3b3a3a12ebec738c545897ac9f314620470fcbc368cdac88cf14974ba20/coverage-7.6.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c15b32a7aca8038ed7644f854bf17b663bc38e1671b5d6f43f9a2b2bd0c46f63", size = 207574 }, - { url = "https://files.pythonhosted.org/packages/db/c0/5bf95d42b6a8d21dfce5025ce187f15db57d6460a59b67a95fe8728162f1/coverage-7.6.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63068a11171e4276f6ece913bde059e77c713b48c3a848814a6537f35afb8365", size = 240090 }, - { url = "https://files.pythonhosted.org/packages/57/b8/d6fd17d1a8e2b0e1a4e8b9cb1f0f261afd422570735899759c0584236916/coverage-7.6.8-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f4548c5ead23ad13fb7a2c8ea541357474ec13c2b736feb02e19a3085fac002", size = 237237 }, - { url = "https://files.pythonhosted.org/packages/d4/e4/a91e9bb46809c8b63e68fc5db5c4d567d3423b6691d049a4f950e38fbe9d/coverage-7.6.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4b4299dd0d2c67caaaf286d58aef5e75b125b95615dda4542561a5a566a1e3", size = 239225 }, - { url = "https://files.pythonhosted.org/packages/31/9c/9b99b0591ec4555b7292d271e005f27b465388ce166056c435b288db6a69/coverage-7.6.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9ebfb2507751f7196995142f057d1324afdab56db1d9743aab7f50289abd022", size = 238888 }, - { url = "https://files.pythonhosted.org/packages/a6/85/285c2df9a04bc7c31f21fd9d4a24d19e040ec5e2ff06e572af1f6514c9e7/coverage-7.6.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c1b4474beee02ede1eef86c25ad4600a424fe36cff01a6103cb4533c6bf0169e", size = 236974 }, - { url = "https://files.pythonhosted.org/packages/cb/a1/95ec8522206f76cdca033bf8bb61fff56429fb414835fc4d34651dfd29fc/coverage-7.6.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9fd2547e6decdbf985d579cf3fc78e4c1d662b9b0ff7cc7862baaab71c9cc5b", size = 238815 }, - { url = "https://files.pythonhosted.org/packages/8d/ac/687e9ba5e6d0979e9dab5c02e01c4f24ac58260ef82d88d3b433b3f84f1e/coverage-7.6.8-cp313-cp313-win32.whl", hash = "sha256:8aae5aea53cbfe024919715eca696b1a3201886ce83790537d1c3668459c7146", size = 209957 }, - { url = "https://files.pythonhosted.org/packages/2f/a3/b61cc8e3fcf075293fb0f3dee405748453c5ba28ac02ceb4a87f52bdb105/coverage-7.6.8-cp313-cp313-win_amd64.whl", hash = "sha256:ae270e79f7e169ccfe23284ff5ea2d52a6f401dc01b337efb54b3783e2ce3f28", size = 210711 }, - { url = "https://files.pythonhosted.org/packages/ee/4b/891c8b9acf1b62c85e4a71dac142ab9284e8347409b7355de02e3f38306f/coverage-7.6.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de38add67a0af869b0d79c525d3e4588ac1ffa92f39116dbe0ed9753f26eba7d", size = 208053 }, - { url = "https://files.pythonhosted.org/packages/18/a9/9e330409b291cc002723d339346452800e78df1ce50774ca439ade1d374f/coverage-7.6.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b07c25d52b1c16ce5de088046cd2432b30f9ad5e224ff17c8f496d9cb7d1d451", size = 208329 }, - { url = "https://files.pythonhosted.org/packages/9c/0d/33635fd429f6589c6e1cdfc7bf581aefe4c1792fbff06383f9d37f59db60/coverage-7.6.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62a66ff235e4c2e37ed3b6104d8b478d767ff73838d1222132a7a026aa548764", size = 251052 }, - { url = "https://files.pythonhosted.org/packages/23/32/8a08da0e46f3830bbb9a5b40614241b2e700f27a9c2889f53122486443ed/coverage-7.6.8-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09b9f848b28081e7b975a3626e9081574a7b9196cde26604540582da60235fdf", size = 246765 }, - { url = "https://files.pythonhosted.org/packages/56/3f/3b86303d2c14350fdb1c6c4dbf9bc76000af2382f42ca1d4d99c6317666e/coverage-7.6.8-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:093896e530c38c8e9c996901858ac63f3d4171268db2c9c8b373a228f459bbc5", size = 249125 }, - { url = "https://files.pythonhosted.org/packages/36/cb/c4f081b9023f9fd8646dbc4ef77be0df090263e8f66f4ea47681e0dc2cff/coverage-7.6.8-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a7b8ac36fd688c8361cbc7bf1cb5866977ece6e0b17c34aa0df58bda4fa18a4", size = 248615 }, - { url = "https://files.pythonhosted.org/packages/32/ee/53bdbf67760928c44b57b2c28a8c0a4bf544f85a9ee129a63ba5c78fdee4/coverage-7.6.8-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:38c51297b35b3ed91670e1e4efb702b790002e3245a28c76e627478aa3c10d83", size = 246507 }, - { url = "https://files.pythonhosted.org/packages/57/49/5a57910bd0af6d8e802b4ca65292576d19b54b49f81577fd898505dee075/coverage-7.6.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2e4e0f60cb4bd7396108823548e82fdab72d4d8a65e58e2c19bbbc2f1e2bfa4b", size = 247785 }, - { url = "https://files.pythonhosted.org/packages/bd/37/e450c9f6b297c79bb9858407396ed3e084dcc22990dd110ab01d5ceb9770/coverage-7.6.8-cp313-cp313t-win32.whl", hash = "sha256:6535d996f6537ecb298b4e287a855f37deaf64ff007162ec0afb9ab8ba3b8b71", size = 210605 }, - { url = "https://files.pythonhosted.org/packages/44/79/7d0c7dd237c6905018e2936cd1055fe1d42e7eba2ebab3c00f4aad2a27d7/coverage-7.6.8-cp313-cp313t-win_amd64.whl", hash = "sha256:c79c0685f142ca53256722a384540832420dff4ab15fec1863d7e5bc8691bdcc", size = 211777 }, +version = "7.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/4f/2251e65033ed2ce1e68f00f91a0294e0f80c80ae8c3ebbe2f12828c4cd53/coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501", size = 811872, upload-time = "2025-03-30T20:36:45.376Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/21/87e9b97b568e223f3438d93072479c2f36cc9b3f6b9f7094b9d50232acc0/coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd", size = 211708, upload-time = "2025-03-30T20:35:47.417Z" }, + { url = "https://files.pythonhosted.org/packages/75/be/882d08b28a0d19c9c4c2e8a1c6ebe1f79c9c839eb46d4fca3bd3b34562b9/coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00", size = 211981, upload-time = "2025-03-30T20:35:49.002Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1d/ce99612ebd58082fbe3f8c66f6d8d5694976c76a0d474503fa70633ec77f/coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64", size = 245495, upload-time = "2025-03-30T20:35:51.073Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8d/6115abe97df98db6b2bd76aae395fcc941d039a7acd25f741312ced9a78f/coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067", size = 242538, upload-time = "2025-03-30T20:35:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/cb/74/2f8cc196643b15bc096d60e073691dadb3dca48418f08bc78dd6e899383e/coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008", size = 244561, upload-time = "2025-03-30T20:35:54.658Z" }, + { url = "https://files.pythonhosted.org/packages/22/70/c10c77cd77970ac965734fe3419f2c98665f6e982744a9bfb0e749d298f4/coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733", size = 244633, upload-time = "2025-03-30T20:35:56.221Z" }, + { url = "https://files.pythonhosted.org/packages/38/5a/4f7569d946a07c952688debee18c2bb9ab24f88027e3d71fd25dbc2f9dca/coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323", size = 242712, upload-time = "2025-03-30T20:35:57.801Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a1/03a43b33f50475a632a91ea8c127f7e35e53786dbe6781c25f19fd5a65f8/coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3", size = 244000, upload-time = "2025-03-30T20:35:59.378Z" }, + { url = "https://files.pythonhosted.org/packages/6a/89/ab6c43b1788a3128e4d1b7b54214548dcad75a621f9d277b14d16a80d8a1/coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d", size = 214195, upload-time = "2025-03-30T20:36:01.005Z" }, + { url = "https://files.pythonhosted.org/packages/12/12/6bf5f9a8b063d116bac536a7fb594fc35cb04981654cccb4bbfea5dcdfa0/coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487", size = 214998, upload-time = "2025-03-30T20:36:03.006Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e6/1e9df74ef7a1c983a9c7443dac8aac37a46f1939ae3499424622e72a6f78/coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25", size = 212541, upload-time = "2025-03-30T20:36:04.638Z" }, + { url = "https://files.pythonhosted.org/packages/04/51/c32174edb7ee49744e2e81c4b1414ac9df3dacfcb5b5f273b7f285ad43f6/coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42", size = 212767, upload-time = "2025-03-30T20:36:06.503Z" }, + { url = "https://files.pythonhosted.org/packages/e9/8f/f454cbdb5212f13f29d4a7983db69169f1937e869a5142bce983ded52162/coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502", size = 256997, upload-time = "2025-03-30T20:36:08.137Z" }, + { url = "https://files.pythonhosted.org/packages/e6/74/2bf9e78b321216d6ee90a81e5c22f912fc428442c830c4077b4a071db66f/coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1", size = 252708, upload-time = "2025-03-30T20:36:09.781Z" }, + { url = "https://files.pythonhosted.org/packages/92/4d/50d7eb1e9a6062bee6e2f92e78b0998848a972e9afad349b6cdde6fa9e32/coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4", size = 255046, upload-time = "2025-03-30T20:36:11.409Z" }, + { url = "https://files.pythonhosted.org/packages/40/9e/71fb4e7402a07c4198ab44fc564d09d7d0ffca46a9fb7b0a7b929e7641bd/coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73", size = 256139, upload-time = "2025-03-30T20:36:13.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/1a/78d37f7a42b5beff027e807c2843185961fdae7fe23aad5a4837c93f9d25/coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a", size = 254307, upload-time = "2025-03-30T20:36:16.074Z" }, + { url = "https://files.pythonhosted.org/packages/58/e9/8fb8e0ff6bef5e170ee19d59ca694f9001b2ec085dc99b4f65c128bb3f9a/coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883", size = 255116, upload-time = "2025-03-30T20:36:18.033Z" }, + { url = "https://files.pythonhosted.org/packages/56/b0/d968ecdbe6fe0a863de7169bbe9e8a476868959f3af24981f6a10d2b6924/coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada", size = 214909, upload-time = "2025-03-30T20:36:19.644Z" }, + { url = "https://files.pythonhosted.org/packages/87/e9/d6b7ef9fecf42dfb418d93544af47c940aa83056c49e6021a564aafbc91f/coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257", size = 216068, upload-time = "2025-03-30T20:36:21.282Z" }, + { url = "https://files.pythonhosted.org/packages/59/f1/4da7717f0063a222db253e7121bd6a56f6fb1ba439dcc36659088793347c/coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7", size = 203435, upload-time = "2025-03-30T20:36:43.61Z" }, ] [[package]] name = "cycler" version = "0.12.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615 } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321 }, + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, ] [[package]] name = "docutils" version = "0.21.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } +sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 }, + { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, ] [[package]] name = "dom-toml" -version = "2.0.0" +version = "2.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "domdf-python-tools" }, { name = "tomli" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/34/f7690cf288eaa86b55c8f1b890d0834e6df44a026a88eca12274fcd624ab/dom_toml-2.0.0.tar.gz", hash = "sha256:3c07e8436538994974127b1ae037661d1a779ac915c44fd06b3ab5fe140ff589", size = 11133 } +sdist = { url = "https://files.pythonhosted.org/packages/fd/38/5df2387f84efce3c7ef8d211cae6ca2736a730efc13b7d15a9584bb81b30/dom_toml-2.0.1.tar.gz", hash = "sha256:31c5874595c777f41cc191c34c66dbea215c8289a7b148b425fb7a10c3f4fbc8", size = 11180, upload-time = "2025-02-05T11:59:36.552Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/22/99/b6fc87dff3138491d81676bdcbf1531080925ba41486ec1dafd86e33fdbc/dom_toml-2.0.0-py3-none-any.whl", hash = "sha256:0b6d02a72bcbc6be8175c61afc30623bbb6b74c4650f2a806fbc3fb7fe86935d", size = 13376 }, + { url = "https://files.pythonhosted.org/packages/33/c6/57f64b0e93da6f43393dfcc1281ee1ce8eafbeb940d3861056caa28ae818/dom_toml-2.0.1-py3-none-any.whl", hash = "sha256:6681a793c94a5d1fb7b59690009cc3b1dfb1bcaae108fb8054c712a8f128efc7", size = 13459, upload-time = "2025-02-05T11:59:34.706Z" }, ] [[package]] name = "domdf-python-tools" -version = "3.9.0" +version = "3.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "natsort" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6b/78/974e10c583ba9d2302e748c9585313a7f2c7ba00e4f600324f432e38fe68/domdf_python_tools-3.9.0.tar.gz", hash = "sha256:1f8a96971178333a55e083e35610d7688cd7620ad2b99790164e1fc1a3614c18", size = 103792 } +sdist = { url = "https://files.pythonhosted.org/packages/36/8b/ab2d8a292bba8fe3135cacc8bfd3576710a14b8f2d0a8cde19130d5c9d21/domdf_python_tools-3.10.0.tar.gz", hash = "sha256:2ae308d2f4f1e9145f5f4ba57f840fbfd1c2983ee26e4824347789649d3ae298", size = 100458, upload-time = "2025-02-12T17:34:05.747Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/de/e9/7447a88b217650a74927d3444a89507986479a69b83741900eddd34167fe/domdf_python_tools-3.9.0-py3-none-any.whl", hash = "sha256:4e1ef365cbc24627d6d1e90cf7d46d8ab8df967e1237f4a26885f6986c78872e", size = 127106 }, + { url = "https://files.pythonhosted.org/packages/5b/11/208f72084084d3f6a2ed5ebfdfc846692c3f7ad6dce65e400194924f7eed/domdf_python_tools-3.10.0-py3-none-any.whl", hash = "sha256:5e71c1be71bbcc1f881d690c8984b60e64298ec256903b3147f068bc33090c36", size = 126860, upload-time = "2025-02-12T17:34:04.093Z" }, ] [[package]] name = "fake-useragent" -version = "1.5.1" +version = "2.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/a1/1f662631ab153975fa8dbf09296324ecbaf53370dce922054e8de6b57370/fake-useragent-1.5.1.tar.gz", hash = "sha256:6387269f5a2196b5ba7ed8935852f75486845a1c95c50e72460e6a8e762f5c49", size = 22631 } +sdist = { url = "https://files.pythonhosted.org/packages/41/43/948d10bf42735709edb5ae51e23297d034086f17fc7279fef385a7acb473/fake_useragent-2.2.0.tar.gz", hash = "sha256:4e6ab6571e40cc086d788523cf9e018f618d07f9050f822ff409a4dfe17c16b2", size = 158898, upload-time = "2025-04-14T15:32:19.238Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/99/60d8cf1b26938c2e0a57e232f7f15641dfcd6f8deda454d73e4145910ff6/fake_useragent-1.5.1-py3-none-any.whl", hash = "sha256:57415096557c8a4e23b62a375c21c55af5fd4ba30549227f562d2c4f5b60e3b3", size = 17190 }, + { url = "https://files.pythonhosted.org/packages/51/37/b3ea9cd5558ff4cb51957caca2193981c6b0ff30bd0d2630ac62505d99d0/fake_useragent-2.2.0-py3-none-any.whl", hash = "sha256:67f35ca4d847b0d298187443aaf020413746e56acd985a611908c73dba2daa24", size = 161695, upload-time = "2025-04-14T15:32:17.732Z" }, ] [[package]] name = "fonttools" -version = "4.55.0" +version = "4.58.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/4e/053fe1b5c0ce346c0a9d0557492c654362bafb14f026eae0d3ee98009152/fonttools-4.55.0.tar.gz", hash = "sha256:7636acc6ab733572d5e7eec922b254ead611f1cdad17be3f0be7418e8bfaca71", size = 3490431 } +sdist = { url = "https://files.pythonhosted.org/packages/9a/cf/4d037663e2a1fe30fddb655d755d76e18624be44ad467c07412c2319ab97/fonttools-4.58.0.tar.gz", hash = "sha256:27423d0606a2c7b336913254bf0b1193ebd471d5f725d665e875c5e88a011a43", size = 3514522, upload-time = "2025-05-10T17:36:35.886Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/87/a669ac26c6077e37ffb06abf29c5571789eefe518d06c52df392181ee694/fonttools-4.55.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8118dc571921dc9e4b288d9cb423ceaf886d195a2e5329cc427df82bba872cd9", size = 2752519 }, - { url = "https://files.pythonhosted.org/packages/0c/e9/4822ad238fe215133c7df20f1cdb1a58cfb634a31523e77ff0fb2033970a/fonttools-4.55.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01124f2ca6c29fad4132d930da69158d3f49b2350e4a779e1efbe0e82bd63f6c", size = 2286819 }, - { url = "https://files.pythonhosted.org/packages/3e/a4/d7941c3897129e60fe68d20e4819fda4d0c4858d77badae0e80ca6440b36/fonttools-4.55.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ffd58d2691f11f7c8438796e9f21c374828805d33e83ff4b76e4635633674c", size = 4770382 }, - { url = "https://files.pythonhosted.org/packages/31/cf/c51ea1348f9fba9c627439afad9dee0090040809ab431f4422b5bfdda34c/fonttools-4.55.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5435e5f1eb893c35c2bc2b9cd3c9596b0fcb0a59e7a14121562986dd4c47b8dd", size = 4858336 }, - { url = "https://files.pythonhosted.org/packages/73/be/36c1fe0e5c9a96b068ddd7e82001243bbe7fe12549c8d14e1bd025bf40c9/fonttools-4.55.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d12081729280c39d001edd0f4f06d696014c26e6e9a0a55488fabc37c28945e4", size = 4756072 }, - { url = "https://files.pythonhosted.org/packages/5c/18/6dd381c29f215a017f79aa9fea0722424a0046b47991c4390a78ff87ce0c/fonttools-4.55.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7ad1f1b98ab6cb927ab924a38a8649f1ffd7525c75fe5b594f5dab17af70e18", size = 5008668 }, - { url = "https://files.pythonhosted.org/packages/b8/95/316f20092b389b927dba1d1dccd3f541853f96e707e210f1b9f4e7bacdd5/fonttools-4.55.0-cp313-cp313-win32.whl", hash = "sha256:abe62987c37630dca69a104266277216de1023cf570c1643bb3a19a9509e7a1b", size = 2155841 }, - { url = "https://files.pythonhosted.org/packages/35/ca/b4638aa3e446184892e2f9cc8ef44bb506f47fea04580df7fb84f5a4363d/fonttools-4.55.0-cp313-cp313-win_amd64.whl", hash = "sha256:2863555ba90b573e4201feaf87a7e71ca3b97c05aa4d63548a4b69ea16c9e998", size = 2200587 }, - { url = "https://files.pythonhosted.org/packages/b4/4a/786589606d4989cb34d8bc766cd687d955aaf3039c367fe7104bcf82dc98/fonttools-4.55.0-py3-none-any.whl", hash = "sha256:12db5888cd4dd3fcc9f0ee60c6edd3c7e1fd44b7dd0f31381ea03df68f8a153f", size = 1100249 }, + { url = "https://files.pythonhosted.org/packages/0c/d7/d77cae11c445916d767cace93ba8283b3f360197d95d7470b90a9e984e10/fonttools-4.58.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:4809790f2371d8a08e59e1ce2b734c954cf09742e75642d7f4c46cfdac488fdd", size = 2728320, upload-time = "2025-05-10T17:35:56.455Z" }, + { url = "https://files.pythonhosted.org/packages/77/48/7d8b3c519ef4b48081d40310262224a38785e39a8610ccb92a229a6f085d/fonttools-4.58.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b00f240280f204ce4546b05ff3515bf8ff47a9cae914c718490025ea2bb9b324", size = 2302570, upload-time = "2025-05-10T17:35:58.794Z" }, + { url = "https://files.pythonhosted.org/packages/2c/48/156b83eb8fb7261056e448bfda1b495b90e761b28ec23cee10e3e19f1967/fonttools-4.58.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a62015ad463e1925544e9159dd6eefe33ebfb80938d5ab15d8b1c4b354ff47b", size = 4790066, upload-time = "2025-05-10T17:36:01.174Z" }, + { url = "https://files.pythonhosted.org/packages/60/49/aaecb1b3cea2b9b9c7cea6240d6bc8090feb5489a6fbf93cb68003be979b/fonttools-4.58.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ceef6f6ab58061a811967e3e32e630747fcb823dcc33a9a2c80e2d0d17cb292", size = 4861076, upload-time = "2025-05-10T17:36:03.663Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c8/97cbb41bee81ea9daf6109e0f3f70a274a3c69418e5ac6b0193f5dacf506/fonttools-4.58.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c7be21ac52370b515cdbdd0f400803fd29432a4fa4ddb4244ac8b322e54f36c0", size = 4858394, upload-time = "2025-05-10T17:36:06.087Z" }, + { url = "https://files.pythonhosted.org/packages/4d/23/c2c231457361f869a7d7374a557208e303b469d48a4a697c0fb249733ea1/fonttools-4.58.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:85836be4c3c4aacf6fcb7a6f263896d0e9ce431da9fa6fe9213d70f221f131c9", size = 5002160, upload-time = "2025-05-10T17:36:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/a9/e0/c2262f941a43b810c5c192db94b5d1ce8eda91bec2757f7e2416398f4072/fonttools-4.58.0-cp313-cp313-win32.whl", hash = "sha256:2b32b7130277bd742cb8c4379a6a303963597d22adea77a940343f3eadbcaa4c", size = 2171919, upload-time = "2025-05-10T17:36:10.644Z" }, + { url = "https://files.pythonhosted.org/packages/8f/ee/e4aa7bb4ce510ad57a808d321df1bbed1eeb6e1dfb20aaee1a5d9c076849/fonttools-4.58.0-cp313-cp313-win_amd64.whl", hash = "sha256:75e68ee2ec9aaa173cf5e33f243da1d51d653d5e25090f2722bc644a78db0f1a", size = 2222972, upload-time = "2025-05-10T17:36:12.495Z" }, + { url = "https://files.pythonhosted.org/packages/9b/1f/4417c26e26a1feab85a27e927f7a73d8aabc84544be8ba108ce4aa90eb1e/fonttools-4.58.0-py3-none-any.whl", hash = "sha256:c96c36880be2268be409df7b08c5b5dacac1827083461a6bc2cb07b8cbcec1d7", size = 1111440, upload-time = "2025-05-10T17:36:33.607Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, ] [[package]] name = "h5py" -version = "3.12.1" +version = "3.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cc/0c/5c2b0a88158682aeafb10c1c2b735df5bc31f165bfe192f2ee9f2a23b5f1/h5py-3.12.1.tar.gz", hash = "sha256:326d70b53d31baa61f00b8aa5f95c2fcb9621a3ee8365d770c551a13dbbcbfdf", size = 411457 } +sdist = { url = "https://files.pythonhosted.org/packages/03/2e/a22d6a8bfa6f8be33e7febd985680fba531562795f0a9077ed1eb047bfb0/h5py-3.13.0.tar.gz", hash = "sha256:1870e46518720023da85d0895a1960ff2ce398c5671eac3b1a41ec696b7105c3", size = 414876, upload-time = "2025-02-18T16:04:01.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/43/f276f27921919a9144074320ce4ca40882fc67b3cfee81c3f5c7df083e97/h5py-3.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e520ec76de00943dd017c8ea3f354fa1d2f542eac994811943a8faedf2a7d5cb", size = 3358040, upload-time = "2025-02-18T16:03:20.579Z" }, + { url = "https://files.pythonhosted.org/packages/1b/86/ad4a4cf781b08d4572be8bbdd8f108bb97b266a14835c640dc43dafc0729/h5py-3.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e79d8368cd9295045956bfb436656bea3f915beaa11d342e9f79f129f5178763", size = 2892766, upload-time = "2025-02-18T16:03:26.831Z" }, + { url = "https://files.pythonhosted.org/packages/69/84/4c6367d6b58deaf0fa84999ec819e7578eee96cea6cbd613640d0625ed5e/h5py-3.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56dd172d862e850823c4af02dc4ddbc308f042b85472ffdaca67f1598dff4a57", size = 4664255, upload-time = "2025-02-18T16:03:31.903Z" }, + { url = "https://files.pythonhosted.org/packages/fd/41/bc2df86b72965775f6d621e0ee269a5f3ac23e8f870abf519de9c7d93b4d/h5py-3.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be949b46b7388074c5acae017fbbe3e5ba303fd9daaa52157fdfef30bbdacadd", size = 4927580, upload-time = "2025-02-18T16:03:36.429Z" }, + { url = "https://files.pythonhosted.org/packages/97/34/165b87ea55184770a0c1fcdb7e017199974ad2e271451fd045cfe35f3add/h5py-3.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:4f97ecde7ac6513b21cd95efdfc38dc6d19f96f6ca6f2a30550e94e551458e0a", size = 2940890, upload-time = "2025-02-18T16:03:41.037Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/1c/ecdd0efab52c24f2a9bf2324289828b860e8dd1e3c5ada3cf0889e14fdc1/h5py-3.12.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:513171e90ed92236fc2ca363ce7a2fc6f2827375efcbb0cc7fbdd7fe11fecafc", size = 3346239 }, - { url = "https://files.pythonhosted.org/packages/93/cd/5b6f574bf3e318bbe305bc93ba45181676550eb44ba35e006d2e98004eaa/h5py-3.12.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:59400f88343b79655a242068a9c900001a34b63e3afb040bd7cdf717e440f653", size = 2843416 }, - { url = "https://files.pythonhosted.org/packages/8a/4f/b74332f313bfbe94ba03fff784219b9db385e6139708e55b11490149f90a/h5py-3.12.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3e465aee0ec353949f0f46bf6c6f9790a2006af896cee7c178a8c3e5090aa32", size = 5154390 }, - { url = "https://files.pythonhosted.org/packages/1a/57/93ea9e10a6457ea8d3b867207deb29a527e966a08a84c57ffd954e32152a/h5py-3.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba51c0c5e029bb5420a343586ff79d56e7455d496d18a30309616fdbeed1068f", size = 5378244 }, - { url = "https://files.pythonhosted.org/packages/50/51/0bbf3663062b2eeee78aa51da71e065f8a0a6e3cb950cc7020b4444999e6/h5py-3.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:52ab036c6c97055b85b2a242cb540ff9590bacfda0c03dd0cf0661b311f522f8", size = 2979760 }, + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, ] [[package]] name = "idna" version = "3.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, ] [[package]] name = "imageio" -version = "2.36.1" +version = "2.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "pillow" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/aa/2e7a49259339e691ff2b477ae0696b1784a09313c5872700bbbdd00a3030/imageio-2.36.1.tar.gz", hash = "sha256:e4e1d231f47f9a9e16100b0f7ce1a86e8856fb4d1c0fa2c4365a316f1746be62", size = 389522 } +sdist = { url = "https://files.pythonhosted.org/packages/0c/47/57e897fb7094afb2d26e8b2e4af9a45c7cf1a405acdeeca001fdf2c98501/imageio-2.37.0.tar.gz", hash = "sha256:71b57b3669666272c818497aebba2b4c5f20d5b37c81720e5e1a56d59c492996", size = 389963, upload-time = "2025-01-20T02:42:37.089Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/f9/f78e7f5ac8077c481bf6b43b8bc736605363034b3d5eb3ce8eb79f53f5f1/imageio-2.36.1-py3-none-any.whl", hash = "sha256:20abd2cae58e55ca1af8a8dcf43293336a59adf0391f1917bf8518633cfc2cdf", size = 315435 }, + { url = "https://files.pythonhosted.org/packages/cb/bd/b394387b598ed84d8d0fa90611a90bee0adc2021820ad5729f7ced74a8e2/imageio-2.37.0-py3-none-any.whl", hash = "sha256:11efa15b87bc7871b61590326b2d635439acc321cf7f8ce996f812543ce10eed", size = 315796, upload-time = "2025-01-20T02:42:34.931Z" }, ] [[package]] name = "imagesize" version = "1.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026 } +sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769 }, + { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, ] [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] [[package]] name = "jinja2" -version = "3.1.4" +version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 } +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 }, + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] [[package]] name = "joblib" -version = "1.4.2" +version = "1.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/64/33/60135848598c076ce4b231e1b1895170f45fbcaeaa2c9d5e38b04db70c35/joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e", size = 2116621 } +sdist = { url = "https://files.pythonhosted.org/packages/30/08/8bd4a0250247861420a040b33ccf42f43c426ac91d99405374ef117e5872/joblib-1.5.0.tar.gz", hash = "sha256:d8757f955389a3dd7a23152e43bc297c2e0c2d3060056dad0feefc88a06939b5", size = 330234, upload-time = "2025-05-03T21:09:39.553Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/91/29/df4b9b42f2be0b623cbd5e2140cafcaa2bef0759a00b7b70104dcfe2fb51/joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6", size = 301817 }, + { url = "https://files.pythonhosted.org/packages/da/d3/13ee227a148af1c693654932b8b0b02ed64af5e1f7406d56b088b57574cd/joblib-1.5.0-py3-none-any.whl", hash = "sha256:206144b320246485b712fc8cc51f017de58225fa8b414a1fe1764a7231aca491", size = 307682, upload-time = "2025-05-03T21:09:37.892Z" }, ] [[package]] name = "keras" -version = "3.7.0" +version = "3.9.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "absl-py" }, @@ -325,58 +367,70 @@ dependencies = [ { name = "packaging" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/c3/56fc6800c5eab94bd0f5e930751bd4c0fa1ee0aee272fad4a72723ffae87/keras-3.7.0.tar.gz", hash = "sha256:a4451a5591e75dfb414d0b84a3fd2fb9c0240cc87ebe7e397f547ce10b0e67b7", size = 924719 } +sdist = { url = "https://files.pythonhosted.org/packages/28/4e/82a1176f1ea70982ade0f7e360c6f259b68203f64a108cc1967500d4b7ff/keras-3.9.2.tar.gz", hash = "sha256:322aab6418ee3de1e2bd0871b60a07f0e444e744a7e8cba79af8b42408879ecf", size = 1002482, upload-time = "2025-04-02T19:03:08.953Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/bf/9e3f10e55df30b0fb4bf6c2ee7d50bda2e070599b86f62ea3f9954af172b/keras-3.7.0-py3-none-any.whl", hash = "sha256:546a64f302e4779c129c06d9826fa586de752cdfd43d7dc4010c31b282587969", size = 1228365 }, + { url = "https://files.pythonhosted.org/packages/3f/0a/678ebcf4b6dad6ad63dfc2445d190f79a97fa7bc7150f57a6c505459e2bc/keras-3.9.2-py3-none-any.whl", hash = "sha256:404427856c2dc30e38c9fa6fa6a13ffb1844a8c35af312ca32a8e7dea9840f1e", size = 1341966, upload-time = "2025-04-02T19:03:07.502Z" }, ] [[package]] name = "kiwisolver" -version = "1.4.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/85/4d/2255e1c76304cbd60b48cee302b66d1dde4468dc5b1160e4b7cb43778f2a/kiwisolver-1.4.7.tar.gz", hash = "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60", size = 97286 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/06/7da99b04259b0f18b557a4effd1b9c901a747f7fdd84cf834ccf520cb0b2/kiwisolver-1.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2e6039dcbe79a8e0f044f1c39db1986a1b8071051efba3ee4d74f5b365f5226e", size = 121913 }, - { url = "https://files.pythonhosted.org/packages/97/f5/b8a370d1aa593c17882af0a6f6755aaecd643640c0ed72dcfd2eafc388b9/kiwisolver-1.4.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a1ecf0ac1c518487d9d23b1cd7139a6a65bc460cd101ab01f1be82ecf09794b6", size = 65627 }, - { url = "https://files.pythonhosted.org/packages/2a/fc/6c0374f7503522539e2d4d1b497f5ebad3f8ed07ab51aed2af988dd0fb65/kiwisolver-1.4.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ab9ccab2b5bd5702ab0803676a580fffa2aa178c2badc5557a84cc943fcf750", size = 63888 }, - { url = "https://files.pythonhosted.org/packages/bf/3e/0b7172793d0f41cae5c923492da89a2ffcd1adf764c16159ca047463ebd3/kiwisolver-1.4.7-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f816dd2277f8d63d79f9c8473a79fe54047bc0467754962840782c575522224d", size = 1369145 }, - { url = "https://files.pythonhosted.org/packages/77/92/47d050d6f6aced2d634258123f2688fbfef8ded3c5baf2c79d94d91f1f58/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf8bcc23ceb5a1b624572a1623b9f79d2c3b337c8c455405ef231933a10da379", size = 1461448 }, - { url = "https://files.pythonhosted.org/packages/9c/1b/8f80b18e20b3b294546a1adb41701e79ae21915f4175f311a90d042301cf/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dea0bf229319828467d7fca8c7c189780aa9ff679c94539eed7532ebe33ed37c", size = 1578750 }, - { url = "https://files.pythonhosted.org/packages/a4/fe/fe8e72f3be0a844f257cadd72689c0848c6d5c51bc1d60429e2d14ad776e/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c06a4c7cf15ec739ce0e5971b26c93638730090add60e183530d70848ebdd34", size = 1507175 }, - { url = "https://files.pythonhosted.org/packages/39/fa/cdc0b6105d90eadc3bee525fecc9179e2b41e1ce0293caaf49cb631a6aaf/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913983ad2deb14e66d83c28b632fd35ba2b825031f2fa4ca29675e665dfecbe1", size = 1463963 }, - { url = "https://files.pythonhosted.org/packages/6e/5c/0c03c4e542720c6177d4f408e56d1c8315899db72d46261a4e15b8b33a41/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5337ec7809bcd0f424c6b705ecf97941c46279cf5ed92311782c7c9c2026f07f", size = 2248220 }, - { url = "https://files.pythonhosted.org/packages/3d/ee/55ef86d5a574f4e767df7da3a3a7ff4954c996e12d4fbe9c408170cd7dcc/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c26ed10c4f6fa6ddb329a5120ba3b6db349ca192ae211e882970bfc9d91420b", size = 2404463 }, - { url = "https://files.pythonhosted.org/packages/0f/6d/73ad36170b4bff4825dc588acf4f3e6319cb97cd1fb3eb04d9faa6b6f212/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c619b101e6de2222c1fcb0531e1b17bbffbe54294bfba43ea0d411d428618c27", size = 2352842 }, - { url = "https://files.pythonhosted.org/packages/0b/16/fa531ff9199d3b6473bb4d0f47416cdb08d556c03b8bc1cccf04e756b56d/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:073a36c8273647592ea332e816e75ef8da5c303236ec0167196793eb1e34657a", size = 2501635 }, - { url = "https://files.pythonhosted.org/packages/78/7e/aa9422e78419db0cbe75fb86d8e72b433818f2e62e2e394992d23d23a583/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3ce6b2b0231bda412463e152fc18335ba32faf4e8c23a754ad50ffa70e4091ee", size = 2314556 }, - { url = "https://files.pythonhosted.org/packages/a8/b2/15f7f556df0a6e5b3772a1e076a9d9f6c538ce5f05bd590eca8106508e06/kiwisolver-1.4.7-cp313-cp313-win32.whl", hash = "sha256:f4c9aee212bc89d4e13f58be11a56cc8036cabad119259d12ace14b34476fd07", size = 46364 }, - { url = "https://files.pythonhosted.org/packages/0b/db/32e897e43a330eee8e4770bfd2737a9584b23e33587a0812b8e20aac38f7/kiwisolver-1.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:8a3ec5aa8e38fc4c8af308917ce12c536f1c88452ce554027e55b22cbbfbff76", size = 55887 }, - { url = "https://files.pythonhosted.org/packages/c8/a4/df2bdca5270ca85fd25253049eb6708d4127be2ed0e5c2650217450b59e9/kiwisolver-1.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:76c8094ac20ec259471ac53e774623eb62e6e1f56cd8690c67ce6ce4fcb05650", size = 48530 }, +version = "1.4.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/59/7c91426a8ac292e1cdd53a63b6d9439abd573c875c3f92c146767dd33faf/kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e", size = 97538, upload-time = "2024-12-24T18:30:51.519Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/b3/e62464a652f4f8cd9006e13d07abad844a47df1e6537f73ddfbf1bc997ec/kiwisolver-1.4.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1c8ceb754339793c24aee1c9fb2485b5b1f5bb1c2c214ff13368431e51fc9a09", size = 124156, upload-time = "2024-12-24T18:29:45.368Z" }, + { url = "https://files.pythonhosted.org/packages/8d/2d/f13d06998b546a2ad4f48607a146e045bbe48030774de29f90bdc573df15/kiwisolver-1.4.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a62808ac74b5e55a04a408cda6156f986cefbcf0ada13572696b507cc92fa1", size = 66555, upload-time = "2024-12-24T18:29:46.37Z" }, + { url = "https://files.pythonhosted.org/packages/59/e3/b8bd14b0a54998a9fd1e8da591c60998dc003618cb19a3f94cb233ec1511/kiwisolver-1.4.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68269e60ee4929893aad82666821aaacbd455284124817af45c11e50a4b42e3c", size = 65071, upload-time = "2024-12-24T18:29:47.333Z" }, + { url = "https://files.pythonhosted.org/packages/f0/1c/6c86f6d85ffe4d0ce04228d976f00674f1df5dc893bf2dd4f1928748f187/kiwisolver-1.4.8-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34d142fba9c464bc3bbfeff15c96eab0e7310343d6aefb62a79d51421fcc5f1b", size = 1378053, upload-time = "2024-12-24T18:29:49.636Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b9/1c6e9f6dcb103ac5cf87cb695845f5fa71379021500153566d8a8a9fc291/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc373e0eef45b59197de815b1b28ef89ae3955e7722cc9710fb91cd77b7f47", size = 1472278, upload-time = "2024-12-24T18:29:51.164Z" }, + { url = "https://files.pythonhosted.org/packages/ee/81/aca1eb176de671f8bda479b11acdc42c132b61a2ac861c883907dde6debb/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77e6f57a20b9bd4e1e2cedda4d0b986ebd0216236f0106e55c28aea3d3d69b16", size = 1478139, upload-time = "2024-12-24T18:29:52.594Z" }, + { url = "https://files.pythonhosted.org/packages/49/f4/e081522473671c97b2687d380e9e4c26f748a86363ce5af48b4a28e48d06/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08e77738ed7538f036cd1170cbed942ef749137b1311fa2bbe2a7fda2f6bf3cc", size = 1413517, upload-time = "2024-12-24T18:29:53.941Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e9/6a7d025d8da8c4931522922cd706105aa32b3291d1add8c5427cdcd66e63/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5ce1e481a74b44dd5e92ff03ea0cb371ae7a0268318e202be06c8f04f4f1246", size = 1474952, upload-time = "2024-12-24T18:29:56.523Z" }, + { url = "https://files.pythonhosted.org/packages/82/13/13fa685ae167bee5d94b415991c4fc7bb0a1b6ebea6e753a87044b209678/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fc2ace710ba7c1dfd1a3b42530b62b9ceed115f19a1656adefce7b1782a37794", size = 2269132, upload-time = "2024-12-24T18:29:57.989Z" }, + { url = "https://files.pythonhosted.org/packages/ef/92/bb7c9395489b99a6cb41d502d3686bac692586db2045adc19e45ee64ed23/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3452046c37c7692bd52b0e752b87954ef86ee2224e624ef7ce6cb21e8c41cc1b", size = 2425997, upload-time = "2024-12-24T18:29:59.393Z" }, + { url = "https://files.pythonhosted.org/packages/ed/12/87f0e9271e2b63d35d0d8524954145837dd1a6c15b62a2d8c1ebe0f182b4/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7e9a60b50fe8b2ec6f448fe8d81b07e40141bfced7f896309df271a0b92f80f3", size = 2376060, upload-time = "2024-12-24T18:30:01.338Z" }, + { url = "https://files.pythonhosted.org/packages/02/6e/c8af39288edbce8bf0fa35dee427b082758a4b71e9c91ef18fa667782138/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:918139571133f366e8362fa4a297aeba86c7816b7ecf0bc79168080e2bd79957", size = 2520471, upload-time = "2024-12-24T18:30:04.574Z" }, + { url = "https://files.pythonhosted.org/packages/13/78/df381bc7b26e535c91469f77f16adcd073beb3e2dd25042efd064af82323/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e063ef9f89885a1d68dd8b2e18f5ead48653176d10a0e324e3b0030e3a69adeb", size = 2338793, upload-time = "2024-12-24T18:30:06.25Z" }, + { url = "https://files.pythonhosted.org/packages/d0/dc/c1abe38c37c071d0fc71c9a474fd0b9ede05d42f5a458d584619cfd2371a/kiwisolver-1.4.8-cp313-cp313-win_amd64.whl", hash = "sha256:a17b7c4f5b2c51bb68ed379defd608a03954a1845dfed7cc0117f1cc8a9b7fd2", size = 71855, upload-time = "2024-12-24T18:30:07.535Z" }, + { url = "https://files.pythonhosted.org/packages/a0/b6/21529d595b126ac298fdd90b705d87d4c5693de60023e0efcb4f387ed99e/kiwisolver-1.4.8-cp313-cp313-win_arm64.whl", hash = "sha256:3cd3bc628b25f74aedc6d374d5babf0166a92ff1317f46267f12d2ed54bc1d30", size = 65430, upload-time = "2024-12-24T18:30:08.504Z" }, + { url = "https://files.pythonhosted.org/packages/34/bd/b89380b7298e3af9b39f49334e3e2a4af0e04819789f04b43d560516c0c8/kiwisolver-1.4.8-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:370fd2df41660ed4e26b8c9d6bbcad668fbe2560462cba151a721d49e5b6628c", size = 126294, upload-time = "2024-12-24T18:30:09.508Z" }, + { url = "https://files.pythonhosted.org/packages/83/41/5857dc72e5e4148eaac5aa76e0703e594e4465f8ab7ec0fc60e3a9bb8fea/kiwisolver-1.4.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:84a2f830d42707de1d191b9490ac186bf7997a9495d4e9072210a1296345f7dc", size = 67736, upload-time = "2024-12-24T18:30:11.039Z" }, + { url = "https://files.pythonhosted.org/packages/e1/d1/be059b8db56ac270489fb0b3297fd1e53d195ba76e9bbb30e5401fa6b759/kiwisolver-1.4.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7a3ad337add5148cf51ce0b55642dc551c0b9d6248458a757f98796ca7348712", size = 66194, upload-time = "2024-12-24T18:30:14.886Z" }, + { url = "https://files.pythonhosted.org/packages/e1/83/4b73975f149819eb7dcf9299ed467eba068ecb16439a98990dcb12e63fdd/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7506488470f41169b86d8c9aeff587293f530a23a23a49d6bc64dab66bedc71e", size = 1465942, upload-time = "2024-12-24T18:30:18.927Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2c/30a5cdde5102958e602c07466bce058b9d7cb48734aa7a4327261ac8e002/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f0121b07b356a22fb0414cec4666bbe36fd6d0d759db3d37228f496ed67c880", size = 1595341, upload-time = "2024-12-24T18:30:22.102Z" }, + { url = "https://files.pythonhosted.org/packages/ff/9b/1e71db1c000385aa069704f5990574b8244cce854ecd83119c19e83c9586/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6d6bd87df62c27d4185de7c511c6248040afae67028a8a22012b010bc7ad062", size = 1598455, upload-time = "2024-12-24T18:30:24.947Z" }, + { url = "https://files.pythonhosted.org/packages/85/92/c8fec52ddf06231b31cbb779af77e99b8253cd96bd135250b9498144c78b/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:291331973c64bb9cce50bbe871fb2e675c4331dab4f31abe89f175ad7679a4d7", size = 1522138, upload-time = "2024-12-24T18:30:26.286Z" }, + { url = "https://files.pythonhosted.org/packages/0b/51/9eb7e2cd07a15d8bdd976f6190c0164f92ce1904e5c0c79198c4972926b7/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:893f5525bb92d3d735878ec00f781b2de998333659507d29ea4466208df37bed", size = 1582857, upload-time = "2024-12-24T18:30:28.86Z" }, + { url = "https://files.pythonhosted.org/packages/0f/95/c5a00387a5405e68ba32cc64af65ce881a39b98d73cc394b24143bebc5b8/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b47a465040146981dc9db8647981b8cb96366fbc8d452b031e4f8fdffec3f26d", size = 2293129, upload-time = "2024-12-24T18:30:30.34Z" }, + { url = "https://files.pythonhosted.org/packages/44/83/eeb7af7d706b8347548313fa3a3a15931f404533cc54fe01f39e830dd231/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:99cea8b9dd34ff80c521aef46a1dddb0dcc0283cf18bde6d756f1e6f31772165", size = 2421538, upload-time = "2024-12-24T18:30:33.334Z" }, + { url = "https://files.pythonhosted.org/packages/05/f9/27e94c1b3eb29e6933b6986ffc5fa1177d2cd1f0c8efc5f02c91c9ac61de/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:151dffc4865e5fe6dafce5480fab84f950d14566c480c08a53c663a0020504b6", size = 2390661, upload-time = "2024-12-24T18:30:34.939Z" }, + { url = "https://files.pythonhosted.org/packages/d9/d4/3c9735faa36ac591a4afcc2980d2691000506050b7a7e80bcfe44048daa7/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:577facaa411c10421314598b50413aa1ebcf5126f704f1e5d72d7e4e9f020d90", size = 2546710, upload-time = "2024-12-24T18:30:37.281Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fa/be89a49c640930180657482a74970cdcf6f7072c8d2471e1babe17a222dc/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:be4816dc51c8a471749d664161b434912eee82f2ea66bd7628bd14583a833e85", size = 2349213, upload-time = "2024-12-24T18:30:40.019Z" }, ] [[package]] name = "lxml" -version = "5.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/6b/20c3a4b24751377aaa6307eb230b66701024012c29dd374999cc92983269/lxml-5.3.0.tar.gz", hash = "sha256:4e109ca30d1edec1ac60cdbe341905dc3b8f55b16855e03a54aaf59e51ec8c6f", size = 3679318 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/94/6a/42141e4d373903bfea6f8e94b2f554d05506dfda522ada5343c651410dc8/lxml-5.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c72e9563347c7395910de6a3100a4840a75a6f60e05af5e58566868d5eb2d6a", size = 8156284 }, - { url = "https://files.pythonhosted.org/packages/91/5e/fa097f0f7d8b3d113fb7312c6308af702f2667f22644441715be961f2c7e/lxml-5.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e92ce66cd919d18d14b3856906a61d3f6b6a8500e0794142338da644260595cd", size = 4432407 }, - { url = "https://files.pythonhosted.org/packages/2d/a1/b901988aa6d4ff937f2e5cfc114e4ec561901ff00660c3e56713642728da/lxml-5.3.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d04f064bebdfef9240478f7a779e8c5dc32b8b7b0b2fc6a62e39b928d428e51", size = 5048331 }, - { url = "https://files.pythonhosted.org/packages/30/0f/b2a54f48e52de578b71bbe2a2f8160672a8a5e103df3a78da53907e8c7ed/lxml-5.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c2fb570d7823c2bbaf8b419ba6e5662137f8166e364a8b2b91051a1fb40ab8b", size = 4744835 }, - { url = "https://files.pythonhosted.org/packages/82/9d/b000c15538b60934589e83826ecbc437a1586488d7c13f8ee5ff1f79a9b8/lxml-5.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c120f43553ec759f8de1fee2f4794452b0946773299d44c36bfe18e83caf002", size = 5316649 }, - { url = "https://files.pythonhosted.org/packages/e3/ee/ffbb9eaff5e541922611d2c56b175c45893d1c0b8b11e5a497708a6a3b3b/lxml-5.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:562e7494778a69086f0312ec9689f6b6ac1c6b65670ed7d0267e49f57ffa08c4", size = 4812046 }, - { url = "https://files.pythonhosted.org/packages/15/ff/7ff89d567485c7b943cdac316087f16b2399a8b997007ed352a1248397e5/lxml-5.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:423b121f7e6fa514ba0c7918e56955a1d4470ed35faa03e3d9f0e3baa4c7e492", size = 4918597 }, - { url = "https://files.pythonhosted.org/packages/c6/a3/535b6ed8c048412ff51268bdf4bf1cf052a37aa7e31d2e6518038a883b29/lxml-5.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c00f323cc00576df6165cc9d21a4c21285fa6b9989c5c39830c3903dc4303ef3", size = 4738071 }, - { url = "https://files.pythonhosted.org/packages/7a/8f/cbbfa59cb4d4fd677fe183725a76d8c956495d7a3c7f111ab8f5e13d2e83/lxml-5.3.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:1fdc9fae8dd4c763e8a31e7630afef517eab9f5d5d31a278df087f307bf601f4", size = 5342213 }, - { url = "https://files.pythonhosted.org/packages/5c/fb/db4c10dd9958d4b52e34d1d1f7c1f434422aeaf6ae2bbaaff2264351d944/lxml-5.3.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:658f2aa69d31e09699705949b5fc4719cbecbd4a97f9656a232e7d6c7be1a367", size = 4893749 }, - { url = "https://files.pythonhosted.org/packages/f2/38/bb4581c143957c47740de18a3281a0cab7722390a77cc6e610e8ebf2d736/lxml-5.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1473427aff3d66a3fa2199004c3e601e6c4500ab86696edffdbc84954c72d832", size = 4945901 }, - { url = "https://files.pythonhosted.org/packages/fc/d5/18b7de4960c731e98037bd48fa9f8e6e8f2558e6fbca4303d9b14d21ef3b/lxml-5.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a87de7dd873bf9a792bf1e58b1c3887b9264036629a5bf2d2e6579fe8e73edff", size = 4815447 }, - { url = "https://files.pythonhosted.org/packages/97/a8/cd51ceaad6eb849246559a8ef60ae55065a3df550fc5fcd27014361c1bab/lxml-5.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0d7b36afa46c97875303a94e8f3ad932bf78bace9e18e603f2085b652422edcd", size = 5411186 }, - { url = "https://files.pythonhosted.org/packages/89/c3/1e3dabab519481ed7b1fdcba21dcfb8832f57000733ef0e71cf6d09a5e03/lxml-5.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:cf120cce539453ae086eacc0130a324e7026113510efa83ab42ef3fcfccac7fb", size = 5324481 }, - { url = "https://files.pythonhosted.org/packages/b6/17/71e9984cf0570cd202ac0a1c9ed5c1b8889b0fc8dc736f5ef0ffb181c284/lxml-5.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:df5c7333167b9674aa8ae1d4008fa4bc17a313cc490b2cca27838bbdcc6bb15b", size = 5011053 }, - { url = "https://files.pythonhosted.org/packages/69/68/9f7e6d3312a91e30829368c2b3217e750adef12a6f8eb10498249f4e8d72/lxml-5.3.0-cp313-cp313-win32.whl", hash = "sha256:c802e1c2ed9f0c06a65bc4ed0189d000ada8049312cfeab6ca635e39c9608957", size = 3485634 }, - { url = "https://files.pythonhosted.org/packages/7d/db/214290d58ad68c587bd5d6af3d34e56830438733d0d0856c0275fde43652/lxml-5.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:406246b96d552e0503e17a1006fd27edac678b3fcc9f1be71a2f94b4ff61528d", size = 3814417 }, +version = "5.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/3d/14e82fc7c8fb1b7761f7e748fd47e2ec8276d137b6acfe5a4bb73853e08f/lxml-5.4.0.tar.gz", hash = "sha256:d12832e1dbea4be280b22fd0ea7c9b87f0d8fc51ba06e92dc62d52f804f78ebd", size = 3679479, upload-time = "2025-04-23T01:50:29.322Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/cb/2ba1e9dd953415f58548506fa5549a7f373ae55e80c61c9041b7fd09a38a/lxml-5.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:773e27b62920199c6197130632c18fb7ead3257fce1ffb7d286912e56ddb79e0", size = 8110086, upload-time = "2025-04-23T01:46:52.218Z" }, + { url = "https://files.pythonhosted.org/packages/b5/3e/6602a4dca3ae344e8609914d6ab22e52ce42e3e1638c10967568c5c1450d/lxml-5.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ce9c671845de9699904b1e9df95acfe8dfc183f2310f163cdaa91a3535af95de", size = 4404613, upload-time = "2025-04-23T01:46:55.281Z" }, + { url = "https://files.pythonhosted.org/packages/4c/72/bf00988477d3bb452bef9436e45aeea82bb40cdfb4684b83c967c53909c7/lxml-5.4.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9454b8d8200ec99a224df8854786262b1bd6461f4280064c807303c642c05e76", size = 5012008, upload-time = "2025-04-23T01:46:57.817Z" }, + { url = "https://files.pythonhosted.org/packages/92/1f/93e42d93e9e7a44b2d3354c462cd784dbaaf350f7976b5d7c3f85d68d1b1/lxml-5.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cccd007d5c95279e529c146d095f1d39ac05139de26c098166c4beb9374b0f4d", size = 4760915, upload-time = "2025-04-23T01:47:00.745Z" }, + { url = "https://files.pythonhosted.org/packages/45/0b/363009390d0b461cf9976a499e83b68f792e4c32ecef092f3f9ef9c4ba54/lxml-5.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0fce1294a0497edb034cb416ad3e77ecc89b313cff7adbee5334e4dc0d11f422", size = 5283890, upload-time = "2025-04-23T01:47:04.702Z" }, + { url = "https://files.pythonhosted.org/packages/19/dc/6056c332f9378ab476c88e301e6549a0454dbee8f0ae16847414f0eccb74/lxml-5.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24974f774f3a78ac12b95e3a20ef0931795ff04dbb16db81a90c37f589819551", size = 4812644, upload-time = "2025-04-23T01:47:07.833Z" }, + { url = "https://files.pythonhosted.org/packages/ee/8a/f8c66bbb23ecb9048a46a5ef9b495fd23f7543df642dabeebcb2eeb66592/lxml-5.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:497cab4d8254c2a90bf988f162ace2ddbfdd806fce3bda3f581b9d24c852e03c", size = 4921817, upload-time = "2025-04-23T01:47:10.317Z" }, + { url = "https://files.pythonhosted.org/packages/04/57/2e537083c3f381f83d05d9b176f0d838a9e8961f7ed8ddce3f0217179ce3/lxml-5.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:e794f698ae4c5084414efea0f5cc9f4ac562ec02d66e1484ff822ef97c2cadff", size = 4753916, upload-time = "2025-04-23T01:47:12.823Z" }, + { url = "https://files.pythonhosted.org/packages/d8/80/ea8c4072109a350848f1157ce83ccd9439601274035cd045ac31f47f3417/lxml-5.4.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:2c62891b1ea3094bb12097822b3d44b93fc6c325f2043c4d2736a8ff09e65f60", size = 5289274, upload-time = "2025-04-23T01:47:15.916Z" }, + { url = "https://files.pythonhosted.org/packages/b3/47/c4be287c48cdc304483457878a3f22999098b9a95f455e3c4bda7ec7fc72/lxml-5.4.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:142accb3e4d1edae4b392bd165a9abdee8a3c432a2cca193df995bc3886249c8", size = 4874757, upload-time = "2025-04-23T01:47:19.793Z" }, + { url = "https://files.pythonhosted.org/packages/2f/04/6ef935dc74e729932e39478e44d8cfe6a83550552eaa072b7c05f6f22488/lxml-5.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1a42b3a19346e5601d1b8296ff6ef3d76038058f311902edd574461e9c036982", size = 4947028, upload-time = "2025-04-23T01:47:22.401Z" }, + { url = "https://files.pythonhosted.org/packages/cb/f9/c33fc8daa373ef8a7daddb53175289024512b6619bc9de36d77dca3df44b/lxml-5.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4291d3c409a17febf817259cb37bc62cb7eb398bcc95c1356947e2871911ae61", size = 4834487, upload-time = "2025-04-23T01:47:25.513Z" }, + { url = "https://files.pythonhosted.org/packages/8d/30/fc92bb595bcb878311e01b418b57d13900f84c2b94f6eca9e5073ea756e6/lxml-5.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4f5322cf38fe0e21c2d73901abf68e6329dc02a4994e483adbcf92b568a09a54", size = 5381688, upload-time = "2025-04-23T01:47:28.454Z" }, + { url = "https://files.pythonhosted.org/packages/43/d1/3ba7bd978ce28bba8e3da2c2e9d5ae3f8f521ad3f0ca6ea4788d086ba00d/lxml-5.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0be91891bdb06ebe65122aa6bf3fc94489960cf7e03033c6f83a90863b23c58b", size = 5242043, upload-time = "2025-04-23T01:47:31.208Z" }, + { url = "https://files.pythonhosted.org/packages/ee/cd/95fa2201041a610c4d08ddaf31d43b98ecc4b1d74b1e7245b1abdab443cb/lxml-5.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:15a665ad90054a3d4f397bc40f73948d48e36e4c09f9bcffc7d90c87410e478a", size = 5021569, upload-time = "2025-04-23T01:47:33.805Z" }, + { url = "https://files.pythonhosted.org/packages/2d/a6/31da006fead660b9512d08d23d31e93ad3477dd47cc42e3285f143443176/lxml-5.4.0-cp313-cp313-win32.whl", hash = "sha256:d5663bc1b471c79f5c833cffbc9b87d7bf13f87e055a5c86c363ccd2348d7e82", size = 3485270, upload-time = "2025-04-23T01:47:36.133Z" }, + { url = "https://files.pythonhosted.org/packages/fc/14/c115516c62a7d2499781d2d3d7215218c0731b2c940753bf9f9b7b73924d/lxml-5.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:bcb7a1096b4b6b24ce1ac24d4942ad98f983cd3810f9711bcd0293f43a9d8b9f", size = 3814606, upload-time = "2025-04-23T01:47:39.028Z" }, ] [[package]] @@ -386,42 +440,42 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, ] [[package]] name = "markupsafe" version = "3.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, - { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, - { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, - { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 }, - { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 }, - { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 }, - { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 }, - { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 }, - { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 }, - { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 }, - { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 }, - { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 }, - { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 }, - { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 }, - { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 }, - { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 }, - { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 }, - { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 }, - { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 }, - { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, ] [[package]] name = "matplotlib" -version = "3.9.3" +version = "3.10.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "contourpy" }, @@ -434,20 +488,20 @@ dependencies = [ { name = "pyparsing" }, { name = "python-dateutil" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/75/9f/562ed484b11ac9f4bb4f9d2d7546954ec106a8c0f06cc755d6f63e519274/matplotlib-3.9.3.tar.gz", hash = "sha256:cd5dbbc8e25cad5f706845c4d100e2c8b34691b412b93717ce38d8ae803bcfa5", size = 36113438 } +sdist = { url = "https://files.pythonhosted.org/packages/26/91/d49359a21893183ed2a5b6c76bec40e0b1dcbf8ca148f864d134897cfc75/matplotlib-3.10.3.tar.gz", hash = "sha256:2f82d2c5bb7ae93aaaa4cd42aca65d76ce6376f83304fa3a630b569aca274df0", size = 34799811, upload-time = "2025-05-08T19:10:54.39Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/60/04/949640040982822416c471d9ebe4e9e6c69ca9f9bb6ba82ed30808863c02/matplotlib-3.9.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:203d18df84f5288973b2d56de63d4678cc748250026ca9e1ad8f8a0fd8a75d83", size = 7883417 }, - { url = "https://files.pythonhosted.org/packages/9f/90/ebd37143cd3150b6c650ee1580024df3dd649d176e68d346f826b8d24e37/matplotlib-3.9.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b651b0d3642991259109dc0351fc33ad44c624801367bb8307be9bfc35e427ad", size = 7768720 }, - { url = "https://files.pythonhosted.org/packages/dc/84/6591e6b55d755d16dacdc113205067031867c1f5e3c08b32c01aad831420/matplotlib-3.9.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66d7b171fecf96940ce069923a08ba3df33ef542de82c2ff4fe8caa8346fa95a", size = 8192723 }, - { url = "https://files.pythonhosted.org/packages/29/09/146a17d37e32313507f11ac984e65311f2d5805d731eb981d4f70eb928dc/matplotlib-3.9.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6be0ba61f6ff2e6b68e4270fb63b6813c9e7dec3d15fc3a93f47480444fd72f0", size = 8305801 }, - { url = "https://files.pythonhosted.org/packages/85/cb/d2690572c08f19ca7c0f44b1fb4d11c121d63467a57b508cc3656ff80b43/matplotlib-3.9.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d6b2e8856dec3a6db1ae51aec85c82223e834b228c1d3228aede87eee2b34f9", size = 9086564 }, - { url = "https://files.pythonhosted.org/packages/28/dd/0a5176027c1cb94fe75f69f76cb274180c8abf740df6fc0e6a1e4cbaec3f/matplotlib-3.9.3-cp313-cp313-win_amd64.whl", hash = "sha256:90a85a004fefed9e583597478420bf904bb1a065b0b0ee5b9d8d31b04b0f3f70", size = 7833257 }, - { url = "https://files.pythonhosted.org/packages/42/d4/e477d50a8e4b437c2afbb5c665cb8e5d79b06abe6fe3c6915d6f7f0c2ef2/matplotlib-3.9.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3119b2f16de7f7b9212ba76d8fe6a0e9f90b27a1e04683cd89833a991682f639", size = 7911906 }, - { url = "https://files.pythonhosted.org/packages/ae/a1/ba5ab89666c42ace8e31b4ff5a2c76a17e4d6f91aefce476b064c56ff61d/matplotlib-3.9.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:87ad73763d93add1b6c1f9fcd33af662fd62ed70e620c52fcb79f3ac427cf3a6", size = 7801336 }, - { url = "https://files.pythonhosted.org/packages/77/59/4dcdb3a6695af6c698a95aec13016a550ef2f85144d22f61f81d1e064148/matplotlib-3.9.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:026bdf3137ab6022c866efa4813b6bbeddc2ed4c9e7e02f0e323a7bca380dfa0", size = 8218178 }, - { url = "https://files.pythonhosted.org/packages/4f/27/7c72db0d0ee35d9237572565ffa3c0eb25fc46a3f47e0f16412a587bc9d8/matplotlib-3.9.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760a5e89ebbb172989e8273024a1024b0f084510b9105261b3b00c15e9c9f006", size = 8327768 }, - { url = "https://files.pythonhosted.org/packages/de/ad/213eee624feadba7b77e881c9d2c04c1e036efe69d19031e3fa927fdb5dc/matplotlib-3.9.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a42b9dc42de2cfe357efa27d9c50c7833fc5ab9b2eb7252ccd5d5f836a84e1e4", size = 9094075 }, - { url = "https://files.pythonhosted.org/packages/19/1b/cb8e99a5fe2e2b14e3b8234cb1649a675be63f74a5224a648ae4ab61f60c/matplotlib-3.9.3-cp313-cp313t-win_amd64.whl", hash = "sha256:e0fcb7da73fbf67b5f4bdaa57d85bb585a4e913d4a10f3e15b32baea56a67f0a", size = 7888937 }, + { url = "https://files.pythonhosted.org/packages/3b/c1/23cfb566a74c696a3b338d8955c549900d18fe2b898b6e94d682ca21e7c2/matplotlib-3.10.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9f2efccc8dcf2b86fc4ee849eea5dcaecedd0773b30f47980dc0cbeabf26ec84", size = 8180318, upload-time = "2025-05-08T19:10:20.426Z" }, + { url = "https://files.pythonhosted.org/packages/6c/0c/02f1c3b66b30da9ee343c343acbb6251bef5b01d34fad732446eaadcd108/matplotlib-3.10.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3ddbba06a6c126e3301c3d272a99dcbe7f6c24c14024e80307ff03791a5f294e", size = 8051132, upload-time = "2025-05-08T19:10:22.569Z" }, + { url = "https://files.pythonhosted.org/packages/b4/ab/8db1a5ac9b3a7352fb914133001dae889f9fcecb3146541be46bed41339c/matplotlib-3.10.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748302b33ae9326995b238f606e9ed840bf5886ebafcb233775d946aa8107a15", size = 8457633, upload-time = "2025-05-08T19:10:24.749Z" }, + { url = "https://files.pythonhosted.org/packages/f5/64/41c4367bcaecbc03ef0d2a3ecee58a7065d0a36ae1aa817fe573a2da66d4/matplotlib-3.10.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a80fcccbef63302c0efd78042ea3c2436104c5b1a4d3ae20f864593696364ac7", size = 8601031, upload-time = "2025-05-08T19:10:27.03Z" }, + { url = "https://files.pythonhosted.org/packages/12/6f/6cc79e9e5ab89d13ed64da28898e40fe5b105a9ab9c98f83abd24e46d7d7/matplotlib-3.10.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:55e46cbfe1f8586adb34f7587c3e4f7dedc59d5226719faf6cb54fc24f2fd52d", size = 9406988, upload-time = "2025-05-08T19:10:29.056Z" }, + { url = "https://files.pythonhosted.org/packages/b1/0f/eed564407bd4d935ffabf561ed31099ed609e19287409a27b6d336848653/matplotlib-3.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:151d89cb8d33cb23345cd12490c76fd5d18a56581a16d950b48c6ff19bb2ab93", size = 8068034, upload-time = "2025-05-08T19:10:31.221Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e5/2f14791ff69b12b09e9975e1d116d9578ac684460860ce542c2588cb7a1c/matplotlib-3.10.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c26dd9834e74d164d06433dc7be5d75a1e9890b926b3e57e74fa446e1a62c3e2", size = 8218223, upload-time = "2025-05-08T19:10:33.114Z" }, + { url = "https://files.pythonhosted.org/packages/5c/08/30a94afd828b6e02d0a52cae4a29d6e9ccfcf4c8b56cc28b021d3588873e/matplotlib-3.10.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:24853dad5b8c84c8c2390fc31ce4858b6df504156893292ce8092d190ef8151d", size = 8094985, upload-time = "2025-05-08T19:10:35.337Z" }, + { url = "https://files.pythonhosted.org/packages/89/44/f3bc6b53066c889d7a1a3ea8094c13af6a667c5ca6220ec60ecceec2dabe/matplotlib-3.10.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68f7878214d369d7d4215e2a9075fef743be38fa401d32e6020bab2dfabaa566", size = 8483109, upload-time = "2025-05-08T19:10:37.611Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c7/473bc559beec08ebee9f86ca77a844b65747e1a6c2691e8c92e40b9f42a8/matplotlib-3.10.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6929fc618cb6db9cb75086f73b3219bbb25920cb24cee2ea7a12b04971a4158", size = 8618082, upload-time = "2025-05-08T19:10:39.892Z" }, + { url = "https://files.pythonhosted.org/packages/d8/e9/6ce8edd264c8819e37bbed8172e0ccdc7107fe86999b76ab5752276357a4/matplotlib-3.10.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c7818292a5cc372a2dc4c795e5c356942eb8350b98ef913f7fda51fe175ac5d", size = 9413699, upload-time = "2025-05-08T19:10:42.376Z" }, + { url = "https://files.pythonhosted.org/packages/1b/92/9a45c91089c3cf690b5badd4be81e392ff086ccca8a1d4e3a08463d8a966/matplotlib-3.10.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4f23ffe95c5667ef8a2b56eea9b53db7f43910fa4a2d5472ae0f72b64deab4d5", size = 8139044, upload-time = "2025-05-08T19:10:44.551Z" }, ] [[package]] @@ -457,47 +511,50 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542 } +sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542, upload-time = "2024-09-09T20:27:49.564Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316 }, + { url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316, upload-time = "2024-09-09T20:27:48.397Z" }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] [[package]] name = "ml-dtypes" -version = "0.5.0" +version = "0.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", marker = "python_full_version >= '3.13'" }, + { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ab/79/717c5e22ad25d63ce3acdfe8ff8d64bdedec18914256c59b838218708b16/ml_dtypes-0.5.0.tar.gz", hash = "sha256:3e7d3a380fe73a63c884f06136f8baa7a5249cc8e9fdec677997dd78549f8128", size = 699367 } +sdist = { url = "https://files.pythonhosted.org/packages/32/49/6e67c334872d2c114df3020e579f3718c333198f8312290e09ec0216703a/ml_dtypes-0.5.1.tar.gz", hash = "sha256:ac5b58559bb84a95848ed6984eb8013249f90b6bab62aa5acbad876e256002c9", size = 698772, upload-time = "2025-01-07T03:34:55.613Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/4a/18f670a2703e771a6775fbc354208e597ff062a88efb0cecc220a282210b/ml_dtypes-0.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d3b3db9990c3840986a0e70524e122cfa32b91139c3653df76121ba7776e015f", size = 753345 }, - { url = "https://files.pythonhosted.org/packages/ed/c6/358d85e274e22d53def0c85f3cbe0933475fa3cf6922e9dca66eb25cb22f/ml_dtypes-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e04fde367b2fe901b1d47234426fe8819909bd1dd862a5adb630f27789c20599", size = 4424962 }, - { url = "https://files.pythonhosted.org/packages/4c/b4/d766586e24e7a073333c8eb8bd9275f3c6fe0569b509ae7b1699d4f00c74/ml_dtypes-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54415257f00eb44fbcc807454efac3356f75644f1cbfc2d4e5522a72ae1dacab", size = 4475201 }, - { url = "https://files.pythonhosted.org/packages/14/87/30323ad2e52f56262019a4493fe5f5e71067c5561ce7e2f9c75de520f5e8/ml_dtypes-0.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:cb5cc7b25acabd384f75bbd78892d0c724943f3e2e1986254665a1aa10982e07", size = 213195 }, + { url = "https://files.pythonhosted.org/packages/0f/92/bb6a3d18e16fddd18ce6d5f480e1919b33338c70e18cba831c6ae59812ee/ml_dtypes-0.5.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:12651420130ee7cc13059fc56dac6ad300c3af3848b802d475148c9defd27c23", size = 667696, upload-time = "2025-01-07T03:34:27.526Z" }, + { url = "https://files.pythonhosted.org/packages/6d/29/cfc89d842767e9a51146043b0fa18332c2b38f8831447e6cb1160e3c6102/ml_dtypes-0.5.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9945669d3dadf8acb40ec2e57d38c985d8c285ea73af57fc5b09872c516106d", size = 4638365, upload-time = "2025-01-07T03:34:30.43Z" }, + { url = "https://files.pythonhosted.org/packages/be/26/adc36e3ea09603d9f6d114894e1c1b7b8e8a9ef6d0b031cc270c6624a37c/ml_dtypes-0.5.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9975bda82a99dc935f2ae4c83846d86df8fd6ba179614acac8e686910851da", size = 4702722, upload-time = "2025-01-07T03:34:33.813Z" }, + { url = "https://files.pythonhosted.org/packages/da/8a/a2b9375c94077e5a488a624a195621407846f504068ce22ccf805c674156/ml_dtypes-0.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:fd918d4e6a4e0c110e2e05be7a7814d10dc1b95872accbf6512b80a109b71ae1", size = 210850, upload-time = "2025-01-07T03:34:36.897Z" }, + { url = "https://files.pythonhosted.org/packages/52/38/703169100fdde27957f061d4d0ea3e00525775a09acaccf7e655d9609d55/ml_dtypes-0.5.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:05f23447a1c20ddf4dc7c2c661aa9ed93fcb2658f1017c204d1e758714dc28a8", size = 693043, upload-time = "2025-01-07T03:34:38.457Z" }, + { url = "https://files.pythonhosted.org/packages/28/ff/4e234c9c23e0d456f5da5a326c103bf890c746d93351524d987e41f438b3/ml_dtypes-0.5.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b7fbe5571fdf28fd3aaab3ef4aafc847de9ebf263be959958c1ca58ec8eadf5", size = 4903946, upload-time = "2025-01-07T03:34:40.236Z" }, + { url = "https://files.pythonhosted.org/packages/b7/45/c1a1ccfdd02bc4173ca0f4a2d327683a27df85797b885eb1da1ca325b85c/ml_dtypes-0.5.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d13755f8e8445b3870114e5b6240facaa7cb0c3361e54beba3e07fa912a6e12b", size = 5052731, upload-time = "2025-01-07T03:34:45.308Z" }, ] [[package]] name = "mpmath" version = "1.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106 } +sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 }, + { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" }, ] [[package]] name = "myst-parser" -version = "4.0.0" +version = "4.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils" }, @@ -507,130 +564,130 @@ dependencies = [ { name = "pyyaml" }, { name = "sphinx" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/85/55/6d1741a1780e5e65038b74bce6689da15f620261c490c3511eb4c12bac4b/myst_parser-4.0.0.tar.gz", hash = "sha256:851c9dfb44e36e56d15d05e72f02b80da21a9e0d07cba96baf5e2d476bb91531", size = 93858 } +sdist = { url = "https://files.pythonhosted.org/packages/66/a5/9626ba4f73555b3735ad86247a8077d4603aa8628537687c839ab08bfe44/myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4", size = 93985, upload-time = "2025-02-12T10:53:03.833Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/b4/b036f8fdb667587bb37df29dc6644681dd78b7a2a6321a34684b79412b28/myst_parser-4.0.0-py3-none-any.whl", hash = "sha256:b9317997552424448c6096c2558872fdb6f81d3ecb3a40ce84a7518798f3f28d", size = 84563 }, + { url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579, upload-time = "2025-02-12T10:53:02.078Z" }, ] [[package]] name = "namex" -version = "0.0.8" +version = "0.0.9" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/48/d275cdb6216c6bb4f9351675795a0b48974e138f16b1ffe0252c1f8faa28/namex-0.0.8.tar.gz", hash = "sha256:32a50f6c565c0bb10aa76298c959507abdc0e850efe085dc38f3440fcb3aa90b", size = 6623 } +sdist = { url = "https://files.pythonhosted.org/packages/ca/03/00afe7f32962d0778d757aed89cd7f970179e5f7fbe42e883fd494ebbbc7/namex-0.0.9.tar.gz", hash = "sha256:8adfea9da5cea5be8f4e632349b4669e30172c7859e1fd97459fdf3b17469253", size = 6569, upload-time = "2025-04-22T18:00:15.808Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/73/59/7854fbfb59f8ae35483ce93493708be5942ebb6328cd85b3a609df629736/namex-0.0.8-py3-none-any.whl", hash = "sha256:7ddb6c2bb0e753a311b7590f84f6da659dd0c05e65cb89d519d54c0a250c0487", size = 5806 }, + { url = "https://files.pythonhosted.org/packages/46/16/7f616b55a147d9d4e9eb910a7eacde96cfa7ce3109d4c57ac32b91348ef3/namex-0.0.9-py3-none-any.whl", hash = "sha256:7bd4e4a2cc3876592111609fdf4cbe6ff19883adbe6b3b40d842fd340f77025e", size = 5847, upload-time = "2025-04-22T18:00:14.558Z" }, ] [[package]] name = "natsort" version = "8.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575 } +sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575, upload-time = "2023-06-20T04:17:19.925Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268 }, + { url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268, upload-time = "2023-06-20T04:17:17.522Z" }, ] [[package]] name = "numpy" -version = "2.1.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/25/ca/1166b75c21abd1da445b97bf1fa2f14f423c6cfb4fc7c4ef31dccf9f6a94/numpy-2.1.3.tar.gz", hash = "sha256:aa08e04e08aaf974d4458def539dece0d28146d866a39da5639596f4921fd761", size = 20166090 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/0b/620591441457e25f3404c8057eb924d04f161244cb8a3680d529419aa86e/numpy-2.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96fe52fcdb9345b7cd82ecd34547fca4321f7656d500eca497eb7ea5a926692f", size = 20836263 }, - { url = "https://files.pythonhosted.org/packages/45/e1/210b2d8b31ce9119145433e6ea78046e30771de3fe353f313b2778142f34/numpy-2.1.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f653490b33e9c3a4c1c01d41bc2aef08f9475af51146e4a7710c450cf9761598", size = 13507771 }, - { url = "https://files.pythonhosted.org/packages/55/44/aa9ee3caee02fa5a45f2c3b95cafe59c44e4b278fbbf895a93e88b308555/numpy-2.1.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dc258a761a16daa791081d026f0ed4399b582712e6fc887a95af09df10c5ca57", size = 5075805 }, - { url = "https://files.pythonhosted.org/packages/78/d6/61de6e7e31915ba4d87bbe1ae859e83e6582ea14c6add07c8f7eefd8488f/numpy-2.1.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:016d0f6f5e77b0f0d45d77387ffa4bb89816b57c835580c3ce8e099ef830befe", size = 6608380 }, - { url = "https://files.pythonhosted.org/packages/3e/46/48bdf9b7241e317e6cf94276fe11ba673c06d1fdf115d8b4ebf616affd1a/numpy-2.1.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c181ba05ce8299c7aa3125c27b9c2167bca4a4445b7ce73d5febc411ca692e43", size = 13602451 }, - { url = "https://files.pythonhosted.org/packages/70/50/73f9a5aa0810cdccda9c1d20be3cbe4a4d6ea6bfd6931464a44c95eef731/numpy-2.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5641516794ca9e5f8a4d17bb45446998c6554704d888f86df9b200e66bdcce56", size = 16039822 }, - { url = "https://files.pythonhosted.org/packages/ad/cd/098bc1d5a5bc5307cfc65ee9369d0ca658ed88fbd7307b0d49fab6ca5fa5/numpy-2.1.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ea4dedd6e394a9c180b33c2c872b92f7ce0f8e7ad93e9585312b0c5a04777a4a", size = 16411822 }, - { url = "https://files.pythonhosted.org/packages/83/a2/7d4467a2a6d984549053b37945620209e702cf96a8bc658bc04bba13c9e2/numpy-2.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0df3635b9c8ef48bd3be5f862cf71b0a4716fa0e702155c45067c6b711ddcef", size = 14079598 }, - { url = "https://files.pythonhosted.org/packages/e9/6a/d64514dcecb2ee70bfdfad10c42b76cab657e7ee31944ff7a600f141d9e9/numpy-2.1.3-cp313-cp313-win32.whl", hash = "sha256:50ca6aba6e163363f132b5c101ba078b8cbd3fa92c7865fd7d4d62d9779ac29f", size = 6236021 }, - { url = "https://files.pythonhosted.org/packages/bb/f9/12297ed8d8301a401e7d8eb6b418d32547f1d700ed3c038d325a605421a4/numpy-2.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:747641635d3d44bcb380d950679462fae44f54b131be347d5ec2bce47d3df9ed", size = 12560405 }, - { url = "https://files.pythonhosted.org/packages/a7/45/7f9244cd792e163b334e3a7f02dff1239d2890b6f37ebf9e82cbe17debc0/numpy-2.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:996bb9399059c5b82f76b53ff8bb686069c05acc94656bb259b1d63d04a9506f", size = 20859062 }, - { url = "https://files.pythonhosted.org/packages/b1/b4/a084218e7e92b506d634105b13e27a3a6645312b93e1c699cc9025adb0e1/numpy-2.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:45966d859916ad02b779706bb43b954281db43e185015df6eb3323120188f9e4", size = 13515839 }, - { url = "https://files.pythonhosted.org/packages/27/45/58ed3f88028dcf80e6ea580311dc3edefdd94248f5770deb980500ef85dd/numpy-2.1.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:baed7e8d7481bfe0874b566850cb0b85243e982388b7b23348c6db2ee2b2ae8e", size = 5116031 }, - { url = "https://files.pythonhosted.org/packages/37/a8/eb689432eb977d83229094b58b0f53249d2209742f7de529c49d61a124a0/numpy-2.1.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f7f672a3388133335589cfca93ed468509cb7b93ba3105fce780d04a6576a0", size = 6629977 }, - { url = "https://files.pythonhosted.org/packages/42/a3/5355ad51ac73c23334c7caaed01adadfda49544f646fcbfbb4331deb267b/numpy-2.1.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7aac50327da5d208db2eec22eb11e491e3fe13d22653dce51b0f4109101b408", size = 13575951 }, - { url = "https://files.pythonhosted.org/packages/c4/70/ea9646d203104e647988cb7d7279f135257a6b7e3354ea6c56f8bafdb095/numpy-2.1.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4394bc0dbd074b7f9b52024832d16e019decebf86caf909d94f6b3f77a8ee3b6", size = 16022655 }, - { url = "https://files.pythonhosted.org/packages/14/ce/7fc0612903e91ff9d0b3f2eda4e18ef9904814afcae5b0f08edb7f637883/numpy-2.1.3-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:50d18c4358a0a8a53f12a8ba9d772ab2d460321e6a93d6064fc22443d189853f", size = 16399902 }, - { url = "https://files.pythonhosted.org/packages/ef/62/1d3204313357591c913c32132a28f09a26357e33ea3c4e2fe81269e0dca1/numpy-2.1.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:14e253bd43fc6b37af4921b10f6add6925878a42a0c5fe83daee390bca80bc17", size = 14067180 }, - { url = "https://files.pythonhosted.org/packages/24/d7/78a40ed1d80e23a774cb8a34ae8a9493ba1b4271dde96e56ccdbab1620ef/numpy-2.1.3-cp313-cp313t-win32.whl", hash = "sha256:08788d27a5fd867a663f6fc753fd7c3ad7e92747efc73c53bca2f19f8bc06f48", size = 6291907 }, - { url = "https://files.pythonhosted.org/packages/86/09/a5ab407bd7f5f5599e6a9261f964ace03a73e7c6928de906981c31c38082/numpy-2.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2564fbdf2b99b3f815f2107c1bbc93e2de8ee655a69c261363a1172a79a257d4", size = 12644098 }, +version = "2.2.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/b2/ce4b867d8cd9c0ee84938ae1e6a6f7926ebf928c9090d036fc3c6a04f946/numpy-2.2.5.tar.gz", hash = "sha256:a9c0d994680cd991b1cb772e8b297340085466a6fe964bc9d4e80f5e2f43c291", size = 20273920, upload-time = "2025-04-19T23:27:42.561Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/a0/0aa7f0f4509a2e07bd7a509042967c2fab635690d4f48c6c7b3afd4f448c/numpy-2.2.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:059b51b658f4414fff78c6d7b1b4e18283ab5fa56d270ff212d5ba0c561846f4", size = 20935102, upload-time = "2025-04-19T22:41:16.234Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e4/a6a9f4537542912ec513185396fce52cdd45bdcf3e9d921ab02a93ca5aa9/numpy-2.2.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:47f9ed103af0bc63182609044b0490747e03bd20a67e391192dde119bf43d52f", size = 14191709, upload-time = "2025-04-19T22:41:38.472Z" }, + { url = "https://files.pythonhosted.org/packages/be/65/72f3186b6050bbfe9c43cb81f9df59ae63603491d36179cf7a7c8d216758/numpy-2.2.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:261a1ef047751bb02f29dfe337230b5882b54521ca121fc7f62668133cb119c9", size = 5149173, upload-time = "2025-04-19T22:41:47.823Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e9/83e7a9432378dde5802651307ae5e9ea07bb72b416728202218cd4da2801/numpy-2.2.5-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4520caa3807c1ceb005d125a75e715567806fed67e315cea619d5ec6e75a4191", size = 6684502, upload-time = "2025-04-19T22:41:58.689Z" }, + { url = "https://files.pythonhosted.org/packages/ea/27/b80da6c762394c8ee516b74c1f686fcd16c8f23b14de57ba0cad7349d1d2/numpy-2.2.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d14b17b9be5f9c9301f43d2e2a4886a33b53f4e6fdf9ca2f4cc60aeeee76372", size = 14084417, upload-time = "2025-04-19T22:42:19.897Z" }, + { url = "https://files.pythonhosted.org/packages/aa/fc/ebfd32c3e124e6a1043e19c0ab0769818aa69050ce5589b63d05ff185526/numpy-2.2.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ba321813a00e508d5421104464510cc962a6f791aa2fca1c97b1e65027da80d", size = 16133807, upload-time = "2025-04-19T22:42:44.433Z" }, + { url = "https://files.pythonhosted.org/packages/bf/9b/4cc171a0acbe4666f7775cfd21d4eb6bb1d36d3a0431f48a73e9212d2278/numpy-2.2.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4cbdef3ddf777423060c6f81b5694bad2dc9675f110c4b2a60dc0181543fac7", size = 15575611, upload-time = "2025-04-19T22:43:09.928Z" }, + { url = "https://files.pythonhosted.org/packages/a3/45/40f4135341850df48f8edcf949cf47b523c404b712774f8855a64c96ef29/numpy-2.2.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:54088a5a147ab71a8e7fdfd8c3601972751ded0739c6b696ad9cb0343e21ab73", size = 17895747, upload-time = "2025-04-19T22:43:36.983Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4c/b32a17a46f0ffbde8cc82df6d3daeaf4f552e346df143e1b188a701a8f09/numpy-2.2.5-cp313-cp313-win32.whl", hash = "sha256:c8b82a55ef86a2d8e81b63da85e55f5537d2157165be1cb2ce7cfa57b6aef38b", size = 6309594, upload-time = "2025-04-19T22:47:10.523Z" }, + { url = "https://files.pythonhosted.org/packages/13/ae/72e6276feb9ef06787365b05915bfdb057d01fceb4a43cb80978e518d79b/numpy-2.2.5-cp313-cp313-win_amd64.whl", hash = "sha256:d8882a829fd779f0f43998e931c466802a77ca1ee0fe25a3abe50278616b1471", size = 12638356, upload-time = "2025-04-19T22:47:30.253Z" }, + { url = "https://files.pythonhosted.org/packages/79/56/be8b85a9f2adb688e7ded6324e20149a03541d2b3297c3ffc1a73f46dedb/numpy-2.2.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e8b025c351b9f0e8b5436cf28a07fa4ac0204d67b38f01433ac7f9b870fa38c6", size = 20963778, upload-time = "2025-04-19T22:44:09.251Z" }, + { url = "https://files.pythonhosted.org/packages/ff/77/19c5e62d55bff507a18c3cdff82e94fe174957bad25860a991cac719d3ab/numpy-2.2.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dfa94b6a4374e7851bbb6f35e6ded2120b752b063e6acdd3157e4d2bb922eba", size = 14207279, upload-time = "2025-04-19T22:44:31.383Z" }, + { url = "https://files.pythonhosted.org/packages/75/22/aa11f22dc11ff4ffe4e849d9b63bbe8d4ac6d5fae85ddaa67dfe43be3e76/numpy-2.2.5-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:97c8425d4e26437e65e1d189d22dff4a079b747ff9c2788057bfb8114ce1e133", size = 5199247, upload-time = "2025-04-19T22:44:40.361Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6c/12d5e760fc62c08eded0394f62039f5a9857f758312bf01632a81d841459/numpy-2.2.5-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:352d330048c055ea6db701130abc48a21bec690a8d38f8284e00fab256dc1376", size = 6711087, upload-time = "2025-04-19T22:44:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/ef/94/ece8280cf4218b2bee5cec9567629e61e51b4be501e5c6840ceb593db945/numpy-2.2.5-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b4c0773b6ada798f51f0f8e30c054d32304ccc6e9c5d93d46cb26f3d385ab19", size = 14059964, upload-time = "2025-04-19T22:45:12.451Z" }, + { url = "https://files.pythonhosted.org/packages/39/41/c5377dac0514aaeec69115830a39d905b1882819c8e65d97fc60e177e19e/numpy-2.2.5-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55f09e00d4dccd76b179c0f18a44f041e5332fd0e022886ba1c0bbf3ea4a18d0", size = 16121214, upload-time = "2025-04-19T22:45:37.734Z" }, + { url = "https://files.pythonhosted.org/packages/db/54/3b9f89a943257bc8e187145c6bc0eb8e3d615655f7b14e9b490b053e8149/numpy-2.2.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02f226baeefa68f7d579e213d0f3493496397d8f1cff5e2b222af274c86a552a", size = 15575788, upload-time = "2025-04-19T22:46:01.908Z" }, + { url = "https://files.pythonhosted.org/packages/b1/c4/2e407e85df35b29f79945751b8f8e671057a13a376497d7fb2151ba0d290/numpy-2.2.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c26843fd58f65da9491165072da2cccc372530681de481ef670dcc8e27cfb066", size = 17893672, upload-time = "2025-04-19T22:46:28.585Z" }, + { url = "https://files.pythonhosted.org/packages/29/7e/d0b44e129d038dba453f00d0e29ebd6eaf2f06055d72b95b9947998aca14/numpy-2.2.5-cp313-cp313t-win32.whl", hash = "sha256:1a161c2c79ab30fe4501d5a2bbfe8b162490757cf90b7f05be8b80bc02f7bb8e", size = 6377102, upload-time = "2025-04-19T22:46:39.949Z" }, + { url = "https://files.pythonhosted.org/packages/63/be/b85e4aa4bf42c6502851b971f1c326d583fcc68227385f92089cf50a7b45/numpy-2.2.5-cp313-cp313t-win_amd64.whl", hash = "sha256:d403c84991b5ad291d3809bace5e85f4bbf44a04bdc9a88ed2bb1807b3360bb8", size = 12750096, upload-time = "2025-04-19T22:47:00.147Z" }, ] [[package]] name = "nvidia-nccl-cu12" -version = "2.23.4" +version = "2.26.5" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/3a/0112397396dec37ffc8edd7836d48261b4d14ca60ec8ed7bc857cce1d916/nvidia_nccl_cu12-2.23.4-py3-none-manylinux2014_aarch64.whl", hash = "sha256:aa946c8327e22ced28e7cef508a334673abc42064ec85f02d005ba1785ea4cec", size = 198953892 }, - { url = "https://files.pythonhosted.org/packages/ed/1f/6482380ec8dcec4894e7503490fc536d846b0d59694acad9cf99f27d0e7d/nvidia_nccl_cu12-2.23.4-py3-none-manylinux2014_x86_64.whl", hash = "sha256:b097258d9aab2fa9f686e33c6fe40ae57b27df60cedbd15d139701bb5509e0c1", size = 198954603 }, + { url = "https://files.pythonhosted.org/packages/55/66/ed9d28946ead0fe1322df2f4fc6ea042340c0fe73b79a1419dc1fdbdd211/nvidia_nccl_cu12-2.26.5-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:adb1bf4adcc5a47f597738a0700da6aef61f8ea4251b375540ae138c7d239588", size = 318058262, upload-time = "2025-05-02T23:32:43.197Z" }, + { url = "https://files.pythonhosted.org/packages/48/fb/ec4ac065d9b0d56f72eaf1d9b0df601e33da28197b32ca351dc05b342611/nvidia_nccl_cu12-2.26.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ea5ed3e053c735f16809bee7111deac62ac35b10128a8c102960a0462ce16cbe", size = 318069637, upload-time = "2025-05-02T23:33:18.306Z" }, ] [[package]] name = "oauthlib" version = "3.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/fa/fbf4001037904031639e6bfbfc02badfc7e12f137a8afa254df6c4c8a670/oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918", size = 177352 } +sdist = { url = "https://files.pythonhosted.org/packages/6d/fa/fbf4001037904031639e6bfbfc02badfc7e12f137a8afa254df6c4c8a670/oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918", size = 177352, upload-time = "2022-10-17T20:04:27.471Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/80/cab10959dc1faead58dc8384a781dfbf93cb4d33d50988f7a69f1b7c9bbe/oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", size = 151688 }, + { url = "https://files.pythonhosted.org/packages/7e/80/cab10959dc1faead58dc8384a781dfbf93cb4d33d50988f7a69f1b7c9bbe/oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", size = 151688, upload-time = "2022-10-17T20:04:24.037Z" }, ] [[package]] name = "opencv-python" -version = "4.10.0.84" +version = "4.11.0.86" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", marker = "python_full_version >= '3.13'" }, + { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/b70a2d9ab205110d715906fc8ec83fbb00404aeb3a37a0654fdb68eb0c8c/opencv-python-4.10.0.84.tar.gz", hash = "sha256:72d234e4582e9658ffea8e9cae5b63d488ad06994ef12d81dc303b17472f3526", size = 95103981 } +sdist = { url = "https://files.pythonhosted.org/packages/17/06/68c27a523103dad5837dc5b87e71285280c4f098c60e4fe8a8db6486ab09/opencv-python-4.11.0.86.tar.gz", hash = "sha256:03d60ccae62304860d232272e4a4fda93c39d595780cb40b161b310244b736a4", size = 95171956, upload-time = "2025-01-16T13:52:24.737Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/66/82/564168a349148298aca281e342551404ef5521f33fba17b388ead0a84dc5/opencv_python-4.10.0.84-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:fc182f8f4cda51b45f01c64e4cbedfc2f00aff799debebc305d8d0210c43f251", size = 54835524 }, - { url = "https://files.pythonhosted.org/packages/64/4a/016cda9ad7cf18c58ba074628a4eaae8aa55f3fd06a266398cef8831a5b9/opencv_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl", hash = "sha256:71e575744f1d23f79741450254660442785f45a0797212852ee5199ef12eed98", size = 56475426 }, - { url = "https://files.pythonhosted.org/packages/81/e4/7a987ebecfe5ceaf32db413b67ff18eb3092c598408862fff4d7cc3fd19b/opencv_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09a332b50488e2dda866a6c5573ee192fe3583239fb26ff2f7f9ceb0bc119ea6", size = 41746971 }, - { url = "https://files.pythonhosted.org/packages/3f/a4/d2537f47fd7fcfba966bd806e3ec18e7ee1681056d4b0a9c8d983983e4d5/opencv_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ace140fc6d647fbe1c692bcb2abce768973491222c067c131d80957c595b71f", size = 62548253 }, - { url = "https://files.pythonhosted.org/packages/1e/39/bbf57e7b9dab623e8773f6ff36385456b7ae7fa9357a5e53db732c347eac/opencv_python-4.10.0.84-cp37-abi3-win32.whl", hash = "sha256:2db02bb7e50b703f0a2d50c50ced72e95c574e1e5a0bb35a8a86d0b35c98c236", size = 28737688 }, - { url = "https://files.pythonhosted.org/packages/ec/6c/fab8113424af5049f85717e8e527ca3773299a3c6b02506e66436e19874f/opencv_python-4.10.0.84-cp37-abi3-win_amd64.whl", hash = "sha256:32dbbd94c26f611dc5cc6979e6b7aa1f55a64d6b463cc1dcd3c95505a63e48fe", size = 38842521 }, + { url = "https://files.pythonhosted.org/packages/05/4d/53b30a2a3ac1f75f65a59eb29cf2ee7207ce64867db47036ad61743d5a23/opencv_python-4.11.0.86-cp37-abi3-macosx_13_0_arm64.whl", hash = "sha256:432f67c223f1dc2824f5e73cdfcd9db0efc8710647d4e813012195dc9122a52a", size = 37326322, upload-time = "2025-01-16T13:52:25.887Z" }, + { url = "https://files.pythonhosted.org/packages/3b/84/0a67490741867eacdfa37bc18df96e08a9d579583b419010d7f3da8ff503/opencv_python-4.11.0.86-cp37-abi3-macosx_13_0_x86_64.whl", hash = "sha256:9d05ef13d23fe97f575153558653e2d6e87103995d54e6a35db3f282fe1f9c66", size = 56723197, upload-time = "2025-01-16T13:55:21.222Z" }, + { url = "https://files.pythonhosted.org/packages/f3/bd/29c126788da65c1fb2b5fb621b7fed0ed5f9122aa22a0868c5e2c15c6d23/opencv_python-4.11.0.86-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b92ae2c8852208817e6776ba1ea0d6b1e0a1b5431e971a2a0ddd2a8cc398202", size = 42230439, upload-time = "2025-01-16T13:51:35.822Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8b/90eb44a40476fa0e71e05a0283947cfd74a5d36121a11d926ad6f3193cc4/opencv_python-4.11.0.86-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b02611523803495003bd87362db3e1d2a0454a6a63025dc6658a9830570aa0d", size = 62986597, upload-time = "2025-01-16T13:52:08.836Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d7/1d5941a9dde095468b288d989ff6539dd69cd429dbf1b9e839013d21b6f0/opencv_python-4.11.0.86-cp37-abi3-win32.whl", hash = "sha256:810549cb2a4aedaa84ad9a1c92fbfdfc14090e2749cedf2c1589ad8359aa169b", size = 29384337, upload-time = "2025-01-16T13:52:13.549Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/f1c30a92854540bf789e9cd5dde7ef49bbe63f855b85a2e6b3db8135c591/opencv_python-4.11.0.86-cp37-abi3-win_amd64.whl", hash = "sha256:085ad9b77c18853ea66283e98affefe2de8cc4c1f43eda4c100cf9b2721142ec", size = 39488044, upload-time = "2025-01-16T13:52:21.928Z" }, ] [[package]] name = "optree" -version = "0.13.1" +version = "0.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f7/f2/56afdaeaae36b076659be7db8e72be0924dd64ebd1c131675c77f7e704a6/optree-0.13.1.tar.gz", hash = "sha256:af67856aa8073d237fe67313d84f8aeafac32c1cef7239c628a2768d02679c43", size = 155738 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/53/f3727cad24f16a06666f328f1212476988cadac9b9e7919ddfb2c22eb662/optree-0.13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f788b2ad120deb73b4908a74473cd6de79cfb9f33bbe9dcb59cea2e2477d4e28", size = 608270 }, - { url = "https://files.pythonhosted.org/packages/64/f2/68beb9da2dd52baa50e7a589ed2bd8434fdd70cdba06754aa5910263da06/optree-0.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2909cb42add6bb1a5a2b0243bdd8c4b861bf072f3741e26239481907ac8ad4e6", size = 325703 }, - { url = "https://files.pythonhosted.org/packages/45/db/08921e56f3425bf649eb593eb28775263c935d029985d35572dc5690cc1a/optree-0.13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbc5fa2ff5090389f3a906567446f01d692bd6fe5cfcc5ae2d5861f24e8e0e4d", size = 355813 }, - { url = "https://files.pythonhosted.org/packages/e5/e3/587e0d28dc2cee064902adfebca97db124e12b275dbe9c2b05a70a22345f/optree-0.13.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4711f5cac5a2a49c3d6c9f0eca7b77c22b452170bb33ea01c3214ebb17931db9", size = 402566 }, - { url = "https://files.pythonhosted.org/packages/8a/1d/0d5bbab8c99580b732b89ef2c5fcdd6ef410478295949fdf2984fa1bfc28/optree-0.13.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c4ab1d391b89cb88eb3c63383d5eb0930bc21141de9d5acd277feed9e38eb65", size = 397005 }, - { url = "https://files.pythonhosted.org/packages/16/fa/fc2a8183e14f0d195d25824bf65095ff32b34bd469614a6c30d0a596a30f/optree-0.13.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5e5f09c85ae558a6bdaea57e63168082e728e777391393e9e2792f0d15b7b59", size = 369400 }, - { url = "https://files.pythonhosted.org/packages/9f/42/8c08ce4ebb3d9a6e4415f1a97830c84879e2d1a43710a7c8a18b2c3e169d/optree-0.13.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c8ee1e988c634a451146b87d9ebdbf650a75dc1f52a9cffcd89fabb7289321c", size = 390179 }, - { url = "https://files.pythonhosted.org/packages/06/02/3a701d6307fdfefe4fcecbac644803e2a4314ab2406ff465e03129cc85f6/optree-0.13.1-cp313-cp313-win32.whl", hash = "sha256:5b6531cd4eb23fadbbf77faf834e1119da06d7af3154f55786b59953cd87bb8a", size = 264264 }, - { url = "https://files.pythonhosted.org/packages/ef/f9/8a1421181c5eb0c0f81d1423a900baeb3faba68a48747bbdffb7581239ac/optree-0.13.1-cp313-cp313-win_amd64.whl", hash = "sha256:27d81dc43b522ba47ba7d2e7d91dbb486940348b1bf85caeb0afc2815c0aa492", size = 293682 }, - { url = "https://files.pythonhosted.org/packages/80/34/d1b1849a6240385c4a3af5da9425b11912204d0b1cf142d802815319b73a/optree-0.13.1-cp313-cp313-win_arm64.whl", hash = "sha256:f39c7174a3f3cdc3f5fe6fb4b832f608c40ac174d7567ed6734b2ee952094631", size = 293670 }, - { url = "https://files.pythonhosted.org/packages/0d/d6/f81e6748bcc3f35a2f570a814014e3418b0ed425d7cbc2b42d88d12863d5/optree-0.13.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:3010ae24e994f6e00071098d34e98e78eb995b7454a2ef629a0bf7df17441b24", size = 702861 }, - { url = "https://files.pythonhosted.org/packages/08/7f/70a2d02110ccb245bc57bd9ad57668acfea0ff364c27d7dfe1735ede79ed/optree-0.13.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5b5626c38d4a18a144063db5c1dbb558431d83ca10682324f74665a12214801f", size = 370740 }, - { url = "https://files.pythonhosted.org/packages/63/37/4ddf05267467809236203e2007e9443519c4d55e0744ce7eea1aa74dffee/optree-0.13.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1935639dd498a42367633e3877797e1330e39d44d48bbca1a136bb4dbe4c1bc9", size = 374695 }, - { url = "https://files.pythonhosted.org/packages/19/f2/51a63a799f6dce31813d7e02a7547394aebcb39f407e62038ecbd999d490/optree-0.13.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01819c3df950696f32c91faf8d376ae6b695ffdba18f330f1cab6b8e314e4612", size = 418671 }, - { url = "https://files.pythonhosted.org/packages/f0/7c/a08191e0c9202f2be9c415057eea3cf3a5af18e9a6d81f4c7b0e6faf0a1f/optree-0.13.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:48c29d9c6c64c8dc48c8ee97f7c1d5cdb83e37320f0be0857c06ce4b97994aea", size = 414966 }, - { url = "https://files.pythonhosted.org/packages/8f/37/7bf815f4da7234e387863228b17246b42b8c02553882581a4013a64a88d0/optree-0.13.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:025d23400b8b579462a251420f0a9ae77d3d3593f84276f3465985731d79d722", size = 389219 }, - { url = "https://files.pythonhosted.org/packages/3d/84/bb521a66d3a84fe2f1500ef67d245c2cc1a26277fcaaf4bc70b22c06e99b/optree-0.13.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55e82426bef151149cfa41d68ac957730fcd420996c0db8324fca81aa6a810ba", size = 405377 }, - { url = "https://files.pythonhosted.org/packages/06/99/3eb53829c4c0b6dc20115d957d2d8e945630ddf40c656dc4e39c5a6e51f2/optree-0.13.1-cp313-cp313t-win32.whl", hash = "sha256:e40f018f522fcfd244688d1b3a360518e636ba7f636385aae0566eae3e7d29bc", size = 292734 }, - { url = "https://files.pythonhosted.org/packages/2f/59/d7601959ad0b90d309794c0975a256304488b4c5671f24e3e12101ade7ef/optree-0.13.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d580f1bf23bb352c4db6b3544f282f1ac08dcb0d9ab537d25e56220353438cf7", size = 331457 }, - { url = "https://files.pythonhosted.org/packages/8b/36/c01a5bc34660d46c6a3b1fe090bbdc8c76af7b5c1a6613cc671aa6df8349/optree-0.13.1-cp313-cp313t-win_arm64.whl", hash = "sha256:c4d13f55dbd509d27be3af54d53b4ca0751bc518244ced6d0567e518e51452a2", size = 331470 }, +sdist = { url = "https://files.pythonhosted.org/packages/4c/10/37411ac8cf8cb07b9db9ddc3e36f84869fd1cabcee3d6af8d347c28744f2/optree-0.15.0.tar.gz", hash = "sha256:d00a45e3b192093ef2cd32bf0d541ecbfc93c1bd73a5f3fe36293499f28a50cf", size = 171403, upload-time = "2025-04-06T16:13:18.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/e3/99135565340ac34857b6edbb3df6e15eb35aa7160f900f12d83f71d38eeb/optree-0.15.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:4ab606720ae319cb43da47c71d7d5fa7cfbb6a02e6da4857331e6f93800c970e", size = 647666, upload-time = "2025-04-06T16:12:14.072Z" }, + { url = "https://files.pythonhosted.org/packages/93/fc/c9c04494d2ab54f98f8d8c18cb5095a81ad23fb64105cb05e926bb3d1a0c/optree-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9cfc5771115f85b0bfa8f72cce1599186fd6a0ea71c8154d8b2751d9170be428", size = 346205, upload-time = "2025-04-06T16:12:15.91Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c8/25484ec6784435d63e64e87a7dca32760eed4ca60ddd4be1ca14ed421e08/optree-0.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f958a20a311854aaab8bdd0f124aab5b9848f07976b54da3e95526a491aa860", size = 372427, upload-time = "2025-04-06T16:12:17.064Z" }, + { url = "https://files.pythonhosted.org/packages/a3/27/615a2987137fd8add27e62217527e49f7fd2ec391bbec354dbc59a0cd0af/optree-0.15.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47ce7e9d81eaed5a05004df1fa279d2608e063dd5eb236e9c95803b4fa0a286c", size = 421611, upload-time = "2025-04-06T16:12:18.219Z" }, + { url = "https://files.pythonhosted.org/packages/98/e7/0106ee7ebec2e4cfa09f0a3b857e03c80bc80521227f4d64c289ac9601e8/optree-0.15.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6d6ab3717d48e0e747d9e348e23be1fa0f8a812f73632face6303c438d259ba", size = 415804, upload-time = "2025-04-06T16:12:19.611Z" }, + { url = "https://files.pythonhosted.org/packages/47/0e/a40ccedb0bac4a894b2b0d17d915b7e8cd3fdc44a5104026cec4102a53fb/optree-0.15.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c7d101a15be39a9c7c4afae9f0bb85f682eb7d719117e2f9e5fb39c9f6f2c92", size = 386208, upload-time = "2025-04-06T16:12:20.784Z" }, + { url = "https://files.pythonhosted.org/packages/c0/f6/1d98163b283048d80cb0c8e67d086a1e0ecabe35004d7180d0f28303f611/optree-0.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aae337ab30b45a096eb5b4ffc3ad8909731617543a7eb288e0b297b9d10a241f", size = 409276, upload-time = "2025-04-06T16:12:22.067Z" }, + { url = "https://files.pythonhosted.org/packages/e4/65/4275cd763bafb22c41443b7c7bfd5986b9c97f984537669c356e2c7008a1/optree-0.15.0-cp313-cp313-win32.whl", hash = "sha256:eb9c51d728485f5908111191b5403a3f9bc310d121a981f29fad45750b9ff89c", size = 277924, upload-time = "2025-04-06T16:12:23.638Z" }, + { url = "https://files.pythonhosted.org/packages/b2/fe/3d9f5463609ac6cb5857d0040739ae7709e1fbc134c58f0dd7cb3d2d93d5/optree-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:7f00e6f011f021ae470efe070ec4d2339fb1a8cd0dcdd16fe3dab782a47aba45", size = 309617, upload-time = "2025-04-06T16:12:24.766Z" }, + { url = "https://files.pythonhosted.org/packages/7d/bb/b7a443be665a91307cd78196018bc45bb0c6ab04fe265f009698311c7bc7/optree-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:17990fbc7f4c461de7ae546fc5661f6a248c3dcee966c89c2e2e5ad7f6228bae", size = 303390, upload-time = "2025-04-06T16:12:25.798Z" }, + { url = "https://files.pythonhosted.org/packages/30/8d/c6977786cc40626f24068d9bd6acbff377b9bed0cd64b7faff1bc3f2d60c/optree-0.15.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b31c88af70e3f5c14ff2aacd38c4076e6cde98f75169fe0bb59543f01bfb9719", size = 747468, upload-time = "2025-04-06T16:12:27.472Z" }, + { url = "https://files.pythonhosted.org/packages/5c/3f/e5b50c7af3712a97d0341744cd8ebd8ab19cd38561e26caa7a8a10fdf702/optree-0.15.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bc440f81f738d9c822030c3b4f53b6dec9ceb52410f02fd06b9338dc25a8447f", size = 392638, upload-time = "2025-04-06T16:12:28.535Z" }, + { url = "https://files.pythonhosted.org/packages/54/3b/1aab1a9dba5c8eb85810ba2683b42b057b1ce1de9bb7ca08c5d35448979e/optree-0.15.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ffc2dd8c754e95495163dde55b38dc37e6712b6a3bc7f2190b0547a2c403bb", size = 390030, upload-time = "2025-04-06T16:12:29.687Z" }, + { url = "https://files.pythonhosted.org/packages/fc/95/195be32055ce48cdf8beb31eda74f4643c6a443f1367346c6a8f6606c9eb/optree-0.15.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9fa9fb0197cd7b5f2b1fa7e05d30946b3b79bcfc3608fe54dbfc67969895cac9", size = 437350, upload-time = "2025-04-06T16:12:30.84Z" }, + { url = "https://files.pythonhosted.org/packages/02/01/9eefcdd9112aebc52db668a87f1df2f45c784e34e5a35182d3dad731fc92/optree-0.15.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6828639b01ba1177c04875dd9529d938d7b28122c97e7ae14ec41c68ec22826c", size = 434500, upload-time = "2025-04-06T16:12:33.168Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b3/0749c3a752b4921d54aa88eb1246315a008b5199c6d0e6127bd672a21c87/optree-0.15.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:93c74eed0f52818c30212dba4867f5672e498567bad49dcdffbe8db6703a0d65", size = 404306, upload-time = "2025-04-06T16:12:34.258Z" }, + { url = "https://files.pythonhosted.org/packages/04/91/1538085ace361f99280a26f9ccdc6023b22e7d0e23fdb849e2ef104fb54f/optree-0.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12188f6832c29dac37385a2f42fce961e303349909cff6d40e21cb27a8d09023", size = 423468, upload-time = "2025-04-06T16:12:35.325Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ec/c4d2203a6f1206790ea8b794df943a16918649b23cd03ec6beb7f75a81df/optree-0.15.0-cp313-cp313t-win32.whl", hash = "sha256:d7b8ce7d13580985922dcfbda515da3f004cd7cb1b03320b96ea32d8cfd76392", size = 308837, upload-time = "2025-04-06T16:12:36.889Z" }, + { url = "https://files.pythonhosted.org/packages/66/db/567ea8d2874eb15e9a8a82598ab84a6b809ca16df083b7650deffb8a6171/optree-0.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:daccdb583abaab14346f0af316ee570152a5c058e7b9fb09d8f8171fe751f2b3", size = 344774, upload-time = "2025-04-06T16:12:38.396Z" }, + { url = "https://files.pythonhosted.org/packages/ae/67/26804ab0222febadab6e27af4f4e607fad2d9520bb32422842509b79cf63/optree-0.15.0-cp313-cp313t-win_arm64.whl", hash = "sha256:e0162a36a6cedb0829efe980d0b370d4e5970fdb28a6609daa2c906d547add5f", size = 337502, upload-time = "2025-04-06T16:12:39.711Z" }, ] [[package]] name = "packaging" -version = "24.2" +version = "25.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] [[package]] @@ -638,26 +695,26 @@ name = "pandas" version = "2.2.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", marker = "python_full_version >= '3.13'" }, + { name = "numpy" }, { name = "python-dateutil" }, { name = "pytz" }, { name = "tzdata" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 } +sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213, upload-time = "2024-09-20T13:10:04.827Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643 }, - { url = "https://files.pythonhosted.org/packages/e4/93/b3f5d1838500e22c8d793625da672f3eec046b1a99257666c94446969282/pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", size = 11281573 }, - { url = "https://files.pythonhosted.org/packages/f5/94/6c79b07f0e5aab1dcfa35a75f4817f5c4f677931d4234afcd75f0e6a66ca/pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", size = 15196085 }, - { url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809 }, - { url = "https://files.pythonhosted.org/packages/ee/7c/c6dbdb0cb2a4344cacfb8de1c5808ca885b2e4dcfde8008266608f9372af/pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", size = 16356316 }, - { url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055 }, - { url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175 }, - { url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650 }, - { url = "https://files.pythonhosted.org/packages/9c/8c/f0fd18f6140ddafc0c24122c8a964e48294acc579d47def376fef12bcb4a/pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", size = 11290177 }, - { url = "https://files.pythonhosted.org/packages/ed/f9/e995754eab9c0f14c6777401f7eece0943840b7a9fc932221c19d1abee9f/pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", size = 14651526 }, - { url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013 }, - { url = "https://files.pythonhosted.org/packages/cc/57/0f72a10f9db6a4628744c8e8f0df4e6e21de01212c7c981d31e50ffc8328/pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", size = 15711620 }, - { url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436 }, + { url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643, upload-time = "2024-09-20T13:09:25.522Z" }, + { url = "https://files.pythonhosted.org/packages/e4/93/b3f5d1838500e22c8d793625da672f3eec046b1a99257666c94446969282/pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", size = 11281573, upload-time = "2024-09-20T13:09:28.012Z" }, + { url = "https://files.pythonhosted.org/packages/f5/94/6c79b07f0e5aab1dcfa35a75f4817f5c4f677931d4234afcd75f0e6a66ca/pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", size = 15196085, upload-time = "2024-09-20T19:02:10.451Z" }, + { url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809, upload-time = "2024-09-20T13:09:30.814Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7c/c6dbdb0cb2a4344cacfb8de1c5808ca885b2e4dcfde8008266608f9372af/pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", size = 16356316, upload-time = "2024-09-20T19:02:13.825Z" }, + { url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055, upload-time = "2024-09-20T13:09:33.462Z" }, + { url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175, upload-time = "2024-09-20T13:09:35.871Z" }, + { url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650, upload-time = "2024-09-20T13:09:38.685Z" }, + { url = "https://files.pythonhosted.org/packages/9c/8c/f0fd18f6140ddafc0c24122c8a964e48294acc579d47def376fef12bcb4a/pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", size = 11290177, upload-time = "2024-09-20T13:09:41.141Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f9/e995754eab9c0f14c6777401f7eece0943840b7a9fc932221c19d1abee9f/pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", size = 14651526, upload-time = "2024-09-20T19:02:16.905Z" }, + { url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013, upload-time = "2024-09-20T13:09:44.39Z" }, + { url = "https://files.pythonhosted.org/packages/cc/57/0f72a10f9db6a4628744c8e8f0df4e6e21de01212c7c981d31e50ffc8328/pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", size = 15711620, upload-time = "2024-09-20T19:02:20.639Z" }, + { url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436, upload-time = "2024-09-20T13:09:48.112Z" }, ] [[package]] @@ -667,68 +724,71 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/81/74f6a65b848ffd16c18f920620ce999fe45fe27f01ab3911260ce4ed85e4/patsy-1.0.1.tar.gz", hash = "sha256:e786a9391eec818c054e359b737bbce692f051aee4c661f4141cc88fb459c0c4", size = 396010 } +sdist = { url = "https://files.pythonhosted.org/packages/d1/81/74f6a65b848ffd16c18f920620ce999fe45fe27f01ab3911260ce4ed85e4/patsy-1.0.1.tar.gz", hash = "sha256:e786a9391eec818c054e359b737bbce692f051aee4c661f4141cc88fb459c0c4", size = 396010, upload-time = "2024-11-12T14:10:54.642Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/2b/b50d3d08ea0fc419c183a84210571eba005328efa62b6b98bc28e9ead32a/patsy-1.0.1-py2.py3-none-any.whl", hash = "sha256:751fb38f9e97e62312e921a1954b81e1bb2bcda4f5eeabaf94db251ee791509c", size = 232923 }, + { url = "https://files.pythonhosted.org/packages/87/2b/b50d3d08ea0fc419c183a84210571eba005328efa62b6b98bc28e9ead32a/patsy-1.0.1-py2.py3-none-any.whl", hash = "sha256:751fb38f9e97e62312e921a1954b81e1bb2bcda4f5eeabaf94db251ee791509c", size = 232923, upload-time = "2024-11-12T14:10:52.85Z" }, ] [[package]] name = "pillow" -version = "11.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a5/26/0d95c04c868f6bdb0c447e3ee2de5564411845e36a858cfd63766bc7b563/pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739", size = 46737780 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/63/24/e2e15e392d00fcf4215907465d8ec2a2f23bcec1481a8ebe4ae760459995/pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699", size = 3147300 }, - { url = "https://files.pythonhosted.org/packages/43/72/92ad4afaa2afc233dc44184adff289c2e77e8cd916b3ddb72ac69495bda3/pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38", size = 2978742 }, - { url = "https://files.pythonhosted.org/packages/9e/da/c8d69c5bc85d72a8523fe862f05ababdc52c0a755cfe3d362656bb86552b/pillow-11.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2", size = 4194349 }, - { url = "https://files.pythonhosted.org/packages/cd/e8/686d0caeed6b998351d57796496a70185376ed9c8ec7d99e1d19ad591fc6/pillow-11.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2", size = 4298714 }, - { url = "https://files.pythonhosted.org/packages/ec/da/430015cec620d622f06854be67fd2f6721f52fc17fca8ac34b32e2d60739/pillow-11.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527", size = 4208514 }, - { url = "https://files.pythonhosted.org/packages/44/ae/7e4f6662a9b1cb5f92b9cc9cab8321c381ffbee309210940e57432a4063a/pillow-11.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa", size = 4380055 }, - { url = "https://files.pythonhosted.org/packages/74/d5/1a807779ac8a0eeed57f2b92a3c32ea1b696e6140c15bd42eaf908a261cd/pillow-11.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f", size = 4296751 }, - { url = "https://files.pythonhosted.org/packages/38/8c/5fa3385163ee7080bc13026d59656267daaaaf3c728c233d530e2c2757c8/pillow-11.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb", size = 4430378 }, - { url = "https://files.pythonhosted.org/packages/ca/1d/ad9c14811133977ff87035bf426875b93097fb50af747793f013979facdb/pillow-11.0.0-cp313-cp313-win32.whl", hash = "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798", size = 2249588 }, - { url = "https://files.pythonhosted.org/packages/fb/01/3755ba287dac715e6afdb333cb1f6d69740a7475220b4637b5ce3d78cec2/pillow-11.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de", size = 2567509 }, - { url = "https://files.pythonhosted.org/packages/c0/98/2c7d727079b6be1aba82d195767d35fcc2d32204c7a5820f822df5330152/pillow-11.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84", size = 2254791 }, - { url = "https://files.pythonhosted.org/packages/eb/38/998b04cc6f474e78b563716b20eecf42a2fa16a84589d23c8898e64b0ffd/pillow-11.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b", size = 3150854 }, - { url = "https://files.pythonhosted.org/packages/13/8e/be23a96292113c6cb26b2aa3c8b3681ec62b44ed5c2bd0b258bd59503d3c/pillow-11.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003", size = 2982369 }, - { url = "https://files.pythonhosted.org/packages/97/8a/3db4eaabb7a2ae8203cd3a332a005e4aba00067fc514aaaf3e9721be31f1/pillow-11.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2", size = 4333703 }, - { url = "https://files.pythonhosted.org/packages/28/ac/629ffc84ff67b9228fe87a97272ab125bbd4dc462745f35f192d37b822f1/pillow-11.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a", size = 4412550 }, - { url = "https://files.pythonhosted.org/packages/d6/07/a505921d36bb2df6868806eaf56ef58699c16c388e378b0dcdb6e5b2fb36/pillow-11.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8", size = 4461038 }, - { url = "https://files.pythonhosted.org/packages/d6/b9/fb620dd47fc7cc9678af8f8bd8c772034ca4977237049287e99dda360b66/pillow-11.0.0-cp313-cp313t-win32.whl", hash = "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8", size = 2253197 }, - { url = "https://files.pythonhosted.org/packages/df/86/25dde85c06c89d7fc5db17940f07aae0a56ac69aa9ccb5eb0f09798862a8/pillow-11.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904", size = 2572169 }, - { url = "https://files.pythonhosted.org/packages/51/85/9c33f2517add612e17f3381aee7c4072779130c634921a756c97bc29fb49/pillow-11.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3", size = 2256828 }, +version = "11.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707, upload-time = "2025-04-12T17:50:03.289Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/9c/447528ee3776e7ab8897fe33697a7ff3f0475bb490c5ac1456a03dc57956/pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28", size = 3190098, upload-time = "2025-04-12T17:48:23.915Z" }, + { url = "https://files.pythonhosted.org/packages/b5/09/29d5cd052f7566a63e5b506fac9c60526e9ecc553825551333e1e18a4858/pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830", size = 3030166, upload-time = "2025-04-12T17:48:25.738Z" }, + { url = "https://files.pythonhosted.org/packages/71/5d/446ee132ad35e7600652133f9c2840b4799bbd8e4adba881284860da0a36/pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0", size = 4408674, upload-time = "2025-04-12T17:48:27.908Z" }, + { url = "https://files.pythonhosted.org/packages/69/5f/cbe509c0ddf91cc3a03bbacf40e5c2339c4912d16458fcb797bb47bcb269/pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1", size = 4496005, upload-time = "2025-04-12T17:48:29.888Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b3/dd4338d8fb8a5f312021f2977fb8198a1184893f9b00b02b75d565c33b51/pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f", size = 4518707, upload-time = "2025-04-12T17:48:31.874Z" }, + { url = "https://files.pythonhosted.org/packages/13/eb/2552ecebc0b887f539111c2cd241f538b8ff5891b8903dfe672e997529be/pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155", size = 4610008, upload-time = "2025-04-12T17:48:34.422Z" }, + { url = "https://files.pythonhosted.org/packages/72/d1/924ce51bea494cb6e7959522d69d7b1c7e74f6821d84c63c3dc430cbbf3b/pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14", size = 4585420, upload-time = "2025-04-12T17:48:37.641Z" }, + { url = "https://files.pythonhosted.org/packages/43/ab/8f81312d255d713b99ca37479a4cb4b0f48195e530cdc1611990eb8fd04b/pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b", size = 4667655, upload-time = "2025-04-12T17:48:39.652Z" }, + { url = "https://files.pythonhosted.org/packages/94/86/8f2e9d2dc3d308dfd137a07fe1cc478df0a23d42a6c4093b087e738e4827/pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2", size = 2332329, upload-time = "2025-04-12T17:48:41.765Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ec/1179083b8d6067a613e4d595359b5fdea65d0a3b7ad623fee906e1b3c4d2/pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691", size = 2676388, upload-time = "2025-04-12T17:48:43.625Z" }, + { url = "https://files.pythonhosted.org/packages/23/f1/2fc1e1e294de897df39fa8622d829b8828ddad938b0eaea256d65b84dd72/pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c", size = 2414950, upload-time = "2025-04-12T17:48:45.475Z" }, + { url = "https://files.pythonhosted.org/packages/c4/3e/c328c48b3f0ead7bab765a84b4977acb29f101d10e4ef57a5e3400447c03/pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22", size = 3192759, upload-time = "2025-04-12T17:48:47.866Z" }, + { url = "https://files.pythonhosted.org/packages/18/0e/1c68532d833fc8b9f404d3a642991441d9058eccd5606eab31617f29b6d4/pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7", size = 3033284, upload-time = "2025-04-12T17:48:50.189Z" }, + { url = "https://files.pythonhosted.org/packages/b7/cb/6faf3fb1e7705fd2db74e070f3bf6f88693601b0ed8e81049a8266de4754/pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16", size = 4445826, upload-time = "2025-04-12T17:48:52.346Z" }, + { url = "https://files.pythonhosted.org/packages/07/94/8be03d50b70ca47fb434a358919d6a8d6580f282bbb7af7e4aa40103461d/pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b", size = 4527329, upload-time = "2025-04-12T17:48:54.403Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a4/bfe78777076dc405e3bd2080bc32da5ab3945b5a25dc5d8acaa9de64a162/pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406", size = 4549049, upload-time = "2025-04-12T17:48:56.383Z" }, + { url = "https://files.pythonhosted.org/packages/65/4d/eaf9068dc687c24979e977ce5677e253624bd8b616b286f543f0c1b91662/pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91", size = 4635408, upload-time = "2025-04-12T17:48:58.782Z" }, + { url = "https://files.pythonhosted.org/packages/1d/26/0fd443365d9c63bc79feb219f97d935cd4b93af28353cba78d8e77b61719/pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751", size = 4614863, upload-time = "2025-04-12T17:49:00.709Z" }, + { url = "https://files.pythonhosted.org/packages/49/65/dca4d2506be482c2c6641cacdba5c602bc76d8ceb618fd37de855653a419/pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9", size = 4692938, upload-time = "2025-04-12T17:49:02.946Z" }, + { url = "https://files.pythonhosted.org/packages/b3/92/1ca0c3f09233bd7decf8f7105a1c4e3162fb9142128c74adad0fb361b7eb/pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd", size = 2335774, upload-time = "2025-04-12T17:49:04.889Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ac/77525347cb43b83ae905ffe257bbe2cc6fd23acb9796639a1f56aa59d191/pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e", size = 2681895, upload-time = "2025-04-12T17:49:06.635Z" }, + { url = "https://files.pythonhosted.org/packages/67/32/32dc030cfa91ca0fc52baebbba2e009bb001122a1daa8b6a79ad830b38d3/pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681", size = 2417234, upload-time = "2025-04-12T17:49:08.399Z" }, ] [[package]] name = "pluggy" version = "1.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, ] [[package]] name = "pygments" -version = "2.18.0" +version = "2.19.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 }, + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, ] [[package]] name = "pyparsing" -version = "3.2.0" +version = "3.2.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/d5/e5aeee5387091148a19e1145f63606619cb5f20b83fccb63efae6474e7b2/pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c", size = 920984 } +sdist = { url = "https://files.pythonhosted.org/packages/bb/22/f1129e69d94ffff626bdb5c835506b3a5b4f3d070f17ea295e12c2c6f60f/pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be", size = 1088608, upload-time = "2025-03-25T05:01:28.114Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84", size = 106921 }, + { url = "https://files.pythonhosted.org/packages/05/e7/df2285f3d08fee213f2d041540fa4fc9ca6c2d44cf36d3a035bf2a8d2bcc/pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", size = 111120, upload-time = "2025-03-25T05:01:24.908Z" }, ] [[package]] name = "pytest" -version = "8.3.4" +version = "8.3.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -736,22 +796,22 @@ dependencies = [ { name = "packaging" }, { name = "pluggy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, ] [[package]] name = "pytest-cov" -version = "6.0.0" +version = "6.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } +sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857, upload-time = "2025-04-05T14:07:51.592Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, + { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841, upload-time = "2025-04-05T14:07:49.641Z" }, ] [[package]] @@ -761,35 +821,35 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] [[package]] name = "pytz" -version = "2024.2" +version = "2025.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3a/31/3c70bf7603cc2dca0f19bdc53b4537a797747a58875b552c8c413d963a3f/pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", size = 319692 } +sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002 }, + { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, ] [[package]] name = "pyyaml" version = "6.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, ] [[package]] @@ -802,65 +862,49 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, ] [[package]] name = "requests-oauthlib" -version = "1.3.1" +version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "oauthlib" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/95/52/531ef197b426646f26b53815a7d2a67cb7a331ef098bb276db26a68ac49f/requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a", size = 52027 } +sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650, upload-time = "2024-03-22T20:32:29.939Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/bb/5deac77a9af870143c684ab46a7934038a53eb4aa975bc0687ed6ca2c610/requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", size = 23892 }, + { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179, upload-time = "2024-03-22T20:32:28.055Z" }, ] [[package]] name = "rich" -version = "13.9.4" +version = "14.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } +sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, + { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" }, ] [[package]] -name = "ruff" -version = "0.8.1" +name = "roman-numerals-py" +version = "3.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/d0/8ff5b189d125f4260f2255d143bf2fa413b69c2610c405ace7a0a8ec81ec/ruff-0.8.1.tar.gz", hash = "sha256:3583db9a6450364ed5ca3f3b4225958b24f78178908d5c4bc0f46251ccca898f", size = 3313222 } +sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017, upload-time = "2025-02-22T07:34:54.333Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/d6/1a6314e568db88acdbb5121ed53e2c52cebf3720d3437a76f82f923bf171/ruff-0.8.1-py3-none-linux_armv6l.whl", hash = "sha256:fae0805bd514066f20309f6742f6ee7904a773eb9e6c17c45d6b1600ca65c9b5", size = 10532605 }, - { url = "https://files.pythonhosted.org/packages/89/a8/a957a8812e31facffb6a26a30be0b5b4af000a6e30c7d43a22a5232a3398/ruff-0.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8a4f7385c2285c30f34b200ca5511fcc865f17578383db154e098150ce0a087", size = 10278243 }, - { url = "https://files.pythonhosted.org/packages/a8/23/9db40fa19c453fabf94f7a35c61c58f20e8200b4734a20839515a19da790/ruff-0.8.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd054486da0c53e41e0086e1730eb77d1f698154f910e0cd9e0d64274979a209", size = 9917739 }, - { url = "https://files.pythonhosted.org/packages/e2/a0/6ee2d949835d5701d832fc5acd05c0bfdad5e89cfdd074a171411f5ccad5/ruff-0.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2029b8c22da147c50ae577e621a5bfbc5d1fed75d86af53643d7a7aee1d23871", size = 10779153 }, - { url = "https://files.pythonhosted.org/packages/7a/25/9c11dca9404ef1eb24833f780146236131a3c7941de394bc356912ef1041/ruff-0.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2666520828dee7dfc7e47ee4ea0d928f40de72056d929a7c5292d95071d881d1", size = 10304387 }, - { url = "https://files.pythonhosted.org/packages/c8/b9/84c323780db1b06feae603a707d82dbbd85955c8c917738571c65d7d5aff/ruff-0.8.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:333c57013ef8c97a53892aa56042831c372e0bb1785ab7026187b7abd0135ad5", size = 11360351 }, - { url = "https://files.pythonhosted.org/packages/6b/e1/9d4bbb2ace7aad14ded20e4674a48cda5b902aed7a1b14e6b028067060c4/ruff-0.8.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:288326162804f34088ac007139488dcb43de590a5ccfec3166396530b58fb89d", size = 12022879 }, - { url = "https://files.pythonhosted.org/packages/75/28/752ff6120c0e7f9981bc4bc275d540c7f36db1379ba9db9142f69c88db21/ruff-0.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b12c39b9448632284561cbf4191aa1b005882acbc81900ffa9f9f471c8ff7e26", size = 11610354 }, - { url = "https://files.pythonhosted.org/packages/ba/8c/967b61c2cc8ebd1df877607fbe462bc1e1220b4a30ae3352648aec8c24bd/ruff-0.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:364e6674450cbac8e998f7b30639040c99d81dfb5bbc6dfad69bc7a8f916b3d1", size = 12813976 }, - { url = "https://files.pythonhosted.org/packages/7f/29/e059f945d6bd2d90213387b8c360187f2fefc989ddcee6bbf3c241329b92/ruff-0.8.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b22346f845fec132aa39cd29acb94451d030c10874408dbf776af3aaeb53284c", size = 11154564 }, - { url = "https://files.pythonhosted.org/packages/55/47/cbd05e5a62f3fb4c072bc65c1e8fd709924cad1c7ec60a1000d1e4ee8307/ruff-0.8.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2f2f7a7e7648a2bfe6ead4e0a16745db956da0e3a231ad443d2a66a105c04fa", size = 10760604 }, - { url = "https://files.pythonhosted.org/packages/bb/ee/4c3981c47147c72647a198a94202633130cfda0fc95cd863a553b6f65c6a/ruff-0.8.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:adf314fc458374c25c5c4a4a9270c3e8a6a807b1bec018cfa2813d6546215540", size = 10391071 }, - { url = "https://files.pythonhosted.org/packages/6b/e6/083eb61300214590b188616a8ac6ae1ef5730a0974240fb4bec9c17de78b/ruff-0.8.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a885d68342a231b5ba4d30b8c6e1b1ee3a65cf37e3d29b3c74069cdf1ee1e3c9", size = 10896657 }, - { url = "https://files.pythonhosted.org/packages/77/bd/aacdb8285d10f1b943dbeb818968efca35459afc29f66ae3bd4596fbf954/ruff-0.8.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d2c16e3508c8cc73e96aa5127d0df8913d2290098f776416a4b157657bee44c5", size = 11228362 }, - { url = "https://files.pythonhosted.org/packages/39/72/fcb7ad41947f38b4eaa702aca0a361af0e9c2bf671d7fd964480670c297e/ruff-0.8.1-py3-none-win32.whl", hash = "sha256:93335cd7c0eaedb44882d75a7acb7df4b77cd7cd0d2255c93b28791716e81790", size = 8803476 }, - { url = "https://files.pythonhosted.org/packages/e4/ea/cae9aeb0f4822c44651c8407baacdb2e5b4dcd7b31a84e1c5df33aa2cc20/ruff-0.8.1-py3-none-win_amd64.whl", hash = "sha256:2954cdbe8dfd8ab359d4a30cd971b589d335a44d444b6ca2cb3d1da21b75e4b6", size = 9614463 }, - { url = "https://files.pythonhosted.org/packages/eb/76/fbb4bd23dfb48fa7758d35b744413b650a9fd2ddd93bca77e30376864414/ruff-0.8.1-py3-none-win_arm64.whl", hash = "sha256:55873cc1a473e5ac129d15eccb3c008c096b94809d693fc7053f588b67822737", size = 8959621 }, + { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742, upload-time = "2025-02-22T07:34:52.422Z" }, ] [[package]] name = "scikit-learn" -version = "1.5.2" +version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "joblib" }, @@ -868,64 +912,87 @@ dependencies = [ { name = "scipy" }, { name = "threadpoolctl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/37/59/44985a2bdc95c74e34fef3d10cb5d93ce13b0e2a7baefffe1b53853b502d/scikit_learn-1.5.2.tar.gz", hash = "sha256:b4237ed7b3fdd0a4882792e68ef2545d5baa50aca3bb45aa7df468138ad8f94d", size = 7001680 } +sdist = { url = "https://files.pythonhosted.org/packages/9e/a5/4ae3b3a0755f7b35a280ac90b28817d1f380318973cff14075ab41ef50d9/scikit_learn-1.6.1.tar.gz", hash = "sha256:b4fc2525eca2c69a59260f583c56a7557c6ccdf8deafdba6e060f94c1c59738e", size = 7068312, upload-time = "2025-01-10T08:07:55.348Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/50/8891028437858cc510e13578fe7046574a60c2aaaa92b02d64aac5b1b412/scikit_learn-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9a702e2de732bbb20d3bad29ebd77fc05a6b427dc49964300340e4c9328b3f5", size = 12025584 }, - { url = "https://files.pythonhosted.org/packages/d2/79/17feef8a1c14149436083bec0e61d7befb4812e272d5b20f9d79ea3e9ab1/scikit_learn-1.5.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:b0768ad641981f5d3a198430a1d31c3e044ed2e8a6f22166b4d546a5116d7908", size = 10959795 }, - { url = "https://files.pythonhosted.org/packages/b1/c8/f08313f9e2e656bd0905930ae8bf99a573ea21c34666a813b749c338202f/scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:178ddd0a5cb0044464fc1bfc4cca5b1833bfc7bb022d70b05db8530da4bb3dd3", size = 12077302 }, - { url = "https://files.pythonhosted.org/packages/a7/48/fbfb4dc72bed0fe31fe045fb30e924909ad03f717c36694351612973b1a9/scikit_learn-1.5.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7284ade780084d94505632241bf78c44ab3b6f1e8ccab3d2af58e0e950f9c12", size = 13002811 }, - { url = "https://files.pythonhosted.org/packages/a5/e7/0c869f9e60d225a77af90d2aefa7a4a4c0e745b149325d1450f0f0ce5399/scikit_learn-1.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:b7b0f9a0b1040830d38c39b91b3a44e1b643f4b36e36567b80b7c6bd2202a27f", size = 10951354 }, + { url = "https://files.pythonhosted.org/packages/2e/59/8eb1872ca87009bdcdb7f3cdc679ad557b992c12f4b61f9250659e592c63/scikit_learn-1.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2ffa1e9e25b3d93990e74a4be2c2fc61ee5af85811562f1288d5d055880c4322", size = 12010001, upload-time = "2025-01-10T08:06:58.613Z" }, + { url = "https://files.pythonhosted.org/packages/9d/05/f2fc4effc5b32e525408524c982c468c29d22f828834f0625c5ef3d601be/scikit_learn-1.6.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:dc5cf3d68c5a20ad6d571584c0750ec641cc46aeef1c1507be51300e6003a7e1", size = 11096360, upload-time = "2025-01-10T08:07:01.556Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e4/4195d52cf4f113573fb8ebc44ed5a81bd511a92c0228889125fac2f4c3d1/scikit_learn-1.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c06beb2e839ecc641366000ca84f3cf6fa9faa1777e29cf0c04be6e4d096a348", size = 12209004, upload-time = "2025-01-10T08:07:06.931Z" }, + { url = "https://files.pythonhosted.org/packages/94/be/47e16cdd1e7fcf97d95b3cb08bde1abb13e627861af427a3651fcb80b517/scikit_learn-1.6.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8ca8cb270fee8f1f76fa9bfd5c3507d60c6438bbee5687f81042e2bb98e5a97", size = 13171776, upload-time = "2025-01-10T08:07:11.715Z" }, + { url = "https://files.pythonhosted.org/packages/34/b0/ca92b90859070a1487827dbc672f998da95ce83edce1270fc23f96f1f61a/scikit_learn-1.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:7a1c43c8ec9fde528d664d947dc4c0789be4077a3647f232869f41d9bf50e0fb", size = 11071865, upload-time = "2025-01-10T08:07:16.088Z" }, + { url = "https://files.pythonhosted.org/packages/12/ae/993b0fb24a356e71e9a894e42b8a9eec528d4c70217353a1cd7a48bc25d4/scikit_learn-1.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a17c1dea1d56dcda2fac315712f3651a1fea86565b64b48fa1bc090249cbf236", size = 11955804, upload-time = "2025-01-10T08:07:20.385Z" }, + { url = "https://files.pythonhosted.org/packages/d6/54/32fa2ee591af44507eac86406fa6bba968d1eb22831494470d0a2e4a1eb1/scikit_learn-1.6.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6a7aa5f9908f0f28f4edaa6963c0a6183f1911e63a69aa03782f0d924c830a35", size = 11100530, upload-time = "2025-01-10T08:07:23.675Z" }, + { url = "https://files.pythonhosted.org/packages/3f/58/55856da1adec655bdce77b502e94a267bf40a8c0b89f8622837f89503b5a/scikit_learn-1.6.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0650e730afb87402baa88afbf31c07b84c98272622aaba002559b614600ca691", size = 12433852, upload-time = "2025-01-10T08:07:26.817Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4f/c83853af13901a574f8f13b645467285a48940f185b690936bb700a50863/scikit_learn-1.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:3f59fe08dc03ea158605170eb52b22a105f238a5d512c4470ddeca71feae8e5f", size = 11337256, upload-time = "2025-01-10T08:07:31.084Z" }, ] [[package]] name = "scipy" -version = "1.14.1" +version = "1.15.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/62/11/4d44a1f274e002784e4dbdb81e0ea96d2de2d1045b2132d5af62cc31fd28/scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417", size = 58620554 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/50/ef/ac98346db016ff18a6ad7626a35808f37074d25796fd0234c2bb0ed1e054/scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79", size = 39091068 }, - { url = "https://files.pythonhosted.org/packages/b9/cc/70948fe9f393b911b4251e96b55bbdeaa8cca41f37c26fd1df0232933b9e/scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e", size = 29875417 }, - { url = "https://files.pythonhosted.org/packages/3b/2e/35f549b7d231c1c9f9639f9ef49b815d816bf54dd050da5da1c11517a218/scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73", size = 23084508 }, - { url = "https://files.pythonhosted.org/packages/3f/d6/b028e3f3e59fae61fb8c0f450db732c43dd1d836223a589a8be9f6377203/scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e", size = 25503364 }, - { url = "https://files.pythonhosted.org/packages/a7/2f/6c142b352ac15967744d62b165537a965e95d557085db4beab2a11f7943b/scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d", size = 35292639 }, - { url = "https://files.pythonhosted.org/packages/56/46/2449e6e51e0d7c3575f289f6acb7f828938eaab8874dbccfeb0cd2b71a27/scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e", size = 40798288 }, - { url = "https://files.pythonhosted.org/packages/32/cd/9d86f7ed7f4497c9fd3e39f8918dd93d9f647ba80d7e34e4946c0c2d1a7c/scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06", size = 42524647 }, - { url = "https://files.pythonhosted.org/packages/f5/1b/6ee032251bf4cdb0cc50059374e86a9f076308c1512b61c4e003e241efb7/scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84", size = 44469524 }, +sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/18/ec27848c9baae6e0d6573eda6e01a602e5649ee72c27c3a8aad673ebecfd/scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759", size = 38728256, upload-time = "2025-05-08T16:06:58.696Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/1aef2184948728b4b6e21267d53b3339762c285a46a274ebb7863c9e4742/scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62", size = 30109540, upload-time = "2025-05-08T16:07:04.209Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d8/59e452c0a255ec352bd0a833537a3bc1bfb679944c4938ab375b0a6b3a3e/scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb", size = 22383115, upload-time = "2025-05-08T16:07:08.998Z" }, + { url = "https://files.pythonhosted.org/packages/08/f5/456f56bbbfccf696263b47095291040655e3cbaf05d063bdc7c7517f32ac/scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730", size = 25163884, upload-time = "2025-05-08T16:07:14.091Z" }, + { url = "https://files.pythonhosted.org/packages/a2/66/a9618b6a435a0f0c0b8a6d0a2efb32d4ec5a85f023c2b79d39512040355b/scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825", size = 35174018, upload-time = "2025-05-08T16:07:19.427Z" }, + { url = "https://files.pythonhosted.org/packages/b5/09/c5b6734a50ad4882432b6bb7c02baf757f5b2f256041da5df242e2d7e6b6/scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7", size = 37269716, upload-time = "2025-05-08T16:07:25.712Z" }, + { url = "https://files.pythonhosted.org/packages/77/0a/eac00ff741f23bcabd352731ed9b8995a0a60ef57f5fd788d611d43d69a1/scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11", size = 36872342, upload-time = "2025-05-08T16:07:31.468Z" }, + { url = "https://files.pythonhosted.org/packages/fe/54/4379be86dd74b6ad81551689107360d9a3e18f24d20767a2d5b9253a3f0a/scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126", size = 39670869, upload-time = "2025-05-08T16:07:38.002Z" }, + { url = "https://files.pythonhosted.org/packages/87/2e/892ad2862ba54f084ffe8cc4a22667eaf9c2bcec6d2bff1d15713c6c0703/scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163", size = 40988851, upload-time = "2025-05-08T16:08:33.671Z" }, + { url = "https://files.pythonhosted.org/packages/1b/e9/7a879c137f7e55b30d75d90ce3eb468197646bc7b443ac036ae3fe109055/scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8", size = 38863011, upload-time = "2025-05-08T16:07:44.039Z" }, + { url = "https://files.pythonhosted.org/packages/51/d1/226a806bbd69f62ce5ef5f3ffadc35286e9fbc802f606a07eb83bf2359de/scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5", size = 30266407, upload-time = "2025-05-08T16:07:49.891Z" }, + { url = "https://files.pythonhosted.org/packages/e5/9b/f32d1d6093ab9eeabbd839b0f7619c62e46cc4b7b6dbf05b6e615bbd4400/scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e", size = 22540030, upload-time = "2025-05-08T16:07:54.121Z" }, + { url = "https://files.pythonhosted.org/packages/e7/29/c278f699b095c1a884f29fda126340fcc201461ee8bfea5c8bdb1c7c958b/scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb", size = 25218709, upload-time = "2025-05-08T16:07:58.506Z" }, + { url = "https://files.pythonhosted.org/packages/24/18/9e5374b617aba742a990581373cd6b68a2945d65cc588482749ef2e64467/scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723", size = 34809045, upload-time = "2025-05-08T16:08:03.929Z" }, + { url = "https://files.pythonhosted.org/packages/e1/fe/9c4361e7ba2927074360856db6135ef4904d505e9b3afbbcb073c4008328/scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb", size = 36703062, upload-time = "2025-05-08T16:08:09.558Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8e/038ccfe29d272b30086b25a4960f757f97122cb2ec42e62b460d02fe98e9/scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4", size = 36393132, upload-time = "2025-05-08T16:08:15.34Z" }, + { url = "https://files.pythonhosted.org/packages/10/7e/5c12285452970be5bdbe8352c619250b97ebf7917d7a9a9e96b8a8140f17/scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5", size = 38979503, upload-time = "2025-05-08T16:08:21.513Z" }, + { url = "https://files.pythonhosted.org/packages/81/06/0a5e5349474e1cbc5757975b21bd4fad0e72ebf138c5592f191646154e06/scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca", size = 40308097, upload-time = "2025-05-08T16:08:27.627Z" }, ] [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, ] [[package]] name = "snowballstemmer" -version = "2.2.0" +version = "3.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699 } +sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002 }, + { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, ] [[package]] name = "soupsieve" -version = "2.6" +version = "2.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 } +sdist = { url = "https://files.pythonhosted.org/packages/3f/f4/4a80cd6ef364b2e8b65b15816a843c0980f7a5a2b4dc701fc574952aa19f/soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a", size = 103418, upload-time = "2025-04-20T18:50:08.518Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 }, + { url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677, upload-time = "2025-04-20T18:50:07.196Z" }, ] [[package]] name = "sphinx" -version = "8.1.3" +version = "8.2.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "alabaster" }, @@ -937,6 +1004,7 @@ dependencies = [ { name = "packaging" }, { name = "pygments" }, { name = "requests" }, + { name = "roman-numerals-py" }, { name = "snowballstemmer" }, { name = "sphinxcontrib-applehelp" }, { name = "sphinxcontrib-devhelp" }, @@ -945,24 +1013,24 @@ dependencies = [ { name = "sphinxcontrib-qthelp" }, { name = "sphinxcontrib-serializinghtml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611 } +sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876, upload-time = "2025-03-02T22:31:59.658Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125 }, + { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741, upload-time = "2025-03-02T22:31:56.836Z" }, ] [[package]] name = "sphinx-autoapi" -version = "3.4.0" +version = "3.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "astroid", marker = "python_full_version >= '3.13'" }, + { name = "astroid" }, { name = "jinja2" }, { name = "pyyaml" }, { name = "sphinx" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4a/eb/cc243583bb1d518ca3b10998c203d919a8ed90affd4831f2b61ad09043d2/sphinx_autoapi-3.4.0.tar.gz", hash = "sha256:e6d5371f9411bbb9fca358c00a9e57aef3ac94cbfc5df4bab285946462f69e0c", size = 29292 } +sdist = { url = "https://files.pythonhosted.org/packages/7f/a8/22b379a2a75ccb881217d3d4ae56d7d35f2d1bb4c8c0c51d0253676746a1/sphinx_autoapi-3.6.0.tar.gz", hash = "sha256:c685f274e41d0842ae7e199460c322c4bd7fec816ccc2da8d806094b4f64af06", size = 55417, upload-time = "2025-02-18T01:50:55.241Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/de/d6/f2acdc2567337fd5f5dc091a4e58d8a0fb14927b9779fc1e5ecee96d9824/sphinx_autoapi-3.4.0-py3-none-any.whl", hash = "sha256:4027fef2875a22c5f2a57107c71641d82f6166bf55beb407a47aaf3ef14e7b92", size = 34095 }, + { url = "https://files.pythonhosted.org/packages/58/17/0eda9dc80fcaf257222b506844207e71b5d59567c41bbdcca2a72da119b9/sphinx_autoapi-3.6.0-py3-none-any.whl", hash = "sha256:f3b66714493cab140b0e896d33ce7137654a16ac1edb6563edcbd47bf975f711", size = 35281, upload-time = "2025-02-18T01:50:52.789Z" }, ] [[package]] @@ -973,63 +1041,63 @@ dependencies = [ { name = "dom-toml" }, { name = "domdf-python-tools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/97/aa8cec3da3e78f2c396b63332e2fe92fe43f7ff2ad19b3998735f28b0a7f/sphinx_pyproject-0.3.0.tar.gz", hash = "sha256:efc4ee9d96f579c4e4ed1ac273868c64565e88c8e37fe6ec2dc59fbcd57684ab", size = 7695 } +sdist = { url = "https://files.pythonhosted.org/packages/39/97/aa8cec3da3e78f2c396b63332e2fe92fe43f7ff2ad19b3998735f28b0a7f/sphinx_pyproject-0.3.0.tar.gz", hash = "sha256:efc4ee9d96f579c4e4ed1ac273868c64565e88c8e37fe6ec2dc59fbcd57684ab", size = 7695, upload-time = "2023-08-18T21:43:45.473Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/90/d5/89cb47c6399fd57ca451af15361499813c5d53e588cb6e00d89411ce724f/sphinx_pyproject-0.3.0-py3-none-any.whl", hash = "sha256:3aca968919f5ecd390f96874c3f64a43c9c7fcfdc2fd4191a781ad9228501b52", size = 23076 }, + { url = "https://files.pythonhosted.org/packages/90/d5/89cb47c6399fd57ca451af15361499813c5d53e588cb6e00d89411ce724f/sphinx_pyproject-0.3.0-py3-none-any.whl", hash = "sha256:3aca968919f5ecd390f96874c3f64a43c9c7fcfdc2fd4191a781ad9228501b52", size = 23076, upload-time = "2023-08-18T21:43:43.808Z" }, ] [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053 } +sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300 }, + { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, ] [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967 } +sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530 }, + { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, ] [[package]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617 } +sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705 }, + { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, ] [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787 } +sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071 }, + { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, ] [[package]] name = "sphinxcontrib-qthelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165 } +sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743 }, + { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, ] [[package]] name = "sphinxcontrib-serializinghtml" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080 } +sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072 }, + { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, ] [[package]] @@ -1043,26 +1111,26 @@ dependencies = [ { name = "patsy" }, { name = "scipy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1f/3b/963a015dd8ea17e10c7b0e2f14d7c4daec903baf60a017e756b57953a4bf/statsmodels-0.14.4.tar.gz", hash = "sha256:5d69e0f39060dc72c067f9bb6e8033b6dccdb0bae101d76a7ef0bcc94e898b67", size = 20354802 } +sdist = { url = "https://files.pythonhosted.org/packages/1f/3b/963a015dd8ea17e10c7b0e2f14d7c4daec903baf60a017e756b57953a4bf/statsmodels-0.14.4.tar.gz", hash = "sha256:5d69e0f39060dc72c067f9bb6e8033b6dccdb0bae101d76a7ef0bcc94e898b67", size = 20354802, upload-time = "2024-10-03T16:15:36.273Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/f8/2662e6a101315ad336f75168fa9bac71f913ebcb92a6be84031d84a0f21f/statsmodels-0.14.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b5a24f5d2c22852d807d2b42daf3a61740820b28d8381daaf59dcb7055bf1a79", size = 10186886 }, - { url = "https://files.pythonhosted.org/packages/fa/c0/ee6e8ed35fc1ca9c7538c592f4974547bf72274bc98db1ae4a6e87481a83/statsmodels-0.14.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df4f7864606fa843d7e7c0e6af288f034a2160dba14e6ccc09020a3cf67cb092", size = 9880066 }, - { url = "https://files.pythonhosted.org/packages/d1/97/3380ca6d8fd66cfb3d12941e472642f26e781a311c355a4e97aab2ed0216/statsmodels-0.14.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91341cbde9e8bea5fb419a76e09114e221567d03f34ca26e6d67ae2c27d8fe3c", size = 10283521 }, - { url = "https://files.pythonhosted.org/packages/fe/2a/55c5b5c5e5124a202ea3fe0bcdbdeceaf91b4ec6164b8434acb9dd97409c/statsmodels-0.14.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1322286a7bfdde2790bf72d29698a1b76c20b8423a55bdcd0d457969d0041f72", size = 10723228 }, - { url = "https://files.pythonhosted.org/packages/4f/76/67747e49dc758daae06f33aad8247b718cd7d224f091d2cd552681215bb2/statsmodels-0.14.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e31b95ac603415887c9f0d344cb523889cf779bc52d68e27e2d23c358958fec7", size = 10859503 }, - { url = "https://files.pythonhosted.org/packages/1d/eb/cb8b01f5edf8f135eb3d0553d159db113a35b2948d0e51eeb735e7ae09ea/statsmodels-0.14.4-cp313-cp313-win_amd64.whl", hash = "sha256:81030108d27aecc7995cac05aa280cf8c6025f6a6119894eef648997936c2dd0", size = 9817574 }, + { url = "https://files.pythonhosted.org/packages/31/f8/2662e6a101315ad336f75168fa9bac71f913ebcb92a6be84031d84a0f21f/statsmodels-0.14.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b5a24f5d2c22852d807d2b42daf3a61740820b28d8381daaf59dcb7055bf1a79", size = 10186886, upload-time = "2024-10-03T17:10:44.074Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c0/ee6e8ed35fc1ca9c7538c592f4974547bf72274bc98db1ae4a6e87481a83/statsmodels-0.14.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df4f7864606fa843d7e7c0e6af288f034a2160dba14e6ccc09020a3cf67cb092", size = 9880066, upload-time = "2024-10-03T17:10:56.972Z" }, + { url = "https://files.pythonhosted.org/packages/d1/97/3380ca6d8fd66cfb3d12941e472642f26e781a311c355a4e97aab2ed0216/statsmodels-0.14.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91341cbde9e8bea5fb419a76e09114e221567d03f34ca26e6d67ae2c27d8fe3c", size = 10283521, upload-time = "2024-10-03T17:14:06.216Z" }, + { url = "https://files.pythonhosted.org/packages/fe/2a/55c5b5c5e5124a202ea3fe0bcdbdeceaf91b4ec6164b8434acb9dd97409c/statsmodels-0.14.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1322286a7bfdde2790bf72d29698a1b76c20b8423a55bdcd0d457969d0041f72", size = 10723228, upload-time = "2024-10-03T17:14:19.587Z" }, + { url = "https://files.pythonhosted.org/packages/4f/76/67747e49dc758daae06f33aad8247b718cd7d224f091d2cd552681215bb2/statsmodels-0.14.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e31b95ac603415887c9f0d344cb523889cf779bc52d68e27e2d23c358958fec7", size = 10859503, upload-time = "2024-10-03T17:14:32.798Z" }, + { url = "https://files.pythonhosted.org/packages/1d/eb/cb8b01f5edf8f135eb3d0553d159db113a35b2948d0e51eeb735e7ae09ea/statsmodels-0.14.4-cp313-cp313-win_amd64.whl", hash = "sha256:81030108d27aecc7995cac05aa280cf8c6025f6a6119894eef648997936c2dd0", size = 9817574, upload-time = "2024-10-03T16:14:37.461Z" }, ] [[package]] name = "sympy" -version = "1.13.3" +version = "1.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mpmath" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/11/8a/5a7fd6284fa8caac23a26c9ddf9c30485a48169344b4bd3b0f02fef1890f/sympy-1.13.3.tar.gz", hash = "sha256:b27fd2c6530e0ab39e275fc9b683895367e51d5da91baa8d3d64db2565fec4d9", size = 7533196 } +sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl", hash = "sha256:54612cf55a62755ee71824ce692986f23c88ffa77207b30c1368eda4a7060f73", size = 6189483 }, + { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" }, ] [[package]] @@ -1072,6 +1140,7 @@ source = { virtual = "." } dependencies = [ { name = "beautifulsoup4" }, { name = "fake-useragent" }, + { name = "httpx" }, { name = "imageio" }, { name = "keras" }, { name = "lxml" }, @@ -1080,7 +1149,6 @@ dependencies = [ { name = "opencv-python" }, { name = "pandas" }, { name = "pillow" }, - { name = "requests" }, { name = "rich" }, { name = "scikit-learn" }, { name = "sphinx-pyproject" }, @@ -1092,30 +1160,25 @@ dependencies = [ ] [package.dev-dependencies] -dev = [ - { name = "pytest" }, - { name = "pytest-cov" }, -] docs = [ { name = "myst-parser" }, { name = "sphinx-autoapi" }, { name = "sphinx-pyproject" }, ] euler-validate = [ + { name = "httpx" }, { name = "numpy" }, +] +test = [ { name = "pytest" }, { name = "pytest-cov" }, - { name = "requests" }, -] -lint = [ - { name = "codespell" }, - { name = "ruff" }, ] [package.metadata] requires-dist = [ { name = "beautifulsoup4", specifier = ">=4.12.3" }, { name = "fake-useragent", specifier = ">=1.5.1" }, + { name = "httpx", specifier = ">=0.28.1" }, { name = "imageio", specifier = ">=2.36.1" }, { name = "keras", specifier = ">=3.7" }, { name = "lxml", specifier = ">=5.3" }, @@ -1124,7 +1187,6 @@ requires-dist = [ { name = "opencv-python", specifier = ">=4.10.0.84" }, { name = "pandas", specifier = ">=2.2.3" }, { name = "pillow", specifier = ">=11" }, - { name = "requests", specifier = ">=2.32.3" }, { name = "rich", specifier = ">=13.9.4" }, { name = "scikit-learn", specifier = ">=1.5.2" }, { name = "sphinx-pyproject", specifier = ">=0.3" }, @@ -1136,111 +1198,105 @@ requires-dist = [ ] [package.metadata.requires-dev] -dev = [ - { name = "pytest", specifier = ">=8.3.4" }, - { name = "pytest-cov", specifier = ">=6" }, -] docs = [ - { name = "myst-parser", specifier = ">=4.0.0" }, - { name = "sphinx-autoapi", specifier = ">=3.4.0" }, - { name = "sphinx-pyproject", specifier = ">=0.3.0" }, + { name = "myst-parser", specifier = ">=4" }, + { name = "sphinx-autoapi", specifier = ">=3.4" }, + { name = "sphinx-pyproject", specifier = ">=0.3" }, ] euler-validate = [ + { name = "httpx", specifier = ">=0.28.1" }, { name = "numpy", specifier = ">=2.1.3" }, - { name = "pytest", specifier = ">=8.3.4" }, - { name = "pytest-cov", specifier = ">=6.0.0" }, - { name = "requests", specifier = ">=2.32.3" }, ] -lint = [ - { name = "codespell", specifier = ">=2.3" }, - { name = "ruff", specifier = ">=0.8.1" }, +test = [ + { name = "pytest", specifier = ">=8.3.4" }, + { name = "pytest-cov", specifier = ">=6" }, ] [[package]] name = "threadpoolctl" -version = "3.5.0" +version = "3.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bd/55/b5148dcbf72f5cde221f8bfe3b6a540da7aa1842f6b491ad979a6c8b84af/threadpoolctl-3.5.0.tar.gz", hash = "sha256:082433502dd922bf738de0d8bcc4fdcbf0979ff44c42bd40f5af8a282f6fa107", size = 41936 } +sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl", hash = "sha256:56c1e26c150397e58c4926da8eeee87533b1e32bef131bd4bf6a2f45f3185467", size = 18414 }, + { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, ] [[package]] name = "tomli" version = "2.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, ] [[package]] name = "tweepy" -version = "4.14.0" +version = "4.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "oauthlib" }, { name = "requests" }, { name = "requests-oauthlib" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/75/1c/0db8c3cf9d31bf63853ff612d201060ae78e6db03468a70e063bef0eda62/tweepy-4.14.0.tar.gz", hash = "sha256:1f9f1707d6972de6cff6c5fd90dfe6a449cd2e0d70bd40043ffab01e07a06c8c", size = 88623 } +sdist = { url = "https://files.pythonhosted.org/packages/99/05/7c2c01bd62900eff24534779f1e1531491dfd872edb6a9d432ae91e18b4b/tweepy-4.15.0.tar.gz", hash = "sha256:1345cbcdf0a75e2d89f424c559fd49fda4d8cd7be25cd5131e3b57bad8a21d76", size = 100268, upload-time = "2025-01-15T21:25:05.307Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/78/ba0065d5636bbf4a35b78c4f81b74e7858b609cdf69e629d6da5c91b9d92/tweepy-4.14.0-py3-none-any.whl", hash = "sha256:db6d3844ccc0c6d27f339f12ba8acc89912a961da513c1ae50fa2be502a56afb", size = 98520 }, + { url = "https://files.pythonhosted.org/packages/81/53/ca632ec02085b5c432e98ae1f872a21f2b6bb6c3d022dcf586809cc65cd0/tweepy-4.15.0-py3-none-any.whl", hash = "sha256:64adcea317158937059e4e2897b3ceb750b0c2dd5df58938c2da8f7eb3b88e6a", size = 99379, upload-time = "2025-01-15T21:25:02.856Z" }, ] [[package]] name = "typing-extensions" -version = "4.12.2" +version = "4.13.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, ] [[package]] name = "tzdata" -version = "2024.2" +version = "2025.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e1/34/943888654477a574a86a98e9896bae89c7aa15078ec29f490fef2f1e5384/tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc", size = 193282 } +sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/ab/7e5f53c3b9d14972843a647d8d7a853969a58aecc7559cb3267302c94774/tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd", size = 346586 }, + { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, ] [[package]] name = "urllib3" -version = "2.2.3" +version = "2.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } +sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, + { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, ] [[package]] name = "xgboost" -version = "2.1.3" +version = "3.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, - { name = "nvidia-nccl-cu12", marker = "platform_machine != 'aarch64' and platform_system == 'Linux'" }, + { name = "nvidia-nccl-cu12", marker = "platform_machine != 'aarch64' and sys_platform == 'linux'" }, { name = "scipy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/48/b0/131ffc4a15fd3acee9be3a7baa6b2fa6faa479799c51b880de9fc3ddf550/xgboost-2.1.3.tar.gz", hash = "sha256:7699ec4226156887d3afc665c63ab87469db9d46e361c702ba9fccd22535730c", size = 1090326 } +sdist = { url = "https://files.pythonhosted.org/packages/82/18/f58f9dcbcca811b30be945fd7f890f87a0ee822f7316e2ddd7a3e3056f08/xgboost-3.0.0.tar.gz", hash = "sha256:45e95416df6f6f01d9a62e60cf09fc57e5ee34697f3858337c796fac9ce3b9ed", size = 1156620, upload-time = "2025-03-15T13:45:01.277Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/c6/773ebd84414879bd0566788868ae46a6574f6efaf81e694f01ea1fed3277/xgboost-2.1.3-py3-none-macosx_10_15_x86_64.macosx_11_0_x86_64.macosx_12_0_x86_64.whl", hash = "sha256:c9b0c92f13e3650e1e1cf92ff9ecef3efc6f5dc3d10ce17858df2081a89976ef", size = 2139909 }, - { url = "https://files.pythonhosted.org/packages/28/3c/ddf5d9eb742cdb7fbcd5c854bce07471bad01194ac37de91db64fbef0c58/xgboost-2.1.3-py3-none-macosx_12_0_arm64.whl", hash = "sha256:fcbf1912a852bd07a7007be350c8dc3a484c5e775b612f2b3cd082fc76240eb3", size = 1938631 }, - { url = "https://files.pythonhosted.org/packages/4a/3a/8cd69a216993fd9d54ceb079d1b357b7ef50678b3c2695d8a71962b8d0aa/xgboost-2.1.3-py3-none-manylinux2014_aarch64.whl", hash = "sha256:27af88df1162cee016c67f267a0a16c3db1c48f256e12f64c45c8f8edf9571cd", size = 4441261 }, - { url = "https://files.pythonhosted.org/packages/48/bc/05d7db90d421c5e3d681a12fd1eb087e37bf2e9bbe2b105422d6319ecc92/xgboost-2.1.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:32a43526208fe676527c698cb852e0e9515e6d7294143780e476d335290a131b", size = 4532380 }, - { url = "https://files.pythonhosted.org/packages/0f/c8/f679a816c06a4a6d23da3f4b448d5f0615b51de2886ad3e3e695d17121b3/xgboost-2.1.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:5d33090880f3d474f8cf5dda557c7bf8dbceefb62f2fd655c77efcabb9cac222", size = 4207000 }, - { url = "https://files.pythonhosted.org/packages/32/93/66826e2f50cefecbb0a44bd1e667316bf0a3c8e78cd1f0cdf52f5b2c5c6f/xgboost-2.1.3-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:8d85d38553855a1f8c40b8fbccca86af19202f91b244e2c7f77afbb2a6d9d785", size = 153894508 }, - { url = "https://files.pythonhosted.org/packages/70/58/2f94976df39470fb00eec2cb4f914dde44cd0df8d96483208bf7db4bc97e/xgboost-2.1.3-py3-none-win_amd64.whl", hash = "sha256:25c0ffcbd62aac5bc22c79e08b5b2edad1d5e37f16610ebefa5f06f3e2ea3d96", size = 124909665 }, + { url = "https://files.pythonhosted.org/packages/95/6c/d2a1636591e204667f320481b036acc9c526608bcc2319be71cce148102d/xgboost-3.0.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:ed8cffd7998bd9431c3b0287a70bec8e45c09b43c9474d9dfd261627713bd890", size = 2245638, upload-time = "2025-03-15T13:46:14.653Z" }, + { url = "https://files.pythonhosted.org/packages/5a/0b/f9f815f240a9610d42367172b9f7ef7e8c9113a09b1bb35d4d85f96b910a/xgboost-3.0.0-py3-none-macosx_12_0_arm64.whl", hash = "sha256:314104bd3a1426a40f0c9662eef40e9ab22eb7a8068a42a8d198ce40412db75c", size = 2025491, upload-time = "2025-03-15T13:46:49.556Z" }, + { url = "https://files.pythonhosted.org/packages/3c/aa/f4597dc989317d2431cd71998cac1f9205c773658e0cf6680bb9011b26eb/xgboost-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:72c3405e8dfc37048f9fe339a058fa12b9f0f03bc31d3e56f0887eed2ed2baa1", size = 4841002, upload-time = "2025-03-15T13:47:19.693Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/b89d99b89946afc842feb8f47302e8022f1405f01212d3e186b6d674b2ba/xgboost-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:72d39e74649e9b628c4221111aa6a8caa860f2e853b25480424403ee61085126", size = 4903442, upload-time = "2025-03-15T13:47:44.917Z" }, + { url = "https://files.pythonhosted.org/packages/bb/68/a7a274bedf43bbf9de120104b438b45e232395f8b9861519040b7b725535/xgboost-3.0.0-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:7bdee5787f86b83bebd75e2c96caf854760788e5f4203d063da50db5bf0efc5f", size = 4602694, upload-time = "2025-03-15T13:48:16.498Z" }, + { url = "https://files.pythonhosted.org/packages/63/f1/653afe1a1b7e1d03f26fd4bd30f3eebcfac2d8982e1a85b6be3355dcae25/xgboost-3.0.0-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:61c7e391e373b8a5312503525c0689f83ef1912a1236377022865ab340f465a4", size = 253877333, upload-time = "2025-03-15T13:51:01.139Z" }, + { url = "https://files.pythonhosted.org/packages/5e/03/15cd49e855c62226ecf1831bbe4c8e73a4324856077a23c495538a36e557/xgboost-3.0.0-py3-none-win_amd64.whl", hash = "sha256:0ea74e97f95b1eddfd27a46b7f22f72ec5a5322e1dc7cb41c9c23fb580763df9", size = 149971978, upload-time = "2025-03-15T13:53:26.596Z" }, ] diff --git a/web_programming/co2_emission.py b/web_programming/co2_emission.py index 19af70489d1d..4f62df8447b0 100644 --- a/web_programming/co2_emission.py +++ b/web_programming/co2_emission.py @@ -2,22 +2,29 @@ Get CO2 emission data from the UK CarbonIntensity API """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + from datetime import date -import requests +import httpx BASE_URL = "https://api.carbonintensity.org.uk/intensity" # Emission in the last half hour def fetch_last_half_hour() -> str: - last_half_hour = requests.get(BASE_URL, timeout=10).json()["data"][0] + last_half_hour = httpx.get(BASE_URL, timeout=10).json()["data"][0] return last_half_hour["intensity"]["actual"] # Emissions in a specific date range def fetch_from_to(start, end) -> list: - return requests.get(f"{BASE_URL}/{start}/{end}", timeout=10).json()["data"] + return httpx.get(f"{BASE_URL}/{start}/{end}", timeout=10).json()["data"] if __name__ == "__main__": diff --git a/web_programming/covid_stats_via_xpath.py b/web_programming/covid_stats_via_xpath.py index c27a5d12bb3f..f7db51b63169 100644 --- a/web_programming/covid_stats_via_xpath.py +++ b/web_programming/covid_stats_via_xpath.py @@ -4,9 +4,17 @@ more convenient to use in Python web projects (e.g. Django or Flask-based) """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# "lxml", +# ] +# /// + from typing import NamedTuple -import requests +import httpx from lxml import html @@ -19,7 +27,7 @@ class CovidData(NamedTuple): def covid_stats(url: str = "https://www.worldometers.info/coronavirus/") -> CovidData: xpath_str = '//div[@class = "maincounter-number"]/span/text()' return CovidData( - *html.fromstring(requests.get(url, timeout=10).content).xpath(xpath_str) + *html.fromstring(httpx.get(url, timeout=10).content).xpath(xpath_str) ) diff --git a/web_programming/crawl_google_results.py b/web_programming/crawl_google_results.py index cb75d450ff82..0ae13792e048 100644 --- a/web_programming/crawl_google_results.py +++ b/web_programming/crawl_google_results.py @@ -1,14 +1,28 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "fake-useragent", +# "httpx", +# ] +# /// + import sys import webbrowser -import requests +import httpx from bs4 import BeautifulSoup from fake_useragent import UserAgent if __name__ == "__main__": print("Googling.....") url = "https://www.google.com/search?q=" + " ".join(sys.argv[1:]) - res = requests.get(url, headers={"UserAgent": UserAgent().random}, timeout=10) + res = httpx.get( + url, + headers={"UserAgent": UserAgent().random}, + timeout=10, + follow_redirects=True, + ) # res.raise_for_status() with open("project1a.html", "wb") as out_file: # only for knowing the class for data in res.iter_content(10000): diff --git a/web_programming/crawl_google_scholar_citation.py b/web_programming/crawl_google_scholar_citation.py index 5f2ccad5f414..77d7be00c7b6 100644 --- a/web_programming/crawl_google_scholar_citation.py +++ b/web_programming/crawl_google_scholar_citation.py @@ -3,7 +3,15 @@ using title and year of publication, and volume and pages of journal. """ -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# ] +# /// + +import httpx from bs4 import BeautifulSoup @@ -12,7 +20,7 @@ def get_citation(base_url: str, params: dict) -> str: Return the citation number. """ soup = BeautifulSoup( - requests.get(base_url, params=params, timeout=10).content, "html.parser" + httpx.get(base_url, params=params, timeout=10).content, "html.parser" ) div = soup.find("div", attrs={"class": "gs_ri"}) anchors = div.find("div", attrs={"class": "gs_fl"}).find_all("a") diff --git a/web_programming/currency_converter.py b/web_programming/currency_converter.py index 9623504b89ea..a007c9c35a65 100644 --- a/web_programming/currency_converter.py +++ b/web_programming/currency_converter.py @@ -3,9 +3,16 @@ https://www.amdoren.com """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + import os -import requests +import httpx URL_BASE = "https://www.amdoren.com/api/currency.php" @@ -176,7 +183,7 @@ def convert_currency( params = locals() # from is a reserved keyword params["from"] = params.pop("from_") - res = requests.get(URL_BASE, params=params, timeout=10).json() + res = httpx.get(URL_BASE, params=params, timeout=10).json() return str(res["amount"]) if res["error"] == 0 else res["error_message"] diff --git a/web_programming/current_stock_price.py b/web_programming/current_stock_price.py index 573e1f575c8e..16b0b6772a9c 100644 --- a/web_programming/current_stock_price.py +++ b/web_programming/current_stock_price.py @@ -1,4 +1,12 @@ -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# ] +# /// + +import httpx from bs4 import BeautifulSoup """ @@ -20,8 +28,8 @@ def stock_price(symbol: str = "AAPL") -> str: True """ url = f"https://finance.yahoo.com/quote/{symbol}?p={symbol}" - yahoo_finance_source = requests.get( - url, headers={"USER-AGENT": "Mozilla/5.0"}, timeout=10 + yahoo_finance_source = httpx.get( + url, headers={"USER-AGENT": "Mozilla/5.0"}, timeout=10, follow_redirects=True ).text soup = BeautifulSoup(yahoo_finance_source, "html.parser") diff --git a/web_programming/current_weather.py b/web_programming/current_weather.py index 4a8fa5e3c845..001eaf9020f4 100644 --- a/web_programming/current_weather.py +++ b/web_programming/current_weather.py @@ -1,4 +1,11 @@ -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + +import httpx # Put your API key(s) here OPENWEATHERMAP_API_KEY = "" @@ -19,13 +26,13 @@ def current_weather(location: str) -> list[dict]: weather_data = [] if OPENWEATHERMAP_API_KEY: params_openweathermap = {"q": location, "appid": OPENWEATHERMAP_API_KEY} - response_openweathermap = requests.get( + response_openweathermap = httpx.get( OPENWEATHERMAP_URL_BASE, params=params_openweathermap, timeout=10 ) weather_data.append({"OpenWeatherMap": response_openweathermap.json()}) if WEATHERSTACK_API_KEY: params_weatherstack = {"query": location, "access_key": WEATHERSTACK_API_KEY} - response_weatherstack = requests.get( + response_weatherstack = httpx.get( WEATHERSTACK_URL_BASE, params=params_weatherstack, timeout=10 ) weather_data.append({"Weatherstack": response_weatherstack.json()}) diff --git a/web_programming/daily_horoscope.py b/web_programming/daily_horoscope.py index 75e637d8e52c..b84ea13238cc 100644 --- a/web_programming/daily_horoscope.py +++ b/web_programming/daily_horoscope.py @@ -1,4 +1,12 @@ -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# ] +# /// + +import httpx from bs4 import BeautifulSoup @@ -7,7 +15,7 @@ def horoscope(zodiac_sign: int, day: str) -> str: "https://www.horoscope.com/us/horoscopes/general/" f"horoscope-general-daily-{day}.aspx?sign={zodiac_sign}" ) - soup = BeautifulSoup(requests.get(url, timeout=10).content, "html.parser") + soup = BeautifulSoup(httpx.get(url, timeout=10).content, "html.parser") return soup.find("div", class_="main-horoscope").p.text diff --git a/web_programming/download_images_from_google_query.py b/web_programming/download_images_from_google_query.py index 235cd35763ef..659cf6a398a3 100644 --- a/web_programming/download_images_from_google_query.py +++ b/web_programming/download_images_from_google_query.py @@ -1,10 +1,18 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# ] +# /// + import json import os import re import sys import urllib.request -import requests +import httpx from bs4 import BeautifulSoup headers = { @@ -39,7 +47,7 @@ def download_images_from_google_query(query: str = "dhaka", max_images: int = 5) "ijn": "0", } - html = requests.get( + html = httpx.get( "https://www.google.com/search", params=params, headers=headers, timeout=10 ) soup = BeautifulSoup(html.text, "html.parser") diff --git a/web_programming/emails_from_url.py b/web_programming/emails_from_url.py index d41dc4893608..3fa24085df95 100644 --- a/web_programming/emails_from_url.py +++ b/web_programming/emails_from_url.py @@ -1,5 +1,12 @@ """Get the site emails from URL.""" +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + from __future__ import annotations __author__ = "Muhammad Umer Farooq" @@ -13,7 +20,7 @@ from html.parser import HTMLParser from urllib import parse -import requests +import httpx class Parser(HTMLParser): @@ -72,7 +79,7 @@ def emails_from_url(url: str = "https://github.com") -> list[str]: try: # Open URL - r = requests.get(url, timeout=10) + r = httpx.get(url, timeout=10, follow_redirects=True) # pass the raw HTML to the parser to get links parser.feed(r.text) @@ -81,9 +88,15 @@ def emails_from_url(url: str = "https://github.com") -> list[str]: valid_emails = set() for link in parser.urls: # open URL. - # read = requests.get(link) + # Check if the link is already absolute + if not link.startswith("http://") and not link.startswith("https://"): + # Prepend protocol only if link starts with domain, normalize otherwise + if link.startswith(domain): + link = f"https://{link}" + else: + link = parse.urljoin(f"https://{domain}", link) try: - read = requests.get(link, timeout=10) + read = httpx.get(link, timeout=10, follow_redirects=True) # Get the valid email. emails = re.findall("[a-zA-Z0-9]+@" + domain, read.text) # If not in list then append it. diff --git a/web_programming/fetch_anime_and_play.py b/web_programming/fetch_anime_and_play.py index e56b7124eeb5..616116595697 100644 --- a/web_programming/fetch_anime_and_play.py +++ b/web_programming/fetch_anime_and_play.py @@ -1,8 +1,17 @@ -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "fake-useragent", +# "httpx", +# ] +# /// + +import httpx from bs4 import BeautifulSoup, NavigableString, Tag from fake_useragent import UserAgent -BASE_URL = "https://ww1.gogoanime2.org" +BASE_URL = "https://ww7.gogoanime2.org" def search_scraper(anime_name: str) -> list: @@ -25,9 +34,9 @@ def search_scraper(anime_name: str) -> list: """ # concat the name to form the search url. - search_url = f"{BASE_URL}/search/{anime_name}" + search_url = f"{BASE_URL}/search?keyword={anime_name}" - response = requests.get( + response = httpx.get( search_url, headers={"UserAgent": UserAgent().chrome}, timeout=10 ) # request the url. @@ -82,7 +91,7 @@ def search_anime_episode_list(episode_endpoint: str) -> list: request_url = f"{BASE_URL}{episode_endpoint}" - response = requests.get( + response = httpx.get( url=request_url, headers={"UserAgent": UserAgent().chrome}, timeout=10 ) response.raise_for_status() @@ -133,7 +142,7 @@ def get_anime_episode(episode_endpoint: str) -> list: episode_page_url = f"{BASE_URL}{episode_endpoint}" - response = requests.get( + response = httpx.get( url=episode_page_url, headers={"User-Agent": UserAgent().chrome}, timeout=10 ) response.raise_for_status() diff --git a/web_programming/fetch_bbc_news.py b/web_programming/fetch_bbc_news.py index e5cd864a9d83..f3121fee7db4 100644 --- a/web_programming/fetch_bbc_news.py +++ b/web_programming/fetch_bbc_news.py @@ -1,13 +1,20 @@ # Created by sarathkaul on 12/11/19 -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + +import httpx _NEWS_API = "https://newsapi.org/v1/articles?source=bbc-news&sortBy=top&apiKey=" def fetch_bbc_news(bbc_news_api_key: str) -> None: # fetching a list of articles in json format - bbc_news_page = requests.get(_NEWS_API + bbc_news_api_key, timeout=10).json() + bbc_news_page = httpx.get(_NEWS_API + bbc_news_api_key, timeout=10).json() # each article in the list is a dict for i, article in enumerate(bbc_news_page["articles"], 1): print(f"{i}.) {article['title']}") diff --git a/web_programming/fetch_github_info.py b/web_programming/fetch_github_info.py index 25d44245bb58..1d3d344e177e 100644 --- a/web_programming/fetch_github_info.py +++ b/web_programming/fetch_github_info.py @@ -18,12 +18,19 @@ export USER_TOKEN="" """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + from __future__ import annotations import os from typing import Any -import requests +import httpx BASE_URL = "https://api.github.com" @@ -36,13 +43,13 @@ def fetch_github_info(auth_token: str) -> dict[Any, Any]: """ - Fetch GitHub info of a user using the requests module + Fetch GitHub info of a user using the httpx module """ headers = { "Authorization": f"token {auth_token}", "Accept": "application/vnd.github.v3+json", } - return requests.get(AUTHENTICATED_USER_ENDPOINT, headers=headers, timeout=10).json() + return httpx.get(AUTHENTICATED_USER_ENDPOINT, headers=headers, timeout=10).json() if __name__ == "__main__": # pragma: no cover diff --git a/web_programming/fetch_jobs.py b/web_programming/fetch_jobs.py index 3753d25bbe5f..7a95f997078d 100644 --- a/web_programming/fetch_jobs.py +++ b/web_programming/fetch_jobs.py @@ -2,20 +2,26 @@ Scraping jobs given job title and location from indeed website """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# ] +# /// + from __future__ import annotations from collections.abc import Generator -import requests +import httpx from bs4 import BeautifulSoup url = "https://www.indeed.co.in/jobs?q=mobile+app+development&l=" def fetch_jobs(location: str = "mumbai") -> Generator[tuple[str, str]]: - soup = BeautifulSoup( - requests.get(url + location, timeout=10).content, "html.parser" - ) + soup = BeautifulSoup(httpx.get(url + location, timeout=10).content, "html.parser") # This attribute finds out all the specifics listed in a job for job in soup.find_all("div", attrs={"data-tn-component": "organicJob"}): job_title = job.find("a", attrs={"data-tn-element": "jobTitle"}).text.strip() diff --git a/web_programming/fetch_quotes.py b/web_programming/fetch_quotes.py index cf0add43f002..38113c888d89 100644 --- a/web_programming/fetch_quotes.py +++ b/web_programming/fetch_quotes.py @@ -6,19 +6,26 @@ https://zenquotes.io/ """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + import pprint -import requests +import httpx API_ENDPOINT_URL = "https://zenquotes.io/api" def quote_of_the_day() -> list: - return requests.get(API_ENDPOINT_URL + "/today", timeout=10).json() + return httpx.get(API_ENDPOINT_URL + "/today", timeout=10).json() def random_quotes() -> list: - return requests.get(API_ENDPOINT_URL + "/random", timeout=10).json() + return httpx.get(API_ENDPOINT_URL + "/random", timeout=10).json() if __name__ == "__main__": diff --git a/web_programming/get_amazon_product_data.py b/web_programming/get_amazon_product_data.py index b98ff2c030af..02db708e02bf 100644 --- a/web_programming/get_amazon_product_data.py +++ b/web_programming/get_amazon_product_data.py @@ -4,9 +4,18 @@ information will include title, URL, price, ratings, and the discount available. """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# "pandas", +# ] +# /// + from itertools import zip_longest -import requests +import httpx from bs4 import BeautifulSoup from pandas import DataFrame @@ -25,7 +34,7 @@ def get_amazon_product_data(product: str = "laptop") -> DataFrame: "Accept-Language": "en-US, en;q=0.5", } soup = BeautifulSoup( - requests.get(url, headers=header, timeout=10).text, features="lxml" + httpx.get(url, headers=header, timeout=10).text, features="lxml" ) # Initialize a Pandas dataframe with the column titles data_frame = DataFrame( diff --git a/web_programming/get_imdb_top_250_movies_csv.py b/web_programming/get_imdb_top_250_movies_csv.py index c914b29cb3b3..4cd29f0e1426 100644 --- a/web_programming/get_imdb_top_250_movies_csv.py +++ b/web_programming/get_imdb_top_250_movies_csv.py @@ -1,16 +1,24 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# ] +# /// + from __future__ import annotations import csv -import requests +import httpx from bs4 import BeautifulSoup def get_imdb_top_250_movies(url: str = "") -> dict[str, float]: url = url or "https://www.imdb.com/chart/top/?ref_=nv_mv_250" - soup = BeautifulSoup(requests.get(url, timeout=10).text, "html.parser") - titles = soup.find_all("td", attrs="titleColumn") - ratings = soup.find_all("td", class_="ratingColumn imdbRating") + soup = BeautifulSoup(httpx.get(url, timeout=10).text, "html.parser") + titles = soup.find_all("h3", class_="ipc-title__text") + ratings = soup.find_all("span", class_="ipc-rating-star--rating") return { title.a.text: float(rating.strong.text) for title, rating in zip(titles, ratings) diff --git a/web_programming/get_ip_geolocation.py b/web_programming/get_ip_geolocation.py index 574d287f0db1..153655257324 100644 --- a/web_programming/get_ip_geolocation.py +++ b/web_programming/get_ip_geolocation.py @@ -1,4 +1,11 @@ -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + +import httpx # Function to get geolocation data for an IP address @@ -8,7 +15,7 @@ def get_ip_geolocation(ip_address: str) -> str: url = f"https://ipinfo.io/{ip_address}/json" # Send a GET request to the API - response = requests.get(url, timeout=10) + response = httpx.get(url, timeout=10) # Check if the HTTP request was successful response.raise_for_status() @@ -23,7 +30,7 @@ def get_ip_geolocation(ip_address: str) -> str: location = "Location data not found." return location - except requests.exceptions.RequestException as e: + except httpx.RequestError as e: # Handle network-related exceptions return f"Request error: {e}" except ValueError as e: diff --git a/web_programming/get_top_billionaires.py b/web_programming/get_top_billionaires.py index 99f6e0be948a..b6f3bf0ca5be 100644 --- a/web_programming/get_top_billionaires.py +++ b/web_programming/get_top_billionaires.py @@ -3,9 +3,17 @@ This works for some of us but fails for others. """ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# "rich", +# ] +# /// + from datetime import UTC, date, datetime -import requests +import httpx from rich import box from rich import console as rich_console from rich import table as rich_table @@ -57,7 +65,7 @@ def get_forbes_real_time_billionaires() -> list[dict[str, int | str]]: Returns: List of top 10 realtime billionaires data. """ - response_json = requests.get(API_URL, timeout=10).json() + response_json = httpx.get(API_URL, timeout=10).json() return [ { "Name": person["personName"], diff --git a/web_programming/get_top_hn_posts.py b/web_programming/get_top_hn_posts.py index f5d4f874c6c6..7d6308ae70c1 100644 --- a/web_programming/get_top_hn_posts.py +++ b/web_programming/get_top_hn_posts.py @@ -1,11 +1,18 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + from __future__ import annotations -import requests +import httpx def get_hackernews_story(story_id: str) -> dict: url = f"https://hacker-news.firebaseio.com/v0/item/{story_id}.json?print=pretty" - return requests.get(url, timeout=10).json() + return httpx.get(url, timeout=10).json() def hackernews_top_stories(max_stories: int = 10) -> list[dict]: @@ -13,7 +20,7 @@ def hackernews_top_stories(max_stories: int = 10) -> list[dict]: Get the top max_stories posts from HackerNews - https://news.ycombinator.com/ """ url = "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty" - story_ids = requests.get(url, timeout=10).json()[:max_stories] + story_ids = httpx.get(url, timeout=10).json()[:max_stories] return [get_hackernews_story(story_id) for story_id in story_ids] diff --git a/web_programming/giphy.py b/web_programming/giphy.py index 2bf3e3ea9c0b..90f4e51a7242 100644 --- a/web_programming/giphy.py +++ b/web_programming/giphy.py @@ -1,5 +1,13 @@ #!/usr/bin/env python3 -import requests + +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + +import httpx giphy_api_key = "YOUR API KEY" # Can be fetched from https://developers.giphy.com/dashboard/ @@ -11,7 +19,7 @@ def get_gifs(query: str, api_key: str = giphy_api_key) -> list: """ formatted_query = "+".join(query.split()) url = f"https://api.giphy.com/v1/gifs/search?q={formatted_query}&api_key={api_key}" - gifs = requests.get(url, timeout=10).json()["data"] + gifs = httpx.get(url, timeout=10).json()["data"] return [gif["url"] for gif in gifs] diff --git a/web_programming/instagram_crawler.py b/web_programming/instagram_crawler.py index df62735fb328..68271c1c4643 100644 --- a/web_programming/instagram_crawler.py +++ b/web_programming/instagram_crawler.py @@ -1,9 +1,19 @@ #!/usr/bin/env python3 + +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "fake-useragent", +# "httpx", +# ] +# /// + from __future__ import annotations import json -import requests +import httpx from bs4 import BeautifulSoup from fake_useragent import UserAgent @@ -39,7 +49,7 @@ def get_json(self) -> dict: """ Return a dict of user information """ - html = requests.get(self.url, headers=headers, timeout=10).text + html = httpx.get(self.url, headers=headers, timeout=10).text scripts = BeautifulSoup(html, "html.parser").find_all("script") try: return extract_user_profile(scripts[4]) diff --git a/web_programming/instagram_pic.py b/web_programming/instagram_pic.py index 292cacc16c04..b6918f35515b 100644 --- a/web_programming/instagram_pic.py +++ b/web_programming/instagram_pic.py @@ -1,6 +1,14 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# ] +# /// + from datetime import UTC, datetime -import requests +import httpx from bs4 import BeautifulSoup @@ -15,9 +23,9 @@ def download_image(url: str) -> str: A message indicating the result of the operation. """ try: - response = requests.get(url, timeout=10) + response = httpx.get(url, timeout=10) response.raise_for_status() - except requests.exceptions.RequestException as e: + except httpx.RequestError as e: return f"An error occurred during the HTTP request to {url}: {e!r}" soup = BeautifulSoup(response.text, "html.parser") @@ -30,13 +38,13 @@ def download_image(url: str) -> str: return f"Image URL not found in meta tag {image_meta_tag}." try: - image_data = requests.get(image_url, timeout=10).content - except requests.exceptions.RequestException as e: + image_data = httpx.get(image_url, timeout=10).content + except httpx.RequestError as e: return f"An error occurred during the HTTP request to {image_url}: {e!r}" if not image_data: return f"Failed to download the image from {image_url}." - file_name = f"{datetime.now(tz=UTC).astimezone():%Y-%m-%d_%H:%M:%S}.jpg" + file_name = f"{datetime.now(tz=UTC).astimezone():%Y-%m-%d_%H-%M-%S}.jpg" with open(file_name, "wb") as out_file: out_file.write(image_data) return f"Image downloaded and saved in the file {file_name}" diff --git a/web_programming/instagram_video.py b/web_programming/instagram_video.py index a4cddce25138..c6f72aef455a 100644 --- a/web_programming/instagram_video.py +++ b/web_programming/instagram_video.py @@ -1,17 +1,24 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + from datetime import UTC, datetime -import requests +import httpx def download_video(url: str) -> bytes: base_url = "https://downloadgram.net/wp-json/wppress/video-downloader/video?url=" - video_url = requests.get(base_url + url, timeout=10).json()[0]["urls"][0]["src"] - return requests.get(video_url, timeout=10).content + video_url = httpx.get(base_url + url, timeout=10) + return httpx.get(video_url, timeout=10).content if __name__ == "__main__": url = input("Enter Video/IGTV url: ").strip() - file_name = f"{datetime.now(tz=UTC).astimezone():%Y-%m-%d_%H:%M:%S}.mp4" + file_name = f"{datetime.now(tz=UTC).astimezone():%Y-%m-%d_%H-%M-%S}.mp4" with open(file_name, "wb") as fp: fp.write(download_video(url)) print(f"Done. Video saved to disk as {file_name}.") diff --git a/web_programming/nasa_data.py b/web_programming/nasa_data.py index 33a6406c52a6..1025d2b4ab5f 100644 --- a/web_programming/nasa_data.py +++ b/web_programming/nasa_data.py @@ -1,6 +1,11 @@ -import shutil +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// -import requests +import httpx def get_apod_data(api_key: str) -> dict: @@ -9,17 +14,17 @@ def get_apod_data(api_key: str) -> dict: Get your API Key from: https://api.nasa.gov/ """ url = "https://api.nasa.gov/planetary/apod" - return requests.get(url, params={"api_key": api_key}, timeout=10).json() + return httpx.get(url, params={"api_key": api_key}, timeout=10).json() def save_apod(api_key: str, path: str = ".") -> dict: apod_data = get_apod_data(api_key) img_url = apod_data["url"] img_name = img_url.split("/")[-1] - response = requests.get(img_url, stream=True, timeout=10) + response = httpx.get(img_url, timeout=10) with open(f"{path}/{img_name}", "wb+") as img_file: - shutil.copyfileobj(response.raw, img_file) + img_file.write(response.content) del response return apod_data @@ -29,7 +34,7 @@ def get_archive_data(query: str) -> dict: Get the data of a particular query from NASA archives """ url = "https://images-api.nasa.gov/search" - return requests.get(url, params={"q": query}, timeout=10).json() + return httpx.get(url, params={"q": query}, timeout=10).json() if __name__ == "__main__": diff --git a/web_programming/open_google_results.py b/web_programming/open_google_results.py index 52dd37d7b91a..f245e4b6d818 100644 --- a/web_programming/open_google_results.py +++ b/web_programming/open_google_results.py @@ -1,8 +1,17 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "fake-useragent", +# "httpx", +# ] +# /// + import webbrowser from sys import argv from urllib.parse import parse_qs, quote -import requests +import httpx from bs4 import BeautifulSoup from fake_useragent import UserAgent @@ -13,26 +22,18 @@ url = f"https://www.google.com/search?q={query}&num=100" - res = requests.get( + res = httpx.get( url, headers={"User-Agent": str(UserAgent().random)}, timeout=10, ) try: - link = ( - BeautifulSoup(res.text, "html.parser") - .find("div", attrs={"class": "yuRUbf"}) - .find("a") - .get("href") - ) + link = BeautifulSoup(res.text, "html.parser").find("div").find("a").get("href") except AttributeError: link = parse_qs( - BeautifulSoup(res.text, "html.parser") - .find("div", attrs={"class": "kCrYT"}) - .find("a") - .get("href") + BeautifulSoup(res.text, "html.parser").find("div").find("a").get("href") )["url"][0] webbrowser.open(link) diff --git a/web_programming/random_anime_character.py b/web_programming/random_anime_character.py index aed932866258..b94894e7ffe1 100644 --- a/web_programming/random_anime_character.py +++ b/web_programming/random_anime_character.py @@ -1,6 +1,15 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "fake-useragent", +# "httpx", +# ] +# /// + import os -import requests +import httpx from bs4 import BeautifulSoup from fake_useragent import UserAgent @@ -12,7 +21,7 @@ def save_image(image_url: str, image_title: str) -> None: """ Saves the image of anime character """ - image = requests.get(image_url, headers=headers, timeout=10) + image = httpx.get(image_url, headers=headers, timeout=10) with open(image_title, "wb") as file: file.write(image.content) @@ -22,7 +31,7 @@ def random_anime_character() -> tuple[str, str, str]: Returns the Title, Description, and Image Title of a random anime character . """ soup = BeautifulSoup( - requests.get(URL, headers=headers, timeout=10).text, "html.parser" + httpx.get(URL, headers=headers, timeout=10).text, "html.parser" ) title = soup.find("meta", attrs={"property": "og:title"}).attrs["content"] image_url = soup.find("meta", attrs={"property": "og:image"}).attrs["content"] diff --git a/web_programming/recaptcha_verification.py b/web_programming/recaptcha_verification.py index 168862204fa9..c3a53da0b3da 100644 --- a/web_programming/recaptcha_verification.py +++ b/web_programming/recaptcha_verification.py @@ -32,7 +32,14 @@ recaptcha verification. """ -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + +import httpx try: from django.contrib.auth import authenticate, login @@ -56,7 +63,7 @@ def login_using_recaptcha(request): client_key = request.POST.get("g-recaptcha-response") # post recaptcha response to Google's recaptcha api - response = requests.post( + response = httpx.post( url, data={"secret": secret_key, "response": client_key}, timeout=10 ) # if the recaptcha api verified our keys diff --git a/web_programming/reddit.py b/web_programming/reddit.py index 6cc1a6b62009..863b44f60b16 100644 --- a/web_programming/reddit.py +++ b/web_programming/reddit.py @@ -1,6 +1,13 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + from __future__ import annotations -import requests +import httpx valid_terms = set( """approved_at_utc approved_by author_flair_background_color @@ -28,13 +35,14 @@ def get_subreddit_data( if invalid_search_terms := ", ".join(sorted(set(wanted_data) - valid_terms)): msg = f"Invalid search term: {invalid_search_terms}" raise ValueError(msg) - response = requests.get( - f"https://reddit.com/r/{subreddit}/{age}.json?limit={limit}", + response = httpx.get( + f"https://www.reddit.com/r/{subreddit}/{age}.json?limit={limit}", headers={"User-agent": "A random string"}, timeout=10, ) + response.raise_for_status() if response.status_code == 429: - raise requests.HTTPError(response=response) + raise httpx.HTTPError(response=response) data = response.json() if not wanted_data: diff --git a/web_programming/search_books_by_isbn.py b/web_programming/search_books_by_isbn.py index 6b69018e6639..02d096181fff 100644 --- a/web_programming/search_books_by_isbn.py +++ b/web_programming/search_books_by_isbn.py @@ -4,9 +4,16 @@ ISBN: https://en.wikipedia.org/wiki/International_Standard_Book_Number """ -from json import JSONDecodeError # Workaround for requests.exceptions.JSONDecodeError +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// -import requests +from json import JSONDecodeError + +import httpx def get_openlibrary_data(olid: str = "isbn/0140328726") -> dict: @@ -25,7 +32,9 @@ def get_openlibrary_data(olid: str = "isbn/0140328726") -> dict: if new_olid.count("/") != 1: msg = f"{olid} is not a valid Open Library olid" raise ValueError(msg) - return requests.get(f"https://openlibrary.org/{new_olid}.json", timeout=10).json() + return httpx.get( + f"https://openlibrary.org/{new_olid}.json", timeout=10, follow_redirects=True + ).json() def summarize_book(ol_book_data: dict) -> dict: @@ -36,8 +45,7 @@ def summarize_book(ol_book_data: dict) -> dict: "title": "Title", "publish_date": "Publish date", "authors": "Authors", - "number_of_pages": "Number of pages:", - "first_sentence": "First sentence", + "number_of_pages": "Number of pages", "isbn_10": "ISBN (10)", "isbn_13": "ISBN (13)", } @@ -45,7 +53,6 @@ def summarize_book(ol_book_data: dict) -> dict: data["Authors"] = [ get_openlibrary_data(author["key"])["name"] for author in data["Authors"] ] - data["First sentence"] = data["First sentence"]["value"] for key, value in data.items(): if isinstance(value, list): data[key] = ", ".join(value) @@ -71,5 +78,5 @@ def summarize_book(ol_book_data: dict) -> dict: try: book_summary = summarize_book(get_openlibrary_data(f"isbn/{isbn}")) print("\n".join(f"{key}: {value}" for key, value in book_summary.items())) - except JSONDecodeError: # Workaround for requests.exceptions.RequestException: + except JSONDecodeError: print(f"Sorry, there are no results for ISBN: {isbn}.") diff --git a/web_programming/slack_message.py b/web_programming/slack_message.py index d4d5658898ac..b00dac16688f 100644 --- a/web_programming/slack_message.py +++ b/web_programming/slack_message.py @@ -1,11 +1,18 @@ # Created by sarathkaul on 12/11/19 -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "httpx", +# ] +# /// + +import httpx def send_slack_message(message_body: str, slack_url: str) -> None: headers = {"Content-Type": "application/json"} - response = requests.post( + response = httpx.post( slack_url, json={"text": message_body}, headers=headers, timeout=10 ) if response.status_code != 200: diff --git a/web_programming/test_fetch_github_info.py b/web_programming/test_fetch_github_info.py index 2da97c782df7..2c433952fe10 100644 --- a/web_programming/test_fetch_github_info.py +++ b/web_programming/test_fetch_github_info.py @@ -1,6 +1,6 @@ import json -import requests +import httpx from .fetch_github_info import AUTHENTICATED_USER_ENDPOINT, fetch_github_info @@ -21,7 +21,7 @@ def mock_response(*args, **kwargs): assert "Accept" in kwargs["headers"] return FakeResponse(b'{"login":"test","id":1}') - monkeypatch.setattr(requests, "get", mock_response) + monkeypatch.setattr(httpx, "get", mock_response) result = fetch_github_info("token") assert result["login"] == "test" assert result["id"] == 1 diff --git a/web_programming/world_covid19_stats.py b/web_programming/world_covid19_stats.py index 4948d8cfd43c..99383577d627 100644 --- a/web_programming/world_covid19_stats.py +++ b/web_programming/world_covid19_stats.py @@ -5,19 +5,31 @@ This data is being scrapped from 'https://www.worldometers.info/coronavirus/'. """ -import requests +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "beautifulsoup4", +# "httpx", +# ] +# /// + +import httpx from bs4 import BeautifulSoup -def world_covid19_stats(url: str = "https://www.worldometers.info/coronavirus") -> dict: +def world_covid19_stats( + url: str = "https://www.worldometers.info/coronavirus/", +) -> dict: """ Return a dict of current worldwide COVID-19 statistics """ - soup = BeautifulSoup(requests.get(url, timeout=10).text, "html.parser") - keys = soup.findAll("h1") - values = soup.findAll("div", {"class": "maincounter-number"}) - keys += soup.findAll("span", {"class": "panel-title"}) - values += soup.findAll("div", {"class": "number-table-main"}) + soup = BeautifulSoup( + httpx.get(url, timeout=10, follow_redirects=True).text, "html.parser" + ) + keys = soup.find_all("h1") + values = soup.find_all("div", {"class": "maincounter-number"}) + keys += soup.find_all("span", {"class": "panel-title"}) + values += soup.find_all("div", {"class": "number-table-main"}) return {key.text.strip(): value.text.strip() for key, value in zip(keys, values)} From 26ad6891d8bdadc7dd88a2c91cdb28977a7a9dc0 Mon Sep 17 00:00:00 2001 From: Isidro Date: Wed, 21 May 2025 20:33:29 +0200 Subject: [PATCH 034/113] Add median() function using Quickselect (#12676) * Add median() function using Quickselect * Update quick_select.py * Update quick_select.py * Update quick_select.py --------- Co-authored-by: Maxim Smolskiy --- searches/quick_select.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/searches/quick_select.py b/searches/quick_select.py index c8282e1fa5fc..f67f939c88c3 100644 --- a/searches/quick_select.py +++ b/searches/quick_select.py @@ -60,3 +60,25 @@ def quick_select(items: list, index: int): # must be in larger else: return quick_select(larger, index - (m + count)) + + +def median(items: list): + """ + One common application of Quickselect is finding the median, which is + the middle element (or average of the two middle elements) in a sorted dataset. + It works efficiently on unsorted lists by partially sorting the data without + fully sorting the entire list. + + >>> median([3, 2, 2, 9, 9]) + 3 + + >>> median([2, 2, 9, 9, 9, 3]) + 6.0 + """ + mid, rem = divmod(len(items), 2) + if rem != 0: + return quick_select(items=items, index=mid) + else: + low_mid = quick_select(items=items, index=mid - 1) + high_mid = quick_select(items=items, index=mid) + return (low_mid + high_mid) / 2 From ca445f52964f74ef5d398fd8dd6561ee198b353a Mon Sep 17 00:00:00 2001 From: Prajwal Choudhari <102746930+prajwalc22@users.noreply.github.com> Date: Thu, 22 May 2025 20:38:37 +0530 Subject: [PATCH 035/113] Add bidirectional search algorithm implementation (#12649) * Add bidirectional search algorithm implementation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix style and linting issues in bidirectional search * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add doctest for main function * Add doctest for main function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed deprications * fixed deprications * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed unused import * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bidirectional_search.py * Update bidirectional_search.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bidirectional_search.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- graphs/bidirectional_search.py | 201 +++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 graphs/bidirectional_search.py diff --git a/graphs/bidirectional_search.py b/graphs/bidirectional_search.py new file mode 100644 index 000000000000..b3ff9f75fd44 --- /dev/null +++ b/graphs/bidirectional_search.py @@ -0,0 +1,201 @@ +""" +Bidirectional Search Algorithm. + +This algorithm searches from both the source and target nodes simultaneously, +meeting somewhere in the middle. This approach can significantly reduce the +search space compared to a traditional one-directional search. + +Time Complexity: O(b^(d/2)) where b is the branching factor and d is the depth +Space Complexity: O(b^(d/2)) + +https://en.wikipedia.org/wiki/Bidirectional_search +""" + +from collections import deque + + +def expand_search( + graph: dict[int, list[int]], + queue: deque[int], + parents: dict[int, int | None], + opposite_direction_parents: dict[int, int | None], +) -> int | None: + if not queue: + return None + + current = queue.popleft() + for neighbor in graph[current]: + if neighbor in parents: + continue + + parents[neighbor] = current + queue.append(neighbor) + + # Check if this creates an intersection + if neighbor in opposite_direction_parents: + return neighbor + + return None + + +def construct_path(current: int | None, parents: dict[int, int | None]) -> list[int]: + path: list[int] = [] + while current is not None: + path.append(current) + current = parents[current] + return path + + +def bidirectional_search( + graph: dict[int, list[int]], start: int, goal: int +) -> list[int] | None: + """ + Perform bidirectional search on a graph to find the shortest path. + + Args: + graph: A dictionary where keys are nodes and values are lists of adjacent nodes + start: The starting node + goal: The target node + + Returns: + A list representing the path from start to goal, or None if no path exists + + Examples: + >>> graph = { + ... 0: [1, 2], + ... 1: [0, 3, 4], + ... 2: [0, 5, 6], + ... 3: [1, 7], + ... 4: [1, 8], + ... 5: [2, 9], + ... 6: [2, 10], + ... 7: [3, 11], + ... 8: [4, 11], + ... 9: [5, 11], + ... 10: [6, 11], + ... 11: [7, 8, 9, 10], + ... } + >>> bidirectional_search(graph=graph, start=0, goal=11) + [0, 1, 3, 7, 11] + >>> bidirectional_search(graph=graph, start=5, goal=5) + [5] + >>> disconnected_graph = { + ... 0: [1, 2], + ... 1: [0], + ... 2: [0], + ... 3: [4], + ... 4: [3], + ... } + >>> bidirectional_search(graph=disconnected_graph, start=0, goal=3) is None + True + """ + if start == goal: + return [start] + + # Check if start and goal are in the graph + if start not in graph or goal not in graph: + return None + + # Initialize forward and backward search dictionaries + # Each maps a node to its parent in the search + forward_parents: dict[int, int | None] = {start: None} + backward_parents: dict[int, int | None] = {goal: None} + + # Initialize forward and backward search queues + forward_queue = deque([start]) + backward_queue = deque([goal]) + + # Intersection node (where the two searches meet) + intersection = None + + # Continue until both queues are empty or an intersection is found + while forward_queue and backward_queue and intersection is None: + # Expand forward search + intersection = expand_search( + graph=graph, + queue=forward_queue, + parents=forward_parents, + opposite_direction_parents=backward_parents, + ) + + # If no intersection found, expand backward search + if intersection is not None: + break + + intersection = expand_search( + graph=graph, + queue=backward_queue, + parents=backward_parents, + opposite_direction_parents=forward_parents, + ) + + # If no intersection found, there's no path + if intersection is None: + return None + + # Construct path from start to intersection + forward_path: list[int] = construct_path( + current=intersection, parents=forward_parents + ) + forward_path.reverse() + + # Construct path from intersection to goal + backward_path: list[int] = construct_path( + current=backward_parents[intersection], parents=backward_parents + ) + + # Return the complete path + return forward_path + backward_path + + +def main() -> None: + """ + Run example of bidirectional search algorithm. + + Examples: + >>> main() # doctest: +NORMALIZE_WHITESPACE + Path from 0 to 11: [0, 1, 3, 7, 11] + Path from 5 to 5: [5] + Path from 0 to 3: None + """ + # Example graph represented as an adjacency list + example_graph = { + 0: [1, 2], + 1: [0, 3, 4], + 2: [0, 5, 6], + 3: [1, 7], + 4: [1, 8], + 5: [2, 9], + 6: [2, 10], + 7: [3, 11], + 8: [4, 11], + 9: [5, 11], + 10: [6, 11], + 11: [7, 8, 9, 10], + } + + # Test case 1: Path exists + start, goal = 0, 11 + path = bidirectional_search(graph=example_graph, start=start, goal=goal) + print(f"Path from {start} to {goal}: {path}") + + # Test case 2: Start and goal are the same + start, goal = 5, 5 + path = bidirectional_search(graph=example_graph, start=start, goal=goal) + print(f"Path from {start} to {goal}: {path}") + + # Test case 3: No path exists (disconnected graph) + disconnected_graph = { + 0: [1, 2], + 1: [0], + 2: [0], + 3: [4], + 4: [3], + } + start, goal = 0, 3 + path = bidirectional_search(graph=disconnected_graph, start=start, goal=goal) + print(f"Path from {start} to {goal}: {path}") + + +if __name__ == "__main__": + main() From c81cc269962b346420b9e551782bd836dedb4528 Mon Sep 17 00:00:00 2001 From: Isidro Date: Thu, 22 May 2025 22:44:25 +0200 Subject: [PATCH 036/113] Improve hash map (#12678) * Mutable _Item * document falsy item * resize_down: expected test result * resize_down: actual result This is a problem since it causes rapid cycling * improve comment about falsy item Co-authored-by: Andrey * fix long line * Update hash_map.py * Update hash_map.py --------- Co-authored-by: Andrey Co-authored-by: Maxim Smolskiy --- data_structures/hashing/hash_map.py | 30 +++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/data_structures/hashing/hash_map.py b/data_structures/hashing/hash_map.py index 9213d6930f67..8c56c327a492 100644 --- a/data_structures/hashing/hash_map.py +++ b/data_structures/hashing/hash_map.py @@ -16,7 +16,7 @@ VAL = TypeVar("VAL") -@dataclass(frozen=True, slots=True) +@dataclass(slots=True) class _Item(Generic[KEY, VAL]): key: KEY val: VAL @@ -72,16 +72,17 @@ def _try_set(self, ind: int, key: KEY, val: VAL) -> bool: If bucket is empty or key is the same, does insert and return True. - If bucket has another key or deleted placeholder, - that means that we need to check next bucket. + If bucket has another key that means that we need to check next bucket. """ stored = self._buckets[ind] if not stored: + # A falsy item means that bucket was never used (None) + # or was deleted (_deleted). self._buckets[ind] = _Item(key, val) self._len += 1 return True elif stored.key == key: - self._buckets[ind] = _Item(key, val) + stored.val = val return True else: return False @@ -228,6 +229,27 @@ def __delitem__(self, key: KEY) -> None: Traceback (most recent call last): ... KeyError: 4 + + # Test resize down when sparse + ## Setup: resize up + >>> hm = HashMap(initial_block_size=100, capacity_factor=0.75) + >>> len(hm._buckets) + 100 + >>> for i in range(75): + ... hm[i] = i + >>> len(hm._buckets) + 100 + >>> hm[75] = 75 + >>> len(hm._buckets) + 200 + + ## Resize down + >>> del hm[75] + >>> len(hm._buckets) + 200 + >>> del hm[74] + >>> len(hm._buckets) + 100 """ for ind in self._iterate_buckets(key): item = self._buckets[ind] From e1115b5f15afa44deb4752483b9b456457f7e683 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Fri, 23 May 2025 00:07:43 +0300 Subject: [PATCH 037/113] Add tests and cleanup sum_of_subsets algorithm (#12746) * Add tests and cleanup sum_of_subsets algorithm. * Update sum_of_subsets.py * Update sum_of_subsets.py * Update sum_of_subsets.py * Update sum_of_subsets.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- backtracking/sum_of_subsets.py | 45 ++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/backtracking/sum_of_subsets.py b/backtracking/sum_of_subsets.py index f34d3ca34339..f26f179f8725 100644 --- a/backtracking/sum_of_subsets.py +++ b/backtracking/sum_of_subsets.py @@ -1,5 +1,5 @@ """ -The sum-of-subsetsproblem states that a set of non-negative integers, and a +The sum-of-subsets problem states that a set of non-negative integers, and a value M, determine all possible subsets of the given set whose summation sum equal to given M. @@ -7,10 +7,20 @@ can be used only once. """ -from __future__ import annotations +def generate_sum_of_subsets_solutions(nums: list[int], max_sum: int) -> list[list[int]]: + """ + The main function. For list of numbers 'nums' find the subsets with sum + equal to 'max_sum' + + >>> generate_sum_of_subsets_solutions(nums=[3, 34, 4, 12, 5, 2], max_sum=9) + [[3, 4, 2], [4, 5]] + >>> generate_sum_of_subsets_solutions(nums=[3, 34, 4, 12, 5, 2], max_sum=3) + [[3]] + >>> generate_sum_of_subsets_solutions(nums=[3, 34, 4, 12, 5, 2], max_sum=1) + [] + """ -def generate_sum_of_subsets_soln(nums: list[int], max_sum: int) -> list[list[int]]: result: list[list[int]] = [] path: list[int] = [] num_index = 0 @@ -34,7 +44,21 @@ def create_state_space_tree( This algorithm follows depth-fist-search and backtracks when the node is not branchable. + >>> path = [] + >>> result = [] + >>> create_state_space_tree( + ... nums=[1], + ... max_sum=1, + ... num_index=0, + ... path=path, + ... result=result, + ... remaining_nums_sum=1) + >>> path + [] + >>> result + [[1]] """ + if sum(path) > max_sum or (remaining_nums_sum + sum(path)) < max_sum: return if sum(path) == max_sum: @@ -51,16 +75,7 @@ def create_state_space_tree( ) -""" -remove the comment to take an input from the user - -print("Enter the elements") -nums = list(map(int, input().split())) -print("Enter max_sum sum") -max_sum = int(input()) +if __name__ == "__main__": + import doctest -""" -nums = [3, 34, 4, 12, 5, 2] -max_sum = 9 -result = generate_sum_of_subsets_soln(nums, max_sum) -print(*result) + doctest.testmod() From a8ad2db2b966fcbd2e6a82b8f1544116838c02b0 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Fri, 23 May 2025 00:17:48 +0300 Subject: [PATCH 038/113] Update matrix_chain_order calculation with more details and test. (#12759) --- dynamic_programming/matrix_chain_order.py | 33 ++++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/dynamic_programming/matrix_chain_order.py b/dynamic_programming/matrix_chain_order.py index d612aea7b99d..6df43e84be28 100644 --- a/dynamic_programming/matrix_chain_order.py +++ b/dynamic_programming/matrix_chain_order.py @@ -5,13 +5,19 @@ Implementation of Matrix Chain Multiplication Time Complexity: O(n^3) Space Complexity: O(n^2) + +Reference: https://en.wikipedia.org/wiki/Matrix_chain_multiplication """ -def matrix_chain_order(array): +def matrix_chain_order(array: list[int]) -> tuple[list[list[int]], list[list[int]]]: + """ + >>> matrix_chain_order([10, 30, 5]) + ([[0, 0, 0], [0, 0, 1500], [0, 0, 0]], [[0, 0, 0], [0, 0, 1], [0, 0, 0]]) + """ n = len(array) - matrix = [[0 for x in range(n)] for x in range(n)] - sol = [[0 for x in range(n)] for x in range(n)] + matrix = [[0 for _ in range(n)] for _ in range(n)] + sol = [[0 for _ in range(n)] for _ in range(n)] for chain_length in range(2, n): for a in range(1, n - chain_length + 1): @@ -28,26 +34,33 @@ def matrix_chain_order(array): return matrix, sol -# Print order of matrix with Ai as Matrix -def print_optiomal_solution(optimal_solution, i, j): +def print_optimal_solution(optimal_solution: list[list[int]], i: int, j: int): + """ + Print order of matrix with Ai as Matrix. + """ + if i == j: print("A" + str(i), end=" ") else: print("(", end=" ") - print_optiomal_solution(optimal_solution, i, optimal_solution[i][j]) - print_optiomal_solution(optimal_solution, optimal_solution[i][j] + 1, j) + print_optimal_solution(optimal_solution, i, optimal_solution[i][j]) + print_optimal_solution(optimal_solution, optimal_solution[i][j] + 1, j) print(")", end=" ") def main(): + """ + Size of matrix created from array [30, 35, 15, 5, 10, 20, 25] will be: + 30*35 35*15 15*5 5*10 10*20 20*25 + """ + array = [30, 35, 15, 5, 10, 20, 25] n = len(array) - # Size of matrix created from above array will be - # 30*35 35*15 15*5 5*10 10*20 20*25 + matrix, optimal_solution = matrix_chain_order(array) print("No. of Operation required: " + str(matrix[1][n - 1])) - print_optiomal_solution(optimal_solution, 1, n - 1) + print_optimal_solution(optimal_solution, 1, n - 1) if __name__ == "__main__": From e26c388af0668c7b4236442691d36a477e02f400 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 22:55:55 +0200 Subject: [PATCH 039/113] [pre-commit.ci] pre-commit autoupdate (#12760) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.9 → v0.11.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.9...v0.11.11) - [github.com/tox-dev/pyproject-fmt: v2.5.1 → v2.6.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.5.1...v2.6.0) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] --- .pre-commit-config.yaml | 4 ++-- DIRECTORY.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 288e3f591403..6c1879ab1ac6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.9 + rev: v0.11.11 hooks: - id: ruff - id: ruff-format @@ -29,7 +29,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.5.1" + rev: "v2.6.0" hooks: - id: pyproject-fmt diff --git a/DIRECTORY.md b/DIRECTORY.md index 4129f9c1a5e2..00f4bb4ef2b2 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -480,6 +480,7 @@ * [Bi Directional Dijkstra](graphs/bi_directional_dijkstra.py) * [Bidirectional A Star](graphs/bidirectional_a_star.py) * [Bidirectional Breadth First Search](graphs/bidirectional_breadth_first_search.py) + * [Bidirectional Search](graphs/bidirectional_search.py) * [Boruvka](graphs/boruvka.py) * [Breadth First Search](graphs/breadth_first_search.py) * [Breadth First Search 2](graphs/breadth_first_search_2.py) From d0d7f0b18ab5cca2c573448b757c45bc0eee69c6 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 29 May 2025 08:56:25 +0200 Subject: [PATCH 040/113] maths/radix2_fft.py: Fix calculation for Python 3.14 (#12772) * maths/radix2_fft.py: Fix calculation for Python 3.14 As suggested at: * https://github.com/TheAlgorithms/Python/issues/12729#issuecomment-2878608477 * https://github.com/TheAlgorithms/Python/pull/12710#discussion_r2080117333 @MaximSmolskiy @KirilBangachev @skirpichev Careful review, please. I am just implementing the suggestion, but I do not have any expertise in this area. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Change test results * GitHub Actions: Rename job from build to directory_writer It is confusing to have two jobs named `build`. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/directory_writer.yml | 2 +- maths/radix2_fft.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml index 55d89f455a25..3edb5c91a951 100644 --- a/.github/workflows/directory_writer.yml +++ b/.github/workflows/directory_writer.yml @@ -3,7 +3,7 @@ name: directory_writer on: [push] jobs: - build: + directory_writer: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/maths/radix2_fft.py b/maths/radix2_fft.py index d41dc82d5588..ccd5cdcc0160 100644 --- a/maths/radix2_fft.py +++ b/maths/radix2_fft.py @@ -40,13 +40,13 @@ class FFT: Print product >>> x.product # 2x + 3x^2 + 8x^3 + 4x^4 + 6x^5 - [(-0+0j), (2+0j), (3+0j), (8+0j), (6+0j), (8+0j)] + [(-0-0j), (2+0j), (3-0j), (8-0j), (6+0j), (8+0j)] __str__ test >>> print(x) A = 0*x^0 + 1*x^1 + 2*x^0 + 3*x^2 B = 0*x^2 + 1*x^3 + 2*x^4 - A*B = 0*x^(-0+0j) + 1*x^(2+0j) + 2*x^(3+0j) + 3*x^(8+0j) + 4*x^(6+0j) + 5*x^(8+0j) + A*B = 0*x^(-0-0j) + 1*x^(2+0j) + 2*x^(3-0j) + 3*x^(8-0j) + 4*x^(6+0j) + 5*x^(8+0j) """ def __init__(self, poly_a=None, poly_b=None): @@ -147,7 +147,9 @@ def __multiply(self): inverce_c = new_inverse_c next_ncol *= 2 # Unpack - inverce_c = [round(x[0].real, 8) + round(x[0].imag, 8) * 1j for x in inverce_c] + inverce_c = [ + complex(round(x[0].real, 8), round(x[0].imag, 8)) for x in inverce_c + ] # Remove leading 0's while inverce_c[-1] == 0: From 4b077c06b623ea20a90e9e5678e38101a4636584 Mon Sep 17 00:00:00 2001 From: JEONGHYUN MIN <161672721+kangaroo-eating-carrots@users.noreply.github.com> Date: Sun, 1 Jun 2025 05:11:46 +0800 Subject: [PATCH 041/113] feat: create straight_line_depreciation (#12377) Co-authored-by: Jeonghyun Min <20122791@tafe.wa.edu.au> --- financial/straight_line_depreciation.py | 103 ++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 financial/straight_line_depreciation.py diff --git a/financial/straight_line_depreciation.py b/financial/straight_line_depreciation.py new file mode 100644 index 000000000000..e11e1c1364ce --- /dev/null +++ b/financial/straight_line_depreciation.py @@ -0,0 +1,103 @@ +""" +In accounting, depreciation refers to the decreases in the value +of a fixed asset during the asset's useful life. +When an organization purchases a fixed asset, +the purchase expenditure is not recognized as an expense immediately. +Instead, the decreases in the asset's value are recognized as expenses +over the years during which the asset is used. + +The following methods are widely used +for depreciation calculation in accounting: +- Straight-line method +- Diminishing balance method +- Units-of-production method + +The straight-line method is the simplest and most widely used. +This method calculates depreciation by spreading the cost evenly +over the asset's useful life. + +The following formula shows how to calculate the yearly depreciation expense: + +- annual depreciation expense = + (purchase cost of asset - residual value) / useful life of asset(years) + +Further information on: +https://en.wikipedia.org/wiki/Depreciation + +The function, straight_line_depreciation, returns a list of +the depreciation expenses over the given period. +""" + + +def straight_line_depreciation( + useful_years: int, + purchase_value: float, + residual_value: float = 0.0, +) -> list[float]: + """ + Calculate the depreciation expenses over the given period + :param useful_years: Number of years the asset will be used + :param purchase_value: Purchase expenditure for the asset + :param residual_value: Residual value of the asset at the end of its useful life + :return: A list of annual depreciation expenses over the asset's useful life + >>> straight_line_depreciation(10, 1100.0, 100.0) + [100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0] + >>> straight_line_depreciation(6, 1250.0, 50.0) + [200.0, 200.0, 200.0, 200.0, 200.0, 200.0] + >>> straight_line_depreciation(4, 1001.0) + [250.25, 250.25, 250.25, 250.25] + >>> straight_line_depreciation(11, 380.0, 50.0) + [30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0] + >>> straight_line_depreciation(1, 4985, 100) + [4885.0] + """ + + if not isinstance(useful_years, int): + raise TypeError("Useful years must be an integer") + + if useful_years < 1: + raise ValueError("Useful years cannot be less than 1") + + if not isinstance(purchase_value, (float, int)): + raise TypeError("Purchase value must be numeric") + + if not isinstance(residual_value, (float, int)): + raise TypeError("Residual value must be numeric") + + if purchase_value < 0.0: + raise ValueError("Purchase value cannot be less than zero") + + if purchase_value < residual_value: + raise ValueError("Purchase value cannot be less than residual value") + + # Calculate annual depreciation expense + depreciable_cost = purchase_value - residual_value + annual_depreciation_expense = depreciable_cost / useful_years + + # List of annual depreciation expenses + list_of_depreciation_expenses = [] + accumulated_depreciation_expense = 0.0 + for period in range(useful_years): + if period != useful_years - 1: + accumulated_depreciation_expense += annual_depreciation_expense + list_of_depreciation_expenses.append(annual_depreciation_expense) + else: + depreciation_expense_in_end_year = ( + depreciable_cost - accumulated_depreciation_expense + ) + list_of_depreciation_expenses.append(depreciation_expense_in_end_year) + + return list_of_depreciation_expenses + + +if __name__ == "__main__": + user_input_useful_years = int(input("Please Enter Useful Years:\n > ")) + user_input_purchase_value = float(input("Please Enter Purchase Value:\n > ")) + user_input_residual_value = float(input("Please Enter Residual Value:\n > ")) + print( + straight_line_depreciation( + user_input_useful_years, + user_input_purchase_value, + user_input_residual_value, + ) + ) From c3d4b9e54d65c90422a0863c38b1ca72e6037bc9 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Mon, 2 Jun 2025 20:32:47 +0300 Subject: [PATCH 042/113] Add doctests for the boyer_moore_search algorithm. (#12769) * Add doctests for the boyer_moore_search algorithm. * Update boyer_moore_search.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update boyer_moore_search.py * Update boyer_moore_search.py --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- strings/boyer_moore_search.py | 49 +++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/strings/boyer_moore_search.py b/strings/boyer_moore_search.py index 9615d2fd659b..ad14a504f792 100644 --- a/strings/boyer_moore_search.py +++ b/strings/boyer_moore_search.py @@ -11,23 +11,31 @@ a shift is proposed that moves the entirety of Pattern past the point of mismatch in the text. -If there no mismatch then the pattern matches with text block. +If there is no mismatch then the pattern matches with text block. Time Complexity : O(n/m) n=length of main string m=length of pattern string """ -from __future__ import annotations - class BoyerMooreSearch: + """ + Example usage: + + bms = BoyerMooreSearch(text="ABAABA", pattern="AB") + positions = bms.bad_character_heuristic() + + where 'positions' contain the locations where the pattern was matched. + """ + def __init__(self, text: str, pattern: str): self.text, self.pattern = text, pattern self.textLen, self.patLen = len(text), len(pattern) def match_in_pattern(self, char: str) -> int: - """finds the index of char in pattern in reverse order + """ + Finds the index of char in pattern in reverse order. Parameters : char (chr): character to be searched @@ -35,6 +43,10 @@ def match_in_pattern(self, char: str) -> int: Returns : i (int): index of char from last in pattern -1 (int): if char is not found in pattern + + >>> bms = BoyerMooreSearch(text="ABAABA", pattern="AB") + >>> bms.match_in_pattern("B") + 1 """ for i in range(self.patLen - 1, -1, -1): @@ -44,8 +56,8 @@ def match_in_pattern(self, char: str) -> int: def mismatch_in_text(self, current_pos: int) -> int: """ - find the index of mis-matched character in text when compared with pattern - from last + Find the index of mis-matched character in text when compared with pattern + from last. Parameters : current_pos (int): current index position of text @@ -53,6 +65,10 @@ def mismatch_in_text(self, current_pos: int) -> int: Returns : i (int): index of mismatched char from last in text -1 (int): if there is no mismatch between pattern and text block + + >>> bms = BoyerMooreSearch(text="ABAABA", pattern="AB") + >>> bms.mismatch_in_text(2) + 3 """ for i in range(self.patLen - 1, -1, -1): @@ -61,7 +77,14 @@ def mismatch_in_text(self, current_pos: int) -> int: return -1 def bad_character_heuristic(self) -> list[int]: - # searches pattern in text and returns index positions + """ + Finds the positions of the pattern location. + + >>> bms = BoyerMooreSearch(text="ABAABA", pattern="AB") + >>> bms.bad_character_heuristic() + [0, 3] + """ + positions = [] for i in range(self.textLen - self.patLen + 1): mismatch_index = self.mismatch_in_text(i) @@ -75,13 +98,7 @@ def bad_character_heuristic(self) -> list[int]: return positions -text = "ABAABA" -pattern = "AB" -bms = BoyerMooreSearch(text, pattern) -positions = bms.bad_character_heuristic() +if __name__ == "__main__": + import doctest -if len(positions) == 0: - print("No match found") -else: - print("Pattern found in following positions: ") - print(positions) + doctest.testmod() From 7665ba5e257a1a42caa36d781925d87968ee1497 Mon Sep 17 00:00:00 2001 From: Qasim Umar <111963035+QasimUmarKhan@users.noreply.github.com> Date: Sat, 5 Jul 2025 15:58:45 +0500 Subject: [PATCH 043/113] Add unit tests for factorial.py (#12815) * Add unit tests for factorial.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * uvx --python=3.12 unittest2pytest --write test_factorial.py * Update error message in current_stock_price.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/test_factorial.py | 37 ++++++++++++++++++++++++++ web_programming/current_stock_price.py | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 maths/test_factorial.py diff --git a/maths/test_factorial.py b/maths/test_factorial.py new file mode 100644 index 000000000000..d80d88add745 --- /dev/null +++ b/maths/test_factorial.py @@ -0,0 +1,37 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "pytest", +# ] +# /// + +import pytest + +from maths.factorial import factorial, factorial_recursive + + +@pytest.mark.parametrize("function", [factorial, factorial_recursive]) +def test_zero(function): + assert function(0) == 1 + + +@pytest.mark.parametrize("function", [factorial, factorial_recursive]) +def test_positive_integers(function): + assert function(1) == 1 + assert function(5) == 120 + assert function(7) == 5040 + + +@pytest.mark.parametrize("function", [factorial, factorial_recursive]) +def test_large_number(function): + assert function(10) == 3628800 + + +@pytest.mark.parametrize("function", [factorial, factorial_recursive]) +def test_negative_number(function): + with pytest.raises(ValueError): + function(-3) + + +if __name__ == "__main__": + pytest.main(["-v", __file__]) diff --git a/web_programming/current_stock_price.py b/web_programming/current_stock_price.py index 16b0b6772a9c..531da949ea50 100644 --- a/web_programming/current_stock_price.py +++ b/web_programming/current_stock_price.py @@ -23,7 +23,7 @@ def stock_price(symbol: str = "AAPL") -> str: """ >>> stock_price("EEEE") - '- ' + 'No tag with the specified data-testid attribute found.' >>> isinstance(float(stock_price("GOOG")),float) True """ From cd3c3c3130f8b067b27993a93fac0e0ffe5e59d2 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 6 Jul 2025 00:35:29 +0200 Subject: [PATCH 044/113] 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 00f4bb4ef2b2..81d6f4c70864 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 33b2529f017b..19422688cd70 100644 --- a/ciphers/hill_cipher.py +++ b/ciphers/hill_cipher.py @@ -79,7 +79,7 @@ def replace_digits(self, num: int) -> str: >>> 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 ca0d5c111c4f..7d1c965fab50 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 @@ 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 8c56c327a492..0d99e578b73e 100644 --- a/data_structures/hashing/hash_map.py +++ b/data_structures/hashing/hash_map.py @@ -10,14 +10,14 @@ 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 7b15e69f13ca..41ef0ddd1005 100644 --- a/data_structures/heap/heap.py +++ b/data_structures/heap/heap.py @@ -2,7 +2,7 @@ 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 @@ def __eq__(self: T, other: object) -> bool: 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 12888c1f4089..9668d3ac2a45 100644 --- a/data_structures/heap/randomized_heap.py +++ b/data_structures/heap/randomized_heap.py @@ -4,12 +4,12 @@ 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 @@ def merge( 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 0839db711cb1..4e82569444fa 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 @@ def merge( 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 13e9a94a8698..f21ca70bbc82 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -7,13 +7,13 @@ 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 @@ def level(self) -> int: 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 4b05be9fd08e..182cc4147c47 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 @@ def __init__(self, iterable: Iterable[_T] | None = None) -> None: >>> 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 @@ def __repr__(self) -> str: 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 @@ def put(self, item: _T) -> None: self.entries.append(item) - def get(self) -> _T: + def get(self) -> T: """ Get `item` from the Queue @@ -118,7 +115,7 @@ def rotate(self, rotation: int) -> None: 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 cd62f155a63b..f9e302ffcedd 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 @@ def __init__(self, iterable: Iterable[_T] | None = None) -> None: >>> 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 @@ def __repr__(self) -> str: """ 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 @@ def put(self, item: _T) -> None: 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 93698f5aa116..3ffa32d4167f 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 50c5236e073c..ad01cd7eb6aa 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 8e77c2b967ef..57a68679eee1 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 @@ def __str__(self) -> str: 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 abc75311cd60..244e59e0e1bf 100644 --- a/graphs/graph_adjacency_list.py +++ b/graphs/graph_adjacency_list.py @@ -21,14 +21,14 @@ 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 568c84166e4b..8eeeae786513 100644 --- a/graphs/graph_adjacency_matrix.py +++ b/graphs/graph_adjacency_matrix.py @@ -21,14 +21,14 @@ 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 6563cbb76132..6b63590bf55a 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 0ddb43ce8e6e..1f6d7255683b 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 @@ def __init__(self, data: T) -> None: 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 @@ def union(self, data1: T, data2: T) -> None: 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 6870cc80f844..d22111289a48 100644 --- a/graphs/minimum_spanning_tree_prims2.py +++ b/graphs/minimum_spanning_tree_prims2.py @@ -10,7 +10,7 @@ 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 @@ def _swap_nodes(self, node1_pos: int, node2_pos: int) -> None: self.position_map[node2_elem] = node1_pos -class GraphUndirectedWeighted(Generic[T]): +class GraphUndirectedWeighted[T]: """ Graph Undirected Weighted Class @@ -217,7 +217,7 @@ def add_edge(self, node1: T, node2: T, weight: int) -> None: 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 a5940a38e836..dee9247282f9 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -260,7 +260,7 @@ def add_row(self, row: list[int], position: int | None = None) -> None: 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 @@ def add_column(self, column: list[int], position: int | None = None) -> None: 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 cb692bb1b1c0..d96960868488 100644 --- a/other/least_recently_used.py +++ b/other/least_recently_used.py @@ -2,12 +2,12 @@ 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 5a143c739b9d..6eaacff2966a 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 @@ def __repr__(self) -> str: ) -class DoubleLinkedList(Generic[T, U]): +class DoubleLinkedList[T, U]: """ Double Linked List built specifically for LFU Cache @@ -161,7 +161,7 @@ def remove( 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 4f0c843c86cc..058b03b021bc 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 @@ def __repr__(self) -> str: ) -class DoubleLinkedList(Generic[T, U]): +class DoubleLinkedList[T, U]: """ Double Linked List built specifically for LRU Cache @@ -143,7 +143,7 @@ def remove( 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 2ead5cd51ae8..b680cc0d439e 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 46b263d84a33..2e39be255df7 100644 --- a/sorts/insertion_sort.py +++ b/sorts/insertion_sort.py @@ -24,7 +24,7 @@ def __lt__(self, other: Any, /) -> bool: ... 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 138f11c71bcc..41ab4a10a87b 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 From 5c05335b27c7f072b35fd9028d81433939054628 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 7 Jul 2025 10:28:59 +0200 Subject: [PATCH 045/113] hill_cipher.py: Use `int()` to gracefully deal with float input (#12833) * https://github.com/TheAlgorithms/Python/pull/12821#discussion_r2186998710 --- ciphers/hill_cipher.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ciphers/hill_cipher.py b/ciphers/hill_cipher.py index 19422688cd70..c690d29bd113 100644 --- a/ciphers/hill_cipher.py +++ b/ciphers/hill_cipher.py @@ -78,8 +78,10 @@ def replace_digits(self, num: int) -> str: 'T' >>> hill_cipher.replace_digits(26) '0' + >>> hill_cipher.replace_digits(26.1) + '0' """ - return self.key_string[(num)] + return self.key_string[int(num)] def check_determinant(self) -> None: """ From ed7c9b51f940307bfbec79e9cc4587e025e657c5 Mon Sep 17 00:00:00 2001 From: Bertrand Awenze <156874668+bertrand-awz@users.noreply.github.com> Date: Wed, 9 Jul 2025 08:25:18 -0400 Subject: [PATCH 046/113] Fix devcontainer build failure (#12837) * add post-installation script * set zsh as default terminal and make post-install execution on postcreate * rename file * rename script * Create devcontainers_ci.yml * Update devcontainer.json * Update devcontainers_ci.yml Never push image built here. It's for build testing purpose only. * postCreateCommand update to reflect that the shell script has been renamed. * update devcontainer readme file * trigger workflow only on devcontainer/** changes * prettier refactor --- .devcontainer/Dockerfile | 5 ++-- .devcontainer/README.md | 43 ++++++++++++++++++++++++++- .devcontainer/devcontainer.json | 7 +++-- .devcontainer/post_install | 29 ++++++++++++++++++ .github/workflows/devcontainer_ci.yml | 19 ++++++++++++ 5 files changed, 97 insertions(+), 6 deletions(-) create mode 100755 .devcontainer/post_install create mode 100644 .github/workflows/devcontainer_ci.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index a0bd05f47ec8..edee3bc4febb 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,6 +3,5 @@ ARG VARIANT=3.13-bookworm FROM mcr.microsoft.com/vscode/devcontainers/python:${VARIANT} COPY requirements.txt /tmp/pip-tmp/ RUN python3 -m pip install --upgrade pip \ - && python3 -m pip install --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \ - && pipx install pre-commit ruff \ - && pre-commit install + && python3 -m pip install --no-cache-dir -r /tmp/pip-tmp/requirements.txt \ + && pipx install pre-commit ruff diff --git a/.devcontainer/README.md b/.devcontainer/README.md index ec3cdb61de7a..8056578ad3a8 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -1 +1,42 @@ -https://code.visualstudio.com/docs/devcontainers/tutorial +# Development Container + +This is **Devcontainer** configuration to provide a consistent development environment for all contributors. + +## Features + +- [x] Pre-configured **Python environment** +- [x] Automatic installation of **pre-commit hooks** +- [x] **Ruff** linter ready to check your code +- [x] **Oh My Zsh** with plugins: +- `zsh-autosuggestions` +- `zsh-syntax-highlighting` + +## Usage + +1. Install [**Docker** ](https://www.docker.com/get-started/) and [**Visual Studio Code**](https://code.visualstudio.com/) +2. Install the **Remote - Containers** extension in VS Code + + - Do `CTRL+P`, paste this command and press `Enter` + + ```shell + ext install ms-vscode-remote.remote-containers + ``` +3. Open this repository in VS Code +4. When prompted, click **"Reopen in Container"** +5. Wait for the environment to build and initialize + +After setup: + +- `pre-commit` hooks are installed +- `ruff` and other tools are available +- The shell uses Zsh by default + +## Tips + +To manually run checks on all files: + +```bash +pre-commit run --all-files +``` + +> For further information here's [Microsoft tutorial about devcontainers.](https://code.visualstudio.com/docs/devcontainers/tutorial) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e23263f5b9de..4951d5eb268d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -7,10 +7,12 @@ // Update 'VARIANT' to pick a Python version: 3, 3.11, 3.10, 3.9, 3.8 // Append -bullseye or -buster to pin to an OS version. // Use -bullseye variants on local on arm64/Apple Silicon. - "VARIANT": "3.13-bookworm", + "VARIANT": "3.13-bookworm" } }, + "postCreateCommand": "zsh .devcontainer/post_install", + // Configure tool-specific properties. "customizations": { // Configure properties specific to VS Code. @@ -20,7 +22,8 @@ "python.defaultInterpreterPath": "/usr/local/bin/python", "python.linting.enabled": true, "python.formatting.blackPath": "/usr/local/py-utils/bin/black", - "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy" + "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", + "terminal.integrated.defaultProfile.linux": "zsh" }, // Add the IDs of extensions you want installed when the container is created. diff --git a/.devcontainer/post_install b/.devcontainer/post_install new file mode 100755 index 000000000000..589ee361f5cb --- /dev/null +++ b/.devcontainer/post_install @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +echo "Begin post-installation steps..." + +set -e + +echo "Installing pre-commit hooks..." +pre-commit install + +echo "Installing Oh My Zsh plugins..." + +# Install zsh-autosuggestions if not present +if [ ! -d "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions" ]; then + echo "Cloning zsh-autosuggestions..." + git clone https://github.com/zsh-users/zsh-autosuggestions \ + "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions" +fi + +# Install zsh-syntax-highlighting if not present +if [ ! -d "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting" ]; then + echo "Cloning zsh-syntax-highlighting..." + git clone https://github.com/zsh-users/zsh-syntax-highlighting.git \ + "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting" +fi + +echo "Configuring plugins in ~/.zshrc..." +sed -i '/^plugins=/c\plugins=(git zsh-autosuggestions zsh-syntax-highlighting)' ~/.zshrc + +echo "Post-installation steps completed successfully. Enjoy!" diff --git a/.github/workflows/devcontainer_ci.yml b/.github/workflows/devcontainer_ci.yml new file mode 100644 index 000000000000..c0b26bb77da6 --- /dev/null +++ b/.github/workflows/devcontainer_ci.yml @@ -0,0 +1,19 @@ +name: Test DevContainer Build + +on: + push: + paths: + - ".devcontainer/**" + pull_request: + paths: + - ".devcontainer/**" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: devcontainers/ci@v0.3 + with: + push: never + runCmd: "true" From 5a4a6a5497776c564774fa915792924eee36865d Mon Sep 17 00:00:00 2001 From: Asim Hanif Date: Sat, 12 Jul 2025 01:25:53 +0500 Subject: [PATCH 047/113] =?UTF-8?q?Update=20.pre-commit-config.yaml=20to?= =?UTF-8?q?=20reflect=20current=20linting=20and=20formatt=E2=80=A6=20(#128?= =?UTF-8?q?41)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update .pre-commit-config.yaml to reflect current linting and formatting setup - Replaced outdated references to `black` with the actual tools used in the repo: `ruff` and `ruff-format`. - Ensured all configured hooks are up to date and relevant to Python development. - This aligns the linting and formatting setup with the project's actual pre-commit pipeline. - Improves consistency for contributors by preventing confusion between formatting tools. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * We use httpx, not requests * response = httpx.get(request_url, timeout=10).raise_for_status() --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 9 ++++--- web_programming/fetch_well_rx_price.py | 33 +++++++++++--------------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c1879ab1ac6..969328415be6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.11.11 hooks: - - id: ruff + - id: ruff-check - id: ruff-format - repo: https://github.com/codespell-project/codespell @@ -29,7 +29,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.6.0" + rev: v2.6.0 hooks: - id: pyproject-fmt @@ -53,12 +53,11 @@ repos: args: - --explicit-package-bases - --ignore-missing-imports - - --install-types # See mirrors-mypy README.md + - --install-types - --non-interactive - additional_dependencies: [types-requests] - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v4.0.0-alpha.8" + rev: v4.0.0-alpha.8 hooks: - id: prettier types_or: [toml, yaml] diff --git a/web_programming/fetch_well_rx_price.py b/web_programming/fetch_well_rx_price.py index 93be2a9235d9..e34a89c19cc8 100644 --- a/web_programming/fetch_well_rx_price.py +++ b/web_programming/fetch_well_rx_price.py @@ -5,12 +5,10 @@ """ -from urllib.error import HTTPError - +import httpx from bs4 import BeautifulSoup -from requests import exceptions, get -BASE_URL = "https://www.wellrx.com/prescriptions/{0}/{1}/?freshSearch=true" +BASE_URL = "https://www.wellrx.com/prescriptions/{}/{}/?freshSearch=true" def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: @@ -18,8 +16,8 @@ def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: This function will take input of drug name and zipcode, then request to the BASE_URL site. - Get the page data and scrape it to the generate the - list of lowest prices for the prescription drug. + Get the page data and scrape it to generate the + list of the lowest prices for the prescription drug. Args: drug_name (str): [Drug name] @@ -28,12 +26,12 @@ def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: Returns: list: [List of pharmacy name and price] - >>> fetch_pharmacy_and_price_list(None, None) - - >>> fetch_pharmacy_and_price_list(None, 30303) - - >>> fetch_pharmacy_and_price_list("eliquis", None) - + >>> print(fetch_pharmacy_and_price_list(None, None)) + None + >>> print(fetch_pharmacy_and_price_list(None, 30303)) + None + >>> print(fetch_pharmacy_and_price_list("eliquis", None)) + None """ try: @@ -42,10 +40,7 @@ def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: return None request_url = BASE_URL.format(drug_name, zip_code) - response = get(request_url, timeout=10) - - # Is the response ok? - response.raise_for_status() + response = httpx.get(request_url, timeout=10).raise_for_status() # Scrape the data using bs4 soup = BeautifulSoup(response.text, "html.parser") @@ -53,14 +48,14 @@ def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: # This list will store the name and price. pharmacy_price_list = [] - # Fetch all the grids that contains the items. + # Fetch all the grids that contain the items. grid_list = soup.find_all("div", {"class": "grid-x pharmCard"}) if grid_list and len(grid_list) > 0: for grid in grid_list: # Get the pharmacy price. pharmacy_name = grid.find("p", {"class": "list-title"}).text - # Get price of the drug. + # Get the price of the drug. price = grid.find("span", {"p", "price price-large"}).text pharmacy_price_list.append( @@ -72,7 +67,7 @@ def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: return pharmacy_price_list - except (HTTPError, exceptions.RequestException, ValueError): + except (httpx.HTTPError, ValueError): return None From d1a9486f09f47a14ea6bfdfcfaf61c0297476d84 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 23:06:49 +0200 Subject: [PATCH 048/113] [pre-commit.ci] pre-commit autoupdate (#12781) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.11 → v0.12.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.11...v0.12.2) - [github.com/pre-commit/mirrors-mypy: v1.15.0 → v1.16.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.15.0...v1.16.1) * Update .pre-commit-config.yaml --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 969328415be6..b7865145fce9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.11 + rev: v0.12.3 hooks: - id: ruff-check - id: ruff-format From 6e1a1048774468ab2d7717ceae34b43f005dce2d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 15:29:24 -0400 Subject: [PATCH 049/113] [pre-commit.ci] pre-commit autoupdate (#12846) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.3 → v0.12.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.3...v0.12.4) - [github.com/pre-commit/mirrors-mypy: v1.15.0 → v1.17.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.15.0...v1.17.0) * Apply suggestion from @cclauss --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b7865145fce9..f733908c2987 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.3 + rev: v0.12.4 hooks: - id: ruff-check - id: ruff-format From 7a0fee401d2990bd5904e94cd5d3a62c50a8b682 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 17:27:27 -0400 Subject: [PATCH 050/113] [pre-commit.ci] pre-commit autoupdate (#12864) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.4 → v0.12.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.4...v0.12.5) - [github.com/pre-commit/mirrors-mypy: v1.15.0 → v1.17.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.15.0...v1.17.0) * Apply suggestion from @cclauss * --ignore=web_programming/current_stock_price.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .github/workflows/build.yml | 3 ++- .pre-commit-config.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8b83cb41c79a..01b67c6de05b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: cache-dependency-glob: uv.lock - uses: actions/setup-python@v5 with: - python-version: 3.13 + python-version: 3.x allow-prereleases: true - run: uv sync --group=test - name: Run tests @@ -30,6 +30,7 @@ jobs: --ignore=project_euler/ --ignore=quantum/q_fourier_transform.py --ignore=scripts/validate_solutions.py + --ignore=web_programming/current_stock_price.py --ignore=web_programming/fetch_anime_and_play.py --cov-report=term-missing:skip-covered --cov=. . diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f733908c2987..d52c31c42592 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.4 + rev: v0.12.5 hooks: - id: ruff-check - id: ruff-format From d05f5d22d92424f1197950d519fc7a2059de4a5a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 21:03:20 +0200 Subject: [PATCH 051/113] [pre-commit.ci] pre-commit autoupdate (#12880) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v5.0.0...v6.0.0) - [github.com/astral-sh/ruff-pre-commit: v0.12.5 → v0.12.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.5...v0.12.8) - [github.com/pre-commit/mirrors-mypy: v1.15.0 → v1.17.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.15.0...v1.17.1) * Apply suggestion from @cclauss --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d52c31c42592..594489d87c76 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-executables-have-shebangs - id: check-toml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.5 + rev: v0.12.8 hooks: - id: ruff-check - id: ruff-format From f662b63d1ad958d6f14a25136979f3ebdabb987a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:30:10 +0200 Subject: [PATCH 052/113] Bump actions/checkout from 4 to 5 (#12891) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/devcontainer_ci.yml | 2 +- .github/workflows/directory_writer.yml | 2 +- .github/workflows/project_euler.yml | 4 ++-- .github/workflows/ruff.yml | 2 +- .github/workflows/sphinx.yml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01b67c6de05b..69192db0c4c6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 with: enable-cache: true diff --git a/.github/workflows/devcontainer_ci.yml b/.github/workflows/devcontainer_ci.yml index c0b26bb77da6..71623e5e6e69 100644 --- a/.github/workflows/devcontainer_ci.yml +++ b/.github/workflows/devcontainer_ci.yml @@ -12,7 +12,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: devcontainers/ci@v0.3 with: push: never diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml index 3edb5c91a951..f5167f8d1a58 100644 --- a/.github/workflows/directory_writer.yml +++ b/.github/workflows/directory_writer.yml @@ -6,7 +6,7 @@ jobs: directory_writer: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 - uses: actions/setup-python@v5 diff --git a/.github/workflows/project_euler.yml b/.github/workflows/project_euler.yml index eaf4150e4eaa..8b8cb2a1e68f 100644 --- a/.github/workflows/project_euler.yml +++ b/.github/workflows/project_euler.yml @@ -14,7 +14,7 @@ jobs: project-euler: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v5 with: @@ -24,7 +24,7 @@ jobs: validate-solutions: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v5 with: diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml index ec9f0202bd7e..7bcc2850782f 100644 --- a/.github/workflows/ruff.yml +++ b/.github/workflows/ruff.yml @@ -11,6 +11,6 @@ jobs: ruff: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - run: uvx ruff check --output-format=github . diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index 2010041d80c5..a5502a586297 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -25,7 +25,7 @@ jobs: build_docs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v5 with: From beb3cfdf283f68545364aedf34dbbb843ffa95b7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 14:28:03 +0200 Subject: [PATCH 053/113] [pre-commit.ci] pre-commit autoupdate (#12900) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.8 → v0.12.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.8...v0.12.9) - [github.com/pre-commit/mirrors-mypy: v1.15.0 → v1.17.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.15.0...v1.17.1) * Apply suggestion from @cclauss --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 594489d87c76..252cfebc53a8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.8 + rev: v0.12.9 hooks: - id: ruff-check - id: ruff-format From e2245321075bcf9b21c580b87adbd95d21b86e91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 23 Aug 2025 05:48:47 +0200 Subject: [PATCH 054/113] Bump actions/upload-pages-artifact from 3 to 4 (#12922) Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/sphinx.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index a5502a586297..e28fa04f3ab4 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -34,7 +34,7 @@ jobs: - run: uv sync --group=docs - uses: actions/configure-pages@v5 - run: uv run sphinx-build -c docs . docs/_build/html - - uses: actions/upload-pages-artifact@v3 + - uses: actions/upload-pages-artifact@v4 with: path: docs/_build/html From a8c5616857bb15d61ee764671820ad82a5197219 Mon Sep 17 00:00:00 2001 From: Milad Khoshdel Date: Sun, 24 Aug 2025 13:37:39 +0330 Subject: [PATCH 055/113] Simplify Capitalize Function (#12879) * Simplify the capitalize function using ASCII arithmetic to make the algorithm five times faster. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update capitalize.py * Update capitalize.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- strings/capitalize.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/strings/capitalize.py b/strings/capitalize.py index c0b45e0d9614..628ebffc8852 100644 --- a/strings/capitalize.py +++ b/strings/capitalize.py @@ -1,6 +1,3 @@ -from string import ascii_lowercase, ascii_uppercase - - def capitalize(sentence: str) -> str: """ Capitalizes the first letter of a sentence or word. @@ -19,11 +16,9 @@ def capitalize(sentence: str) -> str: if not sentence: return "" - # Create a dictionary that maps lowercase letters to uppercase letters # Capitalize the first character if it's a lowercase letter # Concatenate the capitalized character with the rest of the string - lower_to_upper = dict(zip(ascii_lowercase, ascii_uppercase)) - return lower_to_upper.get(sentence[0], sentence[0]) + sentence[1:] + return sentence[0].upper() + sentence[1:] if __name__ == "__main__": From c2b90034a080355bfac463b598e5228950fefa47 Mon Sep 17 00:00:00 2001 From: Chandra Sekhar Pola Date: Sun, 24 Aug 2025 07:01:21 -0400 Subject: [PATCH 056/113] Fix code style in README.md (#12843) * Fix #12840 code style * Update README.md --------- Co-authored-by: Maxim Smolskiy --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d8eba4e016fa..fe65bb253360 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ pre-commit - - code style: black + + code style: black

All algorithms implemented in Python - for education

From 9ddb0272bf58f681b0b2b25650464f87ecfea742 Mon Sep 17 00:00:00 2001 From: Diya <149782916+diya94@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:52:00 +0530 Subject: [PATCH 057/113] Adding doctest for md_prefix function in build_directory_md.py (#12874) * Adding doctests for md_prefix function in build_directory_md.py * Update build_directory_md.py * Update build_directory_md.py * Update build_directory_md.py --------- Co-authored-by: Maxim Smolskiy --- scripts/build_directory_md.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/build_directory_md.py b/scripts/build_directory_md.py index aa95b95db4b5..bdad7686c7e3 100755 --- a/scripts/build_directory_md.py +++ b/scripts/build_directory_md.py @@ -18,8 +18,20 @@ def good_file_paths(top_dir: str = ".") -> Iterator[str]: yield os.path.join(dir_path, filename).lstrip("./") -def md_prefix(i): - return f"{i * ' '}*" if i else "\n##" +def md_prefix(indent: int) -> str: + """ + Markdown prefix based on indent for bullet points + + >>> md_prefix(0) + '\\n##' + >>> md_prefix(1) + ' *' + >>> md_prefix(2) + ' *' + >>> md_prefix(3) + ' *' + """ + return f"{indent * ' '}*" if indent else "\n##" def print_path(old_path: str, new_path: str) -> str: From 060fd8ee2cd389bf4a09e1947c1586fb45b4044c Mon Sep 17 00:00:00 2001 From: conti <130701882+mr-conti@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:49:43 +0200 Subject: [PATCH 058/113] Fix reverse_bits.py: correct 32-bit reversal and improve docstrings (#12924) * Fix reverse_bits.py (#12868) * Update reverse_bits.py * Update reverse_bits.py * Update reverse_bits.py * Update reverse_bits.py * Update reverse_bits.py --------- Co-authored-by: Maxim Smolskiy --- bit_manipulation/reverse_bits.py | 62 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/bit_manipulation/reverse_bits.py b/bit_manipulation/reverse_bits.py index 74b4f2563234..4a0b2ff7047a 100644 --- a/bit_manipulation/reverse_bits.py +++ b/bit_manipulation/reverse_bits.py @@ -1,6 +1,6 @@ def get_reverse_bit_string(number: int) -> str: """ - return the bit string of an integer + Return the reverse bit string of a 32 bit integer >>> get_reverse_bit_string(9) '10010000000000000000000000000000' @@ -8,76 +8,76 @@ def get_reverse_bit_string(number: int) -> str: '11010100000000000000000000000000' >>> get_reverse_bit_string(2873) '10011100110100000000000000000000' + >>> get_reverse_bit_string(2550136832) + '00000000000000000000000000011001' >>> get_reverse_bit_string("this is not a number") Traceback (most recent call last): ... - TypeError: operation can not be conducted on a object of type str + TypeError: operation can not be conducted on an object of type str """ if not isinstance(number, int): msg = ( - "operation can not be conducted on a object of type " + "operation can not be conducted on an object of type " f"{type(number).__name__}" ) raise TypeError(msg) bit_string = "" for _ in range(32): bit_string += str(number % 2) - number = number >> 1 + number >>= 1 return bit_string -def reverse_bit(number: int) -> str: +def reverse_bit(number: int) -> int: """ - Take in an 32 bit integer, reverse its bits, - return a string of reverse bits - - result of a reverse_bit and operation on the integer provided. + Take in a 32 bit integer, reverse its bits, return a 32 bit integer result >>> reverse_bit(25) - '00000000000000000000000000011001' + 2550136832 >>> reverse_bit(37) - '00000000000000000000000000100101' + 2751463424 >>> reverse_bit(21) - '00000000000000000000000000010101' + 2818572288 >>> reverse_bit(58) - '00000000000000000000000000111010' + 1543503872 >>> reverse_bit(0) - '00000000000000000000000000000000' + 0 >>> reverse_bit(256) - '00000000000000000000000100000000' + 8388608 + >>> reverse_bit(2550136832) + 25 >>> reverse_bit(-1) Traceback (most recent call last): ... - ValueError: the value of input must be positive + ValueError: The value of input must be non-negative >>> reverse_bit(1.1) Traceback (most recent call last): ... - TypeError: Input value must be a 'int' type + TypeError: Input value must be an 'int' type >>> reverse_bit("0") Traceback (most recent call last): ... - TypeError: '<' not supported between instances of 'str' and 'int' + TypeError: Input value must be an 'int' type """ + if not isinstance(number, int): + raise TypeError("Input value must be an 'int' type") if number < 0: - raise ValueError("the value of input must be positive") - elif isinstance(number, float): - raise TypeError("Input value must be a 'int' type") - elif isinstance(number, str): - raise TypeError("'<' not supported between instances of 'str' and 'int'") + raise ValueError("The value of input must be non-negative") + result = 0 - # iterator over [1 to 32],since we are dealing with 32 bit integer - for _ in range(1, 33): + # iterator over [0 to 31], since we are dealing with a 32 bit integer + for _ in range(32): # left shift the bits by unity - result = result << 1 + result <<= 1 # get the end bit - end_bit = number % 2 + end_bit = number & 1 # right shift the bits by unity - number = number >> 1 - # add that bit to our ans - result = result | end_bit - return get_reverse_bit_string(result) + number >>= 1 + # add that bit to our answer + result |= end_bit + return result if __name__ == "__main__": From d16cac6e4f00b9182b386d6e3bcbc97a323d8f7f Mon Sep 17 00:00:00 2001 From: Ahmad Alharbi Date: Sun, 24 Aug 2025 05:08:52 -0700 Subject: [PATCH 059/113] feat: Add recursive implication function for lists (#12855) * feat: Add recursive implication function for lists * Update imply_gate.py * Update imply_gate.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- boolean_algebra/imply_gate.py | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/boolean_algebra/imply_gate.py b/boolean_algebra/imply_gate.py index b64ebaceb306..3d71ff12f8d9 100644 --- a/boolean_algebra/imply_gate.py +++ b/boolean_algebra/imply_gate.py @@ -33,6 +33,58 @@ def imply_gate(input_1: int, input_2: int) -> int: return int(input_1 == 0 or input_2 == 1) +def recursive_imply_list(input_list: list[int]) -> int: + """ + Recursively calculates the implication of a list. + Strictly the implication is applied consecutively left to right: + ( (a -> b) -> c ) -> d ... + + >>> recursive_imply_list([]) + Traceback (most recent call last): + ... + ValueError: Input list must contain at least two elements + >>> recursive_imply_list([0]) + Traceback (most recent call last): + ... + ValueError: Input list must contain at least two elements + >>> recursive_imply_list([1]) + Traceback (most recent call last): + ... + ValueError: Input list must contain at least two elements + >>> recursive_imply_list([0, 0]) + 1 + >>> recursive_imply_list([0, 1]) + 1 + >>> recursive_imply_list([1, 0]) + 0 + >>> recursive_imply_list([1, 1]) + 1 + >>> recursive_imply_list([0, 0, 0]) + 0 + >>> recursive_imply_list([0, 0, 1]) + 1 + >>> recursive_imply_list([0, 1, 0]) + 0 + >>> recursive_imply_list([0, 1, 1]) + 1 + >>> recursive_imply_list([1, 0, 0]) + 1 + >>> recursive_imply_list([1, 0, 1]) + 1 + >>> recursive_imply_list([1, 1, 0]) + 0 + >>> recursive_imply_list([1, 1, 1]) + 1 + """ + if len(input_list) < 2: + raise ValueError("Input list must contain at least two elements") + first_implication = imply_gate(input_list[0], input_list[1]) + if len(input_list) == 2: + return first_implication + new_list = [first_implication, *input_list[2:]] + return recursive_imply_list(new_list) + + if __name__ == "__main__": import doctest From 37b34c2bac250a20dd534f0658c500c4c61ffe47 Mon Sep 17 00:00:00 2001 From: Sowndappan S <147894621+sowndappan5@users.noreply.github.com> Date: Sun, 24 Aug 2025 18:03:18 +0530 Subject: [PATCH 060/113] perf(strings): optimize anagram signature using frequency counts (#12927) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(strings): use frequency-based signature for anagrams Replaced the sorting-based signature implementation with a frequency-based approach using `collections.Counter`. This ensures that the signature represents both characters and their counts, preventing collisions and better grouping of true anagrams. Examples: - "test" → "e1s1t2" - "finaltest" → "a1e1f1i1l1n1s1t2" - "this is a test" → " 3a1e1h1i2s3t3" Also updated the anagram lookup to use the new frequency-based signatures, making results more accurate and avoiding false positives. * Refactor anagram function return type to list[str] * Update anagrams.py * Update anagrams.py * Update anagrams.py * Update anagrams.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- strings/anagrams.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/strings/anagrams.py b/strings/anagrams.py index fb9ac0bd1f45..71cc142fb2ad 100644 --- a/strings/anagrams.py +++ b/strings/anagrams.py @@ -6,19 +6,26 @@ def signature(word: str) -> str: - """Return a word sorted + """ + Return a word's frequency-based signature. + >>> signature("test") - 'estt' + 'e1s1t2' >>> signature("this is a test") - ' aehiisssttt' + ' 3a1e1h1i2s3t3' >>> signature("finaltest") - 'aefilnstt' + 'a1e1f1i1l1n1s1t2' """ - return "".join(sorted(word)) + frequencies = collections.Counter(word) + return "".join( + f"{char}{frequency}" for char, frequency in sorted(frequencies.items()) + ) def anagram(my_word: str) -> list[str]: - """Return every anagram of the given word + """ + Return every anagram of the given word from the dictionary. + >>> anagram('test') ['sett', 'stet', 'test'] >>> anagram('this is a test') @@ -40,5 +47,5 @@ def anagram(my_word: str) -> list[str]: all_anagrams = {word: anagram(word) for word in word_list if len(anagram(word)) > 1} with open("anagrams.txt", "w") as file: - file.write("all_anagrams = \n ") + file.write("all_anagrams = \n") file.write(pprint.pformat(all_anagrams)) From d927d67c4afafe82bddb4765c7f660b56e1b31e0 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Sun, 24 Aug 2025 17:48:59 +0300 Subject: [PATCH 061/113] Update Linked List from sequence script to use doctests (#12766) * Update comments for linked list script. * Add doctests for the linked list script. * Update from_sequence.py --------- Co-authored-by: Maxim Smolskiy --- data_structures/linked_list/from_sequence.py | 41 +++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/data_structures/linked_list/from_sequence.py b/data_structures/linked_list/from_sequence.py index fa43f4d10e08..b16b2258c1f1 100644 --- a/data_structures/linked_list/from_sequence.py +++ b/data_structures/linked_list/from_sequence.py @@ -1,5 +1,7 @@ -# Recursive Program to create a Linked List from a sequence and -# print a string representation of it. +""" +Recursive Program to create a Linked List from a sequence and +print a string representation of it. +""" class Node: @@ -18,13 +20,32 @@ def __repr__(self): return string_rep -def make_linked_list(elements_list): - """Creates a Linked List from the elements of the given sequence - (list/tuple) and returns the head of the Linked List.""" +def make_linked_list(elements_list: list | tuple) -> Node: + """ + Creates a Linked List from the elements of the given sequence + (list/tuple) and returns the head of the Linked List. + + >>> make_linked_list([]) + Traceback (most recent call last): + ... + ValueError: The Elements List is empty + >>> make_linked_list(()) + Traceback (most recent call last): + ... + ValueError: The Elements List is empty + >>> make_linked_list([1]) + <1> ---> + >>> make_linked_list((1,)) + <1> ---> + >>> make_linked_list([1, 3, 5, 32, 44, 12, 43]) + <1> ---> <3> ---> <5> ---> <32> ---> <44> ---> <12> ---> <43> ---> + >>> make_linked_list((1, 3, 5, 32, 44, 12, 43)) + <1> ---> <3> ---> <5> ---> <32> ---> <44> ---> <12> ---> <43> ---> + """ # if elements_list is empty if not elements_list: - raise Exception("The Elements List is empty") + raise ValueError("The Elements List is empty") # Set first element as Head head = Node(elements_list[0]) @@ -34,11 +55,3 @@ def make_linked_list(elements_list): current.next = Node(data) current = current.next return head - - -list_data = [1, 3, 5, 32, 44, 12, 43] -print(f"List: {list_data}") -print("Creating Linked List from List.") -linked_list = make_linked_list(list_data) -print("Linked List:") -print(linked_list) From 561cc383ec04ba61eb9bab5ae891ef5328551df9 Mon Sep 17 00:00:00 2001 From: "S. M. Mohiuddin Khan Shiam" <147746955+mohiuddin-khan-shiam@users.noreply.github.com> Date: Mon, 25 Aug 2025 03:47:46 +0600 Subject: [PATCH 062/113] Fix RuntimeError in bipartite-check DFS/BFS and clean up doctests (#12814) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix `RuntimeError` in bipartite-check DFS/BFS and clean up doctests * Iteration over `graph` mutated by `defaultdict` neighbours caused `RuntimeError: dictionary changed size during iteration`. – Iterate over `list(graph)` in both DFS and BFS helpers. * Corrected `if __name__ == "__main__":` typo. * Updated two doctests that now succeed after the fix. All doctests now pass (`30/30`), eliminating a critical runtime failure and improving reliability of the graph algorithms. Co-Authored-By: S. M. Mohiuddin Khan Shiam <147746955+mohiuddin-khan-shiam@users.noreply.github.com> * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py * Update check_bipatrite.py --------- Co-authored-by: Odio Marcelino Co-authored-by: Maxim Smolskiy --- graphs/check_bipatrite.py | 68 +++++++++++++-------------------------- 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/graphs/check_bipatrite.py b/graphs/check_bipatrite.py index 213f3f9480b5..897c78850d58 100644 --- a/graphs/check_bipatrite.py +++ b/graphs/check_bipatrite.py @@ -1,7 +1,7 @@ from collections import defaultdict, deque -def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool: +def is_bipartite_dfs(graph: dict[int, list[int]]) -> bool: """ Check if a graph is bipartite using depth-first search (DFS). @@ -16,12 +16,9 @@ def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool: Examples: - >>> # FIXME: This test should pass. - >>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]})) - Traceback (most recent call last): - ... - RuntimeError: dictionary changed size during iteration - >>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 1]})) + >>> is_bipartite_dfs({0: [1, 2], 1: [0, 3], 2: [0, 4]}) + True + >>> is_bipartite_dfs({0: [1, 2], 1: [0, 3], 2: [0, 1]}) False >>> is_bipartite_dfs({}) True @@ -34,36 +31,26 @@ def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool: >>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]}) False >>> is_bipartite_dfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]}) - Traceback (most recent call last): - ... - KeyError: 0 + False >>> # FIXME: This test should fails with KeyError: 4. >>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]}) False >>> is_bipartite_dfs({0: [-1, 3], 1: [0, -2]}) - Traceback (most recent call last): - ... - KeyError: -1 + False >>> is_bipartite_dfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]}) True >>> is_bipartite_dfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]}) - Traceback (most recent call last): - ... - KeyError: 0 + True >>> # FIXME: This test should fails with >>> # TypeError: list indices must be integers or... >>> is_bipartite_dfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]}) True >>> is_bipartite_dfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]}) - Traceback (most recent call last): - ... - KeyError: 1 + True >>> is_bipartite_dfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]}) - Traceback (most recent call last): - ... - KeyError: 'b' + True """ def depth_first_search(node: int, color: int) -> bool: @@ -80,6 +67,8 @@ def depth_first_search(node: int, color: int) -> bool: """ if visited[node] == -1: visited[node] = color + if node not in graph: + return True for neighbor in graph[node]: if not depth_first_search(neighbor, 1 - color): return False @@ -92,7 +81,7 @@ def depth_first_search(node: int, color: int) -> bool: return True -def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool: +def is_bipartite_bfs(graph: dict[int, list[int]]) -> bool: """ Check if a graph is bipartite using a breadth-first search (BFS). @@ -107,12 +96,9 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool: Examples: - >>> # FIXME: This test should pass. - >>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]})) - Traceback (most recent call last): - ... - RuntimeError: dictionary changed size during iteration - >>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]})) + >>> is_bipartite_bfs({0: [1, 2], 1: [0, 3], 2: [0, 4]}) + True + >>> is_bipartite_bfs({0: [1, 2], 1: [0, 2], 2: [0, 1]}) False >>> is_bipartite_bfs({}) True @@ -125,36 +111,26 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool: >>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]}) False >>> is_bipartite_bfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]}) - Traceback (most recent call last): - ... - KeyError: 0 + False >>> # FIXME: This test should fails with KeyError: 4. >>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]}) False >>> is_bipartite_bfs({0: [-1, 3], 1: [0, -2]}) - Traceback (most recent call last): - ... - KeyError: -1 + False >>> is_bipartite_bfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]}) True >>> is_bipartite_bfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]}) - Traceback (most recent call last): - ... - KeyError: 0 + True >>> # FIXME: This test should fails with >>> # TypeError: list indices must be integers or... >>> is_bipartite_bfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]}) True >>> is_bipartite_bfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]}) - Traceback (most recent call last): - ... - KeyError: 1 + True >>> is_bipartite_bfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]}) - Traceback (most recent call last): - ... - KeyError: 'b' + True """ visited: defaultdict[int, int] = defaultdict(lambda: -1) for node in graph: @@ -164,6 +140,8 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool: visited[node] = 0 while queue: curr_node = queue.popleft() + if curr_node not in graph: + continue for neighbor in graph[curr_node]: if visited[neighbor] == -1: visited[neighbor] = 1 - visited[curr_node] @@ -173,7 +151,7 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool: return True -if __name__ == "__main": +if __name__ == "__main__": import doctest result = doctest.testmod() From b0be30443393b019c469684554a3c8748ffeacbe Mon Sep 17 00:00:00 2001 From: John Liu <154310237+john-liu2@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:59:44 -0700 Subject: [PATCH 063/113] Use deque as queue in breadth_first_search_shortest_path_2.py (#12861) * Fixes #12857 Use collections.deque as queue in graphs BFS shortest path 2 * Use collections.deque as queue in the correct syntax: queue = deque([start]) * Fix CI error due to HTTP 404 on https://finance.yahoo.com/quote/GOOG/\?p\=GOOG * Undo change in workflows/build.yml as it's fixed in PR 12864 --------- Co-authored-by: Maxim Smolskiy --- .../breadth_first_search_shortest_path_2.py | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/graphs/breadth_first_search_shortest_path_2.py b/graphs/breadth_first_search_shortest_path_2.py index 4f9b6e65bdf3..efba9b7b6ae6 100644 --- a/graphs/breadth_first_search_shortest_path_2.py +++ b/graphs/breadth_first_search_shortest_path_2.py @@ -1,10 +1,12 @@ -"""Breadth-first search shortest path implementations. +"""Breadth-first search the shortest path implementations. doctest: -python -m doctest -v bfs_shortest_path.py +python -m doctest -v breadth_first_search_shortest_path_2.py Manual test: -python bfs_shortest_path.py +python breadth_first_search_shortest_path_2.py """ +from collections import deque + demo_graph = { "A": ["B", "C", "E"], "B": ["A", "D", "E"], @@ -17,7 +19,7 @@ def bfs_shortest_path(graph: dict, start, goal) -> list[str]: - """Find shortest path between `start` and `goal` nodes. + """Find the shortest path between `start` and `goal` nodes. Args: graph (dict): node/list of neighboring nodes key/value pairs. start: start node. @@ -36,7 +38,7 @@ def bfs_shortest_path(graph: dict, start, goal) -> list[str]: # keep track of explored nodes explored = set() # keep track of all the paths to be checked - queue = [[start]] + queue = deque([[start]]) # return path if start is goal if start == goal: @@ -45,7 +47,7 @@ def bfs_shortest_path(graph: dict, start, goal) -> list[str]: # keeps looping until all possible paths have been checked while queue: # pop the first path from the queue - path = queue.pop(0) + path = queue.popleft() # get the last node from the path node = path[-1] if node not in explored: @@ -68,13 +70,13 @@ def bfs_shortest_path(graph: dict, start, goal) -> list[str]: def bfs_shortest_path_distance(graph: dict, start, target) -> int: - """Find shortest path distance between `start` and `target` nodes. + """Find the shortest path distance between `start` and `target` nodes. Args: graph: node/list of neighboring nodes key/value pairs. start: node to start search from. target: node to search for. Returns: - Number of edges in shortest path between `start` and `target` nodes. + Number of edges in the shortest path between `start` and `target` nodes. -1 if no path exists. Example: >>> bfs_shortest_path_distance(demo_graph, "G", "D") @@ -88,12 +90,12 @@ def bfs_shortest_path_distance(graph: dict, start, target) -> int: return -1 if start == target: return 0 - queue = [start] + queue = deque([start]) visited = set(start) # Keep tab on distances from `start` node. dist = {start: 0, target: -1} while queue: - node = queue.pop(0) + node = queue.popleft() if node == target: dist[target] = ( dist[node] if dist[target] == -1 else min(dist[target], dist[node]) From 8c1c6c1763e8d4695754dceea072cc1ff58308bb Mon Sep 17 00:00:00 2001 From: alejandroaldas <52395149+alejandroaldas@users.noreply.github.com> Date: Sun, 24 Aug 2025 17:16:05 -0500 Subject: [PATCH 064/113] Codex/find and fix a bug (#12782) * Fix enumeration order in FFT string representation * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update radix2_fft.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: alejandroaldas Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- maths/radix2_fft.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/maths/radix2_fft.py b/maths/radix2_fft.py index ccd5cdcc0160..5efbccc7a17d 100644 --- a/maths/radix2_fft.py +++ b/maths/radix2_fft.py @@ -39,14 +39,14 @@ class FFT: >>> x = FFT(A, B) Print product - >>> x.product # 2x + 3x^2 + 8x^3 + 4x^4 + 6x^5 + >>> x.product # 2x + 3x^2 + 8x^3 + 6x^4 + 8x^5 [(-0-0j), (2+0j), (3-0j), (8-0j), (6+0j), (8+0j)] __str__ test >>> print(x) - A = 0*x^0 + 1*x^1 + 2*x^0 + 3*x^2 - B = 0*x^2 + 1*x^3 + 2*x^4 - A*B = 0*x^(-0-0j) + 1*x^(2+0j) + 2*x^(3-0j) + 3*x^(8-0j) + 4*x^(6+0j) + 5*x^(8+0j) + A = 0*x^0 + 1*x^1 + 0*x^2 + 2*x^3 + B = 2*x^0 + 3*x^1 + 4*x^2 + A*B = (-0-0j)*x^0 + (2+0j)*x^1 + (3-0j)*x^2 + (8-0j)*x^3 + (6+0j)*x^4 + (8+0j)*x^5 """ def __init__(self, poly_a=None, poly_b=None): @@ -159,13 +159,13 @@ def __multiply(self): # Overwrite __str__ for print(); Shows A, B and A*B def __str__(self): a = "A = " + " + ".join( - f"{coef}*x^{i}" for coef, i in enumerate(self.polyA[: self.len_A]) + f"{coef}*x^{i}" for i, coef in enumerate(self.polyA[: self.len_A]) ) b = "B = " + " + ".join( - f"{coef}*x^{i}" for coef, i in enumerate(self.polyB[: self.len_B]) + f"{coef}*x^{i}" for i, coef in enumerate(self.polyB[: self.len_B]) ) c = "A*B = " + " + ".join( - f"{coef}*x^{i}" for coef, i in enumerate(self.product) + f"{coef}*x^{i}" for i, coef in enumerate(self.product) ) return f"{a}\n{b}\n{c}" From dc1b2003b44b9fd831b5870d988e4f0af93b3389 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 26 Aug 2025 15:32:39 +0300 Subject: [PATCH 065/113] [pre-commit.ci] pre-commit autoupdate (#12930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.9 → v0.12.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.9...v0.12.10) - [github.com/pre-commit/mirrors-mypy: v1.15.0 → v1.17.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.15.0...v1.17.1) * Update word_break.py * Update word_break.py * Update word_break.py * Update word_break.py * Update word_break.py * Update covid_stats_via_xpath.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pyproject.toml * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pyproject.toml * Update pyproject.toml * Update covid_stats_via_xpath.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- .pre-commit-config.yaml | 4 ++-- dynamic_programming/word_break.py | 2 +- web_programming/covid_stats_via_xpath.py | 12 +++++++----- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 252cfebc53a8..6eb0906fb23a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.9 + rev: v0.12.10 hooks: - id: ruff-check - id: ruff-format @@ -47,7 +47,7 @@ repos: - id: validate-pyproject - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.15.0 + rev: v1.17.1 hooks: - id: mypy args: diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 4d7ac869080c..c4ba2d7aa976 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -90,7 +90,7 @@ def is_breakable(index: int) -> bool: if index == len_string: return True - trie_node = trie + trie_node: Any = trie for i in range(index, len_string): trie_node = trie_node.get(string[i], None) diff --git a/web_programming/covid_stats_via_xpath.py b/web_programming/covid_stats_via_xpath.py index f7db51b63169..9c016ba414ea 100644 --- a/web_programming/covid_stats_via_xpath.py +++ b/web_programming/covid_stats_via_xpath.py @@ -1,5 +1,5 @@ """ -This is to show simple COVID19 info fetching from worldometers site using lxml +This is to show simple COVID19 info fetching from worldometers archive site using lxml * The main motivation to use lxml in place of bs4 is that it is faster and therefore more convenient to use in Python web projects (e.g. Django or Flask-based) """ @@ -19,12 +19,14 @@ class CovidData(NamedTuple): - cases: int - deaths: int - recovered: int + cases: str + deaths: str + recovered: str -def covid_stats(url: str = "https://www.worldometers.info/coronavirus/") -> CovidData: +def covid_stats( + url: str = "https://web.archive.org/web/20250825095350/https://www.worldometers.info/coronavirus/", +) -> CovidData: xpath_str = '//div[@class = "maincounter-number"]/span/text()' return CovidData( *html.fromstring(httpx.get(url, timeout=10).content).xpath(xpath_str) From 55db5a1b8d463a514522dd759053d30357538b62 Mon Sep 17 00:00:00 2001 From: Mindaugas <76015221+mindaugl@users.noreply.github.com> Date: Tue, 26 Aug 2025 21:17:18 +0300 Subject: [PATCH 066/113] Add new solution for the euler project problem 9 (#12771) * Add new solution for the euler project problem 9 - precompute the squares. * Update sol4.py * updating DIRECTORY.md * Update sol4.py * Update sol4.py * Update sol4.py --------- Co-authored-by: Maxim Smolskiy Co-authored-by: MaximSmolskiy --- DIRECTORY.md | 1 + project_euler/problem_009/sol4.py | 60 +++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 project_euler/problem_009/sol4.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 81d6f4c70864..2e3b4398f26e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -956,6 +956,7 @@ * [Sol1](project_euler/problem_009/sol1.py) * [Sol2](project_euler/problem_009/sol2.py) * [Sol3](project_euler/problem_009/sol3.py) + * [Sol4](project_euler/problem_009/sol4.py) * Problem 010 * [Sol1](project_euler/problem_010/sol1.py) * [Sol2](project_euler/problem_010/sol2.py) diff --git a/project_euler/problem_009/sol4.py b/project_euler/problem_009/sol4.py new file mode 100644 index 000000000000..a07d40ccb54d --- /dev/null +++ b/project_euler/problem_009/sol4.py @@ -0,0 +1,60 @@ +""" +Project Euler Problem 9: https://projecteuler.net/problem=9 + +Special Pythagorean triplet + +A Pythagorean triplet is a set of three natural numbers, a < b < c, for which, + + a^2 + b^2 = c^2. + +For example, 3^2 + 4^2 = 9 + 16 = 25 = 5^2. + +There exists exactly one Pythagorean triplet for which a + b + c = 1000. +Find the product abc. + +References: + - https://en.wikipedia.org/wiki/Pythagorean_triple +""" + + +def get_squares(n: int) -> list[int]: + """ + >>> get_squares(0) + [] + >>> get_squares(1) + [0] + >>> get_squares(2) + [0, 1] + >>> get_squares(3) + [0, 1, 4] + >>> get_squares(4) + [0, 1, 4, 9] + """ + return [number * number for number in range(n)] + + +def solution(n: int = 1000) -> int: + """ + Precomputing squares and checking if a^2 + b^2 is the square by set look-up. + + >>> solution(12) + 60 + >>> solution(36) + 1620 + """ + + squares = get_squares(n) + squares_set = set(squares) + for a in range(1, n // 3): + for b in range(a + 1, (n - a) // 2 + 1): + if ( + squares[a] + squares[b] in squares_set + and squares[n - a - b] == squares[a] + squares[b] + ): + return a * b * (n - a - b) + + return -1 + + +if __name__ == "__main__": + print(f"{solution() = }") From 44cf167175cf2a53080006dbedd40b5f5343ef18 Mon Sep 17 00:00:00 2001 From: Sharan Sukesh <77352136+sharansukesh1003@users.noreply.github.com> Date: Tue, 26 Aug 2025 14:42:14 -0400 Subject: [PATCH 067/113] Create cyclic_sort.py (#9256) * Create cyclic_sort.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update cyclic_sort.py * updating DIRECTORY.md * Update cyclic_sort.py * Update cyclic_sort.py * Update cyclic_sort.py * Update cyclic_sort.py * Update cyclic_sort.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy Co-authored-by: MaximSmolskiy --- DIRECTORY.md | 1 + sorts/cyclic_sort.py | 55 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 sorts/cyclic_sort.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 2e3b4398f26e..53c53d208656 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1267,6 +1267,7 @@ * [Comb Sort](sorts/comb_sort.py) * [Counting Sort](sorts/counting_sort.py) * [Cycle Sort](sorts/cycle_sort.py) + * [Cyclic Sort](sorts/cyclic_sort.py) * [Double Sort](sorts/double_sort.py) * [Dutch National Flag Sort](sorts/dutch_national_flag_sort.py) * [Exchange Sort](sorts/exchange_sort.py) diff --git a/sorts/cyclic_sort.py b/sorts/cyclic_sort.py new file mode 100644 index 000000000000..9e81291548d4 --- /dev/null +++ b/sorts/cyclic_sort.py @@ -0,0 +1,55 @@ +""" +This is a pure Python implementation of the Cyclic Sort algorithm. + +For doctests run following command: +python -m doctest -v cyclic_sort.py +or +python3 -m doctest -v cyclic_sort.py +For manual testing run: +python cyclic_sort.py +or +python3 cyclic_sort.py +""" + + +def cyclic_sort(nums: list[int]) -> list[int]: + """ + Sorts the input list of n integers from 1 to n in-place + using the Cyclic Sort algorithm. + + :param nums: List of n integers from 1 to n to be sorted. + :return: The same list sorted in ascending order. + + Time complexity: O(n), where n is the number of integers in the list. + + Examples: + >>> cyclic_sort([]) + [] + >>> cyclic_sort([3, 5, 2, 1, 4]) + [1, 2, 3, 4, 5] + """ + + # Perform cyclic sort + index = 0 + while index < len(nums): + # Calculate the correct index for the current element + correct_index = nums[index] - 1 + # If the current element is not at its correct position, + # swap it with the element at its correct index + if index != correct_index: + nums[index], nums[correct_index] = nums[correct_index], nums[index] + else: + # If the current element is already in its correct position, + # move to the next element + index += 1 + + return nums + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + user_input = input("Enter numbers separated by a comma:\n").strip() + unsorted = [int(item) for item in user_input.split(",")] + print(*cyclic_sort(unsorted), sep=",") From 4961b3aa899f79b02539ec031d8b6e5adafc02d1 Mon Sep 17 00:00:00 2001 From: Wei Jiang <42140605+Jiang15@users.noreply.github.com> Date: Wed, 27 Aug 2025 00:10:22 +0200 Subject: [PATCH 068/113] Enhancement of the knapsack algorithm with memorization and generalisation (#9295) * enhance knapsack problem * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * wei/refactor code * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update test_knapsack.py * Update knapsack.py * Update test_knapsack.py * Update knapsack.py * Update knapsack.py * Update knapsack.py * Update knapsack.py * Update knapsack.py * Update test_knapsack.py --------- Co-authored-by: weijiang Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- knapsack/README.md | 2 +- knapsack/knapsack.py | 65 ++++++++++++++++++++++----------- knapsack/tests/test_knapsack.py | 12 +++++- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/knapsack/README.md b/knapsack/README.md index f31e5f591412..686ea929255a 100644 --- a/knapsack/README.md +++ b/knapsack/README.md @@ -1,4 +1,4 @@ -# A naive recursive implementation of 0-1 Knapsack Problem +# A recursive implementation of 0-N Knapsack Problem This overview is taken from: diff --git a/knapsack/knapsack.py b/knapsack/knapsack.py index bb507be1ba3c..0648773c919f 100644 --- a/knapsack/knapsack.py +++ b/knapsack/knapsack.py @@ -1,14 +1,23 @@ -"""A naive recursive implementation of 0-1 Knapsack Problem +"""A recursive implementation of 0-N Knapsack Problem https://en.wikipedia.org/wiki/Knapsack_problem """ from __future__ import annotations +from functools import lru_cache -def knapsack(capacity: int, weights: list[int], values: list[int], counter: int) -> int: + +def knapsack( + capacity: int, + weights: list[int], + values: list[int], + counter: int, + allow_repetition=False, +) -> int: """ Returns the maximum value that can be put in a knapsack of a capacity cap, - whereby each weight w has a specific value val. + whereby each weight w has a specific value val + with option to allow repetitive selection of items >>> cap = 50 >>> val = [60, 100, 120] @@ -17,28 +26,40 @@ def knapsack(capacity: int, weights: list[int], values: list[int], counter: int) >>> knapsack(cap, w, val, c) 220 - The result is 220 cause the values of 100 and 120 got the weight of 50 + Given the repetition is NOT allowed, + the result is 220 cause the values of 100 and 120 got the weight of 50 which is the limit of the capacity. + >>> knapsack(cap, w, val, c, True) + 300 + + Given the repetition is allowed, + the result is 300 cause the values of 60*5 (pick 5 times) + got the weight of 10*5 which is the limit of the capacity. """ - # Base Case - if counter == 0 or capacity == 0: - return 0 - - # If weight of the nth item is more than Knapsack of capacity, - # then this item cannot be included in the optimal solution, - # else return the maximum of two cases: - # (1) nth item included - # (2) not included - if weights[counter - 1] > capacity: - return knapsack(capacity, weights, values, counter - 1) - else: - left_capacity = capacity - weights[counter - 1] - new_value_included = values[counter - 1] + knapsack( - left_capacity, weights, values, counter - 1 - ) - without_new_value = knapsack(capacity, weights, values, counter - 1) - return max(new_value_included, without_new_value) + @lru_cache + def knapsack_recur(capacity: int, counter: int) -> int: + # Base Case + if counter == 0 or capacity == 0: + return 0 + + # If weight of the nth item is more than Knapsack of capacity, + # then this item cannot be included in the optimal solution, + # else return the maximum of two cases: + # (1) nth item included only once (0-1), if allow_repetition is False + # nth item included one or more times (0-N), if allow_repetition is True + # (2) not included + if weights[counter - 1] > capacity: + return knapsack_recur(capacity, counter - 1) + else: + left_capacity = capacity - weights[counter - 1] + new_value_included = values[counter - 1] + knapsack_recur( + left_capacity, counter - 1 if not allow_repetition else counter + ) + without_new_value = knapsack_recur(capacity, counter - 1) + return max(new_value_included, without_new_value) + + return knapsack_recur(capacity, counter) if __name__ == "__main__": diff --git a/knapsack/tests/test_knapsack.py b/knapsack/tests/test_knapsack.py index 7bfb8780627b..80378aae4579 100644 --- a/knapsack/tests/test_knapsack.py +++ b/knapsack/tests/test_knapsack.py @@ -30,7 +30,7 @@ def test_base_case(self): def test_easy_case(self): """ - test for the base case + test for the easy case """ cap = 3 val = [1, 2, 3] @@ -48,6 +48,16 @@ def test_knapsack(self): c = len(val) assert k.knapsack(cap, w, val, c) == 220 + def test_knapsack_repetition(self): + """ + test for the knapsack repetition + """ + cap = 50 + val = [60, 100, 120] + w = [10, 20, 30] + c = len(val) + assert k.knapsack(cap, w, val, c, True) == 300 + if __name__ == "__main__": unittest.main() From b486ac60e6e047f94615f0489ae8aaa48d33ff41 Mon Sep 17 00:00:00 2001 From: Om Ashishkumar Soni Date: Thu, 28 Aug 2025 00:32:14 +0530 Subject: [PATCH 069/113] added coordinate_compression (#9317) * added coordinate_compression algorithm * added coordinate_compression & doctest * adding return type hints and utilized enumerate * adding exmaple usage in main function * added type hints, for list and dict * updating DIRECTORY.md * Update other/coordinate_compression.py Co-authored-by: Christian Clauss * Update other/coordinate_compression.py Co-authored-by: Christian Clauss * Update other/coordinate_compression.py Co-authored-by: Christian Clauss * Update other/coordinate_compression.py Co-authored-by: Christian Clauss * Update other/coordinate_compression.py Co-authored-by: Christian Clauss * Update other/coordinate_compression.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update other/coordinate_compression.py Co-authored-by: Christian Clauss * Update other/coordinate_compression.py Co-authored-by: Christian Clauss * Update coordinate_compression.py * Create coordinate_compression.py * updating DIRECTORY.md * Delete other/coordinate_compression.py * updating DIRECTORY.md * Update coordinate_compression.py * Update coordinate_compression.py * Update coordinate_compression.py * Update coordinate_compression.py * Update coordinate_compression.py * Update coordinate_compression.py * Update coordinate_compression.py * Update coordinate_compression.py * Update coordinate_compression.py --------- Co-authored-by: Maxim Smolskiy Co-authored-by: MaximSmolskiy Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 1 + data_compression/coordinate_compression.py | 132 +++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 data_compression/coordinate_compression.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 53c53d208656..0636ba0a7ecc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -174,6 +174,7 @@ ## Data Compression * [Burrows Wheeler](data_compression/burrows_wheeler.py) + * [Coordinate Compression](data_compression/coordinate_compression.py) * [Huffman](data_compression/huffman.py) * [Lempel Ziv](data_compression/lempel_ziv.py) * [Lempel Ziv Decompress](data_compression/lempel_ziv_decompress.py) diff --git a/data_compression/coordinate_compression.py b/data_compression/coordinate_compression.py new file mode 100644 index 000000000000..9c4ad9a99ac3 --- /dev/null +++ b/data_compression/coordinate_compression.py @@ -0,0 +1,132 @@ +""" +Assumption: + - The values to compress are assumed to be comparable, + values can be sorted and compared with '<' and '>' operators. +""" + + +class CoordinateCompressor: + """ + A class for coordinate compression. + + This class allows you to compress and decompress a list of values. + + Mapping: + In addition to compression and decompression, this class maintains a mapping + between original values and their compressed counterparts using two data + structures: a dictionary `coordinate_map` and a list `reverse_map`: + - `coordinate_map`: A dictionary that maps original values to their compressed + coordinates. Keys are original values, and values are compressed coordinates. + - `reverse_map`: A list used for reverse mapping, where each index corresponds + to a compressed coordinate, and the value at that index is the original value. + + Example of mapping: + Original: 10, Compressed: 0 + Original: 52, Compressed: 1 + Original: 83, Compressed: 2 + Original: 100, Compressed: 3 + + This mapping allows for efficient compression and decompression of values within + the list. + """ + + def __init__(self, arr: list[int | float | str]) -> None: + """ + Initialize the CoordinateCompressor with a list. + + Args: + arr: The list of values to be compressed. + + >>> arr = [100, 10, 52, 83] + >>> cc = CoordinateCompressor(arr) + >>> cc.compress(100) + 3 + >>> cc.compress(52) + 1 + >>> cc.decompress(1) + 52 + """ + + # A dictionary to store compressed coordinates + self.coordinate_map: dict[int | float | str, int] = {} + + # A list to store reverse mapping + self.reverse_map: list[int | float | str] = [-1] * len(arr) + + self.arr = sorted(arr) # The input list + self.n = len(arr) # The length of the input list + self.compress_coordinates() + + def compress_coordinates(self) -> None: + """ + Compress the coordinates in the input list. + + >>> arr = [100, 10, 52, 83] + >>> cc = CoordinateCompressor(arr) + >>> cc.coordinate_map[83] + 2 + >>> cc.coordinate_map[80] # Value not in the original list + Traceback (most recent call last): + ... + KeyError: 80 + >>> cc.reverse_map[2] + 83 + """ + key = 0 + for val in self.arr: + if val not in self.coordinate_map: + self.coordinate_map[val] = key + self.reverse_map[key] = val + key += 1 + + def compress(self, original: float | str) -> int: + """ + Compress a single value. + + Args: + original: The value to compress. + + Returns: + The compressed integer, or -1 if not found in the original list. + + >>> arr = [100, 10, 52, 83] + >>> cc = CoordinateCompressor(arr) + >>> cc.compress(100) + 3 + >>> cc.compress(7) # Value not in the original list + -1 + """ + return self.coordinate_map.get(original, -1) + + def decompress(self, num: int) -> int | float | str: + """ + Decompress a single integer. + + Args: + num: The compressed integer to decompress. + + Returns: + The original value. + + >>> arr = [100, 10, 52, 83] + >>> cc = CoordinateCompressor(arr) + >>> cc.decompress(0) + 10 + >>> cc.decompress(5) # Compressed coordinate out of range + -1 + """ + return self.reverse_map[num] if 0 <= num < len(self.reverse_map) else -1 + + +if __name__ == "__main__": + from doctest import testmod + + testmod() + + arr: list[int | float | str] = [100, 10, 52, 83] + cc = CoordinateCompressor(arr) + + for original in arr: + compressed = cc.compress(original) + decompressed = cc.decompress(compressed) + print(f"Original: {decompressed}, Compressed: {compressed}") From 2fa65c7d9212514a5c8241c7636166f5758c5ff0 Mon Sep 17 00:00:00 2001 From: Shreyash Kashyap <76607993+SYK-08@users.noreply.github.com> Date: Thu, 28 Aug 2025 02:11:04 +0530 Subject: [PATCH 070/113] Improve blockchain/README.md (#9630) * Update README.md * Update blockchain/README.md Co-authored-by: Tianyi Zheng * Update blockchain/README.md Co-authored-by: Tianyi Zheng * Update blockchain/README.md Co-authored-by: Tianyi Zheng * Update blockchain/README.md Co-authored-by: Tianyi Zheng * Update blockchain/README.md Co-authored-by: Tianyi Zheng * Update blockchain/README.md Co-authored-by: Tianyi Zheng * Update README.md --------- Co-authored-by: Maxim Smolskiy Co-authored-by: Tianyi Zheng --- blockchain/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/blockchain/README.md b/blockchain/README.md index b5fab7b36eaa..ecd784fc2c7d 100644 --- a/blockchain/README.md +++ b/blockchain/README.md @@ -1,8 +1,8 @@ # Blockchain -A Blockchain is a type of **distributed ledger** technology (DLT) that consists of growing list of records, called **blocks**, that are securely linked together using **cryptography**. +A Blockchain is a type of **distributed ledger** technology (DLT) that consists of a growing list of records, called **blocks**, that are securely linked together using **cryptography**. -Let's breakdown the terminologies in the above definition. We find below terminologies, +Let's break down the terminologies in the above definition. We find below terminologies, - Digital Ledger Technology (DLT) - Blocks @@ -10,35 +10,35 @@ Let's breakdown the terminologies in the above definition. We find below termino ## Digital Ledger Technology - It is otherwise called as distributed ledger technology. It is simply the opposite of centralized database. Firstly, what is a **ledger**? A ledger is a book or collection of accounts that records account transactions. +Blockchain is also called distributed ledger technology. It is simply the opposite of a centralized database. Firstly, what is a **ledger**? A ledger is a book or collection of accounts that records account transactions. - *Why is Blockchain addressed as digital ledger if it can record more than account transactions? What other transaction details and information can it hold?* +*Why is Blockchain addressed as a digital ledger if it can record more than account transactions? What other transaction details and information can it hold?* -Digital Ledger Technology is just a ledger which is shared among multiple nodes. This way there exist no need for central authority to hold the info. Okay, how is it differentiated from central database and what are their benefits? +Digital Ledger Technology is just a ledger that is shared among multiple nodes. This way there exists no need for a central authority to hold the info. Okay, how is it differentiated from a central database and what are their benefits? -There is an organization which has 4 branches whose data are stored in a centralized database. So even if one branch needs any data from ledger they need an approval from database in charge. And if one hacks the central database he gets to tamper and control all the data. +Suppose that there is an organization that has 4 branches whose data are stored in a centralized database. So even if one branch needs any data from the ledger it needs approval from the database in charge. And if one hacks the central database he gets to tamper and control all the data. -Now lets assume every branch has a copy of the ledger and then once anything is added to the ledger by anyone branch it is gonna automatically reflect in all other ledgers available in other branch. This is done using Peer-to-peer network. +Now let's assume every branch has a copy of the ledger and then once anything is added to the ledger by any branch it is gonna automatically reflect in all other ledgers available in other branches. This is done using a peer-to-peer network. -So this means even if information is tampered in one branch we can find out. If one branch is hacked we can be alerted ,so we can safeguard other branches. Now, assume these branches as computers or nodes and the ledger is a transaction record or digital receipt. If one ledger is hacked in a node we can detect since there will be a mismatch in comparison with other node information. So this is the concept of Digital Ledger Technology. +This means that even if information is tampered with in one branch we can find out. If one branch is hacked we can be alerted, so we can safeguard other branches. Now, assume these branches as computers or nodes and the ledger is a transaction record or digital receipt. If one ledger is hacked in a node we can detect since there will be a mismatch in comparison with other node information. So this is the concept of Digital Ledger Technology. *Is it required for all nodes to have access to all information in other nodes? Wouldn't this require enormous storage space in each node?* ## Blocks -In short a block is nothing but collections of records with a labelled header. These are connected cryptographically. Once a new block is added to a chain, the previous block is connected, more precisely said as locked and hence, will remain unaltered. We can understand this concept once we get a clear understanding of working mechanism of blockchain. +In short, a block is nothing but a collection of records with a labelled header. These are connected cryptographically. Once a new block is added to a chain, the previous block is connected, more precisely said as locked, and hence will remain unaltered. We can understand this concept once we get a clear understanding of the working mechanism of blockchain. ## Cryptography -It is the practice and study of secure communication techniques in the midst of adversarial behavior. More broadly, cryptography is the creation and analysis of protocols that prevent third parties or the general public from accessing private messages. +Cryptography is the practice and study of secure communication techniques amid adversarial behavior. More broadly, cryptography is the creation and analysis of protocols that prevent third parties or the general public from accessing private messages. *Which cryptography technology is most widely used in blockchain and why?* -So, in general, blockchain technology is a distributed record holder which records the information about ownership of an asset. To define precisely, +So, in general, blockchain technology is a distributed record holder that records the information about ownership of an asset. To define precisely, > Blockchain is a distributed, immutable ledger that makes it easier to record transactions and track assets in a corporate network. An asset could be tangible (such as a house, car, cash, or land) or intangible (such as a business) (intellectual property, patents, copyrights, branding). A blockchain network can track and sell almost anything of value, lowering risk and costs for everyone involved. -So this is all about introduction to blockchain technology. To learn more about the topic refer below links.... +So this is all about the introduction to blockchain technology. To learn more about the topic refer below links.... * * * From 0c39e43af70274944e62e84708585cfd7711d2d3 Mon Sep 17 00:00:00 2001 From: Mary-0165 <146911989+Mary-0165@users.noreply.github.com> Date: Thu, 28 Aug 2025 02:25:27 +0530 Subject: [PATCH 071/113] Algorithm to find unique prime factors (#9935) * algorithm to find unique prime factors * Update prime_factors.py * Update prime_factors.py * Update prime_factors.py --------- Co-authored-by: Maxim Smolskiy --- maths/prime_factors.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/maths/prime_factors.py b/maths/prime_factors.py index 47abcf10e618..6eff57d12d17 100644 --- a/maths/prime_factors.py +++ b/maths/prime_factors.py @@ -47,6 +47,46 @@ def prime_factors(n: int) -> list[int]: return factors +def unique_prime_factors(n: int) -> list[int]: + """ + Returns unique prime factors of n as a list. + + >>> unique_prime_factors(0) + [] + >>> unique_prime_factors(100) + [2, 5] + >>> unique_prime_factors(2560) + [2, 5] + >>> unique_prime_factors(10**-2) + [] + >>> unique_prime_factors(0.02) + [] + >>> unique_prime_factors(10**241) + [2, 5] + >>> unique_prime_factors(10**-354) + [] + >>> unique_prime_factors('hello') + Traceback (most recent call last): + ... + TypeError: '<=' not supported between instances of 'int' and 'str' + >>> unique_prime_factors([1,2,'hello']) + Traceback (most recent call last): + ... + TypeError: '<=' not supported between instances of 'int' and 'list' + """ + i = 2 + factors = [] + while i * i <= n: + if not n % i: + while not n % i: + n //= i + factors.append(i) + i += 1 + if n > 1: + factors.append(n) + return factors + + if __name__ == "__main__": import doctest From e6b5d26d5c9cd23942a52c0210cee244f0aba85e Mon Sep 17 00:00:00 2001 From: architmaheshwari99 <99663695+architmaheshwari99@users.noreply.github.com> Date: Thu, 28 Aug 2025 02:37:46 +0530 Subject: [PATCH 072/113] Combination sum fix and test cases (#10193) * fixed_incorrect_test_combination_sum * reverting fn arg * ruff * Update combination_sum.py * Update combination_sum.py --------- Co-authored-by: Maxim Smolskiy --- backtracking/combination_sum.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/backtracking/combination_sum.py b/backtracking/combination_sum.py index 3c6ed81f44f0..3d954f11d2c5 100644 --- a/backtracking/combination_sum.py +++ b/backtracking/combination_sum.py @@ -47,8 +47,18 @@ def combination_sum(candidates: list, target: int) -> list: >>> combination_sum([-8, 2.3, 0], 1) Traceback (most recent call last): ... - RecursionError: maximum recursion depth exceeded + ValueError: All elements in candidates must be non-negative + >>> combination_sum([], 1) + Traceback (most recent call last): + ... + ValueError: Candidates list should not be empty """ + if not candidates: + raise ValueError("Candidates list should not be empty") + + if any(x < 0 for x in candidates): + raise ValueError("All elements in candidates must be non-negative") + path = [] # type: list[int] answer = [] # type: list[int] backtrack(candidates, path, answer, target, 0) From 84f101ca6eba4255b7780120ef772f64be437a67 Mon Sep 17 00:00:00 2001 From: Prathamesh Gadekar <93116210+Pr0-C0der@users.noreply.github.com> Date: Thu, 28 Aug 2025 03:52:12 +0530 Subject: [PATCH 073/113] Add/generate parentheses iterative approach (#10024) * Generate parantheses iterative * Generate parantheses iterative * Generating parantheses code using iterative approach * Update generate_parentheses_iterative.py * updating DIRECTORY.md * Update generate_parentheses_iterative.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update generate_parentheses_iterative.py * Update generate_parentheses_iterative.py * Update generate_parentheses_iterative.py --------- Co-authored-by: nightmare10123 Co-authored-by: Maxim Smolskiy Co-authored-by: MaximSmolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 1 + .../generate_parentheses_iterative.py | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 backtracking/generate_parentheses_iterative.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 0636ba0a7ecc..41a2d2e9af03 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -12,6 +12,7 @@ * [Combination Sum](backtracking/combination_sum.py) * [Crossword Puzzle Solver](backtracking/crossword_puzzle_solver.py) * [Generate Parentheses](backtracking/generate_parentheses.py) + * [Generate Parentheses Iterative](backtracking/generate_parentheses_iterative.py) * [Hamiltonian Cycle](backtracking/hamiltonian_cycle.py) * [Knight Tour](backtracking/knight_tour.py) * [Match Word Pattern](backtracking/match_word_pattern.py) diff --git a/backtracking/generate_parentheses_iterative.py b/backtracking/generate_parentheses_iterative.py new file mode 100644 index 000000000000..175941c7ae95 --- /dev/null +++ b/backtracking/generate_parentheses_iterative.py @@ -0,0 +1,62 @@ +def generate_parentheses_iterative(length: int) -> list: + """ + Generate all valid combinations of parentheses (Iterative Approach). + + The algorithm works as follows: + 1. Initialize an empty list to store the combinations. + 2. Initialize a stack to keep track of partial combinations. + 3. Start with empty string and push it onstack along with the counts of '(' and ')'. + 4. While the stack is not empty: + a. Pop a partial combination and its open and close counts from the stack. + b. If the combination length is equal to 2*length, add it to the result. + c. If open count < length, push new combination with added '(' on stack. + d. If close count < open count, push new combination with added ')' on stack. + 5. Return the result containing all valid combinations. + + Args: + length: The desired length of the parentheses combinations + + Returns: + A list of strings representing valid combinations of parentheses + + Time Complexity: + O(2^(2*length)) + + Space Complexity: + O(2^(2*length)) + + >>> generate_parentheses_iterative(3) + ['()()()', '()(())', '(())()', '(()())', '((()))'] + >>> generate_parentheses_iterative(2) + ['()()', '(())'] + >>> generate_parentheses_iterative(1) + ['()'] + >>> generate_parentheses_iterative(0) + [''] + """ + result = [] + stack = [] + + # Each element in stack is a tuple (current_combination, open_count, close_count) + stack.append(("", 0, 0)) + + while stack: + current_combination, open_count, close_count = stack.pop() + + if len(current_combination) == 2 * length: + result.append(current_combination) + + if open_count < length: + stack.append((current_combination + "(", open_count + 1, close_count)) + + if close_count < open_count: + stack.append((current_combination + ")", open_count, close_count + 1)) + + return result + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + print(generate_parentheses_iterative(3)) From 54aa73fdf091dfaf25f1971db443b33169d799f4 Mon Sep 17 00:00:00 2001 From: Praful Katare <47990928+Kpraful@users.noreply.github.com> Date: Thu, 28 Aug 2025 04:15:05 +0530 Subject: [PATCH 074/113] Fixes bugs in graphs/dijkstra_algorithm.py (#10092) * Fixes bug in PriorityQueue Algorithm; Fixes syntax in code for array. * Update dijkstra_algorithm.py * Update dijkstra_algorithm.py * Update dijkstra_algorithm.py * Update dijkstra_algorithm.py --------- Co-authored-by: Maxim Smolskiy --- graphs/dijkstra_algorithm.py | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/graphs/dijkstra_algorithm.py b/graphs/dijkstra_algorithm.py index 51412b790bac..60646862fca8 100644 --- a/graphs/dijkstra_algorithm.py +++ b/graphs/dijkstra_algorithm.py @@ -52,45 +52,33 @@ def min_heapify(self, idx): >>> priority_queue_test.array = [(5, 'A'), (10, 'B'), (15, 'C')] >>> priority_queue_test.min_heapify(0) - Traceback (most recent call last): - ... - TypeError: 'list' object is not callable >>> priority_queue_test.array [(5, 'A'), (10, 'B'), (15, 'C')] >>> priority_queue_test.array = [(10, 'A'), (5, 'B'), (15, 'C')] >>> priority_queue_test.min_heapify(0) - Traceback (most recent call last): - ... - TypeError: 'list' object is not callable >>> priority_queue_test.array - [(10, 'A'), (5, 'B'), (15, 'C')] + [(5, 'B'), (10, 'A'), (15, 'C')] >>> priority_queue_test.array = [(10, 'A'), (15, 'B'), (5, 'C')] >>> priority_queue_test.min_heapify(0) - Traceback (most recent call last): - ... - TypeError: 'list' object is not callable >>> priority_queue_test.array - [(10, 'A'), (15, 'B'), (5, 'C')] + [(5, 'C'), (15, 'B'), (10, 'A')] >>> priority_queue_test.array = [(10, 'A'), (5, 'B')] >>> priority_queue_test.cur_size = len(priority_queue_test.array) >>> priority_queue_test.pos = {'A': 0, 'B': 1} >>> priority_queue_test.min_heapify(0) - Traceback (most recent call last): - ... - TypeError: 'list' object is not callable >>> priority_queue_test.array - [(10, 'A'), (5, 'B')] + [(5, 'B'), (10, 'A')] """ lc = self.left(idx) rc = self.right(idx) - if lc < self.cur_size and self.array(lc)[0] < self.array[idx][0]: + if lc < self.cur_size and self.array[lc][0] < self.array[idx][0]: smallest = lc else: smallest = idx - if rc < self.cur_size and self.array(rc)[0] < self.array[smallest][0]: + if rc < self.cur_size and self.array[rc][0] < self.array[smallest][0]: smallest = rc if smallest != idx: self.swap(idx, smallest) @@ -130,12 +118,12 @@ def extract_min(self): >>> priority_queue_test.extract_min() 'C' >>> priority_queue_test.array[0] - (15, 'B') + (10, 'A') """ min_node = self.array[0][1] self.array[0] = self.array[self.cur_size - 1] self.cur_size -= 1 - self.min_heapify(1) + self.min_heapify(0) del self.pos[min_node] return min_node From 4394fd93d384cea5cc46ef61d31995ee28872cc9 Mon Sep 17 00:00:00 2001 From: __Aditya <149356523+aditya7balotra@users.noreply.github.com> Date: Fri, 29 Aug 2025 22:03:43 +0530 Subject: [PATCH 075/113] Weierstrass Method (#12877) * Add weierstrass_method for approximating complex roots - Implements Durand-Kerner (Weierstrass) method for polynomial root finding - Accepts user-defined polynomial function and degree - Uses random perturbation of complex roots of unity for initial guesses - Handles validation, overflow clipping, and includes doctest * Update weierstrass_method.py * add more tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update weierstrass_method.py * Update weierstrass_method.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../numerical_analysis/weierstrass_method.py | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 maths/numerical_analysis/weierstrass_method.py diff --git a/maths/numerical_analysis/weierstrass_method.py b/maths/numerical_analysis/weierstrass_method.py new file mode 100644 index 000000000000..b5a767af3a86 --- /dev/null +++ b/maths/numerical_analysis/weierstrass_method.py @@ -0,0 +1,97 @@ +from collections.abc import Callable + +import numpy as np + + +def weierstrass_method( + polynomial: Callable[[np.ndarray], np.ndarray], + degree: int, + roots: np.ndarray | None = None, + max_iter: int = 100, +) -> np.ndarray: + """ + Approximates all complex roots of a polynomial using the + Weierstrass (Durand-Kerner) method. + Args: + polynomial: A function that takes a NumPy array of complex numbers and returns + the polynomial values at those points. + degree: Degree of the polynomial (number of roots to find). Must be ≥ 1. + roots: Optional initial guess as a NumPy array of complex numbers. + Must have length equal to 'degree'. + If None, perturbed complex roots of unity are used. + max_iter: Number of iterations to perform (default: 100). + + Returns: + np.ndarray: Array of approximated complex roots. + + Raises: + ValueError: If degree < 1, or if initial roots length doesn't match the degree. + + Note: + - Root updates are clipped to prevent numerical overflow. + + Example: + >>> import numpy as np + >>> def check(poly, degree, expected): + ... roots = weierstrass_method(poly, degree) + ... return np.allclose(np.sort(roots), np.sort(expected)) + + >>> check( + ... lambda x: x**2 - 1, + ... 2, + ... np.array([-1, 1])) + True + + >>> check( + ... lambda x: x**3 - 4.5*x**2 + 5.75*x - 1.875, + ... 3, + ... np.array([1.5, 0.5, 2.5]) + ... ) + True + + See Also: + https://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method + """ + + if degree < 1: + raise ValueError("Degree of the polynomial must be at least 1.") + + if roots is None: + # Use perturbed complex roots of unity as initial guesses + rng = np.random.default_rng() + roots = np.array( + [ + np.exp(2j * np.pi * i / degree) * (1 + 1e-3 * rng.random()) + for i in range(degree) + ], + dtype=np.complex128, + ) + + else: + roots = np.asarray(roots, dtype=np.complex128) + if roots.shape[0] != degree: + raise ValueError( + "Length of initial roots must match the degree of the polynomial." + ) + + for _ in range(max_iter): + # Construct the product denominator for each root + denominator = np.array([root - roots for root in roots], dtype=np.complex128) + np.fill_diagonal(denominator, 1.0) # Avoid zero in diagonal + denominator = np.prod(denominator, axis=1) + + # Evaluate polynomial at each root + numerator = polynomial(roots).astype(np.complex128) + + # Compute update and clip to prevent overflow + delta = numerator / denominator + delta = np.clip(delta, -1e10, 1e10) + roots -= delta + + return roots + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 5c5057247683d5851f4d34982ea69de0d648b665 Mon Sep 17 00:00:00 2001 From: Aasheesh <126905285+AasheeshLikePanner@users.noreply.github.com> Date: Sat, 30 Aug 2025 04:47:31 +0530 Subject: [PATCH 076/113] Fixing stock_span_problem.py (#10540) * Adding doctests in simpson_rule.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update stock_span_problem.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update subset_generation.py * Update subset_generation.py * Update data_structures/stacks/stock_span_problem.py Co-authored-by: Christian Clauss * Update stock_span_problem.py * Update data_structures/stacks/stock_span_problem.py Co-authored-by: Christian Clauss * Update stock_span_problem.py * Update stock_span_problem.py * updating DIRECTORY.md * Update stock_span_problem.py * Update stock_span_problem.py * Update stock_span_problem.py * Update stock_span_problem.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: Maxim Smolskiy Co-authored-by: MaximSmolskiy --- DIRECTORY.md | 1 + data_structures/stacks/stock_span_problem.py | 34 ++++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 41a2d2e9af03..2df9d56e99b7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -725,6 +725,7 @@ * [Secant Method](maths/numerical_analysis/secant_method.py) * [Simpson Rule](maths/numerical_analysis/simpson_rule.py) * [Square Root](maths/numerical_analysis/square_root.py) + * [Weierstrass Method](maths/numerical_analysis/weierstrass_method.py) * [Odd Sieve](maths/odd_sieve.py) * [Perfect Cube](maths/perfect_cube.py) * [Perfect Number](maths/perfect_number.py) diff --git a/data_structures/stacks/stock_span_problem.py b/data_structures/stacks/stock_span_problem.py index 5efe58d25798..74c2636784e2 100644 --- a/data_structures/stacks/stock_span_problem.py +++ b/data_structures/stacks/stock_span_problem.py @@ -8,8 +8,29 @@ """ -def calculation_span(price, s): +def calculate_span(price: list[int]) -> list[int]: + """ + Calculate the span values for a given list of stock prices. + Args: + price: List of stock prices. + Returns: + List of span values. + + >>> calculate_span([10, 4, 5, 90, 120, 80]) + [1, 1, 2, 4, 5, 1] + >>> calculate_span([100, 50, 60, 70, 80, 90]) + [1, 1, 2, 3, 4, 5] + >>> calculate_span([5, 4, 3, 2, 1]) + [1, 1, 1, 1, 1] + >>> calculate_span([1, 2, 3, 4, 5]) + [1, 2, 3, 4, 5] + >>> calculate_span([10, 20, 30, 40, 50]) + [1, 2, 3, 4, 5] + >>> calculate_span([100, 80, 60, 70, 60, 75, 85]) + [1, 1, 1, 2, 1, 4, 6] + """ n = len(price) + s = [0] * n # Create a stack and push index of fist element to it st = [] st.append(0) @@ -21,18 +42,20 @@ def calculation_span(price, s): for i in range(1, n): # Pop elements from stack while stack is not # empty and top of stack is smaller than price[i] - while len(st) > 0 and price[st[0]] <= price[i]: + while len(st) > 0 and price[st[-1]] <= price[i]: st.pop() # If stack becomes empty, then price[i] is greater # than all elements on left of it, i.e. price[0], # price[1], ..price[i-1]. Else the price[i] is # greater than elements after top of stack - s[i] = i + 1 if len(st) <= 0 else (i - st[0]) + s[i] = i + 1 if len(st) <= 0 else (i - st[-1]) # Push this element to stack st.append(i) + return s + # A utility function to print elements of array def print_array(arr, n): @@ -42,10 +65,9 @@ def print_array(arr, n): # Driver program to test above function price = [10, 4, 5, 90, 120, 80] -S = [0 for i in range(len(price) + 1)] -# Fill the span values in array S[] -calculation_span(price, S) +# Calculate the span values +S = calculate_span(price) # Print the calculated span values print_array(S, len(price)) From 488f143b8c8b9d1528c2decdc9135d2c749a7a69 Mon Sep 17 00:00:00 2001 From: Venkata Ramana Menda <115451367+RamanaMenda@users.noreply.github.com> Date: Sat, 30 Aug 2025 05:46:21 +0530 Subject: [PATCH 077/113] Performance: 25% faster Project Euler 73 #10503 (#11553) * Seperate slow_solution and solution * Add performance benchmark * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix issues * Update sol1.py * Update sol1.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- project_euler/problem_073/sol1.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/project_euler/problem_073/sol1.py b/project_euler/problem_073/sol1.py index 2b66b7d8769b..c39110252ccd 100644 --- a/project_euler/problem_073/sol1.py +++ b/project_euler/problem_073/sol1.py @@ -36,7 +36,12 @@ def solution(max_d: int = 12_000) -> int: fractions_number = 0 for d in range(max_d + 1): - for n in range(d // 3 + 1, (d + 1) // 2): + n_start = d // 3 + 1 + n_step = 1 + if d % 2 == 0: + n_start += 1 - n_start % 2 + n_step = 2 + for n in range(n_start, (d + 1) // 2, n_step): if gcd(n, d) == 1: fractions_number += 1 return fractions_number From c5de3954ccefaeae76b9ebaca045a396619a6761 Mon Sep 17 00:00:00 2001 From: Sohail khan <62786136+byteninjaa0@users.noreply.github.com> Date: Sat, 30 Aug 2025 05:58:38 +0530 Subject: [PATCH 078/113] Add new test for bucket sort algorithm in sorts/bucket_sort.py (#11605) * Add new test for bucket sort algorithm in sorts/bucket_sort.py * Update fractional_knapsack.py * Update matrix_class.py * Update bucket_sort.py * Update bucket_sort.py --------- Co-authored-by: Maxim Smolskiy --- sorts/bucket_sort.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sorts/bucket_sort.py b/sorts/bucket_sort.py index 1c1320a58a7d..893c7ff3a23a 100644 --- a/sorts/bucket_sort.py +++ b/sorts/bucket_sort.py @@ -51,12 +51,35 @@ def bucket_sort(my_list: list, bucket_count: int = 10) -> list: >>> collection = random.sample(range(-50, 50), 50) >>> bucket_sort(collection) == sorted(collection) True + >>> data = [1, 2, 2, 1, 1, 3] + >>> bucket_sort(data) == sorted(data) + True + >>> data = [5, 5, 5, 5, 5] + >>> bucket_sort(data) == sorted(data) + True + >>> data = [1000, -1000, 500, -500, 0] + >>> bucket_sort(data) == sorted(data) + True + >>> data = [5.5, 2.2, -1.1, 3.3, 0.0] + >>> bucket_sort(data) == sorted(data) + True + >>> bucket_sort([1]) == [1] + True + >>> data = [-1.1, -1.5, -3.4, 2.5, 3.6, -3.3] + >>> bucket_sort(data) == sorted(data) + True + >>> data = [9, 2, 7, 1, 5] + >>> bucket_sort(data) == sorted(data) + True """ if len(my_list) == 0 or bucket_count <= 0: return [] min_value, max_value = min(my_list), max(my_list) + if min_value == max_value: + return my_list + bucket_size = (max_value - min_value) / bucket_count buckets: list[list] = [[] for _ in range(bucket_count)] @@ -73,3 +96,6 @@ def bucket_sort(my_list: list, bucket_count: int = 10) -> list: testmod() assert bucket_sort([4, 5, 3, 2, 1]) == [1, 2, 3, 4, 5] assert bucket_sort([0, 1, -10, 15, 2, -2]) == [-10, -2, 0, 1, 2, 15] + assert bucket_sort([1.1, 1.2, -1.2, 0, 2.4]) == [-1.2, 0, 1.1, 1.2, 2.4] + assert bucket_sort([5, 5, 5, 5, 5]) == [5, 5, 5, 5, 5] + assert bucket_sort([-5, -1, -6, -2]) == [-6, -5, -2, -1] From 1e0d3173fa4566bc03fbc207168225d948153bb6 Mon Sep 17 00:00:00 2001 From: Abhijit Kumar Singh Date: Sat, 30 Aug 2025 06:07:13 +0530 Subject: [PATCH 079/113] Specify space complexity for merge sort (#11749) * Added space complexity Space complexity of merge sort is a key factor, when compared to quick sort * Update merge_sort.py --------- Co-authored-by: Maxim Smolskiy --- sorts/merge_sort.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sorts/merge_sort.py b/sorts/merge_sort.py index 0628b848b794..11c202788035 100644 --- a/sorts/merge_sort.py +++ b/sorts/merge_sort.py @@ -18,6 +18,7 @@ def merge_sort(collection: list) -> list: :return: The same collection ordered in ascending order. Time Complexity: O(n log n) + Space Complexity: O(n) Examples: >>> merge_sort([0, 5, 3, 2, 2]) From b0920454ccae10414aed0cb7ed4ccc60930f341b Mon Sep 17 00:00:00 2001 From: Ronald Ngounou <74538524+ronaldngounou@users.noreply.github.com> Date: Sat, 30 Aug 2025 01:49:44 -0700 Subject: [PATCH 080/113] Add unit tests to binary_tree_path_sum.py (#11833) * test: Add unit tests * test: Add successful tests in binaree_tree_path_sum * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update binary_tree_path_sum.py * Update binary_tree_path_sum.py * Update binary_tree_path_sum.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- .../binary_tree/binary_tree_path_sum.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/data_structures/binary_tree/binary_tree_path_sum.py b/data_structures/binary_tree/binary_tree_path_sum.py index a3fe9ca7a7e2..8477690c777a 100644 --- a/data_structures/binary_tree/binary_tree_path_sum.py +++ b/data_structures/binary_tree/binary_tree_path_sum.py @@ -50,6 +50,26 @@ class BinaryTreePathSum: >>> tree.right.right = Node(10) >>> BinaryTreePathSum().path_sum(tree, 8) 2 + >>> BinaryTreePathSum().path_sum(None, 0) + 0 + >>> BinaryTreePathSum().path_sum(tree, 0) + 0 + + The second tree looks like this + 0 + / \ + 5 5 + + >>> tree2 = Node(0) + >>> tree2.left = Node(5) + >>> tree2.right = Node(5) + + >>> BinaryTreePathSum().path_sum(tree2, 5) + 4 + >>> BinaryTreePathSum().path_sum(tree2, -1) + 0 + >>> BinaryTreePathSum().path_sum(tree2, 0) + 1 """ target: int From 501576f90e97de5eedffc7d7196a5fb1fa751028 Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Sat, 30 Aug 2025 15:41:57 +0530 Subject: [PATCH 081/113] Update README.md (#12345) * Update README.md Add emojis for enhanced visual appeal and readability in README . * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update README.md * Update README.md * Update README.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fe65bb253360..182d36a8d905 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@

The Algorithms - Python

+ @@ -19,6 +20,7 @@ Gitter chat +
@@ -30,20 +32,21 @@ code style: black + -

All algorithms implemented in Python - for education

+

All algorithms implemented in Python - for education 📚

Implementations are for learning purposes only. They may be less efficient than the implementations in the Python standard library. Use them at your discretion. -## Getting Started +## 🚀 Getting Started -Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribute. +📋 Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribute. -## Community Channels +## 🌐 Community Channels We are on [Discord](https://the-algorithms.com/discord) and [Gitter](https://gitter.im/TheAlgorithms/community)! Community channels are a great way for you to ask questions and get help. Please join us! -## List of Algorithms +## 📜 List of Algorithms See our [directory](DIRECTORY.md) for easier navigation and a better overview of the project. From e3a263c1ed4ed1efdf5682714b1493f28d926760 Mon Sep 17 00:00:00 2001 From: lorenzo30salgado <79310171+lorenzo30salgado@users.noreply.github.com> Date: Sat, 30 Aug 2025 22:58:54 +0200 Subject: [PATCH 082/113] Adding a 3D plot to the k-means clustering algorithm (#12372) * Adding a 3D plot to the k-means clustering algorithm * Update k_means_clust.py * Update k_means_clust.py --------- Co-authored-by: Maxim Smolskiy --- machine_learning/k_means_clust.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/machine_learning/k_means_clust.py b/machine_learning/k_means_clust.py index a926362fc18b..a55153628f9c 100644 --- a/machine_learning/k_means_clust.py +++ b/machine_learning/k_means_clust.py @@ -37,7 +37,13 @@ heterogeneity, k ) - 5. Transfers Dataframe into excel format it must have feature called + 5. Plot the labeled 3D data points with centroids. + plot_kmeans( + X, + centroids, + cluster_assignment + ) + 6. Transfers Dataframe into excel format it must have feature called 'Clust' with k means clustering numbers in it. """ @@ -126,6 +132,19 @@ def plot_heterogeneity(heterogeneity, k): plt.show() +def plot_kmeans(data, centroids, cluster_assignment): + ax = plt.axes(projection="3d") + ax.scatter(data[:, 0], data[:, 1], data[:, 2], c=cluster_assignment, cmap="viridis") + ax.scatter( + centroids[:, 0], centroids[:, 1], centroids[:, 2], c="red", s=100, marker="x" + ) + ax.set_xlabel("X") + ax.set_ylabel("Y") + ax.set_zlabel("Z") + ax.set_title("3D K-Means Clustering Visualization") + plt.show() + + def kmeans( data, k, initial_centroids, maxiter=500, record_heterogeneity=None, verbose=False ): @@ -193,6 +212,7 @@ def kmeans( verbose=True, ) plot_heterogeneity(heterogeneity, k) + plot_kmeans(dataset["data"], centroids, cluster_assignment) def report_generator( From 9d52683ecbca6b8dcfa90a2e286d39b66ce5ffef Mon Sep 17 00:00:00 2001 From: ANANT JAIN <139585700+anant-jain01@users.noreply.github.com> Date: Sun, 31 Aug 2025 03:47:55 +0530 Subject: [PATCH 083/113] Create stalin_sort.py (#11989) * Create stalin_sort.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update stalin_sort.py * updating DIRECTORY.md * Update stalin_sort.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy Co-authored-by: MaximSmolskiy --- DIRECTORY.md | 1 + sorts/stalin_sort.py | 47 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 sorts/stalin_sort.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 2df9d56e99b7..36acb3b97f1e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1301,6 +1301,7 @@ * [Shell Sort](sorts/shell_sort.py) * [Shrink Shell Sort](sorts/shrink_shell_sort.py) * [Slowsort](sorts/slowsort.py) + * [Stalin Sort](sorts/stalin_sort.py) * [Stooge Sort](sorts/stooge_sort.py) * [Strand Sort](sorts/strand_sort.py) * [Tim Sort](sorts/tim_sort.py) diff --git a/sorts/stalin_sort.py b/sorts/stalin_sort.py new file mode 100644 index 000000000000..6dd5708c7f01 --- /dev/null +++ b/sorts/stalin_sort.py @@ -0,0 +1,47 @@ +""" +Stalin Sort algorithm: Removes elements that are out of order. +Elements that are not greater than or equal to the previous element are discarded. +Reference: https://medium.com/@kaweendra/the-ultimate-sorting-algorithm-6513d6968420 +""" + + +def stalin_sort(sequence: list[int]) -> list[int]: + """ + Sorts a list using the Stalin sort algorithm. + + >>> stalin_sort([4, 3, 5, 2, 1, 7]) + [4, 5, 7] + + >>> stalin_sort([1, 2, 3, 4]) + [1, 2, 3, 4] + + >>> stalin_sort([4, 5, 5, 2, 3]) + [4, 5, 5] + + >>> stalin_sort([6, 11, 12, 4, 1, 5]) + [6, 11, 12] + + >>> stalin_sort([5, 0, 4, 3]) + [5] + + >>> stalin_sort([5, 4, 3, 2, 1]) + [5] + + >>> stalin_sort([1, 2, 3, 4, 5]) + [1, 2, 3, 4, 5] + + >>> stalin_sort([1, 2, 8, 7, 6]) + [1, 2, 8] + """ + result = [sequence[0]] + for element in sequence[1:]: + if element >= result[-1]: + result.append(element) + + return result + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 0876a87186516f93c8d53ee69a600630905984a9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 20:33:56 +0200 Subject: [PATCH 084/113] [pre-commit.ci] pre-commit autoupdate (#12944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.10 → v0.12.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.10...v0.12.11) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6eb0906fb23a..f60913a743ad 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.10 + rev: v0.12.11 hooks: - id: ruff-check - id: ruff-format From 544f48ff34492eba4cf452fca3eba7bdff1cda5c Mon Sep 17 00:00:00 2001 From: hema_ameh <152301559+PYDIMARRI-HEMA-HARSHINI-23-586@users.noreply.github.com> Date: Thu, 4 Sep 2025 06:19:59 +0530 Subject: [PATCH 085/113] Fix is_palindrome_recursive logic in strings/palindrome.py (#12946) * Fix: is_palindrome_recursive logic for 2-char strings * Update palindrome.py * Update palindrome.py * Update palindrome.py --------- Co-authored-by: Maxim Smolskiy --- strings/palindrome.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/strings/palindrome.py b/strings/palindrome.py index bfdb3ddcf396..e765207e5942 100644 --- a/strings/palindrome.py +++ b/strings/palindrome.py @@ -11,6 +11,8 @@ "BB": True, "ABC": False, "amanaplanacanalpanama": True, # "a man a plan a canal panama" + "abcdba": False, + "AB": False, } # Ensure our test data is valid assert all((key == key[::-1]) is value for key, value in test_data.items()) @@ -61,7 +63,7 @@ def is_palindrome_recursive(s: str) -> bool: >>> all(is_palindrome_recursive(key) is value for key, value in test_data.items()) True """ - if len(s) <= 2: + if len(s) <= 1: return True if s[0] == s[len(s) - 1]: return is_palindrome_recursive(s[1:-1]) From 4ce1185f9e92ecea6805c8ee77404a56d8f70ea9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 08:23:36 +0200 Subject: [PATCH 086/113] Bump actions/setup-python from 5 to 6 (#12952) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/directory_writer.yml | 2 +- .github/workflows/project_euler.yml | 4 ++-- .github/workflows/sphinx.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 69192db0c4c6..731e3fad3b85 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: with: enable-cache: true cache-dependency-glob: uv.lock - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: 3.x allow-prereleases: true diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml index f5167f8d1a58..9a4682677c00 100644 --- a/.github/workflows/directory_writer.yml +++ b/.github/workflows/directory_writer.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v5 with: fetch-depth: 0 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: 3.x - name: Write DIRECTORY.md diff --git a/.github/workflows/project_euler.yml b/.github/workflows/project_euler.yml index 8b8cb2a1e68f..f52ff280b29a 100644 --- a/.github/workflows/project_euler.yml +++ b/.github/workflows/project_euler.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: 3.x - run: uv sync --group=euler-validate --group=test @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: 3.x - run: uv sync --group=euler-validate --group=test diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index e28fa04f3ab4..bd253dc3de65 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -27,7 +27,7 @@ jobs: steps: - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: 3.13 allow-prereleases: true From 8f1a6b0ca0cbe563ea3f48c43695a07959b923a1 Mon Sep 17 00:00:00 2001 From: Juan Dupierris Date: Mon, 8 Sep 2025 01:41:07 +0200 Subject: [PATCH 087/113] Adding the function is_proth_number (#12399) * Adding the function isProthNumber(n : int) which returns true if n is a Proth number * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixing the issues of the isprothnumber function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * New fixes on isprothnumber() * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes on isprothnumber() * Fixes on isprothnumber * Fixes on isprothnumber() * Fixes on isprothnumber * Update proth_number.py * Update proth_number.py * Update proth_number.py * Update proth_number.py * Update proth_number.py * Update proth_number.py * Update proth_number.py * Update proth_number.py --------- Co-authored-by: Juanitoupipou Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- maths/special_numbers/proth_number.py | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/maths/special_numbers/proth_number.py b/maths/special_numbers/proth_number.py index 47747ed260f7..b9b827b6a5a2 100644 --- a/maths/special_numbers/proth_number.py +++ b/maths/special_numbers/proth_number.py @@ -59,6 +59,50 @@ def proth(number: int) -> int: return proth_list[number - 1] +def is_proth_number(number: int) -> bool: + """ + :param number: positive integer number + :return: true if number is a Proth number, false otherwise + >>> is_proth_number(1) + False + >>> is_proth_number(2) + False + >>> is_proth_number(3) + True + >>> is_proth_number(4) + False + >>> is_proth_number(5) + True + >>> is_proth_number(34) + False + >>> is_proth_number(-1) + Traceback (most recent call last): + ... + ValueError: Input value of [number=-1] must be > 0 + >>> is_proth_number(6.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=6.0] must be an integer + """ + if not isinstance(number, int): + message = f"Input value of [{number=}] must be an integer" + raise TypeError(message) + + if number <= 0: + message = f"Input value of [{number=}] must be > 0" + raise ValueError(message) + + if number == 1: + return False + + number -= 1 + n = 0 + while number % 2 == 0: + n += 1 + number //= 2 + return number < 2**n + + if __name__ == "__main__": import doctest @@ -73,3 +117,9 @@ def proth(number: int) -> int: continue print(f"The {number}th Proth number: {value}") + + for number in [1, 2, 3, 4, 5, 9, 13, 49, 57, 193, 241, 163, 201]: + if is_proth_number(number): + print(f"{number} is a Proth number") + else: + print(f"{number} is not a Proth number") From 18c853d301eb03ca2ba829250c3d415485e49d8b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 20:46:04 +0200 Subject: [PATCH 088/113] [pre-commit.ci] pre-commit autoupdate (#12961) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.11 → v0.12.12](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.11...v0.12.12) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f60913a743ad..c30442a2a6f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.11 + rev: v0.12.12 hooks: - id: ruff-check - id: ruff-format From 63180d7e243a95ce28c2b52abcd7c81c452f623f Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 13 Sep 2025 00:56:14 +0200 Subject: [PATCH 089/113] pre-commit autoupdate 2025-09-11 (#12963) * pre-commit autoupdate 2025-09-11 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- data_structures/arrays/sudoku_solver.py | 2 +- data_structures/trie/radix_tree.py | 4 ++-- graphs/graph_adjacency_list.py | 10 +++++----- graphs/graph_adjacency_matrix.py | 10 +++++----- knapsack/tests/test_greedy_knapsack.py | 12 +++++++----- linear_algebra/gaussian_elimination.py | 2 +- linear_algebra/jacobi_iteration_method.py | 4 ++-- machine_learning/polynomial_regression.py | 2 +- machine_learning/principle_component_analysis.py | 2 +- maths/chinese_remainder_theorem.py | 2 +- maths/modular_division.py | 4 ++-- neural_network/convolution_neural_network.py | 4 ++-- project_euler/problem_551/sol1.py | 2 +- pyproject.toml | 1 - scheduling/multi_level_feedback_queue.py | 2 +- 16 files changed, 33 insertions(+), 32 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c30442a2a6f6..4af51c08d8a4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.12 + rev: v0.13.0 hooks: - id: ruff-check - id: ruff-format diff --git a/data_structures/arrays/sudoku_solver.py b/data_structures/arrays/sudoku_solver.py index 4c722f12fd6e..07269e2a69cc 100644 --- a/data_structures/arrays/sudoku_solver.py +++ b/data_structures/arrays/sudoku_solver.py @@ -149,7 +149,7 @@ def search(values): if all(len(values[s]) == 1 for s in squares): return values ## Solved! ## Chose the unfilled square s with the fewest possibilities - n, s = min((len(values[s]), s) for s in squares if len(values[s]) > 1) + _n, s = min((len(values[s]), s) for s in squares if len(values[s]) > 1) return some(search(assign(values.copy(), s, d)) for d in values[s]) diff --git a/data_structures/trie/radix_tree.py b/data_structures/trie/radix_tree.py index caf566a6ce30..bd2306befa79 100644 --- a/data_structures/trie/radix_tree.py +++ b/data_structures/trie/radix_tree.py @@ -115,7 +115,7 @@ def find(self, word: str) -> bool: if not incoming_node: return False else: - matching_string, remaining_prefix, remaining_word = incoming_node.match( + _matching_string, remaining_prefix, remaining_word = incoming_node.match( word ) # If there is remaining prefix, the word can't be on the tree @@ -144,7 +144,7 @@ def delete(self, word: str) -> bool: if not incoming_node: return False else: - matching_string, remaining_prefix, remaining_word = incoming_node.match( + _matching_string, remaining_prefix, remaining_word = incoming_node.match( word ) # If there is remaining prefix, the word can't be on the tree diff --git a/graphs/graph_adjacency_list.py b/graphs/graph_adjacency_list.py index 244e59e0e1bf..c901e2cf3dac 100644 --- a/graphs/graph_adjacency_list.py +++ b/graphs/graph_adjacency_list.py @@ -448,7 +448,7 @@ def test_remove_edge(self) -> None: ( undirected_graph, directed_graph, - random_vertices, + _random_vertices, random_edges, ) = self.__generate_graphs(20, 0, 100, 4) @@ -502,7 +502,7 @@ def test_add_vertex_exception_check(self) -> None: undirected_graph, directed_graph, random_vertices, - random_edges, + _random_edges, ) = self.__generate_graphs(20, 0, 100, 4) for vertex in random_vertices: @@ -516,7 +516,7 @@ def test_remove_vertex_exception_check(self) -> None: undirected_graph, directed_graph, random_vertices, - random_edges, + _random_edges, ) = self.__generate_graphs(20, 0, 100, 4) for i in range(101): @@ -530,7 +530,7 @@ def test_add_edge_exception_check(self) -> None: ( undirected_graph, directed_graph, - random_vertices, + _random_vertices, random_edges, ) = self.__generate_graphs(20, 0, 100, 4) @@ -569,7 +569,7 @@ def test_contains_edge_exception_check(self) -> None: undirected_graph, directed_graph, random_vertices, - random_edges, + _random_edges, ) = self.__generate_graphs(20, 0, 100, 4) for vertex in random_vertices: diff --git a/graphs/graph_adjacency_matrix.py b/graphs/graph_adjacency_matrix.py index 8eeeae786513..6dca0fbbcf05 100644 --- a/graphs/graph_adjacency_matrix.py +++ b/graphs/graph_adjacency_matrix.py @@ -469,7 +469,7 @@ def test_remove_edge(self) -> None: ( undirected_graph, directed_graph, - random_vertices, + _random_vertices, random_edges, ) = self.__generate_graphs(20, 0, 100, 4) @@ -523,7 +523,7 @@ def test_add_vertex_exception_check(self) -> None: undirected_graph, directed_graph, random_vertices, - random_edges, + _random_edges, ) = self.__generate_graphs(20, 0, 100, 4) for vertex in random_vertices: @@ -537,7 +537,7 @@ def test_remove_vertex_exception_check(self) -> None: undirected_graph, directed_graph, random_vertices, - random_edges, + _random_edges, ) = self.__generate_graphs(20, 0, 100, 4) for i in range(101): @@ -551,7 +551,7 @@ def test_add_edge_exception_check(self) -> None: ( undirected_graph, directed_graph, - random_vertices, + _random_vertices, random_edges, ) = self.__generate_graphs(20, 0, 100, 4) @@ -590,7 +590,7 @@ def test_contains_edge_exception_check(self) -> None: undirected_graph, directed_graph, random_vertices, - random_edges, + _random_edges, ) = self.__generate_graphs(20, 0, 100, 4) for vertex in random_vertices: diff --git a/knapsack/tests/test_greedy_knapsack.py b/knapsack/tests/test_greedy_knapsack.py index e6a40084109e..7ebaddd3c99e 100644 --- a/knapsack/tests/test_greedy_knapsack.py +++ b/knapsack/tests/test_greedy_knapsack.py @@ -28,7 +28,7 @@ def test_negative_max_weight(self): # profit = [10, 20, 30, 40, 50, 60] # weight = [2, 4, 6, 8, 10, 12] # max_weight = -15 - pytest.raises(ValueError, match="max_weight must greater than zero.") + pytest.raises(ValueError, match=r"max_weight must greater than zero.") def test_negative_profit_value(self): """ @@ -38,7 +38,7 @@ def test_negative_profit_value(self): # profit = [10, -20, 30, 40, 50, 60] # weight = [2, 4, 6, 8, 10, 12] # max_weight = 15 - pytest.raises(ValueError, match="Weight can not be negative.") + pytest.raises(ValueError, match=r"Weight can not be negative.") def test_negative_weight_value(self): """ @@ -48,7 +48,7 @@ def test_negative_weight_value(self): # profit = [10, 20, 30, 40, 50, 60] # weight = [2, -4, 6, -8, 10, 12] # max_weight = 15 - pytest.raises(ValueError, match="Profit can not be negative.") + pytest.raises(ValueError, match=r"Profit can not be negative.") def test_null_max_weight(self): """ @@ -58,7 +58,7 @@ def test_null_max_weight(self): # profit = [10, 20, 30, 40, 50, 60] # weight = [2, 4, 6, 8, 10, 12] # max_weight = null - pytest.raises(ValueError, match="max_weight must greater than zero.") + pytest.raises(ValueError, match=r"max_weight must greater than zero.") def test_unequal_list_length(self): """ @@ -68,7 +68,9 @@ def test_unequal_list_length(self): # profit = [10, 20, 30, 40, 50] # weight = [2, 4, 6, 8, 10, 12] # max_weight = 100 - pytest.raises(IndexError, match="The length of profit and weight must be same.") + pytest.raises( + IndexError, match=r"The length of profit and weight must be same." + ) if __name__ == "__main__": diff --git a/linear_algebra/gaussian_elimination.py b/linear_algebra/gaussian_elimination.py index 6f4075b710fd..cf816940b0d1 100644 --- a/linear_algebra/gaussian_elimination.py +++ b/linear_algebra/gaussian_elimination.py @@ -33,7 +33,7 @@ def retroactive_resolution( [ 0.5]]) """ - rows, columns = np.shape(coefficients) + rows, _columns = np.shape(coefficients) x: NDArray[float64] = np.zeros((rows, 1), dtype=float) for row in reversed(range(rows)): diff --git a/linear_algebra/jacobi_iteration_method.py b/linear_algebra/jacobi_iteration_method.py index 2cc9c103018b..0f9fcde7af6c 100644 --- a/linear_algebra/jacobi_iteration_method.py +++ b/linear_algebra/jacobi_iteration_method.py @@ -112,7 +112,7 @@ def jacobi_iteration_method( (coefficient_matrix, constant_matrix), axis=1 ) - rows, cols = table.shape + rows, _cols = table.shape strictly_diagonally_dominant(table) @@ -149,7 +149,7 @@ def jacobi_iteration_method( # Here we get 'i_col' - these are the column numbers, for each row # without diagonal elements, except for the last column. - i_row, i_col = np.where(masks) + _i_row, i_col = np.where(masks) ind = i_col.reshape(-1, rows - 1) #'i_col' is converted to a two-dimensional list 'ind', which will be diff --git a/machine_learning/polynomial_regression.py b/machine_learning/polynomial_regression.py index 212f40bea197..f52177df1292 100644 --- a/machine_learning/polynomial_regression.py +++ b/machine_learning/polynomial_regression.py @@ -93,7 +93,7 @@ def _design_matrix(data: np.ndarray, degree: int) -> np.ndarray: ... ValueError: Data must have dimensions N x 1 """ - rows, *remaining = data.shape + _rows, *remaining = data.shape if remaining: raise ValueError("Data must have dimensions N x 1") diff --git a/machine_learning/principle_component_analysis.py b/machine_learning/principle_component_analysis.py index 46ccdb968494..174500d89620 100644 --- a/machine_learning/principle_component_analysis.py +++ b/machine_learning/principle_component_analysis.py @@ -65,7 +65,7 @@ def main() -> None: """ Driver function to execute PCA and display results. """ - data_x, data_y = collect_dataset() + data_x, _data_y = collect_dataset() # Number of principal components to retain n_components = 2 diff --git a/maths/chinese_remainder_theorem.py b/maths/chinese_remainder_theorem.py index 18af63d106e8..b7a7712ae917 100644 --- a/maths/chinese_remainder_theorem.py +++ b/maths/chinese_remainder_theorem.py @@ -65,7 +65,7 @@ def invert_modulo(a: int, n: int) -> int: 1 """ - (b, x) = extended_euclid(a, n) + (b, _x) = extended_euclid(a, n) if b < 0: b = (b % n + n) % n return b diff --git a/maths/modular_division.py b/maths/modular_division.py index 2f8f4479b27d..94f12b3e096e 100644 --- a/maths/modular_division.py +++ b/maths/modular_division.py @@ -31,7 +31,7 @@ def modular_division(a: int, b: int, n: int) -> int: assert n > 1 assert a > 0 assert greatest_common_divisor(a, n) == 1 - (d, t, s) = extended_gcd(n, a) # Implemented below + (_d, _t, s) = extended_gcd(n, a) # Implemented below x = (b * s) % n return x @@ -47,7 +47,7 @@ def invert_modulo(a: int, n: int) -> int: 1 """ - (b, x) = extended_euclid(a, n) # Implemented below + (b, _x) = extended_euclid(a, n) # Implemented below if b < 0: b = (b % n + n) % n return b diff --git a/neural_network/convolution_neural_network.py b/neural_network/convolution_neural_network.py index d4ac360a98de..6b1aa50c7981 100644 --- a/neural_network/convolution_neural_network.py +++ b/neural_network/convolution_neural_network.py @@ -317,7 +317,7 @@ def predict(self, datas_test): print((" - - Shape: Test_Data ", np.shape(datas_test))) for p in range(len(datas_test)): data_test = np.asmatrix(datas_test[p]) - data_focus1, data_conved1 = self.convolute( + _data_focus1, data_conved1 = self.convolute( data_test, self.conv1, self.w_conv1, @@ -339,7 +339,7 @@ def predict(self, datas_test): def convolution(self, data): # return the data of image after convoluting process so we can check it out data_test = np.asmatrix(data) - data_focus1, data_conved1 = self.convolute( + _data_focus1, data_conved1 = self.convolute( data_test, self.conv1, self.w_conv1, diff --git a/project_euler/problem_551/sol1.py b/project_euler/problem_551/sol1.py index 100e9d41dd31..e13cf77a776d 100644 --- a/project_euler/problem_551/sol1.py +++ b/project_euler/problem_551/sol1.py @@ -185,7 +185,7 @@ def solution(n: int = 10**15) -> int: i = 1 dn = 0 while True: - diff, terms_jumped = next_term(digits, 20, i + dn, n) + _diff, terms_jumped = next_term(digits, 20, i + dn, n) dn += terms_jumped if dn == n - i: break diff --git a/pyproject.toml b/pyproject.toml index b680cc0d439e..71eb730f1329 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -124,7 +124,6 @@ lint.ignore = [ "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 "SLF001", # Private member accessed: `_Iterator` -- FIX ME - "UP038", # Use `X | Y` in `{}` call instead of `(X, Y)` -- DO NOT FIX ] lint.per-file-ignores."data_structures/hashing/tests/test_hash_map.py" = [ diff --git a/scheduling/multi_level_feedback_queue.py b/scheduling/multi_level_feedback_queue.py index abee3c85c5a5..58ba2afa0e67 100644 --- a/scheduling/multi_level_feedback_queue.py +++ b/scheduling/multi_level_feedback_queue.py @@ -255,7 +255,7 @@ def multi_level_feedback_queue(self) -> deque[Process]: # all queues except last one have round_robin algorithm for i in range(self.number_of_queues - 1): - finished, self.ready_queue = self.round_robin( + _finished, self.ready_queue = self.round_robin( self.ready_queue, self.time_slices[i] ) # the last queue has first_come_first_served algorithm From 0ee534edde76462eeace007afdba3c6a4d43dbf0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 20:17:29 +0200 Subject: [PATCH 090/113] [pre-commit.ci] pre-commit autoupdate (#12969) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.17.1 → v1.18.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.17.1...v1.18.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4af51c08d8a4..9fbeb9a08682 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,7 +47,7 @@ repos: - id: validate-pyproject - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.17.1 + rev: v1.18.1 hooks: - id: mypy args: From 4ec71a303b4794d5c702c50e1c64b9175ed72b71 Mon Sep 17 00:00:00 2001 From: lighting9999 Date: Thu, 18 Sep 2025 21:55:59 +0800 Subject: [PATCH 091/113] fix covid_stats_via_xpath.py (#12975) * fix covid_stats_via_xpath.py Improve error handling. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix covid_stats_via_xpath.py typo * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix ruff * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * upgrade covid_stats_via_xpath.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and fix covid_stats_via_xpath.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- web_programming/covid_stats_via_xpath.py | 44 +++++++++++++++++------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/web_programming/covid_stats_via_xpath.py b/web_programming/covid_stats_via_xpath.py index 9c016ba414ea..88a248610441 100644 --- a/web_programming/covid_stats_via_xpath.py +++ b/web_programming/covid_stats_via_xpath.py @@ -1,7 +1,8 @@ """ -This is to show simple COVID19 info fetching from worldometers archive site using lxml -* The main motivation to use lxml in place of bs4 is that it is faster and therefore -more convenient to use in Python web projects (e.g. Django or Flask-based) +This script demonstrates fetching simple COVID-19 statistics from the +Worldometers archive site using lxml. lxml is chosen over BeautifulSoup +for its speed and convenience in Python web projects (such as Django or +Flask). """ # /// script @@ -25,15 +26,34 @@ class CovidData(NamedTuple): def covid_stats( - url: str = "https://web.archive.org/web/20250825095350/https://www.worldometers.info/coronavirus/", + url: str = ( + "https://web.archive.org/web/20250825095350/" + "https://www.worldometers.info/coronavirus/" + ), ) -> CovidData: xpath_str = '//div[@class = "maincounter-number"]/span/text()' - return CovidData( - *html.fromstring(httpx.get(url, timeout=10).content).xpath(xpath_str) + try: + response = httpx.get(url, timeout=10).raise_for_status() + except httpx.TimeoutException: + print( + "Request timed out. Please check your network connection " + "or try again later." + ) + return CovidData("N/A", "N/A", "N/A") + except httpx.HTTPStatusError as e: + print(f"HTTP error occurred: {e}") + return CovidData("N/A", "N/A", "N/A") + data = html.fromstring(response.content).xpath(xpath_str) + if len(data) != 3: + print("Unexpected data format. The page structure may have changed.") + data = "N/A", "N/A", "N/A" + return CovidData(*data) + + +if __name__ == "__main__": + fmt = ( + "Total COVID-19 cases in the world: {}\n" + "Total deaths due to COVID-19 in the world: {}\n" + "Total COVID-19 patients recovered in the world: {}" ) - - -fmt = """Total COVID-19 cases in the world: {} -Total deaths due to COVID-19 in the world: {} -Total COVID-19 patients recovered in the world: {}""" -print(fmt.format(*covid_stats())) + print(fmt.format(*covid_stats())) From e696e4dc9007b56d9e14d40d203c36ef861ab1b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 02:18:01 +0200 Subject: [PATCH 092/113] [pre-commit.ci] pre-commit autoupdate (#12988) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.13.0 → v0.13.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.0...v0.13.1) - [github.com/pre-commit/mirrors-mypy: v1.18.1 → v1.18.2](https://github.com/pre-commit/mirrors-mypy/compare/v1.18.1...v1.18.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9fbeb9a08682..2f7c43b06af2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.0 + rev: v0.13.1 hooks: - id: ruff-check - id: ruff-format @@ -47,7 +47,7 @@ repos: - id: validate-pyproject - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.18.1 + rev: v1.18.2 hooks: - id: mypy args: From 8d1fb262dab5d3f04c87f5433e8e2a6b9547ece4 Mon Sep 17 00:00:00 2001 From: kathrynpete <166650430+kathrynpete@users.noreply.github.com> Date: Tue, 23 Sep 2025 02:51:49 -0400 Subject: [PATCH 093/113] Added edit_distance test cases (#12984) * Added edit_distance test cases * Update edit_distance.py --------- Co-authored-by: Maxim Smolskiy --- strings/edit_distance.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/strings/edit_distance.py b/strings/edit_distance.py index e842c8555c8e..77ed23037937 100644 --- a/strings/edit_distance.py +++ b/strings/edit_distance.py @@ -14,6 +14,20 @@ def edit_distance(source: str, target: str) -> int: >>> edit_distance("GATTIC", "GALTIC") 1 + >>> edit_distance("NUM3", "HUM2") + 2 + >>> edit_distance("cap", "CAP") + 3 + >>> edit_distance("Cat", "") + 3 + >>> edit_distance("cat", "cat") + 0 + >>> edit_distance("", "123456789") + 9 + >>> edit_distance("Be@uty", "Beautyyyy!") + 5 + >>> edit_distance("lstring", "lsstring") + 1 """ if len(source) == 0: return len(target) From c0ad5bbde403b8db3097745e500e3f086607ee8f Mon Sep 17 00:00:00 2001 From: Dylanskyep <149001171+Dylanskyep@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:18:44 -0400 Subject: [PATCH 094/113] Add doctests for cross function. Contributes to #9943 (#12991) * Add doctests for cross function. Contributes to #9943 * Update sudoku_solver.py --------- Co-authored-by: Maxim Smolskiy --- data_structures/arrays/sudoku_solver.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/data_structures/arrays/sudoku_solver.py b/data_structures/arrays/sudoku_solver.py index 07269e2a69cc..d2fa43bbf298 100644 --- a/data_structures/arrays/sudoku_solver.py +++ b/data_structures/arrays/sudoku_solver.py @@ -11,6 +11,19 @@ def cross(items_a, items_b): """ Cross product of elements in A and elements in B. + + >>> cross('AB', '12') + ['A1', 'A2', 'B1', 'B2'] + >>> cross('ABC', '123') + ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'] + >>> cross('ABC', '1234') + ['A1', 'A2', 'A3', 'A4', 'B1', 'B2', 'B3', 'B4', 'C1', 'C2', 'C3', 'C4'] + >>> cross('', '12') + [] + >>> cross('A', '') + [] + >>> cross('', '') + [] """ return [a + b for a in items_a for b in items_b] From a71618f891da36ae6a8f9b58273f586ca6acf2a4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 20:30:14 +0200 Subject: [PATCH 095/113] [pre-commit.ci] pre-commit autoupdate (#13006) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.13.1 → v0.13.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.1...v0.13.2) * ci: autoupdate_schedule: monthly --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2f7c43b06af2..5c66d306b0e0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,6 @@ +ci: + autoupdate_schedule: monthly + repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 @@ -16,7 +19,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.1 + rev: v0.13.2 hooks: - id: ruff-check - id: ruff-format From 7530a417e872040d35338d5e43ec176320dab462 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 20:49:00 +0200 Subject: [PATCH 096/113] [pre-commit.ci] pre-commit autoupdate (#13286) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.13.2 → v0.13.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.2...v0.13.3) - [github.com/tox-dev/pyproject-fmt: v2.6.0 → v2.7.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.6.0...v2.7.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5c66d306b0e0..82a669007945 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.2 + rev: v0.13.3 hooks: - id: ruff-check - id: ruff-format @@ -32,7 +32,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.6.0 + rev: v2.7.0 hooks: - id: pyproject-fmt From 9372040da93cf7f77fc4ec2fd9ce5f2761b8800b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 7 Oct 2025 18:23:37 +0200 Subject: [PATCH 097/113] Test on Python 3.14 (#12710) --- .github/workflows/build.yml | 9 ++++++++- .github/workflows/directory_writer.yml | 3 ++- .github/workflows/project_euler.yml | 20 ++++++++++++++++++-- .github/workflows/sphinx.yml | 9 ++++++++- ciphers/gronsfeld_cipher.py | 2 +- machine_learning/xgboost_classifier.py | 2 -- maths/largest_of_very_large_numbers.py | 2 +- pyproject.toml | 7 ++++--- 8 files changed, 42 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 731e3fad3b85..666d45b13c1b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,13 @@ jobs: build: runs-on: ubuntu-latest steps: + - run: + sudo apt-get update && sudo apt-get install -y libtiff5-dev libjpeg8-dev libopenjp2-7-dev + zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk + libharfbuzz-dev libfribidi-dev libxcb1-dev + libxml2-dev libxslt-dev + libhdf5-dev + libopenblas-dev - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 with: @@ -16,7 +23,7 @@ jobs: cache-dependency-glob: uv.lock - uses: actions/setup-python@v6 with: - python-version: 3.x + python-version: 3.14 allow-prereleases: true - run: uv sync --group=test - name: Run tests diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml index 9a4682677c00..866440a37b31 100644 --- a/.github/workflows/directory_writer.yml +++ b/.github/workflows/directory_writer.yml @@ -11,7 +11,8 @@ jobs: fetch-depth: 0 - uses: actions/setup-python@v6 with: - python-version: 3.x + python-version: 3.14 + allow-prereleases: true - name: Write DIRECTORY.md run: | scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md diff --git a/.github/workflows/project_euler.yml b/.github/workflows/project_euler.yml index f52ff280b29a..dbea5aeeea02 100644 --- a/.github/workflows/project_euler.yml +++ b/.github/workflows/project_euler.yml @@ -14,21 +14,37 @@ jobs: project-euler: runs-on: ubuntu-latest steps: + - run: + sudo apt-get update && sudo apt-get install -y libtiff5-dev libjpeg8-dev libopenjp2-7-dev + zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk + libharfbuzz-dev libfribidi-dev libxcb1-dev + libxml2-dev libxslt-dev + libhdf5-dev + libopenblas-dev - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v6 with: - python-version: 3.x + python-version: 3.14 + allow-prereleases: true - run: uv sync --group=euler-validate --group=test - run: uv run pytest --doctest-modules --cov-report=term-missing:skip-covered --cov=project_euler/ project_euler/ validate-solutions: runs-on: ubuntu-latest steps: + - run: + sudo apt-get update && sudo apt-get install -y libtiff5-dev libjpeg8-dev libopenjp2-7-dev + zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk + libharfbuzz-dev libfribidi-dev libxcb1-dev + libxml2-dev libxslt-dev + libhdf5-dev + libopenblas-dev - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v6 with: - python-version: 3.x + python-version: 3.14 + allow-prereleases: true - run: uv sync --group=euler-validate --group=test - run: uv run pytest scripts/validate_solutions.py env: diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index bd253dc3de65..c12ebb23ded3 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -25,11 +25,18 @@ jobs: build_docs: runs-on: ubuntu-24.04-arm steps: + - run: + sudo apt-get update && sudo apt-get install -y libtiff5-dev libjpeg8-dev libopenjp2-7-dev + zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk + libharfbuzz-dev libfribidi-dev libxcb1-dev + libxml2-dev libxslt-dev + libhdf5-dev + libopenblas-dev - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - uses: actions/setup-python@v6 with: - python-version: 3.13 + python-version: 3.14 allow-prereleases: true - run: uv sync --group=docs - uses: actions/configure-pages@v5 diff --git a/ciphers/gronsfeld_cipher.py b/ciphers/gronsfeld_cipher.py index 8fbeab4307fc..a72b141bd502 100644 --- a/ciphers/gronsfeld_cipher.py +++ b/ciphers/gronsfeld_cipher.py @@ -20,7 +20,7 @@ def gronsfeld(text: str, key: str) -> str: >>> gronsfeld('yes, ¥€$ - _!@#%?', '') Traceback (most recent call last): ... - ZeroDivisionError: integer modulo by zero + ZeroDivisionError: division by zero """ ascii_len = len(ascii_uppercase) key_len = len(key) diff --git a/machine_learning/xgboost_classifier.py b/machine_learning/xgboost_classifier.py index 1da933cf690f..e845480074b9 100644 --- a/machine_learning/xgboost_classifier.py +++ b/machine_learning/xgboost_classifier.py @@ -42,8 +42,6 @@ def xgboost(features: np.ndarray, target: np.ndarray) -> XGBClassifier: def main() -> None: """ - >>> main() - Url for the algorithm: https://xgboost.readthedocs.io/en/stable/ Iris type dataset is used to demonstrate algorithm. diff --git a/maths/largest_of_very_large_numbers.py b/maths/largest_of_very_large_numbers.py index edee50371e02..e38ab2edb932 100644 --- a/maths/largest_of_very_large_numbers.py +++ b/maths/largest_of_very_large_numbers.py @@ -15,7 +15,7 @@ def res(x, y): >>> res(-1, 5) Traceback (most recent call last): ... - ValueError: math domain error + ValueError: expected a positive input """ if 0 not in (x, y): # We use the relation x^y = y*log10(x), where 10 is the base. diff --git a/pyproject.toml b/pyproject.toml index 71eb730f1329..7e64ad6f150b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,16 +10,17 @@ classifiers = [ ] dependencies = [ "beautifulsoup4>=4.12.3", + "cython>=3.1.2", "fake-useragent>=1.5.1", "httpx>=0.28.1", "imageio>=2.36.1", "keras>=3.7", - "lxml>=5.3", + "lxml>=6", "matplotlib>=3.9.3", "numpy>=2.1.3", "opencv-python>=4.10.0.84", "pandas>=2.2.3", - "pillow>=11", + "pillow>=11.3", "rich>=13.9.4", "scikit-learn>=1.5.2", "sphinx-pyproject>=0.3", @@ -32,7 +33,7 @@ dependencies = [ [dependency-groups] test = [ - "pytest>=8.3.4", + "pytest>=8.4.1", "pytest-cov>=6", ] From f0d5949e5a86134b6a6172ea102281a142e9f69f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 07:41:20 +0200 Subject: [PATCH 098/113] Bump astral-sh/setup-uv from 6 to 7 (#13335) Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 6 to 7. - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/v6...v7) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/project_euler.yml | 4 ++-- .github/workflows/ruff.yml | 2 +- .github/workflows/sphinx.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 666d45b13c1b..43b3b3d9de1b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: libhdf5-dev libopenblas-dev - uses: actions/checkout@v5 - - uses: astral-sh/setup-uv@v6 + - uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: uv.lock diff --git a/.github/workflows/project_euler.yml b/.github/workflows/project_euler.yml index dbea5aeeea02..05adb43b0bd4 100644 --- a/.github/workflows/project_euler.yml +++ b/.github/workflows/project_euler.yml @@ -22,7 +22,7 @@ jobs: libhdf5-dev libopenblas-dev - uses: actions/checkout@v5 - - uses: astral-sh/setup-uv@v6 + - uses: astral-sh/setup-uv@v7 - uses: actions/setup-python@v6 with: python-version: 3.14 @@ -40,7 +40,7 @@ jobs: libhdf5-dev libopenblas-dev - uses: actions/checkout@v5 - - uses: astral-sh/setup-uv@v6 + - uses: astral-sh/setup-uv@v7 - uses: actions/setup-python@v6 with: python-version: 3.14 diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml index 7bcc2850782f..b17236ccbff9 100644 --- a/.github/workflows/ruff.yml +++ b/.github/workflows/ruff.yml @@ -12,5 +12,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: astral-sh/setup-uv@v6 + - uses: astral-sh/setup-uv@v7 - run: uvx ruff check --output-format=github . diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index c12ebb23ded3..b945869e84a7 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -33,7 +33,7 @@ jobs: libhdf5-dev libopenblas-dev - uses: actions/checkout@v5 - - uses: astral-sh/setup-uv@v6 + - uses: astral-sh/setup-uv@v7 - uses: actions/setup-python@v6 with: python-version: 3.14 From 788d95b4101389617ca9f7fd043998089f98df78 Mon Sep 17 00:00:00 2001 From: Anuska Roy Date: Wed, 8 Oct 2025 17:41:28 +0530 Subject: [PATCH 099/113] added rotate_array.py (#13336) * added rotate_array.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed issues * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed reverse issue * added doctests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * changed k to steps for a descriptive name * fixed non-pep --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- data_structures/arrays/rotate_array.py | 80 ++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 data_structures/arrays/rotate_array.py diff --git a/data_structures/arrays/rotate_array.py b/data_structures/arrays/rotate_array.py new file mode 100644 index 000000000000..d5ce4b4078b3 --- /dev/null +++ b/data_structures/arrays/rotate_array.py @@ -0,0 +1,80 @@ +def rotate_array(arr: list[int], steps: int) -> list[int]: + """ + Rotates a list to the right by steps positions. + + Parameters: + arr (List[int]): The list of integers to rotate. + steps (int): Number of positions to rotate. Can be negative for left rotation. + + Returns: + List[int]: Rotated list. + + Examples: + >>> rotate_array([1, 2, 3, 4, 5], 2) + [4, 5, 1, 2, 3] + >>> rotate_array([1, 2, 3, 4, 5], -2) + [3, 4, 5, 1, 2] + >>> rotate_array([1, 2, 3, 4, 5], 7) + [4, 5, 1, 2, 3] + >>> rotate_array([], 3) + [] + """ + + n = len(arr) + if n == 0: + return arr + + steps = steps % n + + if steps < 0: + steps += n + + def reverse(start: int, end: int) -> None: + """ + Reverses a portion of the list in place from index start to end. + + Parameters: + start (int): Starting index of the portion to reverse. + end (int): Ending index of the portion to reverse. + + Returns: + None + + Examples: + >>> example = [1, 2, 3, 4, 5] + >>> def reverse_test(arr, start, end): + ... while start < end: + ... arr[start], arr[end] = arr[end], arr[start] + ... start += 1 + ... end -= 1 + >>> reverse_test(example, 0, 2) + >>> example + [3, 2, 1, 4, 5] + >>> reverse_test(example, 2, 4) + >>> example + [3, 2, 5, 4, 1] + """ + + while start < end: + arr[start], arr[end] = arr[end], arr[start] + start += 1 + end -= 1 + + reverse(0, n - 1) + reverse(0, steps - 1) + reverse(steps, n - 1) + + return arr + + +if __name__ == "__main__": + examples = [ + ([1, 2, 3, 4, 5], 2), + ([1, 2, 3, 4, 5], -2), + ([1, 2, 3, 4, 5], 7), + ([], 3), + ] + + for arr, steps in examples: + rotated = rotate_array(arr.copy(), steps) + print(f"Rotate {arr} by {steps}: {rotated}") From 1562ae1ec39bed716fc3f9da873844747dc0686c Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 14 Oct 2025 09:33:01 +0200 Subject: [PATCH 100/113] Add a README.md file to the scripts directory (#13480) * Add a README.md file to the scripts directory * updating DIRECTORY.md --------- Co-authored-by: cclauss --- DIRECTORY.md | 1 + scripts/README.md | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 scripts/README.md diff --git a/DIRECTORY.md b/DIRECTORY.md index 36acb3b97f1e..6249b75c4231 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -195,6 +195,7 @@ * [Permutations](data_structures/arrays/permutations.py) * [Prefix Sum](data_structures/arrays/prefix_sum.py) * [Product Sum](data_structures/arrays/product_sum.py) + * [Rotate Array](data_structures/arrays/rotate_array.py) * [Sparse Table](data_structures/arrays/sparse_table.py) * [Sudoku Solver](data_structures/arrays/sudoku_solver.py) * Binary Tree diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000000..92ebf3a7e8ba --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,27 @@ +Dealing with the onslaught of Hacktoberfest +* https://hacktoberfest.com + +Each year, October brings a swarm of new contributors participating in Hacktoberfest. This event has its pros and cons, but it presents a monumental workload for the few active maintainers of this repo. The maintainer workload is further impacted by a new version of CPython being released in the first week of each October. + +To help make our algorithms more valuable to visitors, our CONTRIBUTING.md file outlines several strict requirements, such as tests, type hints, descriptive names, functions, and/or classes. Maintainers reviewing pull requests should try to encourage improvements to meet these goals, but when the workload becomes overwhelming (esp. in October), pull requests that do not meet these goals should be closed. + +Below are a few [`gh`](https://cli.github.com) scripts that should close pull requests that do not match the definition of an acceptable algorithm as defined in CONTRIBUTING.md. I tend to run these scripts in the following order. + +* close_pull_requests_with_require_descriptive_names.sh +* close_pull_requests_with_require_tests.sh +* close_pull_requests_with_require_type_hints.sh +* close_pull_requests_with_failing_tests.sh +* close_pull_requests_with_awaiting_changes.sh +* find_git_conflicts.sh + +### Run on 14 Oct 2025: 107 of 541 (19.77%) pull requests closed. + +Script run | Open pull requests | Pull requests closed +--- | --- | --- +None | 541 | 0 +require_descriptive_names | 515 | 26 +require_tests | 498 | 17 +require_type_hints | 496 | 2 +failing_tests | 438 | ___58___ +awaiting_changes | 434 | 4 +git_conflicts | [ broken ] | 0 From 709c18ee9f1a19659a2187bb3f022037328de09a Mon Sep 17 00:00:00 2001 From: Khansa435 Date: Tue, 14 Oct 2025 16:14:22 +0500 Subject: [PATCH 101/113] Add t stochastic neighbour embedding using Iris dataset (#13476) * Added t-SNE with Iris dataset example * Added t-SNE with Iris dataset example * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated with descriptive variables * Add descriptive variable names * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add Descriptive Variable names * Adding Descriptive variable names * Update machine_learning/t_stochastic_neighbour_embedding.py Co-authored-by: Christian Clauss * Update machine_learning/t_stochastic_neighbour_embedding.py Co-authored-by: Christian Clauss * Improved line formatting * Adding URL for t-SNE Wikipedia * Apply suggestion from @cclauss --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .../t_stochastic_neighbour_embedding.py | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 machine_learning/t_stochastic_neighbour_embedding.py diff --git a/machine_learning/t_stochastic_neighbour_embedding.py b/machine_learning/t_stochastic_neighbour_embedding.py new file mode 100644 index 000000000000..d6f630149087 --- /dev/null +++ b/machine_learning/t_stochastic_neighbour_embedding.py @@ -0,0 +1,178 @@ +""" +t-distributed stochastic neighbor embedding (t-SNE) + +For more details, see: +https://en.wikipedia.org/wiki/T-distributed_stochastic_neighbor_embedding +""" + +import doctest + +import numpy as np +from numpy import ndarray +from sklearn.datasets import load_iris + + +def collect_dataset() -> tuple[ndarray, ndarray]: + """ + Load the Iris dataset and return features and labels. + + Returns: + tuple[ndarray, ndarray]: Feature matrix and target labels. + + >>> features, targets = collect_dataset() + >>> features.shape + (150, 4) + >>> targets.shape + (150,) + """ + iris_dataset = load_iris() + return np.array(iris_dataset.data), np.array(iris_dataset.target) + + +def compute_pairwise_affinities(data_matrix: ndarray, sigma: float = 1.0) -> ndarray: + """ + Compute high-dimensional affinities (P matrix) using a Gaussian kernel. + + Args: + data_matrix: Input data of shape (n_samples, n_features). + sigma: Gaussian kernel bandwidth. + + Returns: + ndarray: Symmetrized probability matrix. + + >>> x = np.array([[0.0, 0.0], [1.0, 0.0]]) + >>> probabilities = compute_pairwise_affinities(x) + >>> float(round(probabilities[0, 1], 3)) + 0.25 + """ + n_samples = data_matrix.shape[0] + squared_sum = np.sum(np.square(data_matrix), axis=1) + squared_distance = np.add( + np.add(-2 * np.dot(data_matrix, data_matrix.T), squared_sum).T, squared_sum + ) + + affinity_matrix = np.exp(-squared_distance / (2 * sigma**2)) + np.fill_diagonal(affinity_matrix, 0) + + affinity_matrix /= np.sum(affinity_matrix) + return (affinity_matrix + affinity_matrix.T) / (2 * n_samples) + + +def compute_low_dim_affinities(embedding_matrix: ndarray) -> tuple[ndarray, ndarray]: + """ + Compute low-dimensional affinities (Q matrix) using a Student-t distribution. + + Args: + embedding_matrix: Low-dimensional embedding of shape (n_samples, n_components). + + Returns: + tuple[ndarray, ndarray]: (Q probability matrix, numerator matrix). + + >>> y = np.array([[0.0, 0.0], [1.0, 0.0]]) + >>> q_matrix, numerators = compute_low_dim_affinities(y) + >>> q_matrix.shape + (2, 2) + """ + squared_sum = np.sum(np.square(embedding_matrix), axis=1) + numerator_matrix = 1 / ( + 1 + + np.add( + np.add(-2 * np.dot(embedding_matrix, embedding_matrix.T), squared_sum).T, + squared_sum, + ) + ) + np.fill_diagonal(numerator_matrix, 0) + + q_matrix = numerator_matrix / np.sum(numerator_matrix) + return q_matrix, numerator_matrix + + +def apply_tsne( + data_matrix: ndarray, + n_components: int = 2, + learning_rate: float = 200.0, + n_iter: int = 500, +) -> ndarray: + """ + Apply t-SNE for dimensionality reduction. + + Args: + data_matrix: Original dataset (features). + n_components: Target dimension (2D or 3D). + learning_rate: Step size for gradient descent. + n_iter: Number of iterations. + + Returns: + ndarray: Low-dimensional embedding of the data. + + >>> features, _ = collect_dataset() + >>> embedding = apply_tsne(features, n_components=2, n_iter=50) + >>> embedding.shape + (150, 2) + """ + if n_components < 1 or n_iter < 1: + raise ValueError("n_components and n_iter must be >= 1") + + n_samples = data_matrix.shape[0] + rng = np.random.default_rng() + embedding = rng.standard_normal((n_samples, n_components)) * 1e-4 + + high_dim_affinities = compute_pairwise_affinities(data_matrix) + high_dim_affinities = np.maximum(high_dim_affinities, 1e-12) + + embedding_increment = np.zeros_like(embedding) + momentum = 0.5 + + for iteration in range(n_iter): + low_dim_affinities, numerator_matrix = compute_low_dim_affinities(embedding) + low_dim_affinities = np.maximum(low_dim_affinities, 1e-12) + + affinity_diff = high_dim_affinities - low_dim_affinities + + gradient = 4 * ( + np.dot((affinity_diff * numerator_matrix), embedding) + - np.multiply( + np.sum(affinity_diff * numerator_matrix, axis=1)[:, np.newaxis], + embedding, + ) + ) + + embedding_increment = momentum * embedding_increment - learning_rate * gradient + embedding += embedding_increment + + if iteration == int(n_iter / 4): + momentum = 0.8 + + return embedding + + +def main() -> None: + """ + Run t-SNE on the Iris dataset and display the first 5 embeddings. + + >>> main() # doctest: +ELLIPSIS + t-SNE embedding (first 5 points): + [[... + """ + features, _labels = collect_dataset() + embedding = apply_tsne(features, n_components=2, n_iter=300) + + if not isinstance(embedding, np.ndarray): + raise TypeError("t-SNE embedding must be an ndarray") + + print("t-SNE embedding (first 5 points):") + print(embedding[:5]) + + # Optional visualization (Ruff/mypy compliant) + + # import matplotlib.pyplot as plt + # plt.scatter(embedding[:, 0], embedding[:, 1], c=labels, cmap="viridis") + # plt.title("t-SNE Visualization of the Iris Dataset") + # plt.xlabel("Dimension 1") + # plt.ylabel("Dimension 2") + # plt.show() + + +if __name__ == "__main__": + doctest.testmod() + main() From e731514bd5f6111c1859895c6b19fae0de551513 Mon Sep 17 00:00:00 2001 From: iddu <127777022+1drie5@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:33:33 +0530 Subject: [PATCH 102/113] Fix typo and function call in maths module (#13515) --- maths/factorial.py | 2 +- maths/fibonacci.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/factorial.py b/maths/factorial.py index aaf90f384bb9..ba61447c7564 100644 --- a/maths/factorial.py +++ b/maths/factorial.py @@ -56,7 +56,7 @@ def factorial_recursive(n: int) -> int: raise ValueError("factorial() only accepts integral values") if n < 0: raise ValueError("factorial() not defined for negative values") - return 1 if n in {0, 1} else n * factorial(n - 1) + return 1 if n in {0, 1} else n * factorial_recursive(n - 1) if __name__ == "__main__": diff --git a/maths/fibonacci.py b/maths/fibonacci.py index 24b2d7ae449e..71ff479f9cc2 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -183,7 +183,7 @@ def fib_memoization(n: int) -> list[int]: """ if n < 0: raise ValueError("n is negative") - # Cache must be outside recursuive function + # Cache must be outside recursive function # other it will reset every time it calls itself. cache: dict[int, int] = {0: 0, 1: 1, 2: 1} # Prefilled cache From 9902c23e14fd90f163ee95d557d374fc44793cd9 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 15 Oct 2025 19:06:25 +0200 Subject: [PATCH 103/113] Delete requirements.txt because dependencies are in pyproject.toml (#13486) --- .github/workflows/build.yml | 9 ++------- DIRECTORY.md | 1 + pyproject.toml | 1 + requirements.txt | 19 ------------------- 4 files changed, 4 insertions(+), 26 deletions(-) delete mode 100644 requirements.txt diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 43b3b3d9de1b..9a97424c56c4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,13 +9,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - run: - sudo apt-get update && sudo apt-get install -y libtiff5-dev libjpeg8-dev libopenjp2-7-dev - zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk - libharfbuzz-dev libfribidi-dev libxcb1-dev - libxml2-dev libxslt-dev - libhdf5-dev - libopenblas-dev + - run: sudo apt-get update && sudo apt-get install -y libhdf5-dev - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v7 with: @@ -32,6 +26,7 @@ jobs: --ignore=computer_vision/cnn_classification.py --ignore=docs/conf.py --ignore=dynamic_programming/k_means_clustering_tensorflow.py + --ignore=machine_learning/local_weighted_learning/local_weighted_learning.py --ignore=machine_learning/lstm/lstm_prediction.py --ignore=neural_network/input_data.py --ignore=project_euler/ diff --git a/DIRECTORY.md b/DIRECTORY.md index 6249b75c4231..0f9859577493 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -624,6 +624,7 @@ * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) * [Similarity Search](machine_learning/similarity_search.py) * [Support Vector Machines](machine_learning/support_vector_machines.py) + * [T Stochastic Neighbour Embedding](machine_learning/t_stochastic_neighbour_embedding.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) * [Xgboost Classifier](machine_learning/xgboost_classifier.py) * [Xgboost Regressor](machine_learning/xgboost_regressor.py) diff --git a/pyproject.toml b/pyproject.toml index 7e64ad6f150b..537ba79bd5f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ dependencies = [ "pillow>=11.3", "rich>=13.9.4", "scikit-learn>=1.5.2", + "scipy>=1.16.2", "sphinx-pyproject>=0.3", "statsmodels>=0.14.4", "sympy>=1.13.3", diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 66b5d8a6b94e..000000000000 --- a/requirements.txt +++ /dev/null @@ -1,19 +0,0 @@ -beautifulsoup4 -fake-useragent -httpx -imageio -keras -lxml -matplotlib -numpy -opencv-python -pandas -pillow -rich -scikit-learn -sphinx-pyproject -statsmodels -sympy -tweepy -typing_extensions -xgboost From 85e67302d8ad4e813b939e18cfd734824d8f966a Mon Sep 17 00:00:00 2001 From: Matt Ryan <44824894+mattryanmtl@users.noreply.github.com> Date: Wed, 15 Oct 2025 13:22:51 -0400 Subject: [PATCH 104/113] Test on 3.14 (#13473) Tested on 3.14. --- sorts/binary_insertion_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorts/binary_insertion_sort.py b/sorts/binary_insertion_sort.py index 50653a99e7ce..b928316a849d 100644 --- a/sorts/binary_insertion_sort.py +++ b/sorts/binary_insertion_sort.py @@ -56,7 +56,7 @@ def binary_insertion_sort(collection: list) -> list: return collection -if __name__ == "__main": +if __name__ == "__main__": user_input = input("Enter numbers separated by a comma:\n").strip() try: unsorted = [int(item) for item in user_input.split(",")] From 3cea94179d40bc80e94fc4191808de86eadf6642 Mon Sep 17 00:00:00 2001 From: Omkaar <79257339+Ombucha@users.noreply.github.com> Date: Wed, 15 Oct 2025 23:05:55 +0530 Subject: [PATCH 105/113] Fix a few typos (#13346) * Fix typo in spheres intersection print statement * Fix typo in CONTRIBUTING.md * Improve comments in comb_sort.py * pyproject.toml: tool.ruff.target-version = "py314" * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix comment formatting in lint.ignore section --------- Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- maths/volume.py | 2 +- pyproject.toml | 8 ++++---- sorts/comb_sort.py | 3 +-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3df39f95b784..35de0bf75ed5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -99,7 +99,7 @@ We want your work to be readable by others; therefore, we encourage you to note ruff check ``` -- Original code submission require docstrings or comments to describe your work. +- Original code submissions require docstrings or comments to describe your work. - More on docstrings and comments: diff --git a/maths/volume.py b/maths/volume.py index 08bdf72b013b..1715c9c300d5 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -555,7 +555,7 @@ def main(): print(f"Torus: {vol_torus(2, 2) = }") # ~= 157.9 print(f"Conical Frustum: {vol_conical_frustum(2, 2, 4) = }") # ~= 58.6 print(f"Spherical cap: {vol_spherical_cap(1, 2) = }") # ~= 5.24 - print(f"Spheres intersetion: {vol_spheres_intersect(2, 2, 1) = }") # ~= 21.21 + print(f"Spheres intersection: {vol_spheres_intersect(2, 2, 1) = }") # ~= 21.21 print(f"Spheres union: {vol_spheres_union(2, 2, 1) = }") # ~= 45.81 print( f"Hollow Circular Cylinder: {vol_hollow_circular_cylinder(1, 2, 3) = }" diff --git a/pyproject.toml b/pyproject.toml index 537ba79bd5f1..60ba0d3b65d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,10 +3,9 @@ name = "thealgorithms-python" version = "0.0.1" description = "TheAlgorithms in Python" authors = [ { name = "TheAlgorithms Contributors" } ] -requires-python = ">=3.13" +requires-python = ">=3.14" classifiers = [ "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.13", ] dependencies = [ "beautifulsoup4>=4.12.3", @@ -49,7 +48,7 @@ euler-validate = [ ] [tool.ruff] -target-version = "py313" +target-version = "py314" output-format = "full" lint.select = [ @@ -110,7 +109,7 @@ lint.ignore = [ # `ruff rule S101` for a description of that rule "B904", # Within an `except` clause, raise exceptions with `raise ... from err` -- FIX ME "B905", # `zip()` without an explicit `strict=` parameter -- FIX ME - "EM101", # Exception must not use a string literal, assign to variable first + "EM101", # Exception must not use a string literal, assign to a variable first "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 @@ -126,6 +125,7 @@ lint.ignore = [ "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 "SLF001", # Private member accessed: `_Iterator` -- FIX ME + "UP037", # FIX ME ] lint.per-file-ignores."data_structures/hashing/tests/test_hash_map.py" = [ diff --git a/sorts/comb_sort.py b/sorts/comb_sort.py index 3c8b1e99a454..94ad8f533328 100644 --- a/sorts/comb_sort.py +++ b/sorts/comb_sort.py @@ -5,8 +5,7 @@ Comb sort improves on bubble sort algorithm. In bubble sort, distance (or gap) between two compared elements is always one. Comb sort improvement is that gap can be much more than 1, in order to prevent slowing -down by small values -at the end of a list. +down by small values at the end of a list. More info on: https://en.wikipedia.org/wiki/Comb_sort From 8edc478a19dda14a63300fc86b3520cc037621f9 Mon Sep 17 00:00:00 2001 From: Gunish Mukherji Date: Fri, 17 Oct 2025 06:06:38 +0530 Subject: [PATCH 106/113] Adding missing return type to pi_estimator function (#13427) - Add -> None return type annotation to pi_estimator function - Improves code clarity and follows Python type hinting best practices - Function already had proper type hints for parameters Co-authored-by: Gunish Mukherji Co-authored-by: Maxim Smolskiy --- maths/monte_carlo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/monte_carlo.py b/maths/monte_carlo.py index d174a0b188a2..5eb176238ffb 100644 --- a/maths/monte_carlo.py +++ b/maths/monte_carlo.py @@ -8,7 +8,7 @@ from statistics import mean -def pi_estimator(iterations: int): +def pi_estimator(iterations: int) -> None: """ An implementation of the Monte Carlo method used to find pi. 1. Draw a 2x2 square centred at (0,0). From c79034ca2114e56ede887a473c2853b8c6d49257 Mon Sep 17 00:00:00 2001 From: Harsh Pathak <156679457+HarshPathak310@users.noreply.github.com> Date: Fri, 17 Oct 2025 06:30:44 +0530 Subject: [PATCH 107/113] Update logical issue in decision_tree.py (#13303) Co-authored-by: Maxim Smolskiy --- machine_learning/decision_tree.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/machine_learning/decision_tree.py b/machine_learning/decision_tree.py index 72970431c3fc..b4df64796bb1 100644 --- a/machine_learning/decision_tree.py +++ b/machine_learning/decision_tree.py @@ -146,14 +146,13 @@ def predict(self, x): """ if self.prediction is not None: return self.prediction - elif self.left or self.right is not None: + elif self.left is not None and self.right is not None: if x >= self.decision_boundary: return self.right.predict(x) else: return self.left.predict(x) else: - print("Error: Decision tree not yet trained") - return None + raise ValueError("Decision tree not yet trained") class TestDecisionTree: @@ -201,4 +200,4 @@ def main(): main() import doctest - doctest.testmod(name="mean_squarred_error", verbose=True) + doctest.testmod(name="mean_squared_error", verbose=True) From 3b08413ab32bb5526c6043681db6e3ae9df4fd4a Mon Sep 17 00:00:00 2001 From: Tejasrahane <161036451+Tejasrahane@users.noreply.github.com> Date: Mon, 20 Oct 2025 02:21:11 +0530 Subject: [PATCH 108/113] Add doctest for circular queue overflow condition (#13590) * Add doctest for circular queue overflow condition Added a doctest to test the QUEUE IS FULL exception when attempting to enqueue an element into a full circular queue. This improves test coverage for line 67 in data_structures/queues/circular_queue.py. Fixes #9943 * Update circular_queue.py * Update circular_queue.py * Update circular_queue.py * Update circular_queue.py --------- Co-authored-by: Maxim Smolskiy --- data_structures/queues/circular_queue.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/data_structures/queues/circular_queue.py b/data_structures/queues/circular_queue.py index efbf1efdc42d..e9cb2cac4fd8 100644 --- a/data_structures/queues/circular_queue.py +++ b/data_structures/queues/circular_queue.py @@ -17,7 +17,7 @@ def __len__(self) -> int: >>> len(cq) 0 >>> cq.enqueue("A") # doctest: +ELLIPSIS - >>> cq.array ['A', None, None, None, None] >>> len(cq) @@ -51,17 +51,24 @@ def enqueue(self, data): """ This function inserts an element at the end of the queue using self.rear value as an index. + >>> cq = CircularQueue(5) >>> cq.enqueue("A") # doctest: +ELLIPSIS - >>> (cq.size, cq.first()) (1, 'A') >>> cq.enqueue("B") # doctest: +ELLIPSIS - >>> cq.array ['A', 'B', None, None, None] >>> (cq.size, cq.first()) (2, 'A') + >>> cq.enqueue("C").enqueue("D").enqueue("E") # doctest: +ELLIPSIS + + >>> cq.enqueue("F") + Traceback (most recent call last): + ... + Exception: QUEUE IS FULL """ if self.size >= self.n: raise Exception("QUEUE IS FULL") @@ -75,6 +82,7 @@ def dequeue(self): """ This function removes an element from the queue using on self.front value as an index and returns it + >>> cq = CircularQueue(5) >>> cq.dequeue() Traceback (most recent call last): From 154cd3e4002d22756cf192c76db0a9ac8a918867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Neto?= Date: Sun, 19 Oct 2025 19:21:00 -0300 Subject: [PATCH 109/113] feat: optimizing the prune function at the apriori_algorithm.py archive (#12992) * feat: optimizing the prune function at the apriori_algorithm.py archive * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: fixing the unsorted importing statment * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: fixing the key structure to a tuple that can be an hashable structure * Update apriori_algorithm.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update apriori_algorithm.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy --- machine_learning/apriori_algorithm.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/machine_learning/apriori_algorithm.py b/machine_learning/apriori_algorithm.py index 09a89ac236bd..5c3e2baba2c2 100644 --- a/machine_learning/apriori_algorithm.py +++ b/machine_learning/apriori_algorithm.py @@ -11,6 +11,7 @@ Examples: https://www.kaggle.com/code/earthian/apriori-association-rules-mining """ +from collections import Counter from itertools import combinations @@ -44,11 +45,16 @@ def prune(itemset: list, candidates: list, length: int) -> list: >>> prune(itemset, candidates, 3) [] """ + itemset_counter = Counter(tuple(item) for item in itemset) pruned = [] for candidate in candidates: is_subsequence = True for item in candidate: - if item not in itemset or itemset.count(item) < length - 1: + item_tuple = tuple(item) + if ( + item_tuple not in itemset_counter + or itemset_counter[item_tuple] < length - 1 + ): is_subsequence = False break if is_subsequence: From 1b0bd167290bbdd5cb56972f1c6fb8d18698c839 Mon Sep 17 00:00:00 2001 From: michaelmccamy <149010657+michaelmccamy@users.noreply.github.com> Date: Sun, 19 Oct 2025 20:29:59 -0400 Subject: [PATCH 110/113] Add doctest for add_vertex in GraphAdjacencyList. Contributes to #9943 (#13143) * Add doctest for add_vertex in GraphAdjacencyList. Contributes to #9943 * Update graph_adjacency_list.py --------- Co-authored-by: Maxim Smolskiy --- graphs/graph_adjacency_list.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/graphs/graph_adjacency_list.py b/graphs/graph_adjacency_list.py index c901e2cf3dac..34014d69dfb8 100644 --- a/graphs/graph_adjacency_list.py +++ b/graphs/graph_adjacency_list.py @@ -61,6 +61,15 @@ def add_vertex(self, vertex: T) -> None: """ Adds a vertex to the graph. If the given vertex already exists, a ValueError will be thrown. + + >>> g = GraphAdjacencyList(vertices=[], edges=[], directed=False) + >>> g.add_vertex("A") + >>> g.adj_list + {'A': []} + >>> g.add_vertex("A") + Traceback (most recent call last): + ... + ValueError: Incorrect input: A is already in the graph. """ if self.contains_vertex(vertex): msg = f"Incorrect input: {vertex} is already in the graph." From e2a78d4e76adbce1f6b93f649820982165d6092d Mon Sep 17 00:00:00 2001 From: Md Mahiuddin <68785084+mahiuddin-dev@users.noreply.github.com> Date: Mon, 20 Oct 2025 06:59:36 +0600 Subject: [PATCH 111/113] Add test for non-integer input to factorial function (#13024) * Add test for non-integer input to factorial function * Update test_factorial.py --------- Co-authored-by: Maxim Smolskiy --- maths/test_factorial.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/maths/test_factorial.py b/maths/test_factorial.py index d80d88add745..1795ebba194f 100644 --- a/maths/test_factorial.py +++ b/maths/test_factorial.py @@ -33,5 +33,11 @@ def test_negative_number(function): function(-3) +@pytest.mark.parametrize("function", [factorial, factorial_recursive]) +def test_float_number(function): + with pytest.raises(ValueError): + function(1.5) + + if __name__ == "__main__": pytest.main(["-v", __file__]) From af17867f409ec80f4d0cc499943c455da4307cd4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:02:38 +0100 Subject: [PATCH 112/113] [pre-commit.ci] pre-commit autoupdate (#13860) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.13.3 → v0.14.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.3...v0.14.3) - [github.com/tox-dev/pyproject-fmt: v2.7.0 → v2.11.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.7.0...v2.11.0) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- pyproject.toml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 82a669007945..e305772298d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.3 + rev: v0.14.3 hooks: - id: ruff-check - id: ruff-format @@ -32,7 +32,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.7.0 + rev: v2.11.0 hooks: - id: pyproject-fmt diff --git a/pyproject.toml b/pyproject.toml index 60ba0d3b65d9..f1559d6bc1b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,7 @@ authors = [ { name = "TheAlgorithms Contributors" } ] requires-python = ">=3.14" classifiers = [ "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.14", ] dependencies = [ "beautifulsoup4>=4.12.3", From ae68a7800883021b4bb5f40ccfb3773a189a8d09 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 6 Nov 2025 13:11:49 +0100 Subject: [PATCH 113/113] uv run --with=pytest-run-parallel --iterations=8 --parallel-threads=auto (#13863) https://github.com/Quansight-Labs/pytest-run-parallel * https://py-free-threading.github.io * https://www.python.org/downloads/release/python-3140/ --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a97424c56c4..bbe4b782a00a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,8 @@ jobs: - run: uv sync --group=test - name: Run tests # TODO: #8818 Re-enable quantum tests - run: uv run pytest + run: uv run --with=pytest-run-parallel pytest + --iterations=8 --parallel-threads=auto --ignore=computer_vision/cnn_classification.py --ignore=docs/conf.py --ignore=dynamic_programming/k_means_clustering_tensorflow.py