From 372f52e13ad01512a35a1538a0a765dff7711095 Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Mon, 25 Aug 2025 18:27:47 +0200 Subject: improve python experience --- .python-version | 1 + Makefile | 2 + generate_json.py | 171 +++++++++++++++++++++++++++++++++-------------------- main.c | 3 +- pyproject.toml | 10 ++++ pyrightconfig.json | 7 +++ uv.lock | 64 ++++++++++++++++++++ 7 files changed, 192 insertions(+), 66 deletions(-) create mode 100644 .python-version create mode 100644 pyproject.toml create mode 100644 pyrightconfig.json create mode 100644 uv.lock diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/Makefile b/Makefile index b5489e8..df7d850 100644 --- a/Makefile +++ b/Makefile @@ -25,4 +25,6 @@ format: check: clang-format -i --dry-run src/*.c include/*.h tests/*.c *.c --fail-on-incomplete-format + ruff check + ruff format --check make test diff --git a/generate_json.py b/generate_json.py index b3e285f..2f0a9d5 100644 --- a/generate_json.py +++ b/generate_json.py @@ -7,23 +7,23 @@ import sys import os from datetime import datetime -def random_string(length): - """Generate a random string of given length.""" - return ''.join(random.choices(string.ascii_letters + string.digits + ' ', k=length)) - -def random_email(): - """Generate a random email address.""" - username = ''.join(random.choices(string.ascii_lowercase, k=random.randint(5, 12))) - domain = ''.join(random.choices(string.ascii_lowercase, k=random.randint(4, 8))) - tld = random.choice(['com', 'org', 'net', 'edu', 'gov']) + +def random_string(length: int) -> str: + return "".join(random.choices(string.ascii_letters + string.digits + " ", k=length)) + + +def random_email() -> str: + username = "".join(random.choices(string.ascii_lowercase, k=random.randint(5, 12))) + domain = "".join(random.choices(string.ascii_lowercase, k=random.randint(4, 8))) + tld = random.choice(["com", "org", "net", "edu", "gov"]) return f"{username}@{domain}.{tld}" -def random_phone(): - """Generate a random phone number.""" + +def random_phone() -> str: return f"+1-{random.randint(100, 999)}-{random.randint(100, 999)}-{random.randint(1000, 9999)}" + def generate_user(): - """Generate a random user object.""" return { "id": random.randint(1, 1000000), "username": random_string(random.randint(6, 15)), @@ -34,38 +34,44 @@ def generate_user(): "phone": random_phone(), "is_active": random.choice([True, False]), "balance": round(random.uniform(0, 10000), 2), - "tags": [random_string(random.randint(3, 8)) for _ in range(random.randint(1, 5))], + "tags": [ + random_string(random.randint(3, 8)) for _ in range(random.randint(1, 5)) + ], "metadata": { "last_login": f"2024-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}T{random.randint(0, 23):02d}:{random.randint(0, 59):02d}:{random.randint(0, 59):02d}Z", "login_count": random.randint(0, 500), "preferences": { "theme": random.choice(["dark", "light", "auto"]), "notifications": random.choice([True, False]), - "language": random.choice(["en", "es", "fr", "de", "ja"]) - } - } + "language": random.choice(["en", "es", "fr", "de", "ja"]), + }, + }, } + def generate_product(): - """Generate a random product object.""" return { "id": f"prod_{random.randint(1000, 99999)}", "name": random_string(random.randint(10, 30)), "description": random_string(random.randint(50, 200)), "price": round(random.uniform(1, 1000), 2), - "category": random.choice(["electronics", "clothing", "books", "home", "sports", "toys"]), + "category": random.choice( + ["electronics", "clothing", "books", "home", "sports", "toys"] + ), "in_stock": random.randint(0, 100), "rating": round(random.uniform(1, 5), 1), "reviews": random.randint(0, 1000), "specifications": { "weight": f"{random.uniform(0.1, 50):.2f}kg", "dimensions": f"{random.randint(1, 100)}x{random.randint(1, 100)}x{random.randint(1, 100)}cm", - "color": random.choice(["red", "blue", "green", "black", "white", "yellow", "purple"]) - } + "color": random.choice( + ["red", "blue", "green", "black", "white", "yellow", "purple"] + ), + }, } + def generate_order(): - """Generate a random order object.""" return { "order_id": f"order_{random.randint(10000, 999999)}", "user_id": random.randint(1, 1000000), @@ -73,38 +79,38 @@ def generate_order(): { "product_id": f"prod_{random.randint(1000, 99999)}", "quantity": random.randint(1, 5), - "price": round(random.uniform(10, 500), 2) - } for _ in range(random.randint(1, 8)) + "price": round(random.uniform(10, 500), 2), + } + for _ in range(random.randint(1, 8)) ], "total": round(random.uniform(20, 2000), 2), - "status": random.choice(["pending", "processing", "shipped", "delivered", "cancelled"]), + "status": random.choice( + ["pending", "processing", "shipped", "delivered", "cancelled"] + ), "created_at": f"2024-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}T{random.randint(0, 23):02d}:{random.randint(0, 59):02d}:{random.randint(0, 59):02d}Z", "shipping_address": { "street": f"{random.randint(1, 9999)} {random_string(random.randint(5, 15))} St", "city": random_string(random.randint(6, 12)), "state": random_string(2).upper(), "zip_code": f"{random.randint(10000, 99999)}", - "country": "US" - } + "country": "US", + }, } -def generate_large_json(target_size_mb=100, output_file="benchmark.json"): - """Generate a large JSON file with mixed data types.""" + +def generate_large_json(target_size_mb: int, output_file: str): target_size_bytes = target_size_mb * 1024 * 1024 data = { "metadata": { "generated_at": datetime.now().isoformat(), "target_size_mb": target_size_mb, - "generator_version": "1.0" + "generator_version": "1.0", }, "users": [], "products": [], "orders": [], - "analytics": { - "page_views": [], - "server_metrics": [] - } + "analytics": {"page_views": [], "server_metrics": []}, } print(f"Generating JSON file targeting {target_size_mb}MB...") @@ -128,37 +134,43 @@ def generate_large_json(target_size_mb=100, output_file="benchmark.json"): # Add some analytics data for _ in range(batch_size): - data["analytics"]["page_views"].append({ - "timestamp": f"2024-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}T{random.randint(0, 23):02d}:{random.randint(0, 59):02d}:{random.randint(0, 59):02d}Z", - "page": f"/{random_string(random.randint(5, 15))}", - "user_id": random.randint(1, 1000000), - "duration": random.randint(1, 300) - }) + data["analytics"]["page_views"].append( + { + "timestamp": f"2024-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}T{random.randint(0, 23):02d}:{random.randint(0, 59):02d}:{random.randint(0, 59):02d}Z", + "page": f"/{random_string(random.randint(5, 15))}", + "user_id": random.randint(1, 1000000), + "duration": random.randint(1, 300), + } + ) for _ in range(batch_size // 10): - data["analytics"]["server_metrics"].append({ - "timestamp": f"2024-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}T{random.randint(0, 23):02d}:{random.randint(0, 59):02d}:{random.randint(0, 59):02d}Z", - "cpu_usage": round(random.uniform(0, 100), 2), - "memory_usage": round(random.uniform(0, 100), 2), - "disk_io": random.randint(0, 1000), - "network_io": random.randint(0, 10000) - }) + data["analytics"]["server_metrics"].append( + { + "timestamp": f"2024-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}T{random.randint(0, 23):02d}:{random.randint(0, 59):02d}:{random.randint(0, 59):02d}Z", + "cpu_usage": round(random.uniform(0, 100), 2), + "memory_usage": round(random.uniform(0, 100), 2), + "disk_io": random.randint(0, 1000), + "network_io": random.randint(0, 10000), + } + ) # Estimate current size (rough approximation) current_size = ( - len(data["users"]) * 400 + # Rough estimate per user - len(data["products"]) * 300 + - len(data["orders"]) * 500 + - len(data["analytics"]["page_views"]) * 150 + - len(data["analytics"]["server_metrics"]) * 200 + len(data["users"]) * 400 # Rough estimate per user + + len(data["products"]) * 300 + + len(data["orders"]) * 500 + + len(data["analytics"]["page_views"]) * 150 + + len(data["analytics"]["server_metrics"]) * 200 ) - if current_size % (10 * 1024 * 1024) < batch_size * 400: # Print progress every ~10MB + if ( + current_size % (10 * 1024 * 1024) < batch_size * 400 + ): # Print progress every ~10MB print(f"Generated approximately {current_size / (1024 * 1024):.1f}MB...") print(f"Writing to {output_file}...") - with open(output_file, 'w') as f: - json.dump(data, f, separators=(',', ':')) # Compact format + with open(output_file, "w") as f: + json.dump(data, f, separators=(",", ":")) # Compact format # Get actual file size actual_size = os.path.getsize(output_file) @@ -173,24 +185,55 @@ def generate_large_json(target_size_mb=100, output_file="benchmark.json"): print(f" Page views: {len(data['analytics']['page_views']):,}") print(f" Server metrics: {len(data['analytics']['server_metrics']):,}") +def generate_descriptive(target_size_mb: int, output_file: str): + target_size_bytes = target_size_mb * 1024 * 1024 + data = [] + current_size = 0 + batch_size = 100 + + print(f"Generating descriptive JSON array targeting {target_size_mb}MB...") + + while current_size < target_size_bytes: + batch = [ + { + "name": random_string(40), + "description": random_string(400), + } + for _ in range(batch_size) + ] + data.extend(batch) + # Estimate current size (approximate: 40+400 chars per object + overhead) + current_size = len(data) * (40 + 400 + 30) + + if ( + current_size % (10 * 1024 * 1024) < batch_size * (40 + 400) + ): + print(f"Generated approximately {current_size / (1024 * 1024):.1f}MB...") + + print(f"Writing to {output_file}...") + with open(output_file, "w") as f: + json.dump(data, f, separators=(",", ":")) + + actual_size = os.path.getsize(output_file) + actual_size_mb = actual_size / (1024 * 1024) + + print(f"✓ Generated {output_file}") + print(f" Target size: {target_size_mb}MB") + print(f" Actual size: {actual_size_mb:.1f}MB ({actual_size:,} bytes)") + print(f" Objects: {len(data):,}") + def main(): assert len(sys.argv) == 2 try: target_size = int(sys.argv[1]) except ValueError: - print("Usage: python3 generate_json.py [size_in_mb] [output_file]") + print("Usage: python3 generate_json.py [size_in_mb]") sys.exit(1) - output_file = f"{target_size}MB.json" + output_file = f"descriptive-{target_size}MB.json" + + generate_descriptive(target_size, output_file) - try: - generate_large_json(target_size, output_file) - except KeyboardInterrupt: - print("\n\nInterrupted! Partial file may have been created.") - sys.exit(1) - except Exception as e: - print(f"Error: {e}") - sys.exit(1) if __name__ == "__main__": main() diff --git a/main.c b/main.c index de186f2..fc389df 100644 --- a/main.c +++ b/main.c @@ -73,8 +73,7 @@ void run_benchmark(const char *filename, i32 iterations) { } i32 main(i32 argc, char *argv[]) { - const char *filename = ""; - + char *filename = ""; // Parse command line arguments assert(argc == 3, "main "); filename = argv[1]; diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..857fbb5 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "kagamic" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "pysimdjson>=7.0.2", + "ruff>=0.12.10", +] diff --git a/pyrightconfig.json b/pyrightconfig.json new file mode 100644 index 0000000..efb7f00 --- /dev/null +++ b/pyrightconfig.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/pyright/refs/heads/main/packages/vscode-pyright/schemas/pyrightconfig.schema.json", + "strict": [ + "." + ], + "typeCheckingMode": "strict" +} diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..2191d5d --- /dev/null +++ b/uv.lock @@ -0,0 +1,64 @@ +version = 1 +revision = 3 +requires-python = ">=3.13" + +[[package]] +name = "kagamic" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "pysimdjson" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "pysimdjson", specifier = ">=7.0.2" }, + { name = "ruff", specifier = ">=0.12.10" }, +] + +[[package]] +name = "pysimdjson" +version = "7.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/24/65e3cad88e74ef8ca59fefded953eb78ebface8a3199c3a97fe318a7387b/pysimdjson-7.0.2.tar.gz", hash = "sha256:44cf276e48912a3b9c7ca362c14da8420a7ac15a9f1a16ec95becff86db3904a", size = 1397812, upload-time = "2025-06-28T20:37:24.071Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/65/65/bf171e0dde8a40a56c6fde4e700daa3b172f1781b26478e92c34317f1225/pysimdjson-7.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a721cc23cd6240430b2c862caff79a411abc987290859cd0f9c5a3e29efa1d2c", size = 1877151, upload-time = "2025-06-28T20:36:54.199Z" }, + { url = "https://files.pythonhosted.org/packages/e2/2d/242c1bebadb960b704066288ae28660da3de7fb5d8f52f655e080e7ffbbf/pysimdjson-7.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdbbf4246cac27dac38043da8f4d82a46d434b5bc3a4e54c0a55de1dd92631ae", size = 1655651, upload-time = "2025-06-28T20:36:55.336Z" }, + { url = "https://files.pythonhosted.org/packages/49/86/3b25e77ae2998342d2bd376eb58baf17b35e6c2fdb9184e8bc8c31ebfafe/pysimdjson-7.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77bbf9afdea8a9aa220cbf29115cc32e81207f9e8e07963ea145ba8d2e8f4053", size = 2771613, upload-time = "2025-06-28T20:36:56.732Z" }, + { url = "https://files.pythonhosted.org/packages/49/d9/3db962802aa5c95a8f89023dcf00eefa30817e9b9862668d5efb91c44d81/pysimdjson-7.0.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43d42ef0660181b67bd833c13bdcbb2743abd40bc348db8f9e788b5d88717459", size = 2819981, upload-time = "2025-06-28T20:36:57.923Z" }, + { url = "https://files.pythonhosted.org/packages/f2/a0/bfbc3c9a1b216cacad74863229c06c576f108e4f67cb6daa3c4d6071a9ff/pysimdjson-7.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13f2820c95d9c74139407921aeec8099e67546ccfcb309561881e877e4a3aa97", size = 3246918, upload-time = "2025-06-28T20:36:59.458Z" }, + { url = "https://files.pythonhosted.org/packages/ed/fc/1d21538d1fd3e4f2f7a96de605fbcdb1f150ff0eb49ac08f005da83e17c7/pysimdjson-7.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f81638ce66a7393ad1b4f5fae6666c417cc01e5ecb81c86ff727349599bbc83f", size = 2524078, upload-time = "2025-06-28T20:37:00.659Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d3/76c05b4d116adcb947955c68700c9e67ee7f748a38d37ba72e5b1109ef1d/pysimdjson-7.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5ffe83c4dbfdabea5f2231cc64ff1a62b7ecd18f64cb04a61439a5c24d08a0cd", size = 3662263, upload-time = "2025-06-28T20:37:01.835Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4c/7f4c326f4022babab518e1295446c58c7f72b7bfb242b47e9fae421c3783/pysimdjson-7.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:08b576531375fa6b9479b43b5358e5e172490bef8969b0f53d6b6be7c5d7b88a", size = 3576295, upload-time = "2025-06-28T20:37:02.989Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9a/c4df622caf46284dd1a4d6e403dccea2a874623563c63d6e1cec4f54259a/pysimdjson-7.0.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1b7e26580d0030b6f7bb6fddc12e7756f4ffae3a9e4f7a8c3522d783173ac459", size = 3813976, upload-time = "2025-06-28T20:37:04.186Z" }, + { url = "https://files.pythonhosted.org/packages/75/b9/e21a5d1f4060ffeca6026a94599f6b68bf62221dd02a7af5962c73040edc/pysimdjson-7.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a8fb78454cd2936f8e27e8948b56b6e44a766eaa162fef02a1436c2d4570053", size = 4197725, upload-time = "2025-06-28T20:37:05.591Z" }, + { url = "https://files.pythonhosted.org/packages/d8/ed/7e4511cabdcb2931cce174ce0ecf17cf4de6039b4d908daca4d313875f1e/pysimdjson-7.0.2-cp313-cp313-win32.whl", hash = "sha256:ef56eacf050e194d4058d6ed818dbbe40d9ec5dcb182ba93a451cad2467aad27", size = 1529585, upload-time = "2025-06-28T20:37:07.016Z" }, + { url = "https://files.pythonhosted.org/packages/e3/fa/3642b49521007362c9eb228ed472927e020b84d6413efa8fd69fd9f7c6b9/pysimdjson-7.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:4ae000c2d45a1af0303fe151e5204188fcbb23acc6cbdf04ac1062ab80538a1b", size = 1574251, upload-time = "2025-06-28T20:37:08.327Z" }, +] + +[[package]] +name = "ruff" +version = "0.12.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/eb/8c073deb376e46ae767f4961390d17545e8535921d2f65101720ed8bd434/ruff-0.12.10.tar.gz", hash = "sha256:189ab65149d11ea69a2d775343adf5f49bb2426fc4780f65ee33b423ad2e47f9", size = 5310076, upload-time = "2025-08-21T18:23:22.595Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/e7/560d049d15585d6c201f9eeacd2fd130def3741323e5ccf123786e0e3c95/ruff-0.12.10-py3-none-linux_armv6l.whl", hash = "sha256:8b593cb0fb55cc8692dac7b06deb29afda78c721c7ccfed22db941201b7b8f7b", size = 11935161, upload-time = "2025-08-21T18:22:26.965Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b0/ad2464922a1113c365d12b8f80ed70fcfb39764288ac77c995156080488d/ruff-0.12.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ebb7333a45d56efc7c110a46a69a1b32365d5c5161e7244aaf3aa20ce62399c1", size = 12660884, upload-time = "2025-08-21T18:22:30.925Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f1/97f509b4108d7bae16c48389f54f005b62ce86712120fd8b2d8e88a7cb49/ruff-0.12.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d59e58586829f8e4a9920788f6efba97a13d1fa320b047814e8afede381c6839", size = 11872754, upload-time = "2025-08-21T18:22:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/12/ad/44f606d243f744a75adc432275217296095101f83f966842063d78eee2d3/ruff-0.12.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:822d9677b560f1fdeab69b89d1f444bf5459da4aa04e06e766cf0121771ab844", size = 12092276, upload-time = "2025-08-21T18:22:36.764Z" }, + { url = "https://files.pythonhosted.org/packages/06/1f/ed6c265e199568010197909b25c896d66e4ef2c5e1c3808caf461f6f3579/ruff-0.12.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b4a64f4062a50c75019c61c7017ff598cb444984b638511f48539d3a1c98db", size = 11734700, upload-time = "2025-08-21T18:22:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/63/c5/b21cde720f54a1d1db71538c0bc9b73dee4b563a7dd7d2e404914904d7f5/ruff-0.12.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c6f4064c69d2542029b2a61d39920c85240c39837599d7f2e32e80d36401d6e", size = 13468783, upload-time = "2025-08-21T18:22:42.559Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/39369e6ac7f2a1848f22fb0b00b690492f20811a1ac5c1fd1d2798329263/ruff-0.12.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:059e863ea3a9ade41407ad71c1de2badfbe01539117f38f763ba42a1206f7559", size = 14436642, upload-time = "2025-08-21T18:22:45.612Z" }, + { url = "https://files.pythonhosted.org/packages/e3/03/5da8cad4b0d5242a936eb203b58318016db44f5c5d351b07e3f5e211bb89/ruff-0.12.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bef6161e297c68908b7218fa6e0e93e99a286e5ed9653d4be71e687dff101cf", size = 13859107, upload-time = "2025-08-21T18:22:48.886Z" }, + { url = "https://files.pythonhosted.org/packages/19/19/dd7273b69bf7f93a070c9cec9494a94048325ad18fdcf50114f07e6bf417/ruff-0.12.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f1345fbf8fb0531cd722285b5f15af49b2932742fc96b633e883da8d841896b", size = 12886521, upload-time = "2025-08-21T18:22:51.567Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1d/b4207ec35e7babaee62c462769e77457e26eb853fbdc877af29417033333/ruff-0.12.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f68433c4fbc63efbfa3ba5db31727db229fa4e61000f452c540474b03de52a9", size = 13097528, upload-time = "2025-08-21T18:22:54.609Z" }, + { url = "https://files.pythonhosted.org/packages/ff/00/58f7b873b21114456e880b75176af3490d7a2836033779ca42f50de3b47a/ruff-0.12.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:141ce3d88803c625257b8a6debf4a0473eb6eed9643a6189b68838b43e78165a", size = 13080443, upload-time = "2025-08-21T18:22:57.413Z" }, + { url = "https://files.pythonhosted.org/packages/12/8c/9e6660007fb10189ccb78a02b41691288038e51e4788bf49b0a60f740604/ruff-0.12.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f3fc21178cd44c98142ae7590f42ddcb587b8e09a3b849cbc84edb62ee95de60", size = 11896759, upload-time = "2025-08-21T18:23:00.473Z" }, + { url = "https://files.pythonhosted.org/packages/67/4c/6d092bb99ea9ea6ebda817a0e7ad886f42a58b4501a7e27cd97371d0ba54/ruff-0.12.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7d1a4e0bdfafcd2e3e235ecf50bf0176f74dd37902f241588ae1f6c827a36c56", size = 11701463, upload-time = "2025-08-21T18:23:03.211Z" }, + { url = "https://files.pythonhosted.org/packages/59/80/d982c55e91df981f3ab62559371380616c57ffd0172d96850280c2b04fa8/ruff-0.12.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e67d96827854f50b9e3e8327b031647e7bcc090dbe7bb11101a81a3a2cbf1cc9", size = 12691603, upload-time = "2025-08-21T18:23:06.935Z" }, + { url = "https://files.pythonhosted.org/packages/ad/37/63a9c788bbe0b0850611669ec6b8589838faf2f4f959647f2d3e320383ae/ruff-0.12.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ae479e1a18b439c59138f066ae79cc0f3ee250712a873d00dbafadaad9481e5b", size = 13164356, upload-time = "2025-08-21T18:23:10.225Z" }, + { url = "https://files.pythonhosted.org/packages/47/d4/1aaa7fb201a74181989970ebccd12f88c0fc074777027e2a21de5a90657e/ruff-0.12.10-py3-none-win32.whl", hash = "sha256:9de785e95dc2f09846c5e6e1d3a3d32ecd0b283a979898ad427a9be7be22b266", size = 11896089, upload-time = "2025-08-21T18:23:14.232Z" }, + { url = "https://files.pythonhosted.org/packages/ad/14/2ad38fd4037daab9e023456a4a40ed0154e9971f8d6aed41bdea390aabd9/ruff-0.12.10-py3-none-win_amd64.whl", hash = "sha256:7837eca8787f076f67aba2ca559cefd9c5cbc3a9852fd66186f4201b87c1563e", size = 13004616, upload-time = "2025-08-21T18:23:17.422Z" }, + { url = "https://files.pythonhosted.org/packages/24/3c/21cf283d67af33a8e6ed242396863af195a8a6134ec581524fd22b9811b6/ruff-0.12.10-py3-none-win_arm64.whl", hash = "sha256:cc138cc06ed9d4bfa9d667a65af7172b47840e1a98b02ce7011c391e54635ffc", size = 12074225, upload-time = "2025-08-21T18:23:20.137Z" }, +] -- cgit v1.3