diff --git a/.agents/rules/code-comments.md b/.agents/rules/code-comments.md index f1740c405..71bf49f29 100644 --- a/.agents/rules/code-comments.md +++ b/.agents/rules/code-comments.md @@ -17,4 +17,11 @@ Do not reference specs, tasks, plans, tickets, issue numbers, user stories, or t ## Type-ignore comments -Use the standard `# type: ignore[]` form (for example `# type: ignore[arg-type]`), never `# ty: ignore`. Only `# type: ignore[...]` is honored by mypy, pyright, and pytype, so a `# ty:` comment suppresses nothing and is dead. +Use the standard `# type: ignore[]` form (for example `# type: ignore[arg-type]`), never `# ty: ignore`. +Inline comments carry mypy codes only. + +`ty` does not read a bare mypy code as a suppression; it wants either `# ty: ignore[]` or a +`ty:`-prefixed code inside the standard brackets (`# type: ignore[arg-type, ty:invalid-argument-type]`). +Do not use either form. Remaining `ty` violations belong in `[[tool.ty.overrides]]` in `pyproject.toml`, +scoped to the narrowest file or glob that covers them and annotated with the violation count so they can be +retired incrementally. diff --git a/infrahub_sdk/ctl/object/update.py b/infrahub_sdk/ctl/object/update.py index cb4c79d7f..5228d33f7 100644 --- a/infrahub_sdk/ctl/object/update.py +++ b/infrahub_sdk/ctl/object/update.py @@ -24,6 +24,7 @@ if TYPE_CHECKING: from infrahub_sdk import InfrahubClient from infrahub_sdk.node import InfrahubNode + from infrahub_sdk.node.relationship import RelationshipManager from infrahub_sdk.schema import MainSchemaTypesAPI console = Console() @@ -205,7 +206,7 @@ def _apply_relationship( return # Cardinality many: access the RelationshipManager from internal storage - many_data: dict[str, object] = getattr(node, "_relationship_cardinality_many_data", {}) + many_data: dict[str, RelationshipManager] = getattr(node, "_relationship_cardinality_many_data", {}) rel_manager = many_data.get(key) if rel_manager is None or not hasattr(rel_manager, "peers"): return diff --git a/infrahub_sdk/schema/__init__.py b/infrahub_sdk/schema/__init__.py index 37658da37..fb2d5cddf 100644 --- a/infrahub_sdk/schema/__init__.py +++ b/infrahub_sdk/schema/__init__.py @@ -506,7 +506,7 @@ async def _mutate_dropdown_attribute( if schema_attr.kind != "Dropdown": raise ValueError(f"Attribute '{schema_attr.name}' is not of kind Dropdown") - input_data: dict[str, Any] = { + input_data: dict[str, dict[str, Any]] = { "data": { "kind": node_kind, "attribute": schema_attr.name, @@ -783,7 +783,7 @@ def _mutate_dropdown_attribute( if schema_attr.kind != "Dropdown": raise ValueError(f"Attribute '{schema_attr.name}' is not of kind Dropdown") - input_data: dict[str, Any] = { + input_data: dict[str, dict[str, Any]] = { "data": { "kind": node_kind, "attribute": schema_attr.name, diff --git a/infrahub_sdk/task/manager.py b/infrahub_sdk/task/manager.py index 59f17f869..feabf2c2c 100644 --- a/infrahub_sdk/task/manager.py +++ b/infrahub_sdk/task/manager.py @@ -28,7 +28,7 @@ def _generate_query( limit: int | None = None, count: bool = False, ) -> Query: - query: dict[str, Any] = { + query: dict[str, dict[str, Any]] = { "InfrahubTask": { "edges": { "node": { @@ -92,7 +92,7 @@ def _generate_query( @classmethod def _generate_count_query(cls, filters: TaskFilter | None = None) -> Query: - query: dict[str, Any] = { + query: dict[str, dict[str, Any]] = { "InfrahubTask": { "count": None, } diff --git a/pyproject.toml b/pyproject.toml index 7fc4dd69b..72d7503df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -98,7 +98,7 @@ lint = [ "mypy==2.3.1", "ruff==0.15.12", "astroid>=3.1,<4.0", - "ty==0.0.14", + "ty==0.0.74", "rumdl==0.2.28", ] types = [ @@ -180,13 +180,50 @@ include = ["infrahub_sdk/node/node.py"] [tool.ty.overrides.rules] invalid-argument-type = "ignore" # 8 violations +unresolved-attribute = "ignore" # 22 violations - `_schema` is a union and only some members carry the attribute +unsupported-operator = "ignore" # 1 violation +[[tool.ty.overrides]] +include = ["infrahub_sdk/pytest_plugin/**"] + +[tool.ty.overrides.rules] +unresolved-attribute = "ignore" # 35 violations - resource_config is a union of repository config element types [[tool.ty.overrides]] -include = ["infrahub_sdk/ctl/config.py"] +include = ["infrahub_sdk/node/attribute.py"] [tool.ty.overrides.rules] -unresolved-import = "ignore" # import tomli as tomllib when running on later versions of Python +invalid-argument-type = "ignore" # 2 violations + +[[tool.ty.overrides]] +include = ["infrahub_sdk/config.py"] + +[tool.ty.overrides.rules] +invalid-return-type = "ignore" # 1 violation + +[[tool.ty.overrides]] +# Mirrors the module-level mypy `return-value` override for the same code. +include = ["infrahub_sdk/utils.py"] + +[tool.ty.overrides.rules] +invalid-return-type = "ignore" # 1 violation + +[[tool.ty.overrides]] +# Mirrors the module-level mypy `call-overload` override for the same code. +include = ["infrahub_sdk/ctl/check.py"] + +[tool.ty.overrides.rules] +no-matching-overload = "ignore" # 1 violation - `**filters` cannot be matched against `get()` overloads + + +[[tool.ty.overrides]] +# Both files fall back to `import tomli as tomllib` below Python 3.11. The `tomli` dependency is +# marked `python_version<'3.11'`, so on a newer interpreter it is absent from site-packages and ty +# cannot resolve the import. Retire alongside Python 3.10 support. +include = ["infrahub_sdk/ctl/config.py", "tests/unit/test_packaging_metadata.py"] + +[tool.ty.overrides.rules] +unresolved-import = "ignore" [[tool.ty.overrides]] @@ -200,6 +237,7 @@ include = ["tests/fixtures/**"] [tool.ty.overrides.rules] possibly-missing-attribute = "ignore" # Test fixtures use dynamic attributes +unresolved-attribute = "ignore" # 5 violations - fixtures use dynamic node attributes # Test-specific overrides - tests have more lenient type checking # Fix these incrementally, starting with files that have fewer violations @@ -237,6 +275,7 @@ invalid-argument-type = "ignore" # ~120 violations across integration tests invalid-assignment = "ignore" no-matching-overload = "ignore" possibly-missing-attribute = "ignore" # Tests use dynamic node attributes +unresolved-attribute = "ignore" # ~205 violations - `node..value` resolves to a union of attribute/relationship types [[tool.ty.overrides]] include = [ @@ -249,6 +288,7 @@ include = [ invalid-argument-type = "ignore" # 25 violations invalid-assignment = "ignore" possibly-missing-attribute = "ignore" +unresolved-attribute = "ignore" # 1 violation in test_client.py [[tool.ty.overrides]] include = [ @@ -261,6 +301,11 @@ include = [ "tests/unit/sdk/test_schema_sorter.py", "tests/unit/sdk/test_topological_sort.py", "tests/unit/sdk/test_schema_export.py", + "tests/unit/ctl/formatters/test_init.py", + "tests/unit/ctl/test_marketplace_app.py", + "tests/unit/sdk/test_file_handler.py", + "tests/unit/sdk/test_graph_traversal.py", + "tests/unit/sdk/test_store.py", ] [tool.ty.overrides.rules] @@ -268,6 +313,27 @@ invalid-argument-type = "ignore" # Remaining files with 1-5 violations each invalid-method-override = "ignore" no-matching-overload = "ignore" +[[tool.ty.overrides]] +include = ["tests/__init__.py", "tests/unit/__init__.py", "tests/unit/sdk/pool/test_allocate.py"] + +[tool.ty.overrides.rules] +unresolved-attribute = "ignore" # 5 violations - `builtins` is patched with rich helpers for tests + +[[tool.ty.overrides]] +include = ["tests/conftest.py", "tests/unit/sdk/test_file_object.py"] + +[tool.ty.overrides.rules] +invalid-assignment = "ignore" # 21 violations - assigning to `node..value` through a union + +[[tool.ty.overrides]] +include = ["tests/unit/sdk/test_priority.py"] + +[tool.ty.overrides.rules] +invalid-argument-type = "ignore" # 22 violations total +invalid-await = "ignore" +unknown-argument = "ignore" +unresolved-attribute = "ignore" + [[tool.ty.overrides]] include = ["docs/**"] diff --git a/uv.lock b/uv.lock index f5fdbaf11..31c23f504 100644 --- a/uv.lock +++ b/uv.lock @@ -896,7 +896,7 @@ dev = [ { name = "ruff", specifier = "==0.15.12" }, { name = "rumdl", specifier = "==0.2.28" }, { name = "towncrier", specifier = ">=24.8.0" }, - { name = "ty", specifier = "==0.0.14" }, + { name = "ty", specifier = "==0.0.74" }, { name = "types-python-slugify", specifier = ">=8.0.0.3" }, { name = "types-pyyaml", specifier = ">=6.0.12" }, { name = "types-ujson", specifier = ">=5.10" }, @@ -908,7 +908,7 @@ lint = [ { name = "mypy", specifier = "==2.3.1" }, { name = "ruff", specifier = "==0.15.12" }, { name = "rumdl", specifier = "==0.2.28" }, - { name = "ty", specifier = "==0.0.14" }, + { name = "ty", specifier = "==0.0.74" }, { name = "yamllint", specifier = ">=1.35" }, ] tests = [ @@ -2735,26 +2735,27 @@ wheels = [ [[package]] name = "ty" -version = "0.0.14" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/57/22c3d6bf95c2229120c49ffc2f0da8d9e8823755a1c3194da56e51f1cc31/ty-0.0.14.tar.gz", hash = "sha256:a691010565f59dd7f15cf324cdcd1d9065e010c77a04f887e1ea070ba34a7de2", size = 5036573, upload-time = "2026-01-27T00:57:31.427Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/99/cb/cc6d1d8de59beb17a41f9a614585f884ec2d95450306c173b3b7cc090d2e/ty-0.0.14-py3-none-linux_armv6l.whl", hash = "sha256:32cf2a7596e693094621d3ae568d7ee16707dce28c34d1762947874060fdddaa", size = 10034228, upload-time = "2026-01-27T00:57:53.133Z" }, - { url = "https://files.pythonhosted.org/packages/f3/96/dd42816a2075a8f31542296ae687483a8d047f86a6538dfba573223eaf9a/ty-0.0.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f971bf9805f49ce8c0968ad53e29624d80b970b9eb597b7cbaba25d8a18ce9a2", size = 9939162, upload-time = "2026-01-27T00:57:43.857Z" }, - { url = "https://files.pythonhosted.org/packages/ff/b4/73c4859004e0f0a9eead9ecb67021438b2e8e5fdd8d03e7f5aca77623992/ty-0.0.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:45448b9e4806423523268bc15e9208c4f3f2ead7c344f615549d2e2354d6e924", size = 9418661, upload-time = "2026-01-27T00:58:03.411Z" }, - { url = "https://files.pythonhosted.org/packages/58/35/839c4551b94613db4afa20ee555dd4f33bfa7352d5da74c5fa416ffa0fd2/ty-0.0.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee94a9b747ff40114085206bdb3205a631ef19a4d3fb89e302a88754cbbae54c", size = 9837872, upload-time = "2026-01-27T00:57:23.718Z" }, - { url = "https://files.pythonhosted.org/packages/41/2b/bbecf7e2faa20c04bebd35fc478668953ca50ee5847ce23e08acf20ea119/ty-0.0.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6756715a3c33182e9ab8ffca2bb314d3c99b9c410b171736e145773ee0ae41c3", size = 9848819, upload-time = "2026-01-27T00:57:58.501Z" }, - { url = "https://files.pythonhosted.org/packages/be/60/3c0ba0f19c0f647ad9d2b5b5ac68c0f0b4dc899001bd53b3a7537fb247a2/ty-0.0.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89d0038a2f698ba8b6fec5cf216a4e44e2f95e4a5095a8c0f57fe549f87087c2", size = 10324371, upload-time = "2026-01-27T00:57:29.291Z" }, - { url = "https://files.pythonhosted.org/packages/24/32/99d0a0b37d0397b0a989ffc2682493286aa3bc252b24004a6714368c2c3d/ty-0.0.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c64a83a2d669b77f50a4957039ca1450626fb474619f18f6f8a3eb885bf7544", size = 10865898, upload-time = "2026-01-27T00:57:33.542Z" }, - { url = "https://files.pythonhosted.org/packages/1a/88/30b583a9e0311bb474269cfa91db53350557ebec09002bfc3fb3fc364e8c/ty-0.0.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:242488bfb547ef080199f6fd81369ab9cb638a778bb161511d091ffd49c12129", size = 10555777, upload-time = "2026-01-27T00:58:05.853Z" }, - { url = "https://files.pythonhosted.org/packages/cd/a2/cb53fb6325dcf3d40f2b1d0457a25d55bfbae633c8e337bde8ec01a190eb/ty-0.0.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4790c3866f6c83a4f424fc7d09ebdb225c1f1131647ba8bdc6fcdc28f09ed0ff", size = 10412913, upload-time = "2026-01-27T00:57:38.834Z" }, - { url = "https://files.pythonhosted.org/packages/42/8f/f2f5202d725ed1e6a4e5ffaa32b190a1fe70c0b1a2503d38515da4130b4c/ty-0.0.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:950f320437f96d4ea9a2332bbfb5b68f1c1acd269ebfa4c09b6970cc1565bd9d", size = 9837608, upload-time = "2026-01-27T00:57:55.898Z" }, - { url = "https://files.pythonhosted.org/packages/f7/ba/59a2a0521640c489dafa2c546ae1f8465f92956fede18660653cce73b4c5/ty-0.0.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4a0ec3ee70d83887f86925bbc1c56f4628bd58a0f47f6f32ddfe04e1f05466df", size = 9884324, upload-time = "2026-01-27T00:57:46.786Z" }, - { url = "https://files.pythonhosted.org/packages/03/95/8d2a49880f47b638743212f011088552ecc454dd7a665ddcbdabea25772a/ty-0.0.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a1a4e6b6da0c58b34415955279eff754d6206b35af56a18bb70eb519d8d139ef", size = 10033537, upload-time = "2026-01-27T00:58:01.149Z" }, - { url = "https://files.pythonhosted.org/packages/e9/40/4523b36f2ce69f92ccf783855a9e0ebbbd0f0bb5cdce6211ee1737159ed3/ty-0.0.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:dc04384e874c5de4c5d743369c277c8aa73d1edea3c7fc646b2064b637db4db3", size = 10495910, upload-time = "2026-01-27T00:57:26.691Z" }, - { url = "https://files.pythonhosted.org/packages/08/d5/655beb51224d1bfd4f9ddc0bb209659bfe71ff141bcf05c418ab670698f0/ty-0.0.14-py3-none-win32.whl", hash = "sha256:b20e22cf54c66b3e37e87377635da412d9a552c9bf4ad9fc449fed8b2e19dad2", size = 9507626, upload-time = "2026-01-27T00:57:41.43Z" }, - { url = "https://files.pythonhosted.org/packages/b6/d9/c569c9961760e20e0a4bc008eeb1415754564304fd53997a371b7cf3f864/ty-0.0.14-py3-none-win_amd64.whl", hash = "sha256:e312ff9475522d1a33186657fe74d1ec98e4a13e016d66f5758a452c90ff6409", size = 10437980, upload-time = "2026-01-27T00:57:36.422Z" }, - { url = "https://files.pythonhosted.org/packages/ad/0c/186829654f5bfd9a028f6648e9caeb11271960a61de97484627d24443f91/ty-0.0.14-py3-none-win_arm64.whl", hash = "sha256:b6facdbe9b740cb2c15293a1d178e22ffc600653646452632541d01c36d5e378", size = 9885831, upload-time = "2026-01-27T00:57:49.747Z" }, +version = "0.0.74" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/0f/c767853e88567a2ec7e996dd95e3105b1bc62c95d103689311ef0f4a603c/ty-0.0.74.tar.gz", hash = "sha256:da14344fc8625fc9ff359bafb856ad575636ea86d9bb6a629b146bff27b380e6", size = 6786318, upload-time = "2026-08-22T15:05:54.054Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/95/6ded58bc97885c6d88fa1f9cd815031489200738f961cbf0466663213f80/ty-0.0.74-py3-none-linux_armv6l.whl", hash = "sha256:8969ef4e508debf00cf58f9ea85a539f799b1732c59cdfcecd037630b9755b30", size = 12790043, upload-time = "2026-08-22T15:05:05.015Z" }, + { url = "https://files.pythonhosted.org/packages/d9/8a/5e323603b6ab8731144421877ee8a0f8ac5a5511e67857127caa09f6730e/ty-0.0.74-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:51fb6cf5b98e1e1140825b2430943f78d744876a735231656eafbb4c3f7eca3c", size = 12371748, upload-time = "2026-08-22T15:05:08.609Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/ee72e08cb705281e8d8c42917dd577aa598a8a098008495fda5176ee3f6e/ty-0.0.74-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ebe60b1f0a948c793d6c77fc9e9ddda599e4f023c04ab16e8e03bcb428c3fa0", size = 12282403, upload-time = "2026-08-22T15:05:11.448Z" }, + { url = "https://files.pythonhosted.org/packages/da/b3/fd935b694ff68bc278af50f7ad04770b36ce6306399baef7e1847b553a9d/ty-0.0.74-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa97f407a695c890a53615966a663c7d2167e2cabe88db7ca1a24d62635cdfc8", size = 12345164, upload-time = "2026-08-22T15:05:14.19Z" }, + { url = "https://files.pythonhosted.org/packages/54/5c/5b5825268e029ebb164c909780103dbbae367f069801410068bf1cef29b3/ty-0.0.74-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:673ddb733d4a0db31385ba1ed9ff1f6bd9dc5565413ce57b1ca5ac4c7803da5d", size = 12556646, upload-time = "2026-08-22T15:05:16.994Z" }, + { url = "https://files.pythonhosted.org/packages/56/e7/515914e571d62ce0101744fed3f881936eeb1b30dc37beb72b4f7ca1e289/ty-0.0.74-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1028e7c6b4f6145e9704552f43a5fffdcd51b42263ffdcd9c9677762bc395a4a", size = 13311653, upload-time = "2026-08-22T15:05:20.254Z" }, + { url = "https://files.pythonhosted.org/packages/b0/07/d1452babb6f9266c2122cabc095180b70ed306fb770b2996753814d2237d/ty-0.0.74-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79841a8890493021fb308772474983316eb91f7b56cb227a6a05a06b262a36f0", size = 13768284, upload-time = "2026-08-22T15:05:23.197Z" }, + { url = "https://files.pythonhosted.org/packages/b1/60/8d4a2fc7842a47210a1cb0a16a187d9de39ad5d509a00fb74c1c073afcde/ty-0.0.74-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94859d321f3c6a6c8f7bfc3f40e8319cda7e6e012e613440f3dfd145d5010e2e", size = 13422306, upload-time = "2026-08-22T15:05:26.248Z" }, + { url = "https://files.pythonhosted.org/packages/de/76/ebbc269a8c4efcc4d44624993bd188145f20d60ebda9680b15aaec42cc50/ty-0.0.74-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:970a8b2c09ff3be04c8a1c6767332d861be4fce85efe7bb205e4ade7c8655274", size = 12970637, upload-time = "2026-08-22T15:05:29.15Z" }, + { url = "https://files.pythonhosted.org/packages/9e/dd/b99f7236acbf856780ca1779a48143d2d9f2c24d7f531a0ce15a022b8a87/ty-0.0.74-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:795f763b3ded85574c2c2846a6fb8acf2aa76e9e83d761143e92b1f0c7ffa2cd", size = 13344891, upload-time = "2026-08-22T15:05:32.033Z" }, + { url = "https://files.pythonhosted.org/packages/0b/d7/9ff7449a4c7e6428f2c6f298e74cf24b70668f29d45c249507a723ff3782/ty-0.0.74-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:dc086db5367d912c31c0cc872deb7387290e779a4b9b54fcb944673a7cd52c7b", size = 12395272, upload-time = "2026-08-22T15:05:34.702Z" }, + { url = "https://files.pythonhosted.org/packages/b1/dd/b23a5b6b35d37df89dc8dc5daa09efd9245a668b50c4c81c25de21567dc1/ty-0.0.74-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0314d7b391cf684e47c2fa093d2ce4c597cfc9b01d9a315fe204aed6359b271b", size = 12573079, upload-time = "2026-08-22T15:05:37.683Z" }, + { url = "https://files.pythonhosted.org/packages/23/c5/ccba16239d6129533c8b3603458d0f4dd2ba69478e47059073968e74261d/ty-0.0.74-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4a45dd2e991e8bdae82ba78c8cd051b253f60bc71a6536598fa3ef580b4fc9b", size = 12832506, upload-time = "2026-08-22T15:05:40.505Z" }, + { url = "https://files.pythonhosted.org/packages/6d/1c/2390912634dff4f341f97b397f2aee341ff062be0a66cda37d59375454f2/ty-0.0.74-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:210e2eac6b018fb934e2b8dac3956a0ba076a3fb1fa6f135058c825e5b759b81", size = 13154752, upload-time = "2026-08-22T15:05:43.355Z" }, + { url = "https://files.pythonhosted.org/packages/c4/33/a8c12188227e6f74f91853a7374e01ed81d6ad21c16c8b70e92dbebfe46a/ty-0.0.74-py3-none-win32.whl", hash = "sha256:db0bb6a8f098ef9bd1be861f73b4f7c0320d40d4c05c7ae0a8677d4e7aa4f6e5", size = 12130002, upload-time = "2026-08-22T15:05:46.058Z" }, + { url = "https://files.pythonhosted.org/packages/21/5c/064f28ccb9c234cfce5a2f7aa69a256663d5ae5bb0290b3a9706cc4d1e4c/ty-0.0.74-py3-none-win_amd64.whl", hash = "sha256:bebff181515255b3c78bd2e7693ae66fab6064ad4feea2065c68bc01022aa678", size = 12771435, upload-time = "2026-08-22T15:05:48.811Z" }, + { url = "https://files.pythonhosted.org/packages/fe/06/d6becdaca0315346c26b6df97cb0eafa81de4f870945d6989e88704374ed/ty-0.0.74-py3-none-win_arm64.whl", hash = "sha256:1a3469eaaf8c85b1c0a15bede25d36daea4b09fce1d913e965b24e24b3f1d6c6", size = 12558299, upload-time = "2026-08-22T15:05:51.543Z" }, ] [[package]]