├── LICENSE ├── README.md ├── examples ├── __init__.py ├── with_playwright.py └── with_selenium.py ├── imgs ├── bezier.png ├── gaussian.png ├── oxy.png └── perlin.png ├── oxymouse ├── __init__.py ├── algorithms │ ├── __init__.py │ ├── base.py │ ├── bezier_mouse │ │ ├── __init__.py │ │ └── bezier_mouse.py │ ├── gaussian_mouse │ │ ├── __init__.py │ │ └── gaussian_mouse.py │ ├── oxy │ │ ├── __init__.py │ │ └── oxy_mouse.py │ └── perlin_mouse │ │ ├── __init__.py │ │ └── perlin_mouse.py ├── config.py └── oxymouse.py ├── poetry.lock ├── pyproject.toml └── visualize.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Oxylabs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 🐭 Oxy® Mouse 3 |

4 |

5 |

Generate mouse movements with Python & different algorithms

6 |

7 |

8 | 9 | 11 |

12 | 13 | [![](https://dcbadge.vercel.app/api/server/eWsVUJrnG5)](https://discord.gg/Pds3gBmKMH) 14 | 15 | OxyMouse is a Python library for generating mouse movements. 16 | 17 | It is designed to work with any browser control library that supports 2D moving of the mouse cursor. 18 | 19 | ## Installation 20 | 21 | ```bash 22 | pip install oxymouse 23 | ``` 24 | 25 | ## Usage 26 | 27 | Specify `algorithm` an algorithm. 28 | 29 | Supported algorithms: 30 | 31 | `bezier`, `gaussian`, `perlin`, 'oxy' 32 | 33 | ```python 34 | 35 | from oxymouse import OxyMouse 36 | 37 | mouse = OxyMouse(algorithm="bezier") 38 | movements = mouse.generate_random_coordinates(viewport_width=1920, viewport_height=1080) 39 | ``` 40 | 41 | 42 | #### generate_random_coordinates 43 | 44 | This method will generate random coordinates based on your viewport width and viewport height. 45 | 46 | 47 | #### generate_coordinates 48 | 49 | This method will generate random coordinates from a given 2D point to another 2D point. 50 | 51 | You can use this to generate movements to a button. 52 | 53 | For example: 54 | 55 | - get button coordinates 56 | - get current mouse coordinates 57 | - generate movements from current mouse coordinates to button coordinates 58 | 59 | ```python 60 | from oxymouse import OxyMouse 61 | 62 | mouse = OxyMouse(algorithm="bezier") 63 | movements = mouse.generate_coordinates(from_x=400, from_y=500, to_x=1000, to_y=1200) 64 | ``` 65 | 66 | #### generate_scroll_coordinates 67 | 68 | This method will generate random coordinates for scrolling. 69 | 70 | ```python 71 | from oxymouse import OxyMouse 72 | 73 | mouse = OxyMouse(algorithm="bezier") 74 | movements = mouse.generate_scroll_coordinates() 75 | ``` 76 | 77 | ## Supported Algorithms 78 | 79 | ### Bezier 80 | 81 | The Bezier algorithm generates mouse movements using the Bezier curve. 82 | Perfect for moving to click a button 83 | 84 | ![bezier.png](imgs/bezier.png) 85 | 86 | ### Gaussian 87 | 88 | The Gaussian algorithm generates mouse movements using the Gaussian distribution. 89 | Perfect for simulating human-like mouse movements 90 | 91 | ![gaussian.png](imgs/gaussian.png) 92 | 93 | ### Perlin 94 | 95 | The Perlin algorithm generates mouse movements using the Perlin noise. 96 | Perfect for simulating human-like mouse movements 97 | 98 | ![perlin.png](imgs/perlin.png) 99 | 100 | ### OxyMouse 101 | 102 | Custom algorithm that generates mouse movements using a custom algorithm. 103 | 104 | ![oxy.png](imgs/oxy.png) 105 | 106 | ### Testing 107 | 108 | You can easily test generated mouse movements visually with specific algorithm. 109 | 110 | Use the CLI to test the generated mouse movements. 111 | 112 | For example, to test the generated mouse movements with the `Bezier` algorithm and `generate_coordinates` function. 113 | 114 | ```bash 115 | python3 visualize.py bezier gc 116 | ``` 117 | 118 | You will see the generated mouse movements in a window. Similar in the examples above. 119 | 120 | Other function names: 121 | ``` 122 | function_names_to_function_map = { 123 | "gc": "generate_coordinates", 124 | "grc": "generate_random_coordinates", 125 | "gsc": "generate_scroll_coordinates", 126 | } 127 | ``` 128 | 129 | ## Contributing 130 | 131 | Contributions are welcome! For feature requests and bug reports please submit an issue! 132 | -------------------------------------------------------------------------------- /examples/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/examples/__init__.py -------------------------------------------------------------------------------- /examples/with_playwright.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import random 3 | 4 | from oxylabs import OxyMouse 5 | from playwright.async_api import async_playwright 6 | 7 | 8 | async def generate_random_movements() -> list[tuple[int, int]]: 9 | mouse = OxyMouse(algorithm="gaussian") 10 | movements = mouse.generate_coordinates() 11 | return movements 12 | 13 | 14 | async def move_mouse_smoothly(page, movements: list[tuple[int, int]]): 15 | for x, y in movements: 16 | await page.mouse.move(x, y) 17 | await asyncio.sleep(random.uniform(0.001, 0.003)) # Add small random delays 18 | 19 | 20 | async def main(): 21 | async with async_playwright() as p: 22 | browser = await p.chromium.launch() 23 | page = await browser.new_page() 24 | 25 | try: 26 | await page.goto("https://oxylabs.io", wait_until="domcontentloaded") 27 | 28 | movements = await generate_random_movements() 29 | 30 | await move_mouse_smoothly(page, movements) 31 | 32 | await asyncio.sleep(5) 33 | 34 | finally: 35 | await browser.close() 36 | 37 | 38 | asyncio.run(main()) 39 | -------------------------------------------------------------------------------- /examples/with_selenium.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | 4 | from selenium import webdriver 5 | from selenium.webdriver.common.action_chains import ActionChains 6 | from selenium.webdriver.common.by import By 7 | from selenium.webdriver.support import expected_conditions as EC 8 | from selenium.webdriver.support.ui import WebDriverWait 9 | 10 | from oxymouse import OxyMouse 11 | 12 | 13 | def generate_random_movements() -> list[tuple[int, int]]: 14 | mouse = OxyMouse(algorithm="perlin") 15 | movements = mouse.generate_coordinates() 16 | return movements 17 | 18 | 19 | def move_mouse_smoothly(driver, movements: list[tuple[int, int]]): 20 | actions = ActionChains(driver) 21 | for x, y in movements: 22 | actions.move_by_offset(x, y) 23 | actions.pause(random.uniform(0.001, 0.003)) # Add small random delays 24 | actions.perform() 25 | 26 | 27 | driver = webdriver.Chrome() 28 | 29 | try: 30 | driver.get("https://oxylabs.io") 31 | 32 | # Wait for the page to load 33 | WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "body"))) 34 | 35 | movements = generate_random_movements() 36 | 37 | move_mouse_smoothly(driver, movements) 38 | 39 | time.sleep(5) 40 | 41 | finally: 42 | driver.quit() 43 | -------------------------------------------------------------------------------- /imgs/bezier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/imgs/bezier.png -------------------------------------------------------------------------------- /imgs/gaussian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/imgs/gaussian.png -------------------------------------------------------------------------------- /imgs/oxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/imgs/oxy.png -------------------------------------------------------------------------------- /imgs/perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/imgs/perlin.png -------------------------------------------------------------------------------- /oxymouse/__init__.py: -------------------------------------------------------------------------------- 1 | from oxymouse.oxymouse import OxyMouse 2 | 3 | __all__ = ["OxyMouse"] 4 | -------------------------------------------------------------------------------- /oxymouse/algorithms/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/oxymouse/algorithms/__init__.py -------------------------------------------------------------------------------- /oxymouse/algorithms/base.py: -------------------------------------------------------------------------------- 1 | import abc 2 | 3 | 4 | class MouseMovement: 5 | @staticmethod 6 | @abc.abstractmethod 7 | def generate_coordinates(from_x: int, from_y: int, to_x: int, to_y: int) -> list[tuple[int, int]]: 8 | """ 9 | Generate a list of coordinates from (from_x, from_y) to (to_x, to_y). 10 | """ 11 | raise NotImplementedError 12 | 13 | @staticmethod 14 | @abc.abstractmethod 15 | def generate_random_coordinates(viewport_width: int, viewport_height: int) -> list[tuple[int, int]]: 16 | """ 17 | Generate random coordinates within the given viewport dimensions. 18 | """ 19 | raise NotImplementedError 20 | 21 | @staticmethod 22 | @abc.abstractmethod 23 | def generate_scroll_coordinates(start_y: int, end_y: int) -> list[tuple[int, int]]: 24 | """ 25 | Generate a list of y-coordinates for scrolling from start_y to end_y. 26 | """ 27 | raise NotImplementedError 28 | -------------------------------------------------------------------------------- /oxymouse/algorithms/bezier_mouse/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/oxymouse/algorithms/bezier_mouse/__init__.py -------------------------------------------------------------------------------- /oxymouse/algorithms/bezier_mouse/bezier_mouse.py: -------------------------------------------------------------------------------- 1 | import random 2 | from typing import Any 3 | 4 | import numpy as np 5 | from scipy.special import comb 6 | 7 | from oxymouse.algorithms.base import MouseMovement 8 | 9 | 10 | class BezierMouse(MouseMovement): 11 | @staticmethod 12 | def bernstein_poly( 13 | i: int, n: int, t: np.ndarray[Any, np.dtype[np.float64]] 14 | ) -> np.ndarray[Any, np.dtype[np.float64]]: 15 | """ 16 | The Bernstein polynomial of n, i as a function of t 17 | """ 18 | return comb(n, i) * (t**i) * (1 - t) ** (n - i) 19 | 20 | @staticmethod 21 | def bezier_curve(points: list[tuple[int, int]], num_steps: int = 1000) -> list[tuple[int, int]]: 22 | """ 23 | Given a set of control points, return the 24 | bezier curve defined by the control points. 25 | points should be a list of lists, or list of tuples 26 | such as [ [1,1], [2,3], [4,5], [3,5] ] 27 | """ 28 | n_points = len(points) 29 | xpoints = np.array([p[0] for p in points]) 30 | ypoints = np.array([p[1] for p in points]) 31 | 32 | t = np.linspace(0.0, 1.0, num_steps) 33 | 34 | polynomial_array = np.array([BezierMouse.bernstein_poly(i, n_points - 1, t) for i in range(n_points)]) 35 | 36 | xvals = np.dot(xpoints, polynomial_array) 37 | yvals = np.dot(ypoints, polynomial_array) 38 | 39 | return list(zip(xvals.astype(int), yvals.astype(int))) 40 | 41 | @staticmethod 42 | def generate_bezier_mouse_movements( # pylint: disable=too-many-positional-arguments 43 | start_x: int, 44 | start_y: int, 45 | end_x: int, 46 | end_y: int, 47 | duration: float = 1.0, 48 | complexity: int = 4, 49 | randomness: float = 1.0, 50 | ) -> list[tuple[int, int]]: 51 | """ 52 | Generate mouse movements using Bézier curves. 53 | 54 | :param start_x: Starting x-coordinate 55 | :param start_y: Starting y-coordinate 56 | :param end_x: Ending x-coordinate 57 | :param end_y: Ending y-coordinate 58 | :param duration: Duration of the movement in seconds 59 | :param complexity: Number of control points (minimum 4, includes start and end points) 60 | :param randomness: Controls the randomness of control points (0.0 to 1.0) 61 | """ 62 | complexity = max(4, complexity) # Ensure at least 4 control points for a cubic Bézier curve 63 | 64 | control_points = [(start_x, start_y)] 65 | for i in range(complexity - 2): 66 | cx = random.randint(min(start_x, end_x), max(start_x, end_x)) 67 | cy = random.randint(min(start_y, end_y), max(start_y, end_y)) 68 | control_points.append((cx, cy)) 69 | control_points.append((end_x, end_y)) 70 | 71 | for i in range(1, len(control_points) - 1): 72 | control_points[i] = ( 73 | int(control_points[i][0] + random.uniform(-randomness * 100, randomness * 100)), 74 | int(control_points[i][1] + random.uniform(-randomness * 100, randomness * 100)), 75 | ) 76 | 77 | num_steps = int(duration * 60) # Assuming 60 fps 78 | curve_points = BezierMouse.bezier_curve(control_points, num_steps) 79 | 80 | return curve_points 81 | 82 | @staticmethod 83 | def generate_coordinates( 84 | from_x: int = 0, from_y: int = 0, to_x: int = 1000, to_y: int = 1000 85 | ) -> list[tuple[int, int]]: 86 | """ 87 | Generate a list of coordinates from (from_x, from_y) to (to_x, to_y) using Bézier curves. 88 | """ 89 | return BezierMouse.generate_bezier_mouse_movements(from_x, from_y, to_x, to_y) 90 | 91 | @staticmethod 92 | def generate_random_coordinates(viewport_width: int = 1920, viewport_height: int = 1080) -> list[tuple[int, int]]: 93 | """ 94 | Generate random coordinates within the given viewport dimensions using Bézier curves. 95 | """ 96 | start_x, start_y = 0, 0 97 | end_x = random.randint(0, viewport_width) 98 | end_y = random.randint(0, viewport_height) 99 | movements = BezierMouse.generate_bezier_mouse_movements(start_x, start_y, end_x, end_y) 100 | return movements 101 | 102 | @staticmethod 103 | def generate_scroll_coordinates(start_y: int = 0, end_y: int = 1000) -> list[tuple[int, int]]: 104 | """ 105 | Generate a list of y-coordinates for scrolling from start_y to end_y using Bézier curves. 106 | """ 107 | movements = BezierMouse.generate_bezier_mouse_movements(0, start_y, 0, end_y) 108 | y_coords = [m[1] for m in movements] 109 | 110 | y_coords.append(end_y) 111 | x_coords = [0] * len(y_coords) 112 | 113 | return list(zip(x_coords, y_coords)) 114 | -------------------------------------------------------------------------------- /oxymouse/algorithms/gaussian_mouse/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/oxymouse/algorithms/gaussian_mouse/__init__.py -------------------------------------------------------------------------------- /oxymouse/algorithms/gaussian_mouse/gaussian_mouse.py: -------------------------------------------------------------------------------- 1 | import random 2 | from typing import Any 3 | 4 | import numpy as np 5 | from scipy.ndimage import gaussian_filter1d 6 | 7 | from oxymouse.algorithms.base import MouseMovement 8 | 9 | 10 | class GaussianMouse(MouseMovement): 11 | @staticmethod 12 | def random_walk(length: int, stddev: float) -> np.ndarray[Any, np.dtype[np.float64]]: 13 | return np.cumsum(np.random.normal(0, stddev, length)) 14 | 15 | @staticmethod 16 | def gaussian_smooth( 17 | data: np.ndarray[Any, np.dtype[np.float64]], sigma: float 18 | ) -> np.ndarray[Any, np.dtype[np.float64]]: 19 | return gaussian_filter1d(data, sigma) 20 | 21 | @staticmethod 22 | def morph_distribution( 23 | data: np.ndarray[Any, np.dtype[np.float64]], target_mean: float, target_std: float 24 | ) -> np.ndarray[Any, np.dtype[np.float64]]: 25 | return (data - np.mean(data)) / np.std(data) * target_std + target_mean 26 | 27 | @staticmethod 28 | def bezier_curve(p0: float, p1: float, p2: float, t: float) -> float: 29 | return (1 - t) ** 2 * p0 + 2 * (1 - t) * t * p1 + t**2 * p2 30 | 31 | @staticmethod 32 | def generate_gaussian_mouse_movements( # pylint: disable=too-many-locals, too-many-positional-arguments 33 | start_x: int, 34 | start_y: int, 35 | end_x: int, 36 | end_y: int, 37 | duration: float = 1.0, 38 | smoothness: float = 2.0, 39 | randomness: float = 1.0, 40 | ) -> list[tuple[int, int]]: 41 | """ 42 | Generate mouse movements using Gaussian random walk and Bezier curves. 43 | 44 | :param start_x: Starting x-coordinate 45 | :param start_y: Starting y-coordinate 46 | :param end_x: Ending x-coordinate 47 | :param end_y: Ending y-coordinate 48 | :param duration: Duration of the movement in seconds 49 | :param smoothness: Controls the smoothness of the path (higher value = smoother) 50 | :param randomness: Controls the randomness of the path (higher value = more random) 51 | """ 52 | num_points = int(duration * 60) 53 | 54 | stddev = randomness * 10 55 | random_x = GaussianMouse.random_walk(num_points, stddev) 56 | random_y = GaussianMouse.random_walk(num_points, stddev) 57 | 58 | smooth_x = GaussianMouse.gaussian_smooth(random_x, sigma=smoothness) 59 | smooth_y = GaussianMouse.gaussian_smooth(random_y, sigma=smoothness) 60 | 61 | human_mean_x, human_std_x = (end_x - start_x) / 2, (end_x - start_x) / 6 62 | human_mean_y, human_std_y = (end_y - start_y) / 2, (end_y - start_y) / 6 63 | morphed_x = GaussianMouse.morph_distribution(smooth_x, human_mean_x, human_std_x) 64 | morphed_y = GaussianMouse.morph_distribution(smooth_y, human_mean_y, human_std_y) 65 | 66 | control_x = random.uniform(start_x, end_x) 67 | control_y = random.uniform(start_y, end_y) 68 | 69 | t_values = np.linspace(0, 1, num_points) 70 | bezier_x = [GaussianMouse.bezier_curve(start_x, control_x, end_x, t) for t in t_values] 71 | bezier_y = [GaussianMouse.bezier_curve(start_y, control_y, end_y, t) for t in t_values] 72 | 73 | final_x = [int(bx + mx) for bx, mx in zip(bezier_x, morphed_x)] 74 | final_y = [int(by + my) for by, my in zip(bezier_y, morphed_y)] 75 | 76 | final_x[0], final_y[0] = start_x, start_y 77 | final_x[-1], final_y[-1] = end_x, end_y 78 | 79 | mouse_path = list(zip(final_x, final_y)) 80 | return mouse_path 81 | 82 | @staticmethod 83 | def generate_coordinates( 84 | from_x: int = 0, from_y: int = 0, to_x: int = 1000, to_y: int = 1000 85 | ) -> list[tuple[int, int]]: 86 | """ 87 | Generate a list of coordinates from (from_x, from_y) to (to_x, to_y) using Gaussian random walk. 88 | """ 89 | return GaussianMouse.generate_gaussian_mouse_movements(from_x, from_y, to_x, to_y) 90 | 91 | @staticmethod 92 | def generate_random_coordinates(viewport_width: int = 1920, viewport_height: int = 1080) -> list[tuple[int, int]]: 93 | """ 94 | Generate random coordinates within the given viewport dimensions using Gaussian random walk. 95 | """ 96 | start_x, start_y = 0, 0 97 | end_x = random.randint(0, viewport_width) 98 | end_y = random.randint(0, viewport_height) 99 | movements = GaussianMouse.generate_gaussian_mouse_movements(start_x, start_y, end_x, end_y) 100 | return movements 101 | 102 | @staticmethod 103 | def generate_scroll_coordinates(start_y: int = 0, end_y: int = 1000) -> list[tuple[int, int]]: 104 | """ 105 | Generate a list of y-coordinates for scrolling from start_y to end_y using Gaussian random walk. 106 | """ 107 | movements = GaussianMouse.generate_gaussian_mouse_movements(0, start_y, 0, end_y) 108 | y_coords = [m[1] for m in movements] 109 | 110 | y_coords.append(end_y) 111 | x_coords = [0] * len(y_coords) 112 | 113 | return list(zip(x_coords, y_coords)) 114 | -------------------------------------------------------------------------------- /oxymouse/algorithms/oxy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/oxymouse/algorithms/oxy/__init__.py -------------------------------------------------------------------------------- /oxymouse/algorithms/oxy/oxy_mouse.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | from enum import Enum 4 | 5 | import numpy as np 6 | from noise import pnoise2 7 | 8 | from oxymouse.algorithms.base import MouseMovement 9 | 10 | 11 | class MouseState(Enum): 12 | ACCELERATING = 1 13 | PRECISE_MOVEMENT = 2 14 | DECELERATING = 3 15 | 16 | 17 | class OxyMouse(MouseMovement): 18 | @staticmethod 19 | def _generate_movements( 20 | duration: float = 1.0, 21 | octaves: int = 6, 22 | persistence: float = 0.5, 23 | lacunarity: float = 2.0, 24 | seed: int = random.randint(0, 100000), 25 | max_velocity: float = 10000.0, 26 | ) -> list[tuple[int, int]]: 27 | """ 28 | Generate mouse movements with realistic acceleration patterns and corrective movements. 29 | """ 30 | random.seed(seed) 31 | start_time = time.time() 32 | coordinates = [] 33 | 34 | phases = [ 35 | (MouseState.ACCELERATING, 0.2), # Initial burst 36 | (MouseState.PRECISE_MOVEMENT, 0.3), # Careful adjustments 37 | (MouseState.DECELERATING, 0.2), # Slowdown 38 | (MouseState.PRECISE_MOVEMENT, 0.2), # Final adjustments 39 | (MouseState.DECELERATING, 0.1), # Final positioning 40 | ] 41 | 42 | last_x, last_y = 0, 0 43 | last_time = start_time 44 | current_velocity = 0 45 | phase_start_time = start_time 46 | current_phase_idx = 0 47 | 48 | while time.time() - start_time < duration and current_phase_idx < len(phases): 49 | current_time = time.time() 50 | dt = current_time - last_time 51 | phase_elapsed = current_time - phase_start_time 52 | 53 | current_state, phase_duration = phases[current_phase_idx] 54 | phase_progress = phase_elapsed / (phase_duration * duration) 55 | 56 | if phase_progress >= 1.0: 57 | current_phase_idx += 1 58 | phase_start_time = current_time 59 | continue 60 | 61 | t = (current_time - start_time) / duration 62 | x_noise = pnoise2(t * 3, seed, octaves=octaves, persistence=persistence, lacunarity=lacunarity) 63 | y_noise = pnoise2(t * 3, seed + 1, octaves=octaves, persistence=persistence, lacunarity=lacunarity) 64 | 65 | if current_state == MouseState.ACCELERATING: 66 | # Rapid acceleration with some overshooting 67 | target_velocity = max_velocity * (1 - np.exp(-phase_progress * 5)) 68 | jitter = random.uniform(-0.1, 0.1) * target_velocity 69 | current_velocity = target_velocity + jitter 70 | 71 | elif current_state == MouseState.PRECISE_MOVEMENT: 72 | # Small corrective movements with reduced speed 73 | target_velocity = max_velocity * 0.2 * (np.sin(phase_progress * 4 * np.pi) * 0.5 + 0.5) 74 | current_velocity = target_velocity * random.uniform(0.8, 1.2) 75 | 76 | elif current_state == MouseState.DECELERATING: 77 | # Smooth deceleration with micro-adjustments 78 | target_velocity = max_velocity * np.exp(-phase_progress * 3) 79 | current_velocity = target_velocity * random.uniform(0.9, 1.1) 80 | 81 | max_movement = current_velocity * dt 82 | movement_angle = np.arctan2(y_noise, x_noise) + random.uniform(-0.1, 0.1) 83 | 84 | dx = np.cos(movement_angle) * max_movement 85 | dy = np.sin(movement_angle) * max_movement 86 | 87 | # Add micro-corrections (tremor) 88 | if current_state == MouseState.PRECISE_MOVEMENT: 89 | tremor_amplitude = 2.0 90 | dx += random.uniform(-tremor_amplitude, tremor_amplitude) 91 | dy += random.uniform(-tremor_amplitude, tremor_amplitude) 92 | 93 | new_x = int(last_x + dx) 94 | new_y = int(last_y + dy) 95 | 96 | coordinates.append((new_x, new_y)) 97 | 98 | last_x, last_y = new_x, new_y 99 | last_time = current_time 100 | time.sleep(0.01) 101 | 102 | return coordinates 103 | 104 | @staticmethod 105 | def generate_coordinates( 106 | from_x: int = 0, from_y: int = 0, to_x: int = 1000, to_y: int = 1000 107 | ) -> list[tuple[int, int]]: 108 | """ 109 | Generate a list of coordinates from (from_x, from_y) to (to_x, to_y) using Perlin noise. 110 | """ 111 | movements = OxyMouse._generate_movements() 112 | 113 | x_scale = (to_x - from_x) / (max(m[0] for m in movements) - min(m[0] for m in movements)) 114 | y_scale = (to_y - from_y) / (max(m[1] for m in movements) - min(m[1] for m in movements)) 115 | 116 | scaled_movements = [ 117 | (int(from_x + (m[0] - movements[0][0]) * x_scale), int(from_y + (m[1] - movements[0][1]) * y_scale)) 118 | for m in movements 119 | ] 120 | 121 | return scaled_movements 122 | 123 | @staticmethod 124 | def generate_random_coordinates(viewport_width: int = 1920, viewport_height: int = 1080) -> list[tuple[int, int]]: 125 | """ 126 | Generate random coordinates within the given viewport dimensions. 127 | """ 128 | 129 | movements = OxyMouse._generate_movements() 130 | return movements 131 | 132 | @staticmethod 133 | def generate_scroll_coordinates(start_y: int = 0, end_y: int = 1000) -> list[tuple[int, int]]: 134 | """ 135 | Generate a list of y-coordinates for scrolling from start_y to end_y. 136 | """ 137 | movements = OxyMouse._generate_movements() 138 | 139 | y_coords = [int(start_y + (m[1] / 1080) * (end_y - start_y)) for m in movements] 140 | 141 | y_coords.append(end_y) 142 | x_coords = [0] * len(y_coords) 143 | return list(zip(x_coords, y_coords)) 144 | -------------------------------------------------------------------------------- /oxymouse/algorithms/perlin_mouse/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxylabs/OxyMouse/da69ab6e3b35f5fde0c2f72711e1e145816841e2/oxymouse/algorithms/perlin_mouse/__init__.py -------------------------------------------------------------------------------- /oxymouse/algorithms/perlin_mouse/perlin_mouse.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | 4 | from noise import pnoise2 5 | 6 | from oxymouse.algorithms.base import MouseMovement 7 | 8 | 9 | class PerlinMouse(MouseMovement): 10 | @staticmethod 11 | def generate_perlin_mouse_movements( 12 | duration: float = 1.0, 13 | octaves: int = 6, 14 | persistence: float = 0.5, 15 | lacunarity: float = 2.0, 16 | seed: int = random.randint(0, 100000), 17 | ) -> list[tuple[int, int]]: 18 | """ 19 | Generate mouse movements using Perlin noise. 20 | 21 | :param duration: Duration of the movement in seconds 22 | :param octaves: Number of octaves for the noise 23 | :param persistence: Persistence for the noise 24 | :param lacunarity: Lacunarity for the noise 25 | :param seed: Seed for reproducible results 26 | """ 27 | start_time = time.time() 28 | screen_width, screen_height = 1920, 1080 29 | 30 | coordinates = [] 31 | 32 | while time.time() - start_time < duration: 33 | # Generate noise values 34 | t = (time.time() - start_time) / duration 35 | x_noise = pnoise2(t, seed, octaves=octaves, persistence=persistence, lacunarity=lacunarity) 36 | y_noise = pnoise2(t, seed + 1, octaves=octaves, persistence=persistence, lacunarity=lacunarity) 37 | 38 | # Map noise to screen coordinates 39 | x = int((x_noise + 1) / 2 * screen_width) 40 | y = int((y_noise + 1) / 2 * screen_height) 41 | 42 | coordinates.append((x, y)) 43 | 44 | time.sleep(0.01) 45 | return coordinates 46 | 47 | @staticmethod 48 | def generate_coordinates( 49 | from_x: int = 0, from_y: int = 0, to_x: int = 1000, to_y: int = 1000 50 | ) -> list[tuple[int, int]]: 51 | """ 52 | Generate a list of coordinates from (from_x, from_y) to (to_x, to_y) using Perlin noise. 53 | """ 54 | movements = PerlinMouse.generate_perlin_mouse_movements() 55 | 56 | # Scale and translate the movements to fit the desired start and end points 57 | x_scale = (to_x - from_x) / (max(m[0] for m in movements) - min(m[0] for m in movements)) 58 | y_scale = (to_y - from_y) / (max(m[1] for m in movements) - min(m[1] for m in movements)) 59 | 60 | scaled_movements = [ 61 | (int(from_x + (m[0] - movements[0][0]) * x_scale), int(from_y + (m[1] - movements[0][1]) * y_scale)) 62 | for m in movements 63 | ] 64 | 65 | return scaled_movements 66 | 67 | @staticmethod 68 | def generate_random_coordinates(viewport_width: int = 1920, viewport_height: int = 1080) -> list[tuple[int, int]]: 69 | """ 70 | Generate random coordinates within the given viewport dimensions using Perlin noise. 71 | """ 72 | 73 | movements = PerlinMouse.generate_perlin_mouse_movements() 74 | return movements 75 | 76 | @staticmethod 77 | def generate_scroll_coordinates(start_y: int = 0, end_y: int = 1000) -> list[tuple[int, int]]: 78 | """ 79 | Generate a list of y-coordinates for scrolling from start_y to end_y using Perlin noise. 80 | """ 81 | movements = PerlinMouse.generate_perlin_mouse_movements() 82 | 83 | y_coords = [int(start_y + (m[1] / 1080) * (end_y - start_y)) for m in movements] 84 | 85 | y_coords.append(end_y) 86 | x_coords = [0] * len(y_coords) 87 | return list(zip(x_coords, y_coords)) 88 | -------------------------------------------------------------------------------- /oxymouse/config.py: -------------------------------------------------------------------------------- 1 | from oxymouse.algorithms.bezier_mouse.bezier_mouse import BezierMouse 2 | from oxymouse.algorithms.gaussian_mouse.gaussian_mouse import GaussianMouse 3 | from oxymouse.algorithms.oxy.oxy_mouse import OxyMouse 4 | from oxymouse.algorithms.perlin_mouse.perlin_mouse import PerlinMouse 5 | 6 | mouses = {"perlin": PerlinMouse(), "bezier": BezierMouse(), "gaussian": GaussianMouse(), "oxy": OxyMouse()} 7 | -------------------------------------------------------------------------------- /oxymouse/oxymouse.py: -------------------------------------------------------------------------------- 1 | from oxymouse.algorithms.base import MouseMovement 2 | from oxymouse.config import mouses 3 | 4 | 5 | class OxyMouse: 6 | def __init__(self, algorithm: str) -> None: 7 | self.mouse: MouseMovement 8 | 9 | self.mouse = mouses.get(algorithm) 10 | if not self.mouse: 11 | raise ValueError("Invalid algorithm") 12 | 13 | def generate_coordinates( 14 | self, from_x: int = 0, from_y: int = 0, to_x: int = 1000, to_y: int = 1000 15 | ) -> list[tuple[int, int]]: 16 | return self.mouse.generate_coordinates(from_x, from_y, to_x, to_y) 17 | 18 | def generate_random_coordinates( 19 | self, viewport_width: int = 1920, viewport_height: int = 1080 20 | ) -> list[tuple[int, int]]: 21 | return self.mouse.generate_random_coordinates(viewport_width, viewport_height) 22 | 23 | def generate_scroll_coordinates(self, start_y: int = 0, end_y: int = 1000) -> list[tuple[int, int]]: 24 | return self.mouse.generate_scroll_coordinates(start_y, end_y) 25 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "astroid" 5 | version = "3.3.4" 6 | description = "An abstract syntax tree for Python with inference support." 7 | optional = false 8 | python-versions = ">=3.9.0" 9 | files = [ 10 | {file = "astroid-3.3.4-py3-none-any.whl", hash = "sha256:5eba185467253501b62a9f113c263524b4f5d55e1b30456370eed4cdbd6438fd"}, 11 | {file = "astroid-3.3.4.tar.gz", hash = "sha256:e73d0b62dd680a7c07cb2cd0ce3c22570b044dd01bd994bc3a2dd16c6cbba162"}, 12 | ] 13 | 14 | [package.dependencies] 15 | typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} 16 | 17 | [[package]] 18 | name = "click" 19 | version = "8.1.7" 20 | description = "Composable command line interface toolkit" 21 | optional = false 22 | python-versions = ">=3.7" 23 | files = [ 24 | {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, 25 | {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, 26 | ] 27 | 28 | [package.dependencies] 29 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 30 | 31 | [[package]] 32 | name = "colorama" 33 | version = "0.4.6" 34 | description = "Cross-platform colored terminal text." 35 | optional = false 36 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 37 | files = [ 38 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 39 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 40 | ] 41 | 42 | [[package]] 43 | name = "contourpy" 44 | version = "1.3.0" 45 | description = "Python library for calculating contours of 2D quadrilateral grids" 46 | optional = false 47 | python-versions = ">=3.9" 48 | files = [ 49 | {file = "contourpy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:880ea32e5c774634f9fcd46504bf9f080a41ad855f4fef54f5380f5133d343c7"}, 50 | {file = "contourpy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:76c905ef940a4474a6289c71d53122a4f77766eef23c03cd57016ce19d0f7b42"}, 51 | {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92f8557cbb07415a4d6fa191f20fd9d2d9eb9c0b61d1b2f52a8926e43c6e9af7"}, 52 | {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36f965570cff02b874773c49bfe85562b47030805d7d8360748f3eca570f4cab"}, 53 | {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cacd81e2d4b6f89c9f8a5b69b86490152ff39afc58a95af002a398273e5ce589"}, 54 | {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69375194457ad0fad3a839b9e29aa0b0ed53bb54db1bfb6c3ae43d111c31ce41"}, 55 | {file = "contourpy-1.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a52040312b1a858b5e31ef28c2e865376a386c60c0e248370bbea2d3f3b760d"}, 56 | {file = "contourpy-1.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3faeb2998e4fcb256542e8a926d08da08977f7f5e62cf733f3c211c2a5586223"}, 57 | {file = "contourpy-1.3.0-cp310-cp310-win32.whl", hash = "sha256:36e0cff201bcb17a0a8ecc7f454fe078437fa6bda730e695a92f2d9932bd507f"}, 58 | {file = "contourpy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:87ddffef1dbe5e669b5c2440b643d3fdd8622a348fe1983fad7a0f0ccb1cd67b"}, 59 | {file = "contourpy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fa4c02abe6c446ba70d96ece336e621efa4aecae43eaa9b030ae5fb92b309ad"}, 60 | {file = "contourpy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:834e0cfe17ba12f79963861e0f908556b2cedd52e1f75e6578801febcc6a9f49"}, 61 | {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbc4c3217eee163fa3984fd1567632b48d6dfd29216da3ded3d7b844a8014a66"}, 62 | {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4865cd1d419e0c7a7bf6de1777b185eebdc51470800a9f42b9e9decf17762081"}, 63 | {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:303c252947ab4b14c08afeb52375b26781ccd6a5ccd81abcdfc1fafd14cf93c1"}, 64 | {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637f674226be46f6ba372fd29d9523dd977a291f66ab2a74fbeb5530bb3f445d"}, 65 | {file = "contourpy-1.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:76a896b2f195b57db25d6b44e7e03f221d32fe318d03ede41f8b4d9ba1bff53c"}, 66 | {file = "contourpy-1.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e1fd23e9d01591bab45546c089ae89d926917a66dceb3abcf01f6105d927e2cb"}, 67 | {file = "contourpy-1.3.0-cp311-cp311-win32.whl", hash = "sha256:d402880b84df3bec6eab53cd0cf802cae6a2ef9537e70cf75e91618a3801c20c"}, 68 | {file = "contourpy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:6cb6cc968059db9c62cb35fbf70248f40994dfcd7aa10444bbf8b3faeb7c2d67"}, 69 | {file = "contourpy-1.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:570ef7cf892f0afbe5b2ee410c507ce12e15a5fa91017a0009f79f7d93a1268f"}, 70 | {file = "contourpy-1.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:da84c537cb8b97d153e9fb208c221c45605f73147bd4cadd23bdae915042aad6"}, 71 | {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0be4d8425bfa755e0fd76ee1e019636ccc7c29f77a7c86b4328a9eb6a26d0639"}, 72 | {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c0da700bf58f6e0b65312d0a5e695179a71d0163957fa381bb3c1f72972537c"}, 73 | {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb8b141bb00fa977d9122636b16aa67d37fd40a3d8b52dd837e536d64b9a4d06"}, 74 | {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3634b5385c6716c258d0419c46d05c8aa7dc8cb70326c9a4fb66b69ad2b52e09"}, 75 | {file = "contourpy-1.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0dce35502151b6bd35027ac39ba6e5a44be13a68f55735c3612c568cac3805fd"}, 76 | {file = "contourpy-1.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea348f053c645100612b333adc5983d87be69acdc6d77d3169c090d3b01dc35"}, 77 | {file = "contourpy-1.3.0-cp312-cp312-win32.whl", hash = "sha256:90f73a5116ad1ba7174341ef3ea5c3150ddf20b024b98fb0c3b29034752c8aeb"}, 78 | {file = "contourpy-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:b11b39aea6be6764f84360fce6c82211a9db32a7c7de8fa6dd5397cf1d079c3b"}, 79 | {file = "contourpy-1.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3e1c7fa44aaae40a2247e2e8e0627f4bea3dd257014764aa644f319a5f8600e3"}, 80 | {file = "contourpy-1.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:364174c2a76057feef647c802652f00953b575723062560498dc7930fc9b1cb7"}, 81 | {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b238b3b3b649e09ce9aaf51f0c261d38644bdfa35cbaf7b263457850957a84"}, 82 | {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d51fca85f9f7ad0b65b4b9fe800406d0d77017d7270d31ec3fb1cc07358fdea0"}, 83 | {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:732896af21716b29ab3e988d4ce14bc5133733b85956316fb0c56355f398099b"}, 84 | {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d73f659398a0904e125280836ae6f88ba9b178b2fed6884f3b1f95b989d2c8da"}, 85 | {file = "contourpy-1.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c6c7c2408b7048082932cf4e641fa3b8ca848259212f51c8c59c45aa7ac18f14"}, 86 | {file = "contourpy-1.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f317576606de89da6b7e0861cf6061f6146ead3528acabff9236458a6ba467f8"}, 87 | {file = "contourpy-1.3.0-cp313-cp313-win32.whl", hash = "sha256:31cd3a85dbdf1fc002280c65caa7e2b5f65e4a973fcdf70dd2fdcb9868069294"}, 88 | {file = "contourpy-1.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4553c421929ec95fb07b3aaca0fae668b2eb5a5203d1217ca7c34c063c53d087"}, 89 | {file = "contourpy-1.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:345af746d7766821d05d72cb8f3845dfd08dd137101a2cb9b24de277d716def8"}, 90 | {file = "contourpy-1.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3bb3808858a9dc68f6f03d319acd5f1b8a337e6cdda197f02f4b8ff67ad2057b"}, 91 | {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:420d39daa61aab1221567b42eecb01112908b2cab7f1b4106a52caaec8d36973"}, 92 | {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d63ee447261e963af02642ffcb864e5a2ee4cbfd78080657a9880b8b1868e18"}, 93 | {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:167d6c890815e1dac9536dca00828b445d5d0df4d6a8c6adb4a7ec3166812fa8"}, 94 | {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:710a26b3dc80c0e4febf04555de66f5fd17e9cf7170a7b08000601a10570bda6"}, 95 | {file = "contourpy-1.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:75ee7cb1a14c617f34a51d11fa7524173e56551646828353c4af859c56b766e2"}, 96 | {file = "contourpy-1.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:33c92cdae89ec5135d036e7218e69b0bb2851206077251f04a6c4e0e21f03927"}, 97 | {file = "contourpy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a11077e395f67ffc2c44ec2418cfebed032cd6da3022a94fc227b6faf8e2acb8"}, 98 | {file = "contourpy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e8134301d7e204c88ed7ab50028ba06c683000040ede1d617298611f9dc6240c"}, 99 | {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e12968fdfd5bb45ffdf6192a590bd8ddd3ba9e58360b29683c6bb71a7b41edca"}, 100 | {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fd2a0fc506eccaaa7595b7e1418951f213cf8255be2600f1ea1b61e46a60c55f"}, 101 | {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfb5c62ce023dfc410d6059c936dcf96442ba40814aefbfa575425a3a7f19dc"}, 102 | {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68a32389b06b82c2fdd68276148d7b9275b5f5cf13e5417e4252f6d1a34f72a2"}, 103 | {file = "contourpy-1.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:94e848a6b83da10898cbf1311a815f770acc9b6a3f2d646f330d57eb4e87592e"}, 104 | {file = "contourpy-1.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d78ab28a03c854a873787a0a42254a0ccb3cb133c672f645c9f9c8f3ae9d0800"}, 105 | {file = "contourpy-1.3.0-cp39-cp39-win32.whl", hash = "sha256:81cb5ed4952aae6014bc9d0421dec7c5835c9c8c31cdf51910b708f548cf58e5"}, 106 | {file = "contourpy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:14e262f67bd7e6eb6880bc564dcda30b15e351a594657e55b7eec94b6ef72843"}, 107 | {file = "contourpy-1.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fe41b41505a5a33aeaed2a613dccaeaa74e0e3ead6dd6fd3a118fb471644fd6c"}, 108 | {file = "contourpy-1.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca7e17a65f72a5133bdbec9ecf22401c62bcf4821361ef7811faee695799779"}, 109 | {file = "contourpy-1.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ec4dc6bf570f5b22ed0d7efba0dfa9c5b9e0431aeea7581aa217542d9e809a4"}, 110 | {file = "contourpy-1.3.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:00ccd0dbaad6d804ab259820fa7cb0b8036bda0686ef844d24125d8287178ce0"}, 111 | {file = "contourpy-1.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ca947601224119117f7c19c9cdf6b3ab54c5726ef1d906aa4a69dfb6dd58102"}, 112 | {file = "contourpy-1.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6ec93afeb848a0845a18989da3beca3eec2c0f852322efe21af1931147d12cb"}, 113 | {file = "contourpy-1.3.0.tar.gz", hash = "sha256:7ffa0db17717a8ffb127efd0c95a4362d996b892c2904db72428d5b52e1938a4"}, 114 | ] 115 | 116 | [package.dependencies] 117 | numpy = ">=1.23" 118 | 119 | [package.extras] 120 | bokeh = ["bokeh", "selenium"] 121 | docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] 122 | mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.11.1)", "types-Pillow"] 123 | test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] 124 | test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] 125 | 126 | [[package]] 127 | name = "cycler" 128 | version = "0.12.1" 129 | description = "Composable style cycles" 130 | optional = false 131 | python-versions = ">=3.8" 132 | files = [ 133 | {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, 134 | {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, 135 | ] 136 | 137 | [package.extras] 138 | docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] 139 | tests = ["pytest", "pytest-cov", "pytest-xdist"] 140 | 141 | [[package]] 142 | name = "dill" 143 | version = "0.3.8" 144 | description = "serialize all of Python" 145 | optional = false 146 | python-versions = ">=3.8" 147 | files = [ 148 | {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, 149 | {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, 150 | ] 151 | 152 | [package.extras] 153 | graph = ["objgraph (>=1.7.2)"] 154 | profile = ["gprof2dot (>=2022.7.29)"] 155 | 156 | [[package]] 157 | name = "fonttools" 158 | version = "4.54.1" 159 | description = "Tools to manipulate font files" 160 | optional = false 161 | python-versions = ">=3.8" 162 | files = [ 163 | {file = "fonttools-4.54.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ed7ee041ff7b34cc62f07545e55e1468808691dddfd315d51dd82a6b37ddef2"}, 164 | {file = "fonttools-4.54.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41bb0b250c8132b2fcac148e2e9198e62ff06f3cc472065dff839327945c5882"}, 165 | {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7965af9b67dd546e52afcf2e38641b5be956d68c425bef2158e95af11d229f10"}, 166 | {file = "fonttools-4.54.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:278913a168f90d53378c20c23b80f4e599dca62fbffae4cc620c8eed476b723e"}, 167 | {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0e88e3018ac809b9662615072dcd6b84dca4c2d991c6d66e1970a112503bba7e"}, 168 | {file = "fonttools-4.54.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4aa4817f0031206e637d1e685251ac61be64d1adef111060df84fdcbc6ab6c44"}, 169 | {file = "fonttools-4.54.1-cp310-cp310-win32.whl", hash = "sha256:7e3b7d44e18c085fd8c16dcc6f1ad6c61b71ff463636fcb13df7b1b818bd0c02"}, 170 | {file = "fonttools-4.54.1-cp310-cp310-win_amd64.whl", hash = "sha256:dd9cc95b8d6e27d01e1e1f1fae8559ef3c02c76317da650a19047f249acd519d"}, 171 | {file = "fonttools-4.54.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5419771b64248484299fa77689d4f3aeed643ea6630b2ea750eeab219588ba20"}, 172 | {file = "fonttools-4.54.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:301540e89cf4ce89d462eb23a89464fef50915255ece765d10eee8b2bf9d75b2"}, 173 | {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ae5091547e74e7efecc3cbf8e75200bc92daaeb88e5433c5e3e95ea8ce5aa7"}, 174 | {file = "fonttools-4.54.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82834962b3d7c5ca98cb56001c33cf20eb110ecf442725dc5fdf36d16ed1ab07"}, 175 | {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d26732ae002cc3d2ecab04897bb02ae3f11f06dd7575d1df46acd2f7c012a8d8"}, 176 | {file = "fonttools-4.54.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58974b4987b2a71ee08ade1e7f47f410c367cdfc5a94fabd599c88165f56213a"}, 177 | {file = "fonttools-4.54.1-cp311-cp311-win32.whl", hash = "sha256:ab774fa225238986218a463f3fe151e04d8c25d7de09df7f0f5fce27b1243dbc"}, 178 | {file = "fonttools-4.54.1-cp311-cp311-win_amd64.whl", hash = "sha256:07e005dc454eee1cc60105d6a29593459a06321c21897f769a281ff2d08939f6"}, 179 | {file = "fonttools-4.54.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:54471032f7cb5fca694b5f1a0aaeba4af6e10ae989df408e0216f7fd6cdc405d"}, 180 | {file = "fonttools-4.54.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fa92cb248e573daab8d032919623cc309c005086d743afb014c836636166f08"}, 181 | {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a911591200114969befa7f2cb74ac148bce5a91df5645443371aba6d222e263"}, 182 | {file = "fonttools-4.54.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93d458c8a6a354dc8b48fc78d66d2a8a90b941f7fec30e94c7ad9982b1fa6bab"}, 183 | {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5eb2474a7c5be8a5331146758debb2669bf5635c021aee00fd7c353558fc659d"}, 184 | {file = "fonttools-4.54.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9c563351ddc230725c4bdf7d9e1e92cbe6ae8553942bd1fb2b2ff0884e8b714"}, 185 | {file = "fonttools-4.54.1-cp312-cp312-win32.whl", hash = "sha256:fdb062893fd6d47b527d39346e0c5578b7957dcea6d6a3b6794569370013d9ac"}, 186 | {file = "fonttools-4.54.1-cp312-cp312-win_amd64.whl", hash = "sha256:e4564cf40cebcb53f3dc825e85910bf54835e8a8b6880d59e5159f0f325e637e"}, 187 | {file = "fonttools-4.54.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6e37561751b017cf5c40fce0d90fd9e8274716de327ec4ffb0df957160be3bff"}, 188 | {file = "fonttools-4.54.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:357cacb988a18aace66e5e55fe1247f2ee706e01debc4b1a20d77400354cddeb"}, 189 | {file = "fonttools-4.54.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e953cc0bddc2beaf3a3c3b5dd9ab7554677da72dfaf46951e193c9653e515a"}, 190 | {file = "fonttools-4.54.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58d29b9a294573d8319f16f2f79e42428ba9b6480442fa1836e4eb89c4d9d61c"}, 191 | {file = "fonttools-4.54.1-cp313-cp313-win32.whl", hash = "sha256:9ef1b167e22709b46bf8168368b7b5d3efeaaa746c6d39661c1b4405b6352e58"}, 192 | {file = "fonttools-4.54.1-cp313-cp313-win_amd64.whl", hash = "sha256:262705b1663f18c04250bd1242b0515d3bbae177bee7752be67c979b7d47f43d"}, 193 | {file = "fonttools-4.54.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ed2f80ca07025551636c555dec2b755dd005e2ea8fbeb99fc5cdff319b70b23b"}, 194 | {file = "fonttools-4.54.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9dc080e5a1c3b2656caff2ac2633d009b3a9ff7b5e93d0452f40cd76d3da3b3c"}, 195 | {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d152d1be65652fc65e695e5619e0aa0982295a95a9b29b52b85775243c06556"}, 196 | {file = "fonttools-4.54.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8583e563df41fdecef31b793b4dd3af8a9caa03397be648945ad32717a92885b"}, 197 | {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0d1d353ef198c422515a3e974a1e8d5b304cd54a4c2eebcae708e37cd9eeffb1"}, 198 | {file = "fonttools-4.54.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:fda582236fee135d4daeca056c8c88ec5f6f6d88a004a79b84a02547c8f57386"}, 199 | {file = "fonttools-4.54.1-cp38-cp38-win32.whl", hash = "sha256:e7d82b9e56716ed32574ee106cabca80992e6bbdcf25a88d97d21f73a0aae664"}, 200 | {file = "fonttools-4.54.1-cp38-cp38-win_amd64.whl", hash = "sha256:ada215fd079e23e060157aab12eba0d66704316547f334eee9ff26f8c0d7b8ab"}, 201 | {file = "fonttools-4.54.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f5b8a096e649768c2f4233f947cf9737f8dbf8728b90e2771e2497c6e3d21d13"}, 202 | {file = "fonttools-4.54.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e10d2e0a12e18f4e2dd031e1bf7c3d7017be5c8dbe524d07706179f355c5dac"}, 203 | {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31c32d7d4b0958600eac75eaf524b7b7cb68d3a8c196635252b7a2c30d80e986"}, 204 | {file = "fonttools-4.54.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c39287f5c8f4a0c5a55daf9eaf9ccd223ea59eed3f6d467133cc727d7b943a55"}, 205 | {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a7a310c6e0471602fe3bf8efaf193d396ea561486aeaa7adc1f132e02d30c4b9"}, 206 | {file = "fonttools-4.54.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d3b659d1029946f4ff9b6183984578041b520ce0f8fb7078bb37ec7445806b33"}, 207 | {file = "fonttools-4.54.1-cp39-cp39-win32.whl", hash = "sha256:e96bc94c8cda58f577277d4a71f51c8e2129b8b36fd05adece6320dd3d57de8a"}, 208 | {file = "fonttools-4.54.1-cp39-cp39-win_amd64.whl", hash = "sha256:e8a4b261c1ef91e7188a30571be6ad98d1c6d9fa2427244c545e2fa0a2494dd7"}, 209 | {file = "fonttools-4.54.1-py3-none-any.whl", hash = "sha256:37cddd62d83dc4f72f7c3f3c2bcf2697e89a30efb152079896544a93907733bd"}, 210 | {file = "fonttools-4.54.1.tar.gz", hash = "sha256:957f669d4922f92c171ba01bef7f29410668db09f6c02111e22b2bce446f3285"}, 211 | ] 212 | 213 | [package.extras] 214 | all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] 215 | graphite = ["lz4 (>=1.7.4.2)"] 216 | interpolatable = ["munkres", "pycairo", "scipy"] 217 | lxml = ["lxml (>=4.0)"] 218 | pathops = ["skia-pathops (>=0.5.0)"] 219 | plot = ["matplotlib"] 220 | repacker = ["uharfbuzz (>=0.23.0)"] 221 | symfont = ["sympy"] 222 | type1 = ["xattr"] 223 | ufo = ["fs (>=2.2.0,<3)"] 224 | unicode = ["unicodedata2 (>=15.1.0)"] 225 | woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] 226 | 227 | [[package]] 228 | name = "isort" 229 | version = "5.13.2" 230 | description = "A Python utility / library to sort Python imports." 231 | optional = false 232 | python-versions = ">=3.8.0" 233 | files = [ 234 | {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, 235 | {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, 236 | ] 237 | 238 | [package.extras] 239 | colors = ["colorama (>=0.4.6)"] 240 | 241 | [[package]] 242 | name = "kiwisolver" 243 | version = "1.4.7" 244 | description = "A fast implementation of the Cassowary constraint solver" 245 | optional = false 246 | python-versions = ">=3.8" 247 | files = [ 248 | {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6"}, 249 | {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17"}, 250 | {file = "kiwisolver-1.4.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aa0abdf853e09aff551db11fce173e2177d00786c688203f52c87ad7fcd91ef9"}, 251 | {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8d53103597a252fb3ab8b5845af04c7a26d5e7ea8122303dd7a021176a87e8b9"}, 252 | {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:88f17c5ffa8e9462fb79f62746428dd57b46eb931698e42e990ad63103f35e6c"}, 253 | {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a9ca9c710d598fd75ee5de59d5bda2684d9db36a9f50b6125eaea3969c2599"}, 254 | {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4d742cb7af1c28303a51b7a27aaee540e71bb8e24f68c736f6f2ffc82f2bf05"}, 255 | {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28c7fea2196bf4c2f8d46a0415c77a1c480cc0724722f23d7410ffe9842c407"}, 256 | {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e968b84db54f9d42046cf154e02911e39c0435c9801681e3fc9ce8a3c4130278"}, 257 | {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0c18ec74c0472de033e1bebb2911c3c310eef5649133dd0bedf2a169a1b269e5"}, 258 | {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8f0ea6da6d393d8b2e187e6a5e3fb81f5862010a40c3945e2c6d12ae45cfb2ad"}, 259 | {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:f106407dda69ae456dd1227966bf445b157ccc80ba0dff3802bb63f30b74e895"}, 260 | {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84ec80df401cfee1457063732d90022f93951944b5b58975d34ab56bb150dfb3"}, 261 | {file = "kiwisolver-1.4.7-cp310-cp310-win32.whl", hash = "sha256:71bb308552200fb2c195e35ef05de12f0c878c07fc91c270eb3d6e41698c3bcc"}, 262 | {file = "kiwisolver-1.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:44756f9fd339de0fb6ee4f8c1696cfd19b2422e0d70b4cefc1cc7f1f64045a8c"}, 263 | {file = "kiwisolver-1.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:78a42513018c41c2ffd262eb676442315cbfe3c44eed82385c2ed043bc63210a"}, 264 | {file = "kiwisolver-1.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d2b0e12a42fb4e72d509fc994713d099cbb15ebf1103545e8a45f14da2dfca54"}, 265 | {file = "kiwisolver-1.4.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95"}, 266 | {file = "kiwisolver-1.4.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46707a10836894b559e04b0fd143e343945c97fd170d69a2d26d640b4e297935"}, 267 | {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef97b8df011141c9b0f6caf23b29379f87dd13183c978a30a3c546d2c47314cb"}, 268 | {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02"}, 269 | {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:803b8e1459341c1bb56d1c5c010406d5edec8a0713a0945851290a7930679b51"}, 270 | {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9a9e8a507420fe35992ee9ecb302dab68550dedc0da9e2880dd88071c5fb052"}, 271 | {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18"}, 272 | {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6af936f79086a89b3680a280c47ea90b4df7047b5bdf3aa5c524bbedddb9e545"}, 273 | {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3abc5b19d24af4b77d1598a585b8a719beb8569a71568b66f4ebe1fb0449460b"}, 274 | {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:933d4de052939d90afbe6e9d5273ae05fb836cc86c15b686edd4b3560cc0ee36"}, 275 | {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:65e720d2ab2b53f1f72fb5da5fb477455905ce2c88aaa671ff0a447c2c80e8e3"}, 276 | {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3bf1ed55088f214ba6427484c59553123fdd9b218a42bbc8c6496d6754b1e523"}, 277 | {file = "kiwisolver-1.4.7-cp311-cp311-win32.whl", hash = "sha256:4c00336b9dd5ad96d0a558fd18a8b6f711b7449acce4c157e7343ba92dd0cf3d"}, 278 | {file = "kiwisolver-1.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b"}, 279 | {file = "kiwisolver-1.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:e33e8fbd440c917106b237ef1a2f1449dfbb9b6f6e1ce17c94cd6a1e0d438376"}, 280 | {file = "kiwisolver-1.4.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5360cc32706dab3931f738d3079652d20982511f7c0ac5711483e6eab08efff2"}, 281 | {file = "kiwisolver-1.4.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942216596dc64ddb25adb215c3c783215b23626f8d84e8eff8d6d45c3f29f75a"}, 282 | {file = "kiwisolver-1.4.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:48b571ecd8bae15702e4f22d3ff6a0f13e54d3d00cd25216d5e7f658242065ee"}, 283 | {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad42ba922c67c5f219097b28fae965e10045ddf145d2928bfac2eb2e17673640"}, 284 | {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:612a10bdae23404a72941a0fc8fa2660c6ea1217c4ce0dbcab8a8f6543ea9e7f"}, 285 | {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e838bba3a3bac0fe06d849d29772eb1afb9745a59710762e4ba3f4cb8424483"}, 286 | {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22f499f6157236c19f4bbbd472fa55b063db77a16cd74d49afe28992dff8c258"}, 287 | {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693902d433cf585133699972b6d7c42a8b9f8f826ebcaf0132ff55200afc599e"}, 288 | {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4e77f2126c3e0b0d055f44513ed349038ac180371ed9b52fe96a32aa071a5107"}, 289 | {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:657a05857bda581c3656bfc3b20e353c232e9193eb167766ad2dc58b56504948"}, 290 | {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4bfa75a048c056a411f9705856abfc872558e33c055d80af6a380e3658766038"}, 291 | {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:34ea1de54beef1c104422d210c47c7d2a4999bdecf42c7b5718fbe59a4cac383"}, 292 | {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:90da3b5f694b85231cf93586dad5e90e2d71b9428f9aad96952c99055582f520"}, 293 | {file = "kiwisolver-1.4.7-cp312-cp312-win32.whl", hash = "sha256:18e0cca3e008e17fe9b164b55735a325140a5a35faad8de92dd80265cd5eb80b"}, 294 | {file = "kiwisolver-1.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:58cb20602b18f86f83a5c87d3ee1c766a79c0d452f8def86d925e6c60fbf7bfb"}, 295 | {file = "kiwisolver-1.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:f5a8b53bdc0b3961f8b6125e198617c40aeed638b387913bf1ce78afb1b0be2a"}, 296 | {file = "kiwisolver-1.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2e6039dcbe79a8e0f044f1c39db1986a1b8071051efba3ee4d74f5b365f5226e"}, 297 | {file = "kiwisolver-1.4.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a1ecf0ac1c518487d9d23b1cd7139a6a65bc460cd101ab01f1be82ecf09794b6"}, 298 | {file = "kiwisolver-1.4.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ab9ccab2b5bd5702ab0803676a580fffa2aa178c2badc5557a84cc943fcf750"}, 299 | {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f816dd2277f8d63d79f9c8473a79fe54047bc0467754962840782c575522224d"}, 300 | {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf8bcc23ceb5a1b624572a1623b9f79d2c3b337c8c455405ef231933a10da379"}, 301 | {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dea0bf229319828467d7fca8c7c189780aa9ff679c94539eed7532ebe33ed37c"}, 302 | {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c06a4c7cf15ec739ce0e5971b26c93638730090add60e183530d70848ebdd34"}, 303 | {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913983ad2deb14e66d83c28b632fd35ba2b825031f2fa4ca29675e665dfecbe1"}, 304 | {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5337ec7809bcd0f424c6b705ecf97941c46279cf5ed92311782c7c9c2026f07f"}, 305 | {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c26ed10c4f6fa6ddb329a5120ba3b6db349ca192ae211e882970bfc9d91420b"}, 306 | {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c619b101e6de2222c1fcb0531e1b17bbffbe54294bfba43ea0d411d428618c27"}, 307 | {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:073a36c8273647592ea332e816e75ef8da5c303236ec0167196793eb1e34657a"}, 308 | {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3ce6b2b0231bda412463e152fc18335ba32faf4e8c23a754ad50ffa70e4091ee"}, 309 | {file = "kiwisolver-1.4.7-cp313-cp313-win32.whl", hash = "sha256:f4c9aee212bc89d4e13f58be11a56cc8036cabad119259d12ace14b34476fd07"}, 310 | {file = "kiwisolver-1.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:8a3ec5aa8e38fc4c8af308917ce12c536f1c88452ce554027e55b22cbbfbff76"}, 311 | {file = "kiwisolver-1.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:76c8094ac20ec259471ac53e774623eb62e6e1f56cd8690c67ce6ce4fcb05650"}, 312 | {file = "kiwisolver-1.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5d5abf8f8ec1f4e22882273c423e16cae834c36856cac348cfbfa68e01c40f3a"}, 313 | {file = "kiwisolver-1.4.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:aeb3531b196ef6f11776c21674dba836aeea9d5bd1cf630f869e3d90b16cfade"}, 314 | {file = "kiwisolver-1.4.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7d755065e4e866a8086c9bdada157133ff466476a2ad7861828e17b6026e22c"}, 315 | {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08471d4d86cbaec61f86b217dd938a83d85e03785f51121e791a6e6689a3be95"}, 316 | {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bbfcb7165ce3d54a3dfbe731e470f65739c4c1f85bb1018ee912bae139e263b"}, 317 | {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d34eb8494bea691a1a450141ebb5385e4b69d38bb8403b5146ad279f4b30fa3"}, 318 | {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9242795d174daa40105c1d86aba618e8eab7bf96ba8c3ee614da8302a9f95503"}, 319 | {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a0f64a48bb81af7450e641e3fe0b0394d7381e342805479178b3d335d60ca7cf"}, 320 | {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8e045731a5416357638d1700927529e2b8ab304811671f665b225f8bf8d8f933"}, 321 | {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4322872d5772cae7369f8351da1edf255a604ea7087fe295411397d0cfd9655e"}, 322 | {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e1631290ee9271dffe3062d2634c3ecac02c83890ada077d225e081aca8aab89"}, 323 | {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:edcfc407e4eb17e037bca59be0e85a2031a2ac87e4fed26d3e9df88b4165f92d"}, 324 | {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:4d05d81ecb47d11e7f8932bd8b61b720bf0b41199358f3f5e36d38e28f0532c5"}, 325 | {file = "kiwisolver-1.4.7-cp38-cp38-win32.whl", hash = "sha256:b38ac83d5f04b15e515fd86f312479d950d05ce2368d5413d46c088dda7de90a"}, 326 | {file = "kiwisolver-1.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:d83db7cde68459fc803052a55ace60bea2bae361fc3b7a6d5da07e11954e4b09"}, 327 | {file = "kiwisolver-1.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f9362ecfca44c863569d3d3c033dbe8ba452ff8eed6f6b5806382741a1334bd"}, 328 | {file = "kiwisolver-1.4.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e8df2eb9b2bac43ef8b082e06f750350fbbaf2887534a5be97f6cf07b19d9583"}, 329 | {file = "kiwisolver-1.4.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f32d6edbc638cde7652bd690c3e728b25332acbadd7cad670cc4a02558d9c417"}, 330 | {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e2e6c39bd7b9372b0be21456caab138e8e69cc0fc1190a9dfa92bd45a1e6e904"}, 331 | {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dda56c24d869b1193fcc763f1284b9126550eaf84b88bbc7256e15028f19188a"}, 332 | {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79849239c39b5e1fd906556c474d9b0439ea6792b637511f3fe3a41158d89ca8"}, 333 | {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e3bc157fed2a4c02ec468de4ecd12a6e22818d4f09cde2c31ee3226ffbefab2"}, 334 | {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3da53da805b71e41053dc670f9a820d1157aae77b6b944e08024d17bcd51ef88"}, 335 | {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8705f17dfeb43139a692298cb6637ee2e59c0194538153e83e9ee0c75c2eddde"}, 336 | {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:82a5c2f4b87c26bb1a0ef3d16b5c4753434633b83d365cc0ddf2770c93829e3c"}, 337 | {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce8be0466f4c0d585cdb6c1e2ed07232221df101a4c6f28821d2aa754ca2d9e2"}, 338 | {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:409afdfe1e2e90e6ee7fc896f3df9a7fec8e793e58bfa0d052c8a82f99c37abb"}, 339 | {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b9c3f4ee0b9a439d2415012bd1b1cc2df59e4d6a9939f4d669241d30b414327"}, 340 | {file = "kiwisolver-1.4.7-cp39-cp39-win32.whl", hash = "sha256:a79ae34384df2b615eefca647a2873842ac3b596418032bef9a7283675962644"}, 341 | {file = "kiwisolver-1.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:cf0438b42121a66a3a667de17e779330fc0f20b0d97d59d2f2121e182b0505e4"}, 342 | {file = "kiwisolver-1.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:764202cc7e70f767dab49e8df52c7455e8de0df5d858fa801a11aa0d882ccf3f"}, 343 | {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:94252291e3fe68001b1dd747b4c0b3be12582839b95ad4d1b641924d68fd4643"}, 344 | {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b7dfa3b546da08a9f622bb6becdb14b3e24aaa30adba66749d38f3cc7ea9706"}, 345 | {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd3de6481f4ed8b734da5df134cd5a6a64fe32124fe83dde1e5b5f29fe30b1e6"}, 346 | {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a91b5f9f1205845d488c928e8570dcb62b893372f63b8b6e98b863ebd2368ff2"}, 347 | {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40fa14dbd66b8b8f470d5fc79c089a66185619d31645f9b0773b88b19f7223c4"}, 348 | {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:eb542fe7933aa09d8d8f9d9097ef37532a7df6497819d16efe4359890a2f417a"}, 349 | {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bfa1acfa0c54932d5607e19a2c24646fb4c1ae2694437789129cf099789a3b00"}, 350 | {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:eee3ea935c3d227d49b4eb85660ff631556841f6e567f0f7bda972df6c2c9935"}, 351 | {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f3160309af4396e0ed04db259c3ccbfdc3621b5559b5453075e5de555e1f3a1b"}, 352 | {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a17f6a29cf8935e587cc8a4dbfc8368c55edc645283db0ce9801016f83526c2d"}, 353 | {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10849fb2c1ecbfae45a693c070e0320a91b35dd4bcf58172c023b994283a124d"}, 354 | {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:ac542bf38a8a4be2dc6b15248d36315ccc65f0743f7b1a76688ffb6b5129a5c2"}, 355 | {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8b01aac285f91ca889c800042c35ad3b239e704b150cfd3382adfc9dcc780e39"}, 356 | {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48be928f59a1f5c8207154f935334d374e79f2b5d212826307d072595ad76a2e"}, 357 | {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f37cfe618a117e50d8c240555331160d73d0411422b59b5ee217843d7b693608"}, 358 | {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:599b5c873c63a1f6ed7eead644a8a380cfbdf5db91dcb6f85707aaab213b1674"}, 359 | {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:801fa7802e5cfabe3ab0c81a34c323a319b097dfb5004be950482d882f3d7225"}, 360 | {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0c6c43471bc764fad4bc99c5c2d6d16a676b1abf844ca7c8702bdae92df01ee0"}, 361 | {file = "kiwisolver-1.4.7.tar.gz", hash = "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60"}, 362 | ] 363 | 364 | [[package]] 365 | name = "markdown-it-py" 366 | version = "3.0.0" 367 | description = "Python port of markdown-it. Markdown parsing, done right!" 368 | optional = false 369 | python-versions = ">=3.8" 370 | files = [ 371 | {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, 372 | {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, 373 | ] 374 | 375 | [package.dependencies] 376 | mdurl = ">=0.1,<1.0" 377 | 378 | [package.extras] 379 | benchmarking = ["psutil", "pytest", "pytest-benchmark"] 380 | code-style = ["pre-commit (>=3.0,<4.0)"] 381 | compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] 382 | linkify = ["linkify-it-py (>=1,<3)"] 383 | plugins = ["mdit-py-plugins"] 384 | profiling = ["gprof2dot"] 385 | rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] 386 | testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] 387 | 388 | [[package]] 389 | name = "matplotlib" 390 | version = "3.9.2" 391 | description = "Python plotting package" 392 | optional = false 393 | python-versions = ">=3.9" 394 | files = [ 395 | {file = "matplotlib-3.9.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9d78bbc0cbc891ad55b4f39a48c22182e9bdaea7fc0e5dbd364f49f729ca1bbb"}, 396 | {file = "matplotlib-3.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c375cc72229614632c87355366bdf2570c2dac01ac66b8ad048d2dabadf2d0d4"}, 397 | {file = "matplotlib-3.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d94ff717eb2bd0b58fe66380bd8b14ac35f48a98e7c6765117fe67fb7684e64"}, 398 | {file = "matplotlib-3.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab68d50c06938ef28681073327795c5db99bb4666214d2d5f880ed11aeaded66"}, 399 | {file = "matplotlib-3.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:65aacf95b62272d568044531e41de26285d54aec8cb859031f511f84bd8b495a"}, 400 | {file = "matplotlib-3.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:3fd595f34aa8a55b7fc8bf9ebea8aa665a84c82d275190a61118d33fbc82ccae"}, 401 | {file = "matplotlib-3.9.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772"}, 402 | {file = "matplotlib-3.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41"}, 403 | {file = "matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f"}, 404 | {file = "matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447"}, 405 | {file = "matplotlib-3.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7741f26a58a240f43bee74965c4882b6c93df3e7eb3de160126d8c8f53a6ae6e"}, 406 | {file = "matplotlib-3.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7"}, 407 | {file = "matplotlib-3.9.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ac43031375a65c3196bee99f6001e7fa5bdfb00ddf43379d3c0609bdca042df9"}, 408 | {file = "matplotlib-3.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be0fc24a5e4531ae4d8e858a1a548c1fe33b176bb13eff7f9d0d38ce5112a27d"}, 409 | {file = "matplotlib-3.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf81de2926c2db243c9b2cbc3917619a0fc85796c6ba4e58f541df814bbf83c7"}, 410 | {file = "matplotlib-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ee45bc4245533111ced13f1f2cace1e7f89d1c793390392a80c139d6cf0e6c"}, 411 | {file = "matplotlib-3.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:306c8dfc73239f0e72ac50e5a9cf19cc4e8e331dd0c54f5e69ca8758550f1e1e"}, 412 | {file = "matplotlib-3.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:5413401594cfaff0052f9d8b1aafc6d305b4bd7c4331dccd18f561ff7e1d3bd3"}, 413 | {file = "matplotlib-3.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:18128cc08f0d3cfff10b76baa2f296fc28c4607368a8402de61bb3f2eb33c7d9"}, 414 | {file = "matplotlib-3.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4876d7d40219e8ae8bb70f9263bcbe5714415acfdf781086601211335e24f8aa"}, 415 | {file = "matplotlib-3.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d9f07a80deab4bb0b82858a9e9ad53d1382fd122be8cde11080f4e7dfedb38b"}, 416 | {file = "matplotlib-3.9.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7c0410f181a531ec4e93bbc27692f2c71a15c2da16766f5ba9761e7ae518413"}, 417 | {file = "matplotlib-3.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:909645cce2dc28b735674ce0931a4ac94e12f5b13f6bb0b5a5e65e7cea2c192b"}, 418 | {file = "matplotlib-3.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:f32c7410c7f246838a77d6d1eff0c0f87f3cb0e7c4247aebea71a6d5a68cab49"}, 419 | {file = "matplotlib-3.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:37e51dd1c2db16ede9cfd7b5cabdfc818b2c6397c83f8b10e0e797501c963a03"}, 420 | {file = "matplotlib-3.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b82c5045cebcecd8496a4d694d43f9cc84aeeb49fe2133e036b207abe73f4d30"}, 421 | {file = "matplotlib-3.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f053c40f94bc51bc03832a41b4f153d83f2062d88c72b5e79997072594e97e51"}, 422 | {file = "matplotlib-3.9.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbe196377a8248972f5cede786d4c5508ed5f5ca4a1e09b44bda889958b33f8c"}, 423 | {file = "matplotlib-3.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5816b1e1fe8c192cbc013f8f3e3368ac56fbecf02fb41b8f8559303f24c5015e"}, 424 | {file = "matplotlib-3.9.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:cef2a73d06601437be399908cf13aee74e86932a5ccc6ccdf173408ebc5f6bb2"}, 425 | {file = "matplotlib-3.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e0830e188029c14e891fadd99702fd90d317df294c3298aad682739c5533721a"}, 426 | {file = "matplotlib-3.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ba9c1299c920964e8d3857ba27173b4dbb51ca4bab47ffc2c2ba0eb5e2cbc5"}, 427 | {file = "matplotlib-3.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cd93b91ab47a3616b4d3c42b52f8363b88ca021e340804c6ab2536344fad9ca"}, 428 | {file = "matplotlib-3.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6d1ce5ed2aefcdce11904fc5bbea7d9c21fff3d5f543841edf3dea84451a09ea"}, 429 | {file = "matplotlib-3.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:b2696efdc08648536efd4e1601b5fd491fd47f4db97a5fbfd175549a7365c1b2"}, 430 | {file = "matplotlib-3.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d52a3b618cb1cbb769ce2ee1dcdb333c3ab6e823944e9a2d36e37253815f9556"}, 431 | {file = "matplotlib-3.9.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:039082812cacd6c6bec8e17a9c1e6baca230d4116d522e81e1f63a74d01d2e21"}, 432 | {file = "matplotlib-3.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6758baae2ed64f2331d4fd19be38b7b4eae3ecec210049a26b6a4f3ae1c85dcc"}, 433 | {file = "matplotlib-3.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:050598c2b29e0b9832cde72bcf97627bf00262adbc4a54e2b856426bb2ef0697"}, 434 | {file = "matplotlib-3.9.2.tar.gz", hash = "sha256:96ab43906269ca64a6366934106fa01534454a69e471b7bf3d79083981aaab92"}, 435 | ] 436 | 437 | [package.dependencies] 438 | contourpy = ">=1.0.1" 439 | cycler = ">=0.10" 440 | fonttools = ">=4.22.0" 441 | kiwisolver = ">=1.3.1" 442 | numpy = ">=1.23" 443 | packaging = ">=20.0" 444 | pillow = ">=8" 445 | pyparsing = ">=2.3.1" 446 | python-dateutil = ">=2.7" 447 | 448 | [package.extras] 449 | dev = ["meson-python (>=0.13.1)", "numpy (>=1.25)", "pybind11 (>=2.6)", "setuptools (>=64)", "setuptools_scm (>=7)"] 450 | 451 | [[package]] 452 | name = "mccabe" 453 | version = "0.7.0" 454 | description = "McCabe checker, plugin for flake8" 455 | optional = false 456 | python-versions = ">=3.6" 457 | files = [ 458 | {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, 459 | {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, 460 | ] 461 | 462 | [[package]] 463 | name = "mdurl" 464 | version = "0.1.2" 465 | description = "Markdown URL utilities" 466 | optional = false 467 | python-versions = ">=3.7" 468 | files = [ 469 | {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, 470 | {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, 471 | ] 472 | 473 | [[package]] 474 | name = "mouseinfo" 475 | version = "0.1.3" 476 | description = "An application to display XY position and RGB color information for the pixel currently under the mouse. Works on Python 2 and 3." 477 | optional = false 478 | python-versions = "*" 479 | files = [ 480 | {file = "MouseInfo-0.1.3.tar.gz", hash = "sha256:2c62fb8885062b8e520a3cce0a297c657adcc08c60952eb05bc8256ef6f7f6e7"}, 481 | ] 482 | 483 | [package.dependencies] 484 | pyperclip = "*" 485 | python3-Xlib = {version = "*", markers = "platform_system == \"Linux\" and python_version >= \"3.0\""} 486 | rubicon-objc = {version = "*", markers = "platform_system == \"Darwin\""} 487 | 488 | [[package]] 489 | name = "mypy" 490 | version = "1.11.2" 491 | description = "Optional static typing for Python" 492 | optional = false 493 | python-versions = ">=3.8" 494 | files = [ 495 | {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, 496 | {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, 497 | {file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"}, 498 | {file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"}, 499 | {file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"}, 500 | {file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"}, 501 | {file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"}, 502 | {file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"}, 503 | {file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"}, 504 | {file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"}, 505 | {file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"}, 506 | {file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"}, 507 | {file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"}, 508 | {file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"}, 509 | {file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"}, 510 | {file = "mypy-1.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b"}, 511 | {file = "mypy-1.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86"}, 512 | {file = "mypy-1.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce"}, 513 | {file = "mypy-1.11.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1"}, 514 | {file = "mypy-1.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b"}, 515 | {file = "mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6"}, 516 | {file = "mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70"}, 517 | {file = "mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d"}, 518 | {file = "mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d"}, 519 | {file = "mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24"}, 520 | {file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"}, 521 | {file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"}, 522 | ] 523 | 524 | [package.dependencies] 525 | mypy-extensions = ">=1.0.0" 526 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 527 | typing-extensions = ">=4.6.0" 528 | 529 | [package.extras] 530 | dmypy = ["psutil (>=4.0)"] 531 | install-types = ["pip"] 532 | mypyc = ["setuptools (>=50)"] 533 | reports = ["lxml"] 534 | 535 | [[package]] 536 | name = "mypy-extensions" 537 | version = "1.0.0" 538 | description = "Type system extensions for programs checked with the mypy type checker." 539 | optional = false 540 | python-versions = ">=3.5" 541 | files = [ 542 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, 543 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, 544 | ] 545 | 546 | [[package]] 547 | name = "noise" 548 | version = "1.2.2" 549 | description = "Perlin noise for Python" 550 | optional = false 551 | python-versions = "*" 552 | files = [ 553 | {file = "noise-1.2.2-cp27-none-win32.whl", hash = "sha256:f7ef26a4c334224e7763e740fc945c26c0abf9ba51a19d4f5befa1d20d7da0b7"}, 554 | {file = "noise-1.2.2-cp27-none-win_amd64.whl", hash = "sha256:15582a58c9ee79b07436a1220bd6c4145266865262d1e6478d37a08b7d910da8"}, 555 | {file = "noise-1.2.2-cp33-none-win32.whl", hash = "sha256:93ac2977cf0e8f5cb90a2e828a5dfefc438bfb1fb8d7fd1ee305f05eadc8578e"}, 556 | {file = "noise-1.2.2-cp33-none-win_amd64.whl", hash = "sha256:20d1c89a2b8c3714abe5a5fa653b3ab9ab01aee1475993b8bdb9d5e26bc081cc"}, 557 | {file = "noise-1.2.2-cp34-none-win32.whl", hash = "sha256:f82933563ef89651865cc7cbfab11721a2229f5c6c8c009a041be4fb887949f2"}, 558 | {file = "noise-1.2.2-cp34-none-win_amd64.whl", hash = "sha256:065be3531a6b7a7dfcb6840646400a75e081511c524caa04feaea11e16e7ab24"}, 559 | {file = "noise-1.2.2.tar.gz", hash = "sha256:57a2797436574391ff63a111e852e53a4164ecd81ad23639641743cd1a209b65"}, 560 | {file = "noise-1.2.2.zip", hash = "sha256:36036cdaca131ddd2ab4397fba649af7f074ec08031e1e0a51031d0ae23b509a"}, 561 | ] 562 | 563 | [[package]] 564 | name = "numpy" 565 | version = "2.1.1" 566 | description = "Fundamental package for array computing in Python" 567 | optional = false 568 | python-versions = ">=3.10" 569 | files = [ 570 | {file = "numpy-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8a0e34993b510fc19b9a2ce7f31cb8e94ecf6e924a40c0c9dd4f62d0aac47d9"}, 571 | {file = "numpy-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7dd86dfaf7c900c0bbdcb8b16e2f6ddf1eb1fe39c6c8cca6e94844ed3152a8fd"}, 572 | {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:5889dd24f03ca5a5b1e8a90a33b5a0846d8977565e4ae003a63d22ecddf6782f"}, 573 | {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:59ca673ad11d4b84ceb385290ed0ebe60266e356641428c845b39cd9df6713ab"}, 574 | {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13ce49a34c44b6de5241f0b38b07e44c1b2dcacd9e36c30f9c2fcb1bb5135db7"}, 575 | {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913cc1d311060b1d409e609947fa1b9753701dac96e6581b58afc36b7ee35af6"}, 576 | {file = "numpy-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:caf5d284ddea7462c32b8d4a6b8af030b6c9fd5332afb70e7414d7fdded4bfd0"}, 577 | {file = "numpy-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:57eb525e7c2a8fdee02d731f647146ff54ea8c973364f3b850069ffb42799647"}, 578 | {file = "numpy-2.1.1-cp310-cp310-win32.whl", hash = "sha256:9a8e06c7a980869ea67bbf551283bbed2856915f0a792dc32dd0f9dd2fb56728"}, 579 | {file = "numpy-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:d10c39947a2d351d6d466b4ae83dad4c37cd6c3cdd6d5d0fa797da56f710a6ae"}, 580 | {file = "numpy-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d07841fd284718feffe7dd17a63a2e6c78679b2d386d3e82f44f0108c905550"}, 581 | {file = "numpy-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5613cfeb1adfe791e8e681128f5f49f22f3fcaa942255a6124d58ca59d9528f"}, 582 | {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0b8cc2715a84b7c3b161f9ebbd942740aaed913584cae9cdc7f8ad5ad41943d0"}, 583 | {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:b49742cdb85f1f81e4dc1b39dcf328244f4d8d1ded95dea725b316bd2cf18c95"}, 584 | {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8d5f8a8e3bc87334f025194c6193e408903d21ebaeb10952264943a985066ca"}, 585 | {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d51fc141ddbe3f919e91a096ec739f49d686df8af254b2053ba21a910ae518bf"}, 586 | {file = "numpy-2.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:98ce7fb5b8063cfdd86596b9c762bf2b5e35a2cdd7e967494ab78a1fa7f8b86e"}, 587 | {file = "numpy-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:24c2ad697bd8593887b019817ddd9974a7f429c14a5469d7fad413f28340a6d2"}, 588 | {file = "numpy-2.1.1-cp311-cp311-win32.whl", hash = "sha256:397bc5ce62d3fb73f304bec332171535c187e0643e176a6e9421a6e3eacef06d"}, 589 | {file = "numpy-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:ae8ce252404cdd4de56dcfce8b11eac3c594a9c16c231d081fb705cf23bd4d9e"}, 590 | {file = "numpy-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c803b7934a7f59563db459292e6aa078bb38b7ab1446ca38dd138646a38203e"}, 591 | {file = "numpy-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6435c48250c12f001920f0751fe50c0348f5f240852cfddc5e2f97e007544cbe"}, 592 | {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3269c9eb8745e8d975980b3a7411a98976824e1fdef11f0aacf76147f662b15f"}, 593 | {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521"}, 594 | {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b"}, 595 | {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b9cd92c8f8e7b313b80e93cedc12c0112088541dcedd9197b5dee3738c1201"}, 596 | {file = "numpy-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:afd9c680df4de71cd58582b51e88a61feed4abcc7530bcd3d48483f20fc76f2a"}, 597 | {file = "numpy-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8661c94e3aad18e1ea17a11f60f843a4933ccaf1a25a7c6a9182af70610b2313"}, 598 | {file = "numpy-2.1.1-cp312-cp312-win32.whl", hash = "sha256:950802d17a33c07cba7fd7c3dcfa7d64705509206be1606f196d179e539111ed"}, 599 | {file = "numpy-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:3fc5eabfc720db95d68e6646e88f8b399bfedd235994016351b1d9e062c4b270"}, 600 | {file = "numpy-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:046356b19d7ad1890c751b99acad5e82dc4a02232013bd9a9a712fddf8eb60f5"}, 601 | {file = "numpy-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6e5a9cb2be39350ae6c8f79410744e80154df658d5bea06e06e0ac5bb75480d5"}, 602 | {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d4c57b68c8ef5e1ebf47238e99bf27657511ec3f071c465f6b1bccbef12d4136"}, 603 | {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8ae0fd135e0b157365ac7cc31fff27f07a5572bdfc38f9c2d43b2aff416cc8b0"}, 604 | {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981707f6b31b59c0c24bcda52e5605f9701cb46da4b86c2e8023656ad3e833cb"}, 605 | {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ca4b53e1e0b279142113b8c5eb7d7a877e967c306edc34f3b58e9be12fda8df"}, 606 | {file = "numpy-2.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e097507396c0be4e547ff15b13dc3866f45f3680f789c1a1301b07dadd3fbc78"}, 607 | {file = "numpy-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7506387e191fe8cdb267f912469a3cccc538ab108471291636a96a54e599556"}, 608 | {file = "numpy-2.1.1-cp313-cp313-win32.whl", hash = "sha256:251105b7c42abe40e3a689881e1793370cc9724ad50d64b30b358bbb3a97553b"}, 609 | {file = "numpy-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:f212d4f46b67ff604d11fff7cc62d36b3e8714edf68e44e9760e19be38c03eb0"}, 610 | {file = "numpy-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:920b0911bb2e4414c50e55bd658baeb78281a47feeb064ab40c2b66ecba85553"}, 611 | {file = "numpy-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bab7c09454460a487e631ffc0c42057e3d8f2a9ddccd1e60c7bb8ed774992480"}, 612 | {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:cea427d1350f3fd0d2818ce7350095c1a2ee33e30961d2f0fef48576ddbbe90f"}, 613 | {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:e30356d530528a42eeba51420ae8bf6c6c09559051887196599d96ee5f536468"}, 614 | {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8dfa9e94fc127c40979c3eacbae1e61fda4fe71d84869cc129e2721973231ef"}, 615 | {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910b47a6d0635ec1bd53b88f86120a52bf56dcc27b51f18c7b4a2e2224c29f0f"}, 616 | {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:13cc11c00000848702322af4de0147ced365c81d66053a67c2e962a485b3717c"}, 617 | {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53e27293b3a2b661c03f79aa51c3987492bd4641ef933e366e0f9f6c9bf257ec"}, 618 | {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7be6a07520b88214ea85d8ac8b7d6d8a1839b0b5cb87412ac9f49fa934eb15d5"}, 619 | {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:52ac2e48f5ad847cd43c4755520a2317f3380213493b9d8a4c5e37f3b87df504"}, 620 | {file = "numpy-2.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a95ca3560a6058d6ea91d4629a83a897ee27c00630aed9d933dff191f170cd"}, 621 | {file = "numpy-2.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:99f4a9ee60eed1385a86e82288971a51e71df052ed0b2900ed30bc840c0f2e39"}, 622 | {file = "numpy-2.1.1.tar.gz", hash = "sha256:d0cf7d55b1051387807405b3898efafa862997b4cba8aa5dbe657be794afeafd"}, 623 | ] 624 | 625 | [[package]] 626 | name = "packaging" 627 | version = "24.1" 628 | description = "Core utilities for Python packages" 629 | optional = false 630 | python-versions = ">=3.8" 631 | files = [ 632 | {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, 633 | {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, 634 | ] 635 | 636 | [[package]] 637 | name = "pillow" 638 | version = "10.4.0" 639 | description = "Python Imaging Library (Fork)" 640 | optional = false 641 | python-versions = ">=3.8" 642 | files = [ 643 | {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, 644 | {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, 645 | {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, 646 | {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, 647 | {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, 648 | {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, 649 | {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, 650 | {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, 651 | {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, 652 | {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, 653 | {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, 654 | {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, 655 | {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, 656 | {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, 657 | {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, 658 | {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, 659 | {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, 660 | {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, 661 | {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, 662 | {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, 663 | {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, 664 | {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, 665 | {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, 666 | {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, 667 | {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, 668 | {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, 669 | {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, 670 | {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, 671 | {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, 672 | {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, 673 | {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, 674 | {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, 675 | {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, 676 | {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, 677 | {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, 678 | {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, 679 | {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, 680 | {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, 681 | {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, 682 | {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, 683 | {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, 684 | {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, 685 | {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, 686 | {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, 687 | {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, 688 | {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, 689 | {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, 690 | {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, 691 | {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, 692 | {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, 693 | {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, 694 | {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, 695 | {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, 696 | {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, 697 | {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, 698 | {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, 699 | {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, 700 | {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, 701 | {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, 702 | {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, 703 | {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, 704 | {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, 705 | {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, 706 | {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, 707 | {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, 708 | {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, 709 | {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, 710 | {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, 711 | {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, 712 | {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, 713 | {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, 714 | {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, 715 | {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, 716 | {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, 717 | {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, 718 | {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, 719 | {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, 720 | {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, 721 | {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, 722 | {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, 723 | ] 724 | 725 | [package.extras] 726 | docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] 727 | fpx = ["olefile"] 728 | mic = ["olefile"] 729 | tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] 730 | typing = ["typing-extensions"] 731 | xmp = ["defusedxml"] 732 | 733 | [[package]] 734 | name = "platformdirs" 735 | version = "4.3.6" 736 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." 737 | optional = false 738 | python-versions = ">=3.8" 739 | files = [ 740 | {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, 741 | {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, 742 | ] 743 | 744 | [package.extras] 745 | docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] 746 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] 747 | type = ["mypy (>=1.11.2)"] 748 | 749 | [[package]] 750 | name = "pyautogui" 751 | version = "0.9.54" 752 | description = "PyAutoGUI lets Python control the mouse and keyboard, and other GUI automation tasks. For Windows, macOS, and Linux, on Python 3 and 2." 753 | optional = false 754 | python-versions = "*" 755 | files = [ 756 | {file = "PyAutoGUI-0.9.54.tar.gz", hash = "sha256:dd1d29e8fd118941cb193f74df57e5c6ff8e9253b99c7b04f39cfc69f3ae04b2"}, 757 | ] 758 | 759 | [package.dependencies] 760 | mouseinfo = "*" 761 | pygetwindow = ">=0.0.5" 762 | pymsgbox = "*" 763 | pyobjc-core = {version = "*", markers = "platform_system == \"Darwin\""} 764 | pyobjc-framework-quartz = {version = "*", markers = "platform_system == \"Darwin\""} 765 | pyscreeze = ">=0.1.21" 766 | python3-Xlib = {version = "*", markers = "platform_system == \"Linux\" and python_version >= \"3.0\""} 767 | pytweening = ">=1.0.4" 768 | 769 | [[package]] 770 | name = "pygetwindow" 771 | version = "0.0.9" 772 | description = "A simple, cross-platform module for obtaining GUI information on application's windows." 773 | optional = false 774 | python-versions = "*" 775 | files = [ 776 | {file = "PyGetWindow-0.0.9.tar.gz", hash = "sha256:17894355e7d2b305cd832d717708384017c1698a90ce24f6f7fbf0242dd0a688"}, 777 | ] 778 | 779 | [package.dependencies] 780 | pyrect = "*" 781 | 782 | [[package]] 783 | name = "pygments" 784 | version = "2.18.0" 785 | description = "Pygments is a syntax highlighting package written in Python." 786 | optional = false 787 | python-versions = ">=3.8" 788 | files = [ 789 | {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, 790 | {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, 791 | ] 792 | 793 | [package.extras] 794 | windows-terminal = ["colorama (>=0.4.6)"] 795 | 796 | [[package]] 797 | name = "pyhm" 798 | version = "0.0.7" 799 | description = "Python Human Movement is a python package which imitates human movements" 800 | optional = false 801 | python-versions = "*" 802 | files = [ 803 | {file = "pyHM-0.0.7-py3-none-any.whl", hash = "sha256:e5d8000a067b4cf7187728d3ab90b57eb4dc8dd2a022dacfba5fc4443aa1b0e3"}, 804 | {file = "pyHM-0.0.7.tar.gz", hash = "sha256:fe4d66a61af30085fe5678d728820d0860738d2ebe3babd318fe7f8052320cd0"}, 805 | ] 806 | 807 | [package.dependencies] 808 | numpy = ">=1.20.1" 809 | PyAutoGUI = ">=0.9.52" 810 | scipy = ">=1.6.1" 811 | 812 | [[package]] 813 | name = "pylint" 814 | version = "3.3.1" 815 | description = "python code static checker" 816 | optional = false 817 | python-versions = ">=3.9.0" 818 | files = [ 819 | {file = "pylint-3.3.1-py3-none-any.whl", hash = "sha256:2f846a466dd023513240bc140ad2dd73bfc080a5d85a710afdb728c420a5a2b9"}, 820 | {file = "pylint-3.3.1.tar.gz", hash = "sha256:9f3dcc87b1203e612b78d91a896407787e708b3f189b5fa0b307712d49ff0c6e"}, 821 | ] 822 | 823 | [package.dependencies] 824 | astroid = ">=3.3.4,<=3.4.0-dev0" 825 | colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} 826 | dill = [ 827 | {version = ">=0.2", markers = "python_version < \"3.11\""}, 828 | {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, 829 | {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, 830 | ] 831 | isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" 832 | mccabe = ">=0.6,<0.8" 833 | platformdirs = ">=2.2.0" 834 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 835 | tomlkit = ">=0.10.1" 836 | 837 | [package.extras] 838 | spelling = ["pyenchant (>=3.2,<4.0)"] 839 | testutils = ["gitpython (>3)"] 840 | 841 | [[package]] 842 | name = "pymsgbox" 843 | version = "1.0.9" 844 | description = "A simple, cross-platform, pure Python module for JavaScript-like message boxes." 845 | optional = false 846 | python-versions = "*" 847 | files = [ 848 | {file = "PyMsgBox-1.0.9.tar.gz", hash = "sha256:2194227de8bff7a3d6da541848705a155dcbb2a06ee120d9f280a1d7f51263ff"}, 849 | ] 850 | 851 | [[package]] 852 | name = "pyobjc-core" 853 | version = "10.3.1" 854 | description = "Python<->ObjC Interoperability Module" 855 | optional = false 856 | python-versions = ">=3.8" 857 | files = [ 858 | {file = "pyobjc_core-10.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ea46d2cda17921e417085ac6286d43ae448113158afcf39e0abe484c58fb3d78"}, 859 | {file = "pyobjc_core-10.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:899d3c84d2933d292c808f385dc881a140cf08632907845043a333a9d7c899f9"}, 860 | {file = "pyobjc_core-10.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:6ff5823d13d0a534cdc17fa4ad47cf5bee4846ce0fd27fc40012e12b46db571b"}, 861 | {file = "pyobjc_core-10.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2581e8e68885bcb0e11ec619e81ef28e08ee3fac4de20d8cc83bc5af5bcf4a90"}, 862 | {file = "pyobjc_core-10.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ea98d4c2ec39ca29e62e0327db21418696161fb138ee6278daf2acbedf7ce504"}, 863 | {file = "pyobjc_core-10.3.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:4c179c26ee2123d0aabffb9dbc60324b62b6f8614fb2c2328b09386ef59ef6d8"}, 864 | {file = "pyobjc_core-10.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cb901fce65c9be420c40d8a6ee6fff5ff27c6945f44fd7191989b982baa66dea"}, 865 | {file = "pyobjc_core-10.3.1.tar.gz", hash = "sha256:b204a80ccc070f9ab3f8af423a3a25a6fd787e228508d00c4c30f8ac538ba720"}, 866 | ] 867 | 868 | [[package]] 869 | name = "pyobjc-framework-cocoa" 870 | version = "10.3.1" 871 | description = "Wrappers for the Cocoa frameworks on macOS" 872 | optional = false 873 | python-versions = ">=3.8" 874 | files = [ 875 | {file = "pyobjc_framework_Cocoa-10.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4cb4f8491ab4d9b59f5187e42383f819f7a46306a4fa25b84f126776305291d1"}, 876 | {file = "pyobjc_framework_Cocoa-10.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5f31021f4f8fdf873b57a97ee1f3c1620dbe285e0b4eaed73dd0005eb72fd773"}, 877 | {file = "pyobjc_framework_Cocoa-10.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11b4e0bad4bbb44a4edda128612f03cdeab38644bbf174de0c13129715497296"}, 878 | {file = "pyobjc_framework_Cocoa-10.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:de5e62e5ccf2871a94acf3bf79646b20ea893cc9db78afa8d1fe1b0d0f7cbdb0"}, 879 | {file = "pyobjc_framework_Cocoa-10.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c5af24610ab639bd1f521ce4500484b40787f898f691b7a23da3339e6bc8b90"}, 880 | {file = "pyobjc_framework_Cocoa-10.3.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:a7151186bb7805deea434fae9a4423335e6371d105f29e73cc2036c6779a9dbc"}, 881 | {file = "pyobjc_framework_Cocoa-10.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:743d2a1ac08027fd09eab65814c79002a1d0421d7c0074ffd1217b6560889744"}, 882 | {file = "pyobjc_framework_cocoa-10.3.1.tar.gz", hash = "sha256:1cf20714daaa986b488fb62d69713049f635c9d41a60c8da97d835710445281a"}, 883 | ] 884 | 885 | [package.dependencies] 886 | pyobjc-core = ">=10.3.1" 887 | 888 | [[package]] 889 | name = "pyobjc-framework-quartz" 890 | version = "10.3.1" 891 | description = "Wrappers for the Quartz frameworks on macOS" 892 | optional = false 893 | python-versions = ">=3.8" 894 | files = [ 895 | {file = "pyobjc_framework_Quartz-10.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ef4fd315ed2bc42ef77fdeb2bae28a88ec986bd7b8079a87ba3b3475348f96e"}, 896 | {file = "pyobjc_framework_Quartz-10.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:96578d4a3e70164efe44ad7dc320ecd4e211758ffcde5dcd694de1bbdfe090a4"}, 897 | {file = "pyobjc_framework_Quartz-10.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ca35f92486869a41847a1703bb176aab8a53dbfd8e678d1f4d68d8e6e1581c71"}, 898 | {file = "pyobjc_framework_Quartz-10.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:00a0933267e3a46ea4afcc35d117b2efb920f06de797fa66279c52e7057e3590"}, 899 | {file = "pyobjc_framework_Quartz-10.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a161bedb4c5257a02ad56a910cd7eefb28bdb0ea78607df0d70ed4efe4ea54c1"}, 900 | {file = "pyobjc_framework_Quartz-10.3.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d7a8028e117a94923a511944bfa9daf9744e212f06cf89010c60934a479863a5"}, 901 | {file = "pyobjc_framework_Quartz-10.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:de00c983b3267eb26fa42c6ed9f15e2bf006bde8afa7fe2b390646aa21a5d6fc"}, 902 | {file = "pyobjc_framework_quartz-10.3.1.tar.gz", hash = "sha256:b6d7e346d735c9a7f147cd78e6da79eeae416a0b7d3874644c83a23786c6f886"}, 903 | ] 904 | 905 | [package.dependencies] 906 | pyobjc-core = ">=10.3.1" 907 | pyobjc-framework-Cocoa = ">=10.3.1" 908 | 909 | [[package]] 910 | name = "pyparsing" 911 | version = "3.1.4" 912 | description = "pyparsing module - Classes and methods to define and execute parsing grammars" 913 | optional = false 914 | python-versions = ">=3.6.8" 915 | files = [ 916 | {file = "pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c"}, 917 | {file = "pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032"}, 918 | ] 919 | 920 | [package.extras] 921 | diagrams = ["jinja2", "railroad-diagrams"] 922 | 923 | [[package]] 924 | name = "pyperclip" 925 | version = "1.9.0" 926 | description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)" 927 | optional = false 928 | python-versions = "*" 929 | files = [ 930 | {file = "pyperclip-1.9.0.tar.gz", hash = "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310"}, 931 | ] 932 | 933 | [[package]] 934 | name = "pyrect" 935 | version = "0.2.0" 936 | description = "PyRect is a simple module with a Rect class for Pygame-like rectangular areas." 937 | optional = false 938 | python-versions = "*" 939 | files = [ 940 | {file = "PyRect-0.2.0.tar.gz", hash = "sha256:f65155f6df9b929b67caffbd57c0947c5ae5449d3b580d178074bffb47a09b78"}, 941 | ] 942 | 943 | [[package]] 944 | name = "pyscreeze" 945 | version = "1.0.1" 946 | description = "A simple, cross-platform screenshot module for Python 2 and 3." 947 | optional = false 948 | python-versions = "*" 949 | files = [ 950 | {file = "pyscreeze-1.0.1.tar.gz", hash = "sha256:cf1662710f1b46aa5ff229ee23f367da9e20af4a78e6e365bee973cad0ead4be"}, 951 | ] 952 | 953 | [package.dependencies] 954 | Pillow = [ 955 | {version = ">=9.2.0", markers = "python_version == \"3.10\""}, 956 | {version = ">=9.3.0", markers = "python_version == \"3.11\""}, 957 | ] 958 | 959 | [[package]] 960 | name = "python-dateutil" 961 | version = "2.9.0.post0" 962 | description = "Extensions to the standard Python datetime module" 963 | optional = false 964 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 965 | files = [ 966 | {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, 967 | {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, 968 | ] 969 | 970 | [package.dependencies] 971 | six = ">=1.5" 972 | 973 | [[package]] 974 | name = "python3-xlib" 975 | version = "0.15" 976 | description = "Python3 X Library" 977 | optional = false 978 | python-versions = "*" 979 | files = [ 980 | {file = "python3-xlib-0.15.tar.gz", hash = "sha256:dc4245f3ae4aa5949c1d112ee4723901ade37a96721ba9645f2bfa56e5b383f8"}, 981 | ] 982 | 983 | [[package]] 984 | name = "pytweening" 985 | version = "1.2.0" 986 | description = "A collection of tweening (aka easing) functions." 987 | optional = false 988 | python-versions = "*" 989 | files = [ 990 | {file = "pytweening-1.2.0.tar.gz", hash = "sha256:243318b7736698066c5f362ec5c2b6434ecf4297c3c8e7caa8abfe6af4cac71b"}, 991 | ] 992 | 993 | [[package]] 994 | name = "rich" 995 | version = "13.8.1" 996 | description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" 997 | optional = false 998 | python-versions = ">=3.7.0" 999 | files = [ 1000 | {file = "rich-13.8.1-py3-none-any.whl", hash = "sha256:1760a3c0848469b97b558fc61c85233e3dafb69c7a071b4d60c38099d3cd4c06"}, 1001 | {file = "rich-13.8.1.tar.gz", hash = "sha256:8260cda28e3db6bf04d2d1ef4dbc03ba80a824c88b0e7668a0f23126a424844a"}, 1002 | ] 1003 | 1004 | [package.dependencies] 1005 | markdown-it-py = ">=2.2.0" 1006 | pygments = ">=2.13.0,<3.0.0" 1007 | 1008 | [package.extras] 1009 | jupyter = ["ipywidgets (>=7.5.1,<9)"] 1010 | 1011 | [[package]] 1012 | name = "rubicon-objc" 1013 | version = "0.4.9" 1014 | description = "A bridge between an Objective C runtime environment and Python." 1015 | optional = false 1016 | python-versions = ">=3.8" 1017 | files = [ 1018 | {file = "rubicon_objc-0.4.9-py3-none-any.whl", hash = "sha256:c351b3800cf74c8c23f7d534f008fd5de46c63818de7a44de96daffdb3ed8b8c"}, 1019 | {file = "rubicon_objc-0.4.9.tar.gz", hash = "sha256:3d77a5b2d10cb1e49679aa90b7824b46f67b3fd636229aa4a1b902d24aec6a58"}, 1020 | ] 1021 | 1022 | [package.extras] 1023 | dev = ["pre-commit (==3.5.0)", "pre-commit (==3.7.0)", "pytest (==8.2.0)", "pytest-tldr (==0.2.5)", "setuptools-scm (==8.0.4)", "tox (==4.15.0)"] 1024 | docs = ["furo (==2024.4.27)", "pyenchant (==3.2.2)", "sphinx (==7.1.2)", "sphinx (==7.3.7)", "sphinx-autobuild (==2021.3.14)", "sphinx-autobuild (==2024.4.16)", "sphinx-copybutton (==0.5.2)", "sphinx-tabs (==3.4.5)", "sphinxcontrib-spelling (==8.0.0)"] 1025 | 1026 | [[package]] 1027 | name = "ruff" 1028 | version = "0.6.7" 1029 | description = "An extremely fast Python linter and code formatter, written in Rust." 1030 | optional = false 1031 | python-versions = ">=3.7" 1032 | files = [ 1033 | {file = "ruff-0.6.7-py3-none-linux_armv6l.whl", hash = "sha256:08277b217534bfdcc2e1377f7f933e1c7957453e8a79764d004e44c40db923f2"}, 1034 | {file = "ruff-0.6.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c6707a32e03b791f4448dc0dce24b636cbcdee4dd5607adc24e5ee73fd86c00a"}, 1035 | {file = "ruff-0.6.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:533d66b7774ef224e7cf91506a7dafcc9e8ec7c059263ec46629e54e7b1f90ab"}, 1036 | {file = "ruff-0.6.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17a86aac6f915932d259f7bec79173e356165518859f94649d8c50b81ff087e9"}, 1037 | {file = "ruff-0.6.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b3f8822defd260ae2460ea3832b24d37d203c3577f48b055590a426a722d50ef"}, 1038 | {file = "ruff-0.6.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ba4efe5c6dbbb58be58dd83feedb83b5e95c00091bf09987b4baf510fee5c99"}, 1039 | {file = "ruff-0.6.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:525201b77f94d2b54868f0cbe5edc018e64c22563da6c5c2e5c107a4e85c1c0d"}, 1040 | {file = "ruff-0.6.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8854450839f339e1049fdbe15d875384242b8e85d5c6947bb2faad33c651020b"}, 1041 | {file = "ruff-0.6.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f0b62056246234d59cbf2ea66e84812dc9ec4540518e37553513392c171cb18"}, 1042 | {file = "ruff-0.6.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b1462fa56c832dc0cea5b4041cfc9c97813505d11cce74ebc6d1aae068de36b"}, 1043 | {file = "ruff-0.6.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:02b083770e4cdb1495ed313f5694c62808e71764ec6ee5db84eedd82fd32d8f5"}, 1044 | {file = "ruff-0.6.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c05fd37013de36dfa883a3854fae57b3113aaa8abf5dea79202675991d48624"}, 1045 | {file = "ruff-0.6.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f49c9caa28d9bbfac4a637ae10327b3db00f47d038f3fbb2195c4d682e925b14"}, 1046 | {file = "ruff-0.6.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a0e1655868164e114ba43a908fd2d64a271a23660195017c17691fb6355d59bb"}, 1047 | {file = "ruff-0.6.7-py3-none-win32.whl", hash = "sha256:a939ca435b49f6966a7dd64b765c9df16f1faed0ca3b6f16acdf7731969deb35"}, 1048 | {file = "ruff-0.6.7-py3-none-win_amd64.whl", hash = "sha256:590445eec5653f36248584579c06252ad2e110a5d1f32db5420de35fb0e1c977"}, 1049 | {file = "ruff-0.6.7-py3-none-win_arm64.whl", hash = "sha256:b28f0d5e2f771c1fe3c7a45d3f53916fc74a480698c4b5731f0bea61e52137c8"}, 1050 | {file = "ruff-0.6.7.tar.gz", hash = "sha256:44e52129d82266fa59b587e2cd74def5637b730a69c4542525dfdecfaae38bd5"}, 1051 | ] 1052 | 1053 | [[package]] 1054 | name = "scipy" 1055 | version = "1.14.1" 1056 | description = "Fundamental algorithms for scientific computing in Python" 1057 | optional = false 1058 | python-versions = ">=3.10" 1059 | files = [ 1060 | {file = "scipy-1.14.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389"}, 1061 | {file = "scipy-1.14.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3"}, 1062 | {file = "scipy-1.14.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0"}, 1063 | {file = "scipy-1.14.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3"}, 1064 | {file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d"}, 1065 | {file = "scipy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69"}, 1066 | {file = "scipy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad"}, 1067 | {file = "scipy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5"}, 1068 | {file = "scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675"}, 1069 | {file = "scipy-1.14.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2"}, 1070 | {file = "scipy-1.14.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617"}, 1071 | {file = "scipy-1.14.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8"}, 1072 | {file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37"}, 1073 | {file = "scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2"}, 1074 | {file = "scipy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2"}, 1075 | {file = "scipy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94"}, 1076 | {file = "scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d"}, 1077 | {file = "scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07"}, 1078 | {file = "scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5"}, 1079 | {file = "scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc"}, 1080 | {file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310"}, 1081 | {file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066"}, 1082 | {file = "scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1"}, 1083 | {file = "scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f"}, 1084 | {file = "scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79"}, 1085 | {file = "scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e"}, 1086 | {file = "scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73"}, 1087 | {file = "scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e"}, 1088 | {file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d"}, 1089 | {file = "scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e"}, 1090 | {file = "scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06"}, 1091 | {file = "scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84"}, 1092 | {file = "scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417"}, 1093 | ] 1094 | 1095 | [package.dependencies] 1096 | numpy = ">=1.23.5,<2.3" 1097 | 1098 | [package.extras] 1099 | dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"] 1100 | doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.13.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<=7.3.7)", "sphinx-design (>=0.4.0)"] 1101 | test = ["Cython", "array-api-strict (>=2.0)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] 1102 | 1103 | [[package]] 1104 | name = "shellingham" 1105 | version = "1.5.4" 1106 | description = "Tool to Detect Surrounding Shell" 1107 | optional = false 1108 | python-versions = ">=3.7" 1109 | files = [ 1110 | {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, 1111 | {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, 1112 | ] 1113 | 1114 | [[package]] 1115 | name = "six" 1116 | version = "1.16.0" 1117 | description = "Python 2 and 3 compatibility utilities" 1118 | optional = false 1119 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 1120 | files = [ 1121 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 1122 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 1123 | ] 1124 | 1125 | [[package]] 1126 | name = "tomli" 1127 | version = "2.0.1" 1128 | description = "A lil' TOML parser" 1129 | optional = false 1130 | python-versions = ">=3.7" 1131 | files = [ 1132 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 1133 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 1134 | ] 1135 | 1136 | [[package]] 1137 | name = "tomlkit" 1138 | version = "0.13.2" 1139 | description = "Style preserving TOML library" 1140 | optional = false 1141 | python-versions = ">=3.8" 1142 | files = [ 1143 | {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, 1144 | {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, 1145 | ] 1146 | 1147 | [[package]] 1148 | name = "typer" 1149 | version = "0.12.5" 1150 | description = "Typer, build great CLIs. Easy to code. Based on Python type hints." 1151 | optional = false 1152 | python-versions = ">=3.7" 1153 | files = [ 1154 | {file = "typer-0.12.5-py3-none-any.whl", hash = "sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b"}, 1155 | {file = "typer-0.12.5.tar.gz", hash = "sha256:f592f089bedcc8ec1b974125d64851029c3b1af145f04aca64d69410f0c9b722"}, 1156 | ] 1157 | 1158 | [package.dependencies] 1159 | click = ">=8.0.0" 1160 | rich = ">=10.11.0" 1161 | shellingham = ">=1.3.0" 1162 | typing-extensions = ">=3.7.4.3" 1163 | 1164 | [[package]] 1165 | name = "typing-extensions" 1166 | version = "4.12.2" 1167 | description = "Backported and Experimental Type Hints for Python 3.8+" 1168 | optional = false 1169 | python-versions = ">=3.8" 1170 | files = [ 1171 | {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, 1172 | {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, 1173 | ] 1174 | 1175 | [metadata] 1176 | lock-version = "2.0" 1177 | python-versions = "^3.10" 1178 | content-hash = "45d7a96f277099d998cc6e0a77c39e0c23608c4d5bed9077c5fe4b2180359b4d" 1179 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "oxymouse" 3 | version = "1.1.1" 4 | description = "Oxymouse is a tool for generating synthetic mouse movements." 5 | authors = ["Tadas Gedgaudas "] 6 | readme = "README.md" 7 | packages = [{ include = "oxymouse" }] 8 | 9 | [project] 10 | name = "oxymouse" 11 | description = "Oxy®Mouse - algorithms for generating mouse movements!" 12 | readme = "README.md" 13 | requires-python = ">=3.10" 14 | license = "MIT" 15 | authors = [ 16 | { name = "Tadas Gedgaudas", email = "tadas.gedgaudas@oxylabs.io" }, 17 | ] 18 | dynamic = ["version"] 19 | 20 | [project.urls] 21 | Homepage = "https://oxylabs.io" 22 | Documentation = "https://github.com/oxylabs/OxyMouse/blob/master/README.md" 23 | Repository = "https://github.com/oxylabs/OxyMouse" 24 | 25 | [tool.poetry.dependencies] 26 | python = "^3.10" 27 | pyhm = "~0.0.7" 28 | noise = "~1.2.2" 29 | matplotlib = "~3.9.2" 30 | typer = "^0.12.5" 31 | 32 | [tool.poetry.dev-dependencies] 33 | ruff = "~0.6.7" 34 | pylint = "~3.3.1" 35 | mypy = "~1.11.2" 36 | 37 | [tool.ruff.lint] 38 | select = [ 39 | "E", "W", # pycodestyle 40 | "F", # Pyflakes 41 | "UP", # pyupgrade 42 | "SIM", # flake8-simplify 43 | "I", # isort 44 | ] 45 | 46 | [tool.ruff] 47 | line-length = 120 48 | 49 | [tool.mypy] 50 | ignore_missing_imports = true 51 | warn_unused_configs = true 52 | disallow_any_generics = true 53 | disallow_untyped_calls = true 54 | disallow_untyped_defs = true 55 | disallow_incomplete_defs = true 56 | check_untyped_defs = true 57 | disallow_untyped_decorators = true 58 | no_implicit_optional = true 59 | warn_redundant_casts = true 60 | warn_unused_ignores = true 61 | strict_equality = true 62 | 63 | [tool.pylint] 64 | [tool.pylint.'MASTER'] 65 | extension-pkg-allow-list='pydantic' 66 | 67 | [tool.pylint.'MESSAGES CONTROL'] 68 | disable=[ 69 | "missing-docstring" 70 | ] 71 | 72 | [tool.pylint.'FORMAT'] 73 | max-line-length = 120 74 | 75 | [tool.pylint.'SIMILARITIES'] 76 | ignore-imports = 'yes' 77 | min-similarity-lines = 15 78 | 79 | [tool.pylint.'DESIGN'] 80 | max-args=10 81 | 82 | [tool.hatch.version] 83 | path = "oxymouse/__init__.py" 84 | 85 | [build-system] 86 | requires = ["hatchling >= 1.7.0"] 87 | build-backend = "hatchling.build" 88 | -------------------------------------------------------------------------------- /visualize.py: -------------------------------------------------------------------------------- 1 | import typer 2 | from matplotlib import pyplot as plt 3 | 4 | from oxymouse.config import mouses 5 | 6 | app = typer.Typer() 7 | 8 | 9 | function_names_to_function_map = { 10 | "gc": "generate_coordinates", 11 | "grc": "generate_random_coordinates", 12 | "gsc": "generate_scroll_coordinates", 13 | } 14 | 15 | 16 | @app.command() 17 | def visualize_mouse_movements(algorithm: str, fn: str) -> None: 18 | print(f"Visualizing {algorithm} with {fn} function") 19 | 20 | algorithm_instance = mouses[algorithm] 21 | function_name = function_names_to_function_map[fn] 22 | 23 | coordinates = getattr(algorithm_instance, function_name)() 24 | 25 | x_coordinates = [point[0] for point in coordinates] 26 | y_coordinates = [point[1] for point in coordinates] 27 | 28 | plt.figure(figsize=(16, 9)) # Set the figure size for 1080p 29 | plt.plot(x_coordinates, y_coordinates, marker="o", linestyle="-") 30 | plt.title(f"Simulated mouse movement path - {algorithm_instance} - {function_name}") 31 | plt.xlabel("X") 32 | plt.ylabel("Y") 33 | plt.grid(True) 34 | plt.show() 35 | 36 | 37 | if __name__ == "__main__": 38 | app() 39 | --------------------------------------------------------------------------------