From 53fd2e44053341d408a4b676130cd0314778ccb5 Mon Sep 17 00:00:00 2001 From: Lars Bogner Date: Thu, 18 Jun 2026 17:38:40 +0200 Subject: [PATCH] Add ruff and ty as dev dependencies, fix lint/type findings ruff removed unused imports across analysis.py and several test files. ty caught a wrong dict[int, int] annotation on StreamingStepsDataset's mat_map (materials are strings) and a real bug in steps_to_parquet.py where --compression none passed None to polars' write_parquet, which only accepts the literal "uncompressed". Also narrows a few Optional-typed attributes (ddpm_schedule, Normalizer.mean/std) with asserts and aligns __getitem__'s parameter name with torch's Dataset base class. Co-Authored-By: Claude Sonnet 4.6 --- giant/analysis.py | 2 +- giant/data/dataset.py | 6 ++--- giant/data/transforms.py | 1 + giant/train.py | 8 +++++- pyproject.toml | 2 ++ scripts/steps_to_parquet.py | 7 +++-- tests/test_analysis.py | 1 - tests/test_dataset.py | 1 - tests/test_flow.py | 3 +-- tests/test_network.py | 1 - tests/test_transforms.py | 1 - uv.lock | 54 +++++++++++++++++++++++++++++++++++++ 12 files changed, 74 insertions(+), 13 deletions(-) diff --git a/giant/analysis.py b/giant/analysis.py index d40f5e1..90a3a42 100644 --- a/giant/analysis.py +++ b/giant/analysis.py @@ -64,7 +64,7 @@ from giant.constants import ( PREDICT_SCHEMA_VERSION, PREDICT_SCHEMA_VERSION_KEY, ) -from giant.data.dataset import StepsDataset, train_val_split +from giant.data.dataset import train_val_split from giant.data.loader import find_parquet_files, load_steps from giant.data.transforms import Normalizer, build_features, inv_log_transform from giant.model.network import DenoisingMLP diff --git a/giant/data/dataset.py b/giant/data/dataset.py index 3d5e6a6..c97b8dc 100644 --- a/giant/data/dataset.py +++ b/giant/data/dataset.py @@ -24,8 +24,8 @@ class StepsDataset(Dataset): def __len__(self) -> int: return len(self.target) - def __getitem__(self, idx): - return self.cond_cont[idx], self.cond_cat[idx], self.target[idx] + def __getitem__(self, index): + return self.cond_cont[index], self.cond_cat[index], self.target[index] def train_val_split( @@ -82,7 +82,7 @@ class StreamingStepsDataset(IterableDataset): files: list[Path], split_events: set, pdg_map: dict[int, int], - mat_map: dict[int, int], + mat_map: dict[str, int], cond_normalizer: Normalizer, target_normalizer: Normalizer, batch_size: int, diff --git a/giant/data/transforms.py b/giant/data/transforms.py index 0c545f6..f92b14b 100644 --- a/giant/data/transforms.py +++ b/giant/data/transforms.py @@ -55,6 +55,7 @@ class Normalizer: return (X * self.std + self.mean).astype(np.float32) def to_dict(self) -> dict: + assert self.mean is not None and self.std is not None, "Normalizer not fitted" return {"mean": self.mean.tolist(), "std": self.std.tolist()} @classmethod diff --git a/giant/train.py b/giant/train.py index 3869154..3cace01 100644 --- a/giant/train.py +++ b/giant/train.py @@ -3,6 +3,8 @@ import os import signal import time from pathlib import Path +from types import FrameType +from typing import Callable import torch import torch.optim as optim @@ -26,7 +28,9 @@ class _GracefulShutdown: def __init__(self) -> None: self.requested = False - self._previous: dict[int, object] = {} + self._previous: dict[ + int, Callable[[int, FrameType | None], object] | signal.Handlers | int | None + ] = {} def __enter__(self) -> "_GracefulShutdown": for sig in _CATCHABLE_SIGNALS: @@ -108,6 +112,7 @@ def train( if mode == "flow": loss = flow_matching_loss(model, x1, cond_cont, cond_cat) else: + assert ddpm_schedule is not None loss = ddpm_schedule.loss(model, x1, cond_cont, cond_cat) optimizer.zero_grad() @@ -139,6 +144,7 @@ def train( if mode == "flow": loss = flow_matching_loss(model, x1, cond_cont, cond_cat) else: + assert ddpm_schedule is not None loss = ddpm_schedule.loss(model, x1, cond_cont, cond_cat) val_loss_sum += loss.item() * x1.size(0) val_n += x1.size(0) diff --git a/pyproject.toml b/pyproject.toml index 5b3a3c8..ad124be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,8 @@ cuda = [ ] dev = [ "pytest>=8,<10", + "ruff>=0.15,<1", + "ty>=0.0.50,<0.1", ] convert = [ "uproot>=5.3,<6", diff --git a/scripts/steps_to_parquet.py b/scripts/steps_to_parquet.py index 61f3e14..6c70ab7 100644 --- a/scripts/steps_to_parquet.py +++ b/scripts/steps_to_parquet.py @@ -9,11 +9,14 @@ Usage: import argparse from pathlib import Path +from typing import Literal import awkward as ak import polars as pl import uproot +ParquetCompression = Literal["lz4", "uncompressed", "snappy", "gzip", "brotli", "zstd"] + def _batch_to_polars(batch: ak.Array) -> pl.DataFrame: """Convert one awkward-array batch to a Polars DataFrame. @@ -37,7 +40,7 @@ def convert_steps_to_parquet( output_path: str | Path | None = None, batch_size: str = "100 MB", tree_name: str = "Steps", - compression: str = "snappy", + compression: ParquetCompression = "snappy", ) -> Path: """Read *tree_name* from *root_path* and write it to a Parquet file. @@ -108,7 +111,7 @@ def main() -> None: output_path=args.output, batch_size=args.batch_size, tree_name=args.tree, - compression=None if args.compression == "none" else args.compression, + compression="uncompressed" if args.compression == "none" else args.compression, ) diff --git a/tests/test_analysis.py b/tests/test_analysis.py index 16ea7ea..fd2de86 100644 --- a/tests/test_analysis.py +++ b/tests/test_analysis.py @@ -3,7 +3,6 @@ import matplotlib matplotlib.use("Agg") # no display needed for plot smoke tests import numpy as np -import pandas as pd import pyarrow as pa import pyarrow.parquet as pq import pytest diff --git a/tests/test_dataset.py b/tests/test_dataset.py index ce24810..02a7eef 100644 --- a/tests/test_dataset.py +++ b/tests/test_dataset.py @@ -1,5 +1,4 @@ import numpy as np -import pytest from giant.data.dataset import StepsDataset, train_val_split diff --git a/tests/test_flow.py b/tests/test_flow.py index 00901ef..5d03db0 100644 --- a/tests/test_flow.py +++ b/tests/test_flow.py @@ -1,8 +1,7 @@ import torch -import pytest from giant.model.network import DenoisingMLP from giant.model.schedule import CosineSchedule, flow_matching_loss -from giant.sample import sample_flow, sample_ddpm, sample_ddim +from giant.sample import sample_flow, sample_ddim def _small_model(): diff --git a/tests/test_network.py b/tests/test_network.py index ba5eee9..52bc540 100644 --- a/tests/test_network.py +++ b/tests/test_network.py @@ -1,5 +1,4 @@ import torch -import pytest from giant.model.network import DenoisingMLP, SinusoidalEmbedding diff --git a/tests/test_transforms.py b/tests/test_transforms.py index 51e0da5..33a96c0 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -1,5 +1,4 @@ import numpy as np -import pytest from giant.data.transforms import ( inv_log_transform, local_frame_rotation, diff --git a/uv.lock b/uv.lock index 9a2d02d..3b81c20 100644 --- a/uv.lock +++ b/uv.lock @@ -339,6 +339,8 @@ cuda = [ ] dev = [ { name = "pytest" }, + { name = "ruff" }, + { name = "ty" }, ] [package.metadata] @@ -351,8 +353,10 @@ requires-dist = [ { name = "polars", marker = "extra == 'convert'", specifier = ">=1.0,<2" }, { name = "pyarrow", specifier = ">=16,<25" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=8,<10" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15,<1" }, { name = "torch", marker = "extra == 'cpu'", specifier = ">=2.3,<2.4", index = "https://download.pytorch.org/whl/cpu", conflict = { package = "giant", extra = "cpu" } }, { name = "torch", marker = "extra == 'cuda'", specifier = ">=2.3,<2.4", index = "https://download.pytorch.org/whl/cu118", conflict = { package = "giant", extra = "cuda" } }, + { name = "ty", marker = "extra == 'dev'", specifier = ">=0.0.50,<0.1" }, { name = "typer", specifier = ">=0.12,<1" }, { name = "uproot", marker = "extra == 'convert'", specifier = ">=5.3,<6" }, ] @@ -1100,6 +1104,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, ] +[[package]] +name = "ruff" +version = "0.15.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/a9/3abdf488f1bf3d24c699415e454ed554a6350d5d89ce183be1ee0a3361ac/ruff-0.15.17.tar.gz", hash = "sha256:2ec446937fd16c8c4de2674a209cc5af64d9c6f17d21fbf1151054fa0bcf5219", size = 4743346, upload-time = "2026-06-11T17:54:47.663Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/4d/e11259f5da07cb6afb2d074c31bf09da9671993f7329d4f15d2fdc458301/ruff-0.15.17-py3-none-linux_armv6l.whl", hash = "sha256:d9feddb927fc68bd295f5eebc587a7e42cfaf9b65f60ca4a2386febff575da8f", size = 10856677, upload-time = "2026-06-11T17:54:49.533Z" }, + { url = "https://files.pythonhosted.org/packages/29/3e/772d679e1a0dc058e58875bd2c0cb713a0530877b4a76fee3c7966df0d49/ruff-0.15.17-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:25805a226d741c47d274a35ad5c10a7dde175fcddfa511d7cf3da0a21eb3eab7", size = 11223443, upload-time = "2026-06-11T17:55:00.573Z" }, + { url = "https://files.pythonhosted.org/packages/68/58/bd41f7688b2fd5623012605130ed70e60aa7f2244baa3d5066bdd61530c8/ruff-0.15.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f6ad73b14c2d18a3bf8ad7cb6974294d7f613a7898604826058e6ac64918ef4d", size = 10566458, upload-time = "2026-06-11T17:55:07.52Z" }, + { url = "https://files.pythonhosted.org/packages/d8/5b/733371013fcf1ec339e477ece6ab42bfe10bdd9bba8ee88a9516aa56bfc0/ruff-0.15.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ba0c1e4f95bcb3869d0d30cbd5917071ef2e28665abfec970cdab0492c713ed", size = 10914483, upload-time = "2026-06-11T17:55:05.501Z" }, + { url = "https://files.pythonhosted.org/packages/bd/cc/6f24251cc0252f7239391ccb85833f320efad14ebe5b443943f37ced6332/ruff-0.15.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81647960f10bff57d2e51cadd0c3950fe598400c852863a038720ef5b8cca91e", size = 10647497, upload-time = "2026-06-11T17:54:57.733Z" }, + { url = "https://files.pythonhosted.org/packages/68/dd/0d10c17ce1a1624d6fc3156309c3f834fdb5dfaad026ec90c85684f3990e/ruff-0.15.17-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e01a84ddbc8c16c23055ba3924476850f1bbc1917cebbb9376665a63e74260d", size = 11416967, upload-time = "2026-06-11T17:54:51.461Z" }, + { url = "https://files.pythonhosted.org/packages/2f/91/556bfb156f6144f355e831c23db00b2fc4120f86b3ce81cc5f7fd2df51f3/ruff-0.15.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fe9f653152f8f294f9f7e03bf3a453d8b4a27f7a59c78c8666167f2b17b96c", size = 12335770, upload-time = "2026-06-11T17:54:45.793Z" }, + { url = "https://files.pythonhosted.org/packages/88/82/8b5999aa13355e926f06d9f42a32dcca862f623bf0363785ff89d607dffd/ruff-0.15.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c0fe88a7676e7a05b73174d4d4a59cb2ac21ff8263583f87a81a6018475a978", size = 11575441, upload-time = "2026-06-11T17:54:32.661Z" }, + { url = "https://files.pythonhosted.org/packages/11/93/f10377bb04109ca0e8cbc483ff1982c54b6d418210041776f93e8cdc7fa9/ruff-0.15.17-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecfc3c7878fff94633ab0348524e093f9ce3243080416dd7d14f8ba400174719", size = 11557614, upload-time = "2026-06-11T17:54:34.698Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a6/eeeae7f7d5493df41649ab3db92f086b2d0a30199e4efdf8e3dd7a033f24/ruff-0.15.17-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b8461180b22420b1bdc289909410930761629fddf2a5aaf60fae1ab26cedc4c4", size = 11544450, upload-time = "2026-06-11T17:54:39.042Z" }, + { url = "https://files.pythonhosted.org/packages/32/88/5991ce565129a24dd4a00db1254b3b5db2e53018cbe4018ea5a89738e727/ruff-0.15.17-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6eccbe50a038b503e7140b441aa9c7fc8c1f36edf23ebef9f4165c2f28f568b7", size = 10892524, upload-time = "2026-06-11T17:55:09.432Z" }, + { url = "https://files.pythonhosted.org/packages/f5/1d/0fdd248313425f55223968af04b0a42125466a8d88d21c1d99c6af0a51e8/ruff-0.15.17-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:382fc0521025f5a8ad447d8bdd523545d0d7646adb718eb1c2dac5065ec27c0f", size = 10659573, upload-time = "2026-06-11T17:54:36.824Z" }, + { url = "https://files.pythonhosted.org/packages/9e/0e/072e8260deb9461062ce9311ced27a8e541229a6ffd483013dd37661e43e/ruff-0.15.17-py3-none-musllinux_1_2_i686.whl", hash = "sha256:456d41fcd1b2777ad63f09a6e7121d43f7b688bbc76a800c10f7f8fb1f912c3f", size = 11127818, upload-time = "2026-06-11T17:55:03.124Z" }, + { url = "https://files.pythonhosted.org/packages/ab/b4/55060a34163121498014696b5f656db5b8c6963768f227dbf0d76b311073/ruff-0.15.17-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b1a04bcc94ae6194e9db05d16ad31f298a7194bfbcb08258bbe589cee1d587b8", size = 11655901, upload-time = "2026-06-11T17:54:53.562Z" }, + { url = "https://files.pythonhosted.org/packages/49/71/9b29d6b87cef468d697f43c6a91e3fae4a80185779d7d5a4ef27d173439f/ruff-0.15.17-py3-none-win32.whl", hash = "sha256:596065960ab1ff593f744220c9fe6580eda00a95003cffa9f4048bb5b1bf0392", size = 10925574, upload-time = "2026-06-11T17:54:55.723Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b2/8fc77f3723228836fa5d12497eb71c808f83782e10d058d2b15cfa14640b/ruff-0.15.17-py3-none-win_amd64.whl", hash = "sha256:6769e5fa1710b179b92e0bfa5a51735b35baea9013dadb06d5f44cbcf9547084", size = 12058788, upload-time = "2026-06-11T17:54:41.042Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c7/c53e8dbff9c9dc4b7928773421ae294a5d28fcb8dcda1a089579d3a7e510/ruff-0.15.17-py3-none-win_arm64.whl", hash = "sha256:f3be1fbb34bcdfd146240d8fb92a709d4c2c8191348580a3c044ec60fa0b4456", size = 11355275, upload-time = "2026-06-11T17:54:43.635Z" }, +] + [[package]] name = "shellingham" version = "1.5.4" @@ -1224,6 +1253,31 @@ wheels = [ { url = "https://download-r2.pytorch.org/whl/cu118/torch-2.3.1%2Bcu118-cp312-cp312-win_amd64.whl", hash = "sha256:f44c7b64d990a6b1a382d1cd63c359806153974e7db8d16f6780645a8a9c9fe0", upload-time = "2024-06-05T21:18:59Z" }, ] +[[package]] +name = "ty" +version = "0.0.50" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ea/fa/930ab48010e89fd1ecccc8f588afc9a79d540a1e8a379cf9cb3a41812254/ty-0.0.50.tar.gz", hash = "sha256:74b8c0df3e7d3294110e9862b7f8a3767f0e073dcb6ffa27f69fd63fd876149c", size = 5935862, upload-time = "2026-06-17T21:36:42.04Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/81/2161de593e722ba27d04ee394d974604e8041c2246e2f75012d612c9934a/ty-0.0.50-py3-none-linux_armv6l.whl", hash = "sha256:b04a7717c22b9c66e9161e5af608669194cdd099c5ba0c507aeb479e6c1f9176", size = 11917031, upload-time = "2026-06-17T21:37:20.615Z" }, + { url = "https://files.pythonhosted.org/packages/05/95/70c0f1915c91c9ed68b89a8f16741d73ad65628e334e1ae5691972003702/ty-0.0.50-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:cd8204f3a8df8fe68581e0b978124a90a143f35e3e7a7725a6e247b5ce1dcb33", size = 11675310, upload-time = "2026-06-17T21:36:51.627Z" }, + { url = "https://files.pythonhosted.org/packages/c7/6c/d0318ed6f52a6b184f6480137f5d1d3d6032fa81e4bd7eff495ccf4d2977/ty-0.0.50-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d336bbad38a68f16f16f84bb18f67215049b33196050c8ff67503e79619e70d2", size = 11060709, upload-time = "2026-06-17T21:36:47.226Z" }, + { url = "https://files.pythonhosted.org/packages/13/13/aff2242a51d66e4b99b71bb24081cf274b58db2909f82041ebd1f4bb2e35/ty-0.0.50-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3933810d0360a108c60cd3ea56e6c2eba2f5ecf7ee99d66ff30775d2ae9ed29", size = 11577192, upload-time = "2026-06-17T21:37:13.953Z" }, + { url = "https://files.pythonhosted.org/packages/1a/c0/46ceb4dd1f6a8a89027e5af6bc7171301e545e7d179403c06e4067c24dee/ty-0.0.50-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:88eed477756c7a0280a38de60bcabc64b3c6dcea1ac8b2a41c9210896358f6b9", size = 11693109, upload-time = "2026-06-17T21:37:09.589Z" }, + { url = "https://files.pythonhosted.org/packages/5e/9c/347e3d9959cd39641a54fc74dd4c152863f55c9079b9e16e9b4c35dd5775/ty-0.0.50-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caa5d1c76f75cb6d3105ec8bf835c0a8fbc0950ccf15e3d1e9c52cb99b0ab2f5", size = 12190755, upload-time = "2026-06-17T21:36:49.193Z" }, + { url = "https://files.pythonhosted.org/packages/85/ca/d8226604f57a8f1ead1973b01f2f8c987a60d0fc09f726cbc9a7ef074dad/ty-0.0.50-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d323f2a663e260923c11434655e95f37e04865b1e1641288a23cbcbca53074ee", size = 12761345, upload-time = "2026-06-17T21:36:55.81Z" }, + { url = "https://files.pythonhosted.org/packages/c4/23/0adcbd4676b30f6b58741ce2c1218c73988fdc8fb8c276005df2fe1817a3/ty-0.0.50-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d61cf42b8517e774354466252b085d83cdd0b51d771a63f99a4f21d5a44afc52", size = 12387850, upload-time = "2026-06-17T21:36:53.611Z" }, + { url = "https://files.pythonhosted.org/packages/c1/43/254fd544e95ec6f2368aab9cc9f7ffdf1329ad95d2c9f62dea22f986bee2/ty-0.0.50-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbcd0ee844fd551bd946bb9d4fd2baf39a12aa0ad2f9f64db48352a82758abb3", size = 12220520, upload-time = "2026-06-17T21:37:00.127Z" }, + { url = "https://files.pythonhosted.org/packages/51/cd/711e649397e34d14f63d42586aebede0d4006a1a77c8c4c63bf4fb36bcbe/ty-0.0.50-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:8acf55714ec075997edfbf4dfd7ba3241c18c773e96f41398bb6d8008b83751a", size = 12439071, upload-time = "2026-06-17T21:36:57.921Z" }, + { url = "https://files.pythonhosted.org/packages/b5/48/743d3ff46307e904377ac264d6c365ef25fd6e36cbc12c10c73437fef3de/ty-0.0.50-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:8b1e02ff71af62d7a1d9b8bfef98847f5c8bfd5bb8ae6da691cea405eb5a5e98", size = 11532092, upload-time = "2026-06-17T21:37:04.892Z" }, + { url = "https://files.pythonhosted.org/packages/27/b5/5589976874b04a62de124f8f79fc11a45207d27f1c1fd2e7b7ddfa55aeea/ty-0.0.50-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7781ace006ab6b8bb9a7591dc20d1aaa79549d9d4e8169e5dc5cf8eef0754cd7", size = 11706451, upload-time = "2026-06-17T21:37:02.5Z" }, + { url = "https://files.pythonhosted.org/packages/6c/f4/e15ea290712e61528287a353cb3103b744a092ea0a59039f17a035960717/ty-0.0.50-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e8015a10f4caf07edc9245f178e64ea388bddb9fb8d2d73d2dc1cfe6b9790493", size = 11842752, upload-time = "2026-06-17T21:37:18.12Z" }, + { url = "https://files.pythonhosted.org/packages/f5/35/323b949d29cf6be2a71638498a1c43e4a2b84a1c1d206228cf3415384604/ty-0.0.50-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:87289648401648f455823334f2a8c67bbc341d502033591c8b044e67537e661b", size = 12325834, upload-time = "2026-06-17T21:37:16.124Z" }, + { url = "https://files.pythonhosted.org/packages/cc/0a/5128b055493e41cb37f4f2a24a8ffce657e8c0d01086000c5f234d9b4622/ty-0.0.50-py3-none-win32.whl", hash = "sha256:ca73efc88be2942c1733e88b026f1cea88cafeca0ee63742dd673971d9a96642", size = 11171705, upload-time = "2026-06-17T21:36:45.191Z" }, + { url = "https://files.pythonhosted.org/packages/0b/65/91ffda139aa2b1d5c0fd321c859c5d10b7a912779d426422c4b25bca4362/ty-0.0.50-py3-none-win_amd64.whl", hash = "sha256:229d08c069beb2d896cc5556c3ba0e7f4c1b6d6a885297fabf2e6bcafa382a71", size = 12319493, upload-time = "2026-06-17T21:37:11.738Z" }, + { url = "https://files.pythonhosted.org/packages/8c/4c/0c1ca628c5da7840e16801caa0bfeed1241e1113d8a5156a34245d4fa927/ty-0.0.50-py3-none-win_arm64.whl", hash = "sha256:96a84d970b59f2eddb92a4af3ba9906f24bda118cf487d923765ccd4ca24627b", size = 11635811, upload-time = "2026-06-17T21:37:07.191Z" }, +] + [[package]] name = "typer" version = "0.26.7"