├── .github └── workflows │ └── build.yml ├── .python-version ├── Area_Calculator.py ├── LICENSE ├── README.md ├── pyproject.toml └── uv.lock /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build Area Calculator 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - "**.md" 7 | - "LICENSE" 8 | pull_request: 9 | paths-ignore: 10 | - "**.md" 11 | - "LICENSE" 12 | workflow_dispatch: 13 | 14 | permissions: 15 | contents: write 16 | 17 | 18 | jobs: 19 | build: 20 | runs-on: windows-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - name: Setup uv 26 | uses: astral-sh/setup-uv@v5 27 | with: 28 | enable-cache: true 29 | cache-dependency-glob: "uv.lock" 30 | 31 | - name: Setup Python 32 | uses: actions/setup-python@v5 33 | with: 34 | python-version-file: ".python-version" 35 | architecture: "x64" 36 | 37 | - name: Install dependencies 38 | run: uv sync --all-extras --dev 39 | 40 | - name: Build Executable 41 | run: uv run pyinstaller --onefile Area_Calculator.py 42 | 43 | - name: Copy README 44 | run: cp README.md ./dist/README.txt 45 | 46 | - name: Upload Artifact 47 | uses: actions/upload-artifact@v4 48 | with: 49 | name: Area_Calculator 50 | path: ./dist/* 51 | 52 | # https://stackoverflow.com/a/73980139 53 | - name: Zip files 54 | if: startsWith(github.ref, 'refs/tags/') 55 | run: tar.exe acvf Area_Calculator.zip -C dist * 56 | 57 | - name: Create Release 58 | uses: softprops/action-gh-release@v2 59 | if: startsWith(github.ref, 'refs/tags/') 60 | with: 61 | generate_release_notes: true 62 | files: Area_Calculator.zip 63 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /Area_Calculator.py: -------------------------------------------------------------------------------- 1 | import time 2 | from typing import Annotated 3 | import numpy as np 4 | from pynput.mouse import Listener 5 | import typer 6 | from rich.progress import track 7 | from rich import print as rprint 8 | 9 | SAMPLE_RATE = 0.01 10 | GRACE_PERIOD = 5 11 | 12 | 13 | def record_movements( 14 | duration: int, 15 | ) -> tuple[np.ndarray[np.uint16], np.ndarray[np.uint16]]: 16 | """Records cursor movements for the given duration""" 17 | for _ in track( 18 | range(GRACE_PERIOD * 100), 19 | description=f"Waiting for {GRACE_PERIOD} seconds before recording...", 20 | ): 21 | time.sleep(0.01) 22 | 23 | x_input = np.array([], dtype=np.uint16) 24 | y_input = np.array([], dtype=np.uint16) 25 | 26 | def on_move(x: int, y: int) -> None: 27 | """Records cursor movements""" 28 | nonlocal x_input, y_input 29 | x_input = np.append(x_input, x) 30 | y_input = np.append(y_input, y) 31 | 32 | with Listener(on_move=on_move): 33 | print(f"Recording started for {duration} seconds...") 34 | # Sampling every 10ms 35 | start_time = time.perf_counter() 36 | while time.perf_counter() - start_time < duration: 37 | time.sleep(SAMPLE_RATE) 38 | 39 | return x_input, y_input 40 | 41 | 42 | def find_peak_near_extremes( 43 | values: np.ndarray[np.uint16], 44 | min_val: np.uint16, 45 | max_val: np.uint16, 46 | threshold_percentage: int = 5, 47 | ) -> tuple[int, int]: 48 | """Finds the most used point near the detected min/max values""" 49 | threshold_range = (max_val - min_val) * (threshold_percentage / 100) 50 | near_min = values[values <= min_val + threshold_range] 51 | near_max = values[values >= max_val - threshold_range] 52 | 53 | # Remove negative values 54 | near_min = near_min[near_min >= 0] 55 | near_max = near_max[near_max >= 0] 56 | 57 | if len(near_min) > 0: 58 | min_peak = np.bincount(near_min.astype(int)).argmax() 59 | else: 60 | min_peak = int(min_val) 61 | 62 | if len(near_max) > 0: 63 | max_peak = np.bincount(near_max.astype(int)).argmax() 64 | else: 65 | max_peak = int(max_val) 66 | 67 | return min_peak, max_peak 68 | 69 | 70 | def analyze_data( 71 | x_input: np.ndarray[np.uint16], 72 | y_input: np.ndarray[np.uint16], 73 | tablet_width_mm: float, 74 | tablet_height_mm: float, 75 | innergameplay_width_px: int, 76 | innergameplay_height_px: int, 77 | ): 78 | """Analyzes the movement data and finds dimensions & peak points""" 79 | # Get's the values in +- 3 standard deviations from the mean 80 | x_mean = np.mean(x_input) 81 | x_std_deviation = np.std(x_input) 82 | y_mean = np.mean(y_input) 83 | y_std_deviation = np.std(y_input) 84 | 85 | x_filtered = x_input[ 86 | (x_input > x_mean - 3 * x_std_deviation) 87 | & (x_input < x_mean + 3 * x_std_deviation) 88 | ] 89 | y_filtered = y_input[ 90 | (y_input > y_mean - 3 * y_std_deviation) 91 | & (y_input < y_mean + 3 * y_std_deviation) 92 | ] 93 | x_max = np.max(x_filtered) 94 | x_min = np.min(x_filtered) 95 | 96 | y_max = np.max(y_filtered) 97 | y_min = np.min(y_filtered) 98 | 99 | # Find peak usage near the filtered extremes 100 | x_min_peak, x_max_peak = find_peak_near_extremes( 101 | values=x_filtered, min_val=x_min, max_val=x_max 102 | ) 103 | y_min_peak, y_max_peak = find_peak_near_extremes( 104 | values=y_filtered, min_val=y_min, max_val=y_max 105 | ) 106 | 107 | x_distance_px = x_max_peak - x_min_peak 108 | y_distance_px = y_max_peak - y_min_peak 109 | x_distance_mm = (x_distance_px * tablet_width_mm) / innergameplay_width_px 110 | y_distance_mm = (y_distance_px * tablet_height_mm) / innergameplay_height_px 111 | 112 | rprint("\n==== RESULTS ====") 113 | rprint( 114 | "Area calculated with most used points near extremes (removed soft outliers):" 115 | f" [green]{x_distance_mm:.2f} x {y_distance_mm:.2f} mm [/green]" 116 | ) 117 | rprint("===================") 118 | 119 | 120 | def main( 121 | screen_width_px: Annotated[ 122 | int, typer.Option(prompt="Enter your screen width in pixels", min=800) 123 | ], 124 | screen_height_px: Annotated[ 125 | int, typer.Option(prompt="Enter your screen height in pixels", min=600) 126 | ], 127 | tablet_width_mm: Annotated[ 128 | float, 129 | typer.Option(prompt="Enter your full active tablet area width in mm", min=1), 130 | ], 131 | tablet_height_mm: Annotated[ 132 | float, 133 | typer.Option(prompt="Enter your full active tablet area height in mm", min=1), 134 | ], 135 | duration: Annotated[ 136 | int, typer.Option(prompt="Enter map duration in seconds", min=10) 137 | ], 138 | ): 139 | 140 | innergameplay_height_px = int((864 / 1080) * screen_height_px) 141 | innergameplay_width_px = int((1152 / 1920) * screen_width_px) 142 | typer.confirm( 143 | "Press Enter to start recording", 144 | default=True, 145 | show_default=False, 146 | prompt_suffix=" ", 147 | ) 148 | 149 | x_input, y_input = record_movements(duration) 150 | analyze_data( 151 | x_input=x_input, 152 | y_input=y_input, 153 | tablet_width_mm=tablet_width_mm, 154 | tablet_height_mm=tablet_height_mm, 155 | innergameplay_width_px=innergameplay_width_px, 156 | innergameplay_height_px=innergameplay_height_px, 157 | ) 158 | 159 | again = typer.confirm("Want to record again?", default=True, prompt_suffix=" ") 160 | if again: 161 | return main( 162 | screen_width_px, 163 | screen_height_px, 164 | tablet_width_mm, 165 | tablet_height_mm, 166 | duration, 167 | ) 168 | rprint("===================") 169 | rprint("Thank you for using the Area Calculator!") 170 | rprint( 171 | "If you find any issues, feel free to report it on" 172 | " [link=https://github.com/denwii/Area_Calculator_Osu]GitHub[/link]!" 173 | ) 174 | raise typer.Exit() 175 | 176 | 177 | if __name__ == "__main__": 178 | typer.run(main) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Jonathan Braat 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 1) Set the full area in your tablet driver, NO forced proportion, (absolute mode) 2 | 2) Make sure you have all filters disabled and your osu sensitivity is 1x 3 | 4) Open the "Area_Calculator.exe" program. 4 | 5) Enter the full area values (in mm) into the program. 5 | 6) Locate a long map. 6 | 7) Input the duration of the map into the program. 7 | 8) Select the "Autopilot" option in the mode selector. 8 | 9) Before pressing Enter, ensure that you are starting 9 | from the position you typically use to play, 10 | with the cursor centered in your usual play area. 11 | Be careful—the program is recording, so avoid moving 12 | outside of your playfield range before the program 13 | finishes. 14 | 10) Play as if you were playing yourself, and tap if you want 15 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "area-calculator-osu" 3 | version = "0.2.1" 4 | description = "TODO" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "numpy>=2.2.4", 9 | "pynput>=1.8.1", 10 | "typer>=0.15.2", 11 | ] 12 | 13 | [dependency-groups] 14 | dev = [ 15 | "pyinstaller>=6.12.0", 16 | ] 17 | -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 1 3 | requires-python = ">=3.12" 4 | 5 | [[package]] 6 | name = "altgraph" 7 | version = "0.17.4" 8 | source = { registry = "https://pypi.org/simple" } 9 | sdist = { url = "https://files.pythonhosted.org/packages/de/a8/7145824cf0b9e3c28046520480f207df47e927df83aa9555fb47f8505922/altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406", size = 48418 } 10 | wheels = [ 11 | { url = "https://files.pythonhosted.org/packages/4d/3f/3bc3f1d83f6e4a7fcb834d3720544ca597590425be5ba9db032b2bf322a2/altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff", size = 21212 }, 12 | ] 13 | 14 | [[package]] 15 | name = "area-calculator-osu" 16 | version = "0.2.1" 17 | source = { virtual = "." } 18 | dependencies = [ 19 | { name = "numpy" }, 20 | { name = "pynput" }, 21 | { name = "typer" }, 22 | ] 23 | 24 | [package.dev-dependencies] 25 | dev = [ 26 | { name = "pyinstaller" }, 27 | ] 28 | 29 | [package.metadata] 30 | requires-dist = [ 31 | { name = "numpy", specifier = ">=2.2.4" }, 32 | { name = "pynput", specifier = ">=1.8.1" }, 33 | { name = "typer", specifier = ">=0.15.2" }, 34 | ] 35 | 36 | [package.metadata.requires-dev] 37 | dev = [{ name = "pyinstaller", specifier = ">=6.12.0" }] 38 | 39 | [[package]] 40 | name = "click" 41 | version = "8.1.8" 42 | source = { registry = "https://pypi.org/simple" } 43 | dependencies = [ 44 | { name = "colorama", marker = "sys_platform == 'win32'" }, 45 | ] 46 | sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } 47 | wheels = [ 48 | { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, 49 | ] 50 | 51 | [[package]] 52 | name = "colorama" 53 | version = "0.4.6" 54 | source = { registry = "https://pypi.org/simple" } 55 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } 56 | wheels = [ 57 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, 58 | ] 59 | 60 | [[package]] 61 | name = "evdev" 62 | version = "1.9.1" 63 | source = { registry = "https://pypi.org/simple" } 64 | sdist = { url = "https://files.pythonhosted.org/packages/d1/99/4d24bb6db12fc170a5f209f4c9108054a2c84d289d1e7f743e979b202023/evdev-1.9.1.tar.gz", hash = "sha256:dc640a064cb1c9fe1f8b970dc2039945a2a275d7b7ee62284bf427238abe45ee", size = 33349 } 65 | 66 | [[package]] 67 | name = "macholib" 68 | version = "1.16.3" 69 | source = { registry = "https://pypi.org/simple" } 70 | dependencies = [ 71 | { name = "altgraph" }, 72 | ] 73 | sdist = { url = "https://files.pythonhosted.org/packages/95/ee/af1a3842bdd5902ce133bd246eb7ffd4375c38642aeb5dc0ae3a0329dfa2/macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30", size = 59309 } 74 | wheels = [ 75 | { url = "https://files.pythonhosted.org/packages/d1/5d/c059c180c84f7962db0aeae7c3b9303ed1d73d76f2bfbc32bc231c8be314/macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c", size = 38094 }, 76 | ] 77 | 78 | [[package]] 79 | name = "markdown-it-py" 80 | version = "3.0.0" 81 | source = { registry = "https://pypi.org/simple" } 82 | dependencies = [ 83 | { name = "mdurl" }, 84 | ] 85 | sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } 86 | wheels = [ 87 | { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, 88 | ] 89 | 90 | [[package]] 91 | name = "mdurl" 92 | version = "0.1.2" 93 | source = { registry = "https://pypi.org/simple" } 94 | sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } 95 | wheels = [ 96 | { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, 97 | ] 98 | 99 | [[package]] 100 | name = "numpy" 101 | version = "2.2.4" 102 | source = { registry = "https://pypi.org/simple" } 103 | sdist = { url = "https://files.pythonhosted.org/packages/e1/78/31103410a57bc2c2b93a3597340a8119588571f6a4539067546cb9a0bfac/numpy-2.2.4.tar.gz", hash = "sha256:9ba03692a45d3eef66559efe1d1096c4b9b75c0986b5dff5530c378fb8331d4f", size = 20270701 } 104 | wheels = [ 105 | { url = "https://files.pythonhosted.org/packages/a2/30/182db21d4f2a95904cec1a6f779479ea1ac07c0647f064dea454ec650c42/numpy-2.2.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a7b9084668aa0f64e64bd00d27ba5146ef1c3a8835f3bd912e7a9e01326804c4", size = 20947156 }, 106 | { url = "https://files.pythonhosted.org/packages/24/6d/9483566acfbda6c62c6bc74b6e981c777229d2af93c8eb2469b26ac1b7bc/numpy-2.2.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dbe512c511956b893d2dacd007d955a3f03d555ae05cfa3ff1c1ff6df8851854", size = 14133092 }, 107 | { url = "https://files.pythonhosted.org/packages/27/f6/dba8a258acbf9d2bed2525cdcbb9493ef9bae5199d7a9cb92ee7e9b2aea6/numpy-2.2.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bb649f8b207ab07caebba230d851b579a3c8711a851d29efe15008e31bb4de24", size = 5163515 }, 108 | { url = "https://files.pythonhosted.org/packages/62/30/82116199d1c249446723c68f2c9da40d7f062551036f50b8c4caa42ae252/numpy-2.2.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:f34dc300df798742b3d06515aa2a0aee20941c13579d7a2f2e10af01ae4901ee", size = 6696558 }, 109 | { url = "https://files.pythonhosted.org/packages/0e/b2/54122b3c6df5df3e87582b2e9430f1bdb63af4023c739ba300164c9ae503/numpy-2.2.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3f7ac96b16955634e223b579a3e5798df59007ca43e8d451a0e6a50f6bfdfba", size = 14084742 }, 110 | { url = "https://files.pythonhosted.org/packages/02/e2/e2cbb8d634151aab9528ef7b8bab52ee4ab10e076509285602c2a3a686e0/numpy-2.2.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f92084defa704deadd4e0a5ab1dc52d8ac9e8a8ef617f3fbb853e79b0ea3592", size = 16134051 }, 111 | { url = "https://files.pythonhosted.org/packages/8e/21/efd47800e4affc993e8be50c1b768de038363dd88865920439ef7b422c60/numpy-2.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4e84a6283b36632e2a5b56e121961f6542ab886bc9e12f8f9818b3c266bfbb", size = 15578972 }, 112 | { url = "https://files.pythonhosted.org/packages/04/1e/f8bb88f6157045dd5d9b27ccf433d016981032690969aa5c19e332b138c0/numpy-2.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:11c43995255eb4127115956495f43e9343736edb7fcdb0d973defd9de14cd84f", size = 17898106 }, 113 | { url = "https://files.pythonhosted.org/packages/2b/93/df59a5a3897c1f036ae8ff845e45f4081bb06943039ae28a3c1c7c780f22/numpy-2.2.4-cp312-cp312-win32.whl", hash = "sha256:65ef3468b53269eb5fdb3a5c09508c032b793da03251d5f8722b1194f1790c00", size = 6311190 }, 114 | { url = "https://files.pythonhosted.org/packages/46/69/8c4f928741c2a8efa255fdc7e9097527c6dc4e4df147e3cadc5d9357ce85/numpy-2.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:2aad3c17ed2ff455b8eaafe06bcdae0062a1db77cb99f4b9cbb5f4ecb13c5146", size = 12644305 }, 115 | { url = "https://files.pythonhosted.org/packages/2a/d0/bd5ad792e78017f5decfb2ecc947422a3669a34f775679a76317af671ffc/numpy-2.2.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cf4e5c6a278d620dee9ddeb487dc6a860f9b199eadeecc567f777daace1e9e7", size = 20933623 }, 116 | { url = "https://files.pythonhosted.org/packages/c3/bc/2b3545766337b95409868f8e62053135bdc7fa2ce630aba983a2aa60b559/numpy-2.2.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1974afec0b479e50438fc3648974268f972e2d908ddb6d7fb634598cdb8260a0", size = 14148681 }, 117 | { url = "https://files.pythonhosted.org/packages/6a/70/67b24d68a56551d43a6ec9fe8c5f91b526d4c1a46a6387b956bf2d64744e/numpy-2.2.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:79bd5f0a02aa16808fcbc79a9a376a147cc1045f7dfe44c6e7d53fa8b8a79392", size = 5148759 }, 118 | { url = "https://files.pythonhosted.org/packages/1c/8b/e2fc8a75fcb7be12d90b31477c9356c0cbb44abce7ffb36be39a0017afad/numpy-2.2.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:3387dd7232804b341165cedcb90694565a6015433ee076c6754775e85d86f1fc", size = 6683092 }, 119 | { url = "https://files.pythonhosted.org/packages/13/73/41b7b27f169ecf368b52533edb72e56a133f9e86256e809e169362553b49/numpy-2.2.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f527d8fdb0286fd2fd97a2a96c6be17ba4232da346931d967a0630050dfd298", size = 14081422 }, 120 | { url = "https://files.pythonhosted.org/packages/4b/04/e208ff3ae3ddfbafc05910f89546382f15a3f10186b1f56bd99f159689c2/numpy-2.2.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bce43e386c16898b91e162e5baaad90c4b06f9dcbe36282490032cec98dc8ae7", size = 16132202 }, 121 | { url = "https://files.pythonhosted.org/packages/fe/bc/2218160574d862d5e55f803d88ddcad88beff94791f9c5f86d67bd8fbf1c/numpy-2.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31504f970f563d99f71a3512d0c01a645b692b12a63630d6aafa0939e52361e6", size = 15573131 }, 122 | { url = "https://files.pythonhosted.org/packages/a5/78/97c775bc4f05abc8a8426436b7cb1be806a02a2994b195945600855e3a25/numpy-2.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:81413336ef121a6ba746892fad881a83351ee3e1e4011f52e97fba79233611fd", size = 17894270 }, 123 | { url = "https://files.pythonhosted.org/packages/b9/eb/38c06217a5f6de27dcb41524ca95a44e395e6a1decdc0c99fec0832ce6ae/numpy-2.2.4-cp313-cp313-win32.whl", hash = "sha256:f486038e44caa08dbd97275a9a35a283a8f1d2f0ee60ac260a1790e76660833c", size = 6308141 }, 124 | { url = "https://files.pythonhosted.org/packages/52/17/d0dd10ab6d125c6d11ffb6dfa3423c3571befab8358d4f85cd4471964fcd/numpy-2.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:207a2b8441cc8b6a2a78c9ddc64d00d20c303d79fba08c577752f080c4007ee3", size = 12636885 }, 125 | { url = "https://files.pythonhosted.org/packages/fa/e2/793288ede17a0fdc921172916efb40f3cbc2aa97e76c5c84aba6dc7e8747/numpy-2.2.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8120575cb4882318c791f839a4fd66161a6fa46f3f0a5e613071aae35b5dd8f8", size = 20961829 }, 126 | { url = "https://files.pythonhosted.org/packages/3a/75/bb4573f6c462afd1ea5cbedcc362fe3e9bdbcc57aefd37c681be1155fbaa/numpy-2.2.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a761ba0fa886a7bb33c6c8f6f20213735cb19642c580a931c625ee377ee8bd39", size = 14161419 }, 127 | { url = "https://files.pythonhosted.org/packages/03/68/07b4cd01090ca46c7a336958b413cdbe75002286295f2addea767b7f16c9/numpy-2.2.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ac0280f1ba4a4bfff363a99a6aceed4f8e123f8a9b234c89140f5e894e452ecd", size = 5196414 }, 128 | { url = "https://files.pythonhosted.org/packages/a5/fd/d4a29478d622fedff5c4b4b4cedfc37a00691079623c0575978d2446db9e/numpy-2.2.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:879cf3a9a2b53a4672a168c21375166171bc3932b7e21f622201811c43cdd3b0", size = 6709379 }, 129 | { url = "https://files.pythonhosted.org/packages/41/78/96dddb75bb9be730b87c72f30ffdd62611aba234e4e460576a068c98eff6/numpy-2.2.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f05d4198c1bacc9124018109c5fba2f3201dbe7ab6e92ff100494f236209c960", size = 14051725 }, 130 | { url = "https://files.pythonhosted.org/packages/00/06/5306b8199bffac2a29d9119c11f457f6c7d41115a335b78d3f86fad4dbe8/numpy-2.2.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f085ce2e813a50dfd0e01fbfc0c12bbe5d2063d99f8b29da30e544fb6483b8", size = 16101638 }, 131 | { url = "https://files.pythonhosted.org/packages/fa/03/74c5b631ee1ded596945c12027649e6344614144369fd3ec1aaced782882/numpy-2.2.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:92bda934a791c01d6d9d8e038363c50918ef7c40601552a58ac84c9613a665bc", size = 15571717 }, 132 | { url = "https://files.pythonhosted.org/packages/cb/dc/4fc7c0283abe0981e3b89f9b332a134e237dd476b0c018e1e21083310c31/numpy-2.2.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ee4d528022f4c5ff67332469e10efe06a267e32f4067dc76bb7e2cddf3cd25ff", size = 17879998 }, 133 | { url = "https://files.pythonhosted.org/packages/e5/2b/878576190c5cfa29ed896b518cc516aecc7c98a919e20706c12480465f43/numpy-2.2.4-cp313-cp313t-win32.whl", hash = "sha256:05c076d531e9998e7e694c36e8b349969c56eadd2cdcd07242958489d79a7286", size = 6366896 }, 134 | { url = "https://files.pythonhosted.org/packages/3e/05/eb7eec66b95cf697f08c754ef26c3549d03ebd682819f794cb039574a0a6/numpy-2.2.4-cp313-cp313t-win_amd64.whl", hash = "sha256:188dcbca89834cc2e14eb2f106c96d6d46f200fe0200310fc29089657379c58d", size = 12739119 }, 135 | ] 136 | 137 | [[package]] 138 | name = "packaging" 139 | version = "24.2" 140 | source = { registry = "https://pypi.org/simple" } 141 | sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } 142 | wheels = [ 143 | { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, 144 | ] 145 | 146 | [[package]] 147 | name = "pefile" 148 | version = "2023.2.7" 149 | source = { registry = "https://pypi.org/simple" } 150 | sdist = { url = "https://files.pythonhosted.org/packages/78/c5/3b3c62223f72e2360737fd2a57c30e5b2adecd85e70276879609a7403334/pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc", size = 74854 } 151 | wheels = [ 152 | { url = "https://files.pythonhosted.org/packages/55/26/d0ad8b448476d0a1e8d3ea5622dc77b916db84c6aa3cb1e1c0965af948fc/pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6", size = 71791 }, 153 | ] 154 | 155 | [[package]] 156 | name = "pygments" 157 | version = "2.19.1" 158 | source = { registry = "https://pypi.org/simple" } 159 | sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } 160 | wheels = [ 161 | { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, 162 | ] 163 | 164 | [[package]] 165 | name = "pyinstaller" 166 | version = "6.12.0" 167 | source = { registry = "https://pypi.org/simple" } 168 | dependencies = [ 169 | { name = "altgraph" }, 170 | { name = "macholib", marker = "sys_platform == 'darwin'" }, 171 | { name = "packaging" }, 172 | { name = "pefile", marker = "sys_platform == 'win32'" }, 173 | { name = "pyinstaller-hooks-contrib" }, 174 | { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, 175 | { name = "setuptools" }, 176 | ] 177 | sdist = { url = "https://files.pythonhosted.org/packages/10/c0/001e86a13f9f6104613f198721c72d377fa1fc2a09550cfe1ac9a1d12406/pyinstaller-6.12.0.tar.gz", hash = "sha256:1834797be48ce1b26015af68bdeb3c61a6c7500136f04e0fc65e468115dec777", size = 4267132 } 178 | wheels = [ 179 | { url = "https://files.pythonhosted.org/packages/b2/73/b897a3fda99a14130111abdb978d63da14cbc9932497b5e5064c5fe28187/pyinstaller-6.12.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:68f1e4cecf88a6272063977fa2a2c69ad37cf568e5901769d7206d0314c74f47", size = 997954 }, 180 | { url = "https://files.pythonhosted.org/packages/4a/bc/0929ed6aca3c5ff3f20f8cfd4f2f7e90f18c9465440e0d151d56d8170851/pyinstaller-6.12.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:fea76fc9b55ffa730fcf90beb897cce4399938460b0b6f40507fbebfc752c753", size = 714097 }, 181 | { url = "https://files.pythonhosted.org/packages/e1/9a/422d5eb04132e4a4735ca9099a53511324ff7d387b80231fe8dbd67bf322/pyinstaller-6.12.0-py3-none-manylinux2014_i686.whl", hash = "sha256:dac8a27988dbc33cdc34f2046803258bc3f6829de24de52745a5daa22bdba0f1", size = 724471 }, 182 | { url = "https://files.pythonhosted.org/packages/64/1c/5028ba2e09f5b57f6792e9d88e888725224f8f016a07666e48664f6a9fcf/pyinstaller-6.12.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:83c7f3bde9871b4a6aa71c66a96e8ba5c21668ce711ed97f510b9382d10aac6c", size = 722753 }, 183 | { url = "https://files.pythonhosted.org/packages/6f/d9/e7742caf4c4dc07d13e355ad2c14c7844c9bb2e66dea4f3386b4644bd106/pyinstaller-6.12.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:a69818815c6e0711c727edc30680cb1f81c691b59de35db81a2d9e0ae26a9ef1", size = 720906 }, 184 | { url = "https://files.pythonhosted.org/packages/80/2b/14404f2dc95d1ec94d08879c62a76d5f26a176fab99fb023c2c70d2ff500/pyinstaller-6.12.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a2abf5fde31a8b38b6df7939bcef8ac1d0c51e97e25317ce3555cd675259750f", size = 716959 }, 185 | { url = "https://files.pythonhosted.org/packages/11/a6/5c3a233cf19aa6d4caacf62f7ee1c728486cc20b73f5817be17485d7b7ff/pyinstaller-6.12.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:8e92e9873a616547bbabbb5a3a9843d5f2ab40c3d8b26810acdf0fe257bee4cf", size = 719414 }, 186 | { url = "https://files.pythonhosted.org/packages/24/57/069d35236806b281a3331ef00ff94e43f3b91e4b36350de8b40b4baf9fd3/pyinstaller-6.12.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:aefe502d55c9cf6aeaed7feba80b5f8491ce43f8f2b5fe2d9aadca3ee5a05bc4", size = 715903 }, 187 | { url = "https://files.pythonhosted.org/packages/4d/5f/857de8798836f9d16a620bd0a7c8899bba05b5fda7b3b4432762f148a86d/pyinstaller-6.12.0-py3-none-win32.whl", hash = "sha256:138856a5a503bb69c066377e0a22671b0db063e9cc14d5cf5c798a53561200d3", size = 1290980 }, 188 | { url = "https://files.pythonhosted.org/packages/99/6e/d7d76d4d15f6351f1f942256633b795eec3d6c691d985869df1bf319cd9d/pyinstaller-6.12.0-py3-none-win_amd64.whl", hash = "sha256:0e62d3906309248409f215b386f33afec845214e69cc0f296b93222b26a88f43", size = 1348786 }, 189 | { url = "https://files.pythonhosted.org/packages/47/c2/298ad6a3aa2cacb55cbc1f845068dc1e4a6c966082ffa0e19c69084cbc42/pyinstaller-6.12.0-py3-none-win_arm64.whl", hash = "sha256:0c271896a3a168f4f91827145702543db9c5427f4c7372a6df8c75925a3ac18a", size = 1289617 }, 190 | ] 191 | 192 | [[package]] 193 | name = "pyinstaller-hooks-contrib" 194 | version = "2025.1" 195 | source = { registry = "https://pypi.org/simple" } 196 | dependencies = [ 197 | { name = "packaging" }, 198 | { name = "setuptools" }, 199 | ] 200 | sdist = { url = "https://files.pythonhosted.org/packages/2f/1b/dc256d42f4217db99b50d6d32dbbf841a41b9615506cde77d2345d94f4a5/pyinstaller_hooks_contrib-2025.1.tar.gz", hash = "sha256:130818f9e9a0a7f2261f1fd66054966a3a50c99d000981c5d1db11d3ad0c6ab2", size = 147043 } 201 | wheels = [ 202 | { url = "https://files.pythonhosted.org/packages/b7/48/833d67a585275e395f351e5787b4b7a8d462d87bca22a8c038f6ffdc2b3c/pyinstaller_hooks_contrib-2025.1-py3-none-any.whl", hash = "sha256:d3c799470cbc0bda60dcc8e6b4ab976777532b77621337f2037f558905e3a8e9", size = 346409 }, 203 | ] 204 | 205 | [[package]] 206 | name = "pynput" 207 | version = "1.8.1" 208 | source = { registry = "https://pypi.org/simple" } 209 | dependencies = [ 210 | { name = "evdev", marker = "'linux' in sys_platform" }, 211 | { name = "pyobjc-framework-applicationservices", marker = "sys_platform == 'darwin'" }, 212 | { name = "pyobjc-framework-quartz", marker = "sys_platform == 'darwin'" }, 213 | { name = "python-xlib", marker = "'linux' in sys_platform" }, 214 | { name = "six" }, 215 | ] 216 | sdist = { url = "https://files.pythonhosted.org/packages/f0/c3/dccf44c68225046df5324db0cc7d563a560635355b3e5f1d249468268a6f/pynput-1.8.1.tar.gz", hash = "sha256:70d7c8373ee98911004a7c938742242840a5628c004573d84ba849d4601df81e", size = 82289 } 217 | wheels = [ 218 | { url = "https://files.pythonhosted.org/packages/59/4f/ac3fa906ae8a375a536b12794128c5efacade9eaa917a35dfd27ce0c7400/pynput-1.8.1-py2.py3-none-any.whl", hash = "sha256:42dfcf27404459ca16ca889c8fb8ffe42a9fe54f722fd1a3e130728e59e768d2", size = 91693 }, 219 | ] 220 | 221 | [[package]] 222 | name = "pyobjc-core" 223 | version = "11.0" 224 | source = { registry = "https://pypi.org/simple" } 225 | sdist = { url = "https://files.pythonhosted.org/packages/5c/94/a111239b98260869780a5767e5d74bfd3a8c13a40457f479c28dcd91f89d/pyobjc_core-11.0.tar.gz", hash = "sha256:63bced211cb8a8fb5c8ff46473603da30e51112861bd02c438fbbbc8578d9a70", size = 994931 } 226 | wheels = [ 227 | { url = "https://files.pythonhosted.org/packages/56/ce/bf3ff9a9347721a398c3dfb83e29b43fb166b7ef590f3f7b7ddcd283df39/pyobjc_core-11.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a03061d4955c62ddd7754224a80cdadfdf17b6b5f60df1d9169a3b1b02923f0b", size = 739750 }, 228 | { url = "https://files.pythonhosted.org/packages/72/16/0c468e73dbecb821e3da8819236fe832dfc53eb5f66a11775b055a7589ea/pyobjc_core-11.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c338c1deb7ab2e9436d4175d1127da2eeed4a1b564b3d83b9f3ae4844ba97e86", size = 743900 }, 229 | { url = "https://files.pythonhosted.org/packages/f3/88/cecec88fd51f62a6cd7775cc4fb6bfde16652f97df88d28c84fb77ca0c18/pyobjc_core-11.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b4e9dc4296110f251a4033ff3f40320b35873ea7f876bd29a1c9705bb5e08c59", size = 791905 }, 230 | ] 231 | 232 | [[package]] 233 | name = "pyobjc-framework-applicationservices" 234 | version = "11.0" 235 | source = { registry = "https://pypi.org/simple" } 236 | dependencies = [ 237 | { name = "pyobjc-core" }, 238 | { name = "pyobjc-framework-cocoa" }, 239 | { name = "pyobjc-framework-coretext" }, 240 | { name = "pyobjc-framework-quartz" }, 241 | ] 242 | sdist = { url = "https://files.pythonhosted.org/packages/ba/fb/4e42573b0d3baa3fa18ec53614cf979f951313f1451e8f2e17df9429da1f/pyobjc_framework_applicationservices-11.0.tar.gz", hash = "sha256:d6ea18dfc7d5626a3ecf4ac72d510405c0d3a648ca38cae8db841acdebecf4d2", size = 224334 } 243 | wheels = [ 244 | { url = "https://files.pythonhosted.org/packages/74/a9/7a45a67e126d32c61ea22ffd80e87ff7e05b4acf32bede6cce071fbfffc8/pyobjc_framework_ApplicationServices-11.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:5fbeb425897d6129471d451ec61a29ddd5b1386eb26b1dd49cb313e34616ee21", size = 30908 }, 245 | { url = "https://files.pythonhosted.org/packages/82/47/ab4155ec966aff2f8f0f6978b40f12255e8ef46111ca0bda7987959b4052/pyobjc_framework_ApplicationServices-11.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:59becf3cd87a4f4cedf4be02ff6cf46ed736f5c1123ce629f788aaafad91eff0", size = 30924 }, 246 | { url = "https://files.pythonhosted.org/packages/a3/73/747aab95970e0b7b5d38c650028e5e034c0432d9451335ff790ca104f11a/pyobjc_framework_ApplicationServices-11.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:44b466e8745fb49e8ac20f29f2ffd7895b45e97aa63a844b2a80a97c3a34346f", size = 31279 }, 247 | ] 248 | 249 | [[package]] 250 | name = "pyobjc-framework-cocoa" 251 | version = "11.0" 252 | source = { registry = "https://pypi.org/simple" } 253 | dependencies = [ 254 | { name = "pyobjc-core" }, 255 | ] 256 | sdist = { url = "https://files.pythonhosted.org/packages/c5/32/53809096ad5fc3e7a2c5ddea642590a5f2cb5b81d0ad6ea67fdb2263d9f9/pyobjc_framework_cocoa-11.0.tar.gz", hash = "sha256:00346a8cb81ad7b017b32ff7bf596000f9faa905807b1bd234644ebd47f692c5", size = 6173848 } 257 | wheels = [ 258 | { url = "https://files.pythonhosted.org/packages/5b/8d/0e2558447c26b3ba64f7c9776a5a6c9d2ae8abf9d34308b174ae0934402e/pyobjc_framework_Cocoa-11.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:280a577b83c68175a28b2b7138d1d2d3111f2b2b66c30e86f81a19c2b02eae71", size = 385811 }, 259 | { url = "https://files.pythonhosted.org/packages/1d/a5/609281a7e89efefbef9db1d8fe66bc0458c3b4e74e2227c644f9c18926fa/pyobjc_framework_Cocoa-11.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:15b2bd977ed340074f930f1330f03d42912d5882b697d78bd06f8ebe263ef92e", size = 385889 }, 260 | { url = "https://files.pythonhosted.org/packages/93/f6/2d5a863673ef7b85a3cba875c43e6c495fb1307427a6801001ae94bb5e54/pyobjc_framework_Cocoa-11.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5750001db544e67f2b66f02067d8f0da96bb2ef71732bde104f01b8628f9d7ea", size = 389831 }, 261 | ] 262 | 263 | [[package]] 264 | name = "pyobjc-framework-coretext" 265 | version = "11.0" 266 | source = { registry = "https://pypi.org/simple" } 267 | dependencies = [ 268 | { name = "pyobjc-core" }, 269 | { name = "pyobjc-framework-cocoa" }, 270 | { name = "pyobjc-framework-quartz" }, 271 | ] 272 | sdist = { url = "https://files.pythonhosted.org/packages/9d/e8/9b68dc788828e38143a3e834e66346713751cb83d7f0955016323005c1a2/pyobjc_framework_coretext-11.0.tar.gz", hash = "sha256:a68437153e627847e3898754dd3f13ae0cb852246b016a91f9c9cbccb9f91a43", size = 274222 } 273 | wheels = [ 274 | { url = "https://files.pythonhosted.org/packages/0d/14/d300b8bf18acd1d98d40820d2a9b5c5b6cf96325bdfc5020bc963218e001/pyobjc_framework_CoreText-11.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fb90e7f370b3fd7cb2fb442e3dc63fedf0b4af6908db1c18df694d10dc94669d", size = 30456 }, 275 | { url = "https://files.pythonhosted.org/packages/94/f0/53b681481e9429e8f9ac2c039da6a820d7417ca92f763f01d629db36c530/pyobjc_framework_CoreText-11.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7947f755782456bd663e0b00c7905eeffd10f839f0bf2af031f68ded6a1ea360", size = 30453 }, 276 | { url = "https://files.pythonhosted.org/packages/2a/3f/a6d09952e83d70be6d337a5f1d457018459a57a110a91c3e771a2f2a7de0/pyobjc_framework_CoreText-11.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5356116bae33ec49f1f212c301378a7d08000440a2d6a7281aab351945528ab9", size = 31092 }, 277 | ] 278 | 279 | [[package]] 280 | name = "pyobjc-framework-quartz" 281 | version = "11.0" 282 | source = { registry = "https://pypi.org/simple" } 283 | dependencies = [ 284 | { name = "pyobjc-core" }, 285 | { name = "pyobjc-framework-cocoa" }, 286 | ] 287 | sdist = { url = "https://files.pythonhosted.org/packages/a5/ad/f00f3f53387c23bbf4e0bb1410e11978cbf87c82fa6baff0ee86f74c5fb6/pyobjc_framework_quartz-11.0.tar.gz", hash = "sha256:3205bf7795fb9ae34747f701486b3db6dfac71924894d1f372977c4d70c3c619", size = 3952463 } 288 | wheels = [ 289 | { url = "https://files.pythonhosted.org/packages/60/5d/df827b78dcb5140652ad08af8038c9ddd7e01e6bdf84462bfee644e6e661/pyobjc_framework_Quartz-11.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:cb4a9f2d9d580ea15e25e6b270f47681afb5689cafc9e25712445ce715bcd18e", size = 212061 }, 290 | { url = "https://files.pythonhosted.org/packages/a6/9e/54c48fe8faab06ee5eb80796c8c17ec61fc313d84398540ee70abeaf7070/pyobjc_framework_Quartz-11.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:973b4f9b8ab844574461a038bd5269f425a7368d6e677e3cc81fcc9b27b65498", size = 212478 }, 291 | { url = "https://files.pythonhosted.org/packages/4a/28/456b54a59bfe11a91b7b4e94f8ffdcf174ffd1efa169f4283e5b3bc10194/pyobjc_framework_Quartz-11.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:66ab58d65348863b8707e63b2ec5cdc54569ee8189d1af90d52f29f5fdf6272c", size = 217973 }, 292 | ] 293 | 294 | [[package]] 295 | name = "python-xlib" 296 | version = "0.33" 297 | source = { registry = "https://pypi.org/simple" } 298 | dependencies = [ 299 | { name = "six" }, 300 | ] 301 | sdist = { url = "https://files.pythonhosted.org/packages/86/f5/8c0653e5bb54e0cbdfe27bf32d41f27bc4e12faa8742778c17f2a71be2c0/python-xlib-0.33.tar.gz", hash = "sha256:55af7906a2c75ce6cb280a584776080602444f75815a7aff4d287bb2d7018b32", size = 269068 } 302 | wheels = [ 303 | { url = "https://files.pythonhosted.org/packages/fc/b8/ff33610932e0ee81ae7f1269c890f697d56ff74b9f5b2ee5d9b7fa2c5355/python_xlib-0.33-py2.py3-none-any.whl", hash = "sha256:c3534038d42e0df2f1392a1b30a15a4ff5fdc2b86cfa94f072bf11b10a164398", size = 182185 }, 304 | ] 305 | 306 | [[package]] 307 | name = "pywin32-ctypes" 308 | version = "0.2.3" 309 | source = { registry = "https://pypi.org/simple" } 310 | sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471 } 311 | wheels = [ 312 | { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756 }, 313 | ] 314 | 315 | [[package]] 316 | name = "rich" 317 | version = "13.9.4" 318 | source = { registry = "https://pypi.org/simple" } 319 | dependencies = [ 320 | { name = "markdown-it-py" }, 321 | { name = "pygments" }, 322 | ] 323 | sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } 324 | wheels = [ 325 | { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, 326 | ] 327 | 328 | [[package]] 329 | name = "setuptools" 330 | version = "77.0.3" 331 | source = { registry = "https://pypi.org/simple" } 332 | sdist = { url = "https://files.pythonhosted.org/packages/81/ed/7101d53811fd359333583330ff976e5177c5e871ca8b909d1d6c30553aa3/setuptools-77.0.3.tar.gz", hash = "sha256:583b361c8da8de57403743e756609670de6fb2345920e36dc5c2d914c319c945", size = 1367236 } 333 | wheels = [ 334 | { url = "https://files.pythonhosted.org/packages/a9/07/99f2cefae815c66eb23148f15d79ec055429c38fa8986edcc712ab5f3223/setuptools-77.0.3-py3-none-any.whl", hash = "sha256:67122e78221da5cf550ddd04cf8742c8fe12094483749a792d56cd669d6cf58c", size = 1255678 }, 335 | ] 336 | 337 | [[package]] 338 | name = "shellingham" 339 | version = "1.5.4" 340 | source = { registry = "https://pypi.org/simple" } 341 | sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 } 342 | wheels = [ 343 | { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, 344 | ] 345 | 346 | [[package]] 347 | name = "six" 348 | version = "1.17.0" 349 | source = { registry = "https://pypi.org/simple" } 350 | sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } 351 | wheels = [ 352 | { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, 353 | ] 354 | 355 | [[package]] 356 | name = "typer" 357 | version = "0.15.2" 358 | source = { registry = "https://pypi.org/simple" } 359 | dependencies = [ 360 | { name = "click" }, 361 | { name = "rich" }, 362 | { name = "shellingham" }, 363 | { name = "typing-extensions" }, 364 | ] 365 | sdist = { url = "https://files.pythonhosted.org/packages/8b/6f/3991f0f1c7fcb2df31aef28e0594d8d54b05393a0e4e34c65e475c2a5d41/typer-0.15.2.tar.gz", hash = "sha256:ab2fab47533a813c49fe1f16b1a370fd5819099c00b119e0633df65f22144ba5", size = 100711 } 366 | wheels = [ 367 | { url = "https://files.pythonhosted.org/packages/7f/fc/5b29fea8cee020515ca82cc68e3b8e1e34bb19a3535ad854cac9257b414c/typer-0.15.2-py3-none-any.whl", hash = "sha256:46a499c6107d645a9c13f7ee46c5d5096cae6f5fc57dd11eccbbb9ae3e44ddfc", size = 45061 }, 368 | ] 369 | 370 | [[package]] 371 | name = "typing-extensions" 372 | version = "4.12.2" 373 | source = { registry = "https://pypi.org/simple" } 374 | sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } 375 | wheels = [ 376 | { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, 377 | ] 378 | --------------------------------------------------------------------------------