Fix ty 0.0.55 diagnostics and prefab-ui protocol version drift (#4428)

This commit is contained in:
Jeremiah Lowin 2026-07-05 16:10:40 -07:00 committed by GitHub
commit 47907e0767
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 58 additions and 58 deletions

View file

@ -388,7 +388,7 @@ class Provider:
matching = [t for t in matching if version.matches(t.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
async def _list_resources(self) -> Sequence[Resource]:
"""Return all available resources.
@ -419,7 +419,7 @@ class Provider:
matching = [r for r in matching if version.matches(r.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
"""Return all available resource templates.
@ -450,7 +450,7 @@ class Provider:
matching = [t for t in matching if version.matches(t.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
async def _list_prompts(self) -> Sequence[Prompt]:
"""Return all available prompts.
@ -481,7 +481,7 @@ class Provider:
matching = [p for p in matching if version.matches(p.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
# -------------------------------------------------------------------------
# Task registration

View file

@ -366,7 +366,7 @@ class LocalProvider(
matching = [t for t in matching if version.matches(t.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
async def _list_resources(self) -> Sequence[Resource]:
"""Return all resources."""
@ -390,7 +390,7 @@ class LocalProvider(
matching = [r for r in matching if version.matches(r.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
"""Return all resource templates."""
@ -416,7 +416,7 @@ class LocalProvider(
matching = [t for t in matching if version.matches(t.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
async def _list_prompts(self) -> Sequence[Prompt]:
"""Return all prompts."""
@ -440,7 +440,7 @@ class LocalProvider(
matching = [p for p in matching if version.matches(p.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
# =========================================================================
# Task registration

View file

@ -425,7 +425,7 @@ class OpenAPIProvider(Provider):
matching = [t for t in matching if version.matches(t.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
async def _list_prompts(self) -> Sequence[Prompt]:
"""Return empty list - OpenAPI doesn't create prompts."""

View file

@ -656,7 +656,7 @@ class ProxyProvider(Provider):
matching = [t for t in matching if version.matches(t.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
# -------------------------------------------------------------------------
# Resource methods
@ -693,7 +693,7 @@ class ProxyProvider(Provider):
matching = [r for r in matching if version.matches(r.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
# -------------------------------------------------------------------------
# Resource template methods
@ -730,7 +730,7 @@ class ProxyProvider(Provider):
matching = [t for t in matching if version.matches(t.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
# -------------------------------------------------------------------------
# Prompt methods
@ -767,7 +767,7 @@ class ProxyProvider(Provider):
matching = [p for p in matching if version.matches(p.version)]
if not matching:
return None
return max(matching, key=version_sort_key) # type: ignore[type-var] # ty:ignore[invalid-return-type]
return max(matching, key=version_sort_key)
# -------------------------------------------------------------------------
# Task methods
@ -1103,7 +1103,7 @@ class ProxyClient(Client[ClientTransportT]):
kwargs["log_handler"] = default_proxy_log_handler
if "progress_handler" not in kwargs:
kwargs["progress_handler"] = default_proxy_progress_handler
super().__init__(transport=transport, **kwargs)
super().__init__(transport=transport, **kwargs) # ty: ignore[no-matching-overload]
# Enable forwarding of inbound HTTP headers (e.g. authorization) to
# the upstream server. This is only appropriate for proxy clients,

View file

@ -780,7 +780,7 @@ class FastMCP(
if not authorized:
return None
return cast(Tool, max(authorized, key=version_sort_key))
return max(authorized, key=version_sort_key)
async def list_resources(
self, *, run_middleware: bool = True
@ -915,7 +915,7 @@ class FastMCP(
if not authorized:
return None
return cast(Resource, max(authorized, key=version_sort_key))
return max(authorized, key=version_sort_key)
async def list_resource_templates(
self, *, run_middleware: bool = True
@ -1051,7 +1051,7 @@ class FastMCP(
if not authorized:
return None
return cast(ResourceTemplate, max(authorized, key=version_sort_key))
return max(authorized, key=version_sort_key)
async def list_prompts(self, *, run_middleware: bool = True) -> Sequence[Prompt]:
"""List all enabled prompts from providers.
@ -1173,7 +1173,7 @@ class FastMCP(
if not authorized:
return None
return cast(Prompt, max(authorized, key=version_sort_key))
return max(authorized, key=version_sort_key)
@overload
async def call_tool(

View file

@ -531,7 +531,7 @@ def _single_pass_optimize(
# this regardless of `in_schema` — a $ref in a user extension
# still pins the referenced $def as "used".
if prune_defs:
ref = node.get("$ref") # type: ignore
ref = node.get("$ref")
if isinstance(ref, str) and ref.startswith("#/$defs/"):
referenced_def = ref.split("/")[-1]
if current_def_name:
@ -565,7 +565,7 @@ def _single_pass_optimize(
if (
prune_additional_properties
and node.get("additionalProperties") is False # type: ignore
and node.get("additionalProperties") is False
):
node.pop("additionalProperties") # type: ignore

View file

@ -17,7 +17,7 @@ from __future__ import annotations
from collections.abc import Callable, Sequence
from dataclasses import dataclass
from functools import total_ordering
from typing import TYPE_CHECKING, Any, TypeVar, cast
from typing import TYPE_CHECKING, Any, TypeVar
from packaging.version import InvalidVersion, Version
@ -325,7 +325,7 @@ def dedupe_with_versions(
result: list[C] = []
for versions in by_key.values():
highest: C = cast(C, max(versions, key=version_sort_key))
highest: C = max(versions, key=version_sort_key)
if any(c.version is not None for c in versions):
all_versions = sorted(
[c.version for c in versions if c.version is not None],

View file

@ -98,7 +98,7 @@ dev = [
"pytest-timeout>=2.4.0",
"pytest-xdist>=3.6.1",
"ruff>=0.12.8",
"ty>=0.0.39",
"ty>=0.0.55",
"prek>=0.2.12",
"loq>=0.1.0a3",
"opentelemetry-exporter-otlp-proto-grpc>=1.39.0",

View file

@ -319,7 +319,7 @@ class TestScalarResponseTypes:
result = await context.elicit(message="", response_type=None)
assert result.action == "accept"
assert isinstance(result, AcceptedElicitation)
accepted = cast(AcceptedElicitation[dict[str, Any]], result)
accepted = result
assert isinstance(accepted.data, dict)
return accepted.data
@ -341,7 +341,7 @@ class TestScalarResponseTypes:
result = await context.elicit(message="", response_type=None)
assert result.action == "accept"
assert isinstance(result, AcceptedElicitation)
accepted = cast(AcceptedElicitation[dict[str, Any]], result)
accepted = result
assert isinstance(accepted.data, dict)
return accepted.data

View file

@ -200,7 +200,7 @@ async def test_list_list_multi_select_untitled():
if result.action == "accept":
assert isinstance(result, AcceptedElicitation)
assert isinstance(result.data, list)
return ",".join(result.data) # type: ignore[no-matching-overload] # ty:ignore[no-matching-overload]
return ",".join(result.data) # type: ignore[no-matching-overload]
return "declined"
async def elicitation_handler(message, response_type, params, ctx):
@ -238,7 +238,7 @@ async def test_list_dict_multi_select_titled():
if result.action == "accept":
assert isinstance(result, AcceptedElicitation)
assert isinstance(result.data, list)
return ",".join(result.data) # type: ignore[no-matching-overload] # ty:ignore[no-matching-overload]
return ",".join(result.data) # type: ignore[no-matching-overload]
return "declined"
async def elicitation_handler(message, response_type, params, ctx):

View file

@ -31,7 +31,7 @@ def create_test_server() -> FastMCP:
result = await ctx.elicit("What is your name?", response_type=str)
if result.action == "accept":
return f"You said your name was: {result.data}!" # ty: ignore[unresolved-attribute]
return f"You said your name was: {result.data}!"
else:
return "No name provided"

View file

@ -9,7 +9,7 @@ from __future__ import annotations
from typing import Annotated
from mcp.types import TextContent
from prefab_ui.app import PrefabApp
from prefab_ui.app import PROTOCOL_VERSION, PrefabApp
from prefab_ui.components import Column, Heading, Text
from prefab_ui.components.base import Component
@ -39,7 +39,7 @@ class TestConvertResult:
assert isinstance(result.content[0], TextContent)
assert result.content[0].text == "[Rendered Prefab UI]"
assert result.structured_content is not None
assert result.structured_content["$prefab"]["version"] == "0.2"
assert result.structured_content["$prefab"]["version"] == PROTOCOL_VERSION
assert result.structured_content["state"] == {"name": "Alice"}
# PrefabApp wraps view in a pf-app-root Div
root = result.structured_content["view"]
@ -55,7 +55,7 @@ class TestConvertResult:
assert isinstance(result, ToolResult)
assert result.structured_content is not None
assert result.structured_content["$prefab"]["version"] == "0.2"
assert result.structured_content["$prefab"]["version"] == PROTOCOL_VERSION
assert result.structured_content["view"]["type"] == "Div"
assert result.structured_content["view"]["children"][0]["type"] == "Heading"
@ -71,7 +71,7 @@ class TestConvertResult:
assert isinstance(result.content[0], TextContent)
assert result.content[0].text == "Custom fallback text"
assert result.structured_content is not None
assert result.structured_content["$prefab"]["version"] == "0.2"
assert result.structured_content["$prefab"]["version"] == PROTOCOL_VERSION
assert result.structured_content["view"]["type"] == "Div"
assert result.structured_content["view"]["children"][0]["type"] == "Heading"
@ -85,7 +85,7 @@ class TestConvertResult:
assert isinstance(result.content[0], TextContent)
assert result.content[0].text == "My text"
assert result.structured_content is not None
assert result.structured_content["$prefab"]["version"] == "0.2"
assert result.structured_content["$prefab"]["version"] == PROTOCOL_VERSION
assert result.structured_content["view"]["type"] == "Div"
assert result.structured_content["view"]["children"][0]["type"] == "Heading"
@ -391,7 +391,7 @@ class TestIntegration:
result = await client.call_tool("greet", {"name": "Alice"})
assert result.structured_content is not None
assert result.structured_content["$prefab"]["version"] == "0.2"
assert result.structured_content["$prefab"]["version"] == PROTOCOL_VERSION
assert result.structured_content["state"] == {"name": "Alice"}
async def test_tool_call_with_custom_text(self):
@ -412,7 +412,7 @@ class TestIntegration:
"Greeting for Alice" in c.text for c in result.content if hasattr(c, "text")
)
assert result.structured_content is not None
assert result.structured_content["$prefab"]["version"] == "0.2"
assert result.structured_content["$prefab"]["version"] == PROTOCOL_VERSION
async def test_tools_list_includes_app_meta(self):
mcp = FastMCP("test")

42
uv.lock generated
View file

@ -10,7 +10,7 @@ resolution-markers = [
]
[options]
exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values.
exclude-newer = "2026-06-28T22:13:51.808463Z"
exclude-newer-span = "P1W"
[options.exclude-newer-package]
@ -936,7 +936,7 @@ dev = [
{ name = "pytest-timeout", specifier = ">=2.4.0" },
{ name = "pytest-xdist", specifier = ">=3.6.1" },
{ name = "ruff", specifier = ">=0.12.8" },
{ name = "ty", specifier = ">=0.0.39" },
{ name = "ty", specifier = ">=0.0.55" },
]
[[package]]
@ -3154,27 +3154,27 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.39"
version = "0.0.55"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d0/8d/7b5c74dc287fbcb37bae9853cec13bf44717c1735298500e4aeba31579a9/ty-0.0.39.tar.gz", hash = "sha256:f750277e76a01ecd86185960eca73823c26a53c51103568d56d4d904575159fd", size = 5702365, upload-time = "2026-05-22T21:09:56.403Z" }
sdist = { url = "https://files.pythonhosted.org/packages/08/48/f687c8d268e3581f2f104d1f2ac5944d5b5e841b3695c613b3f263e5bbf7/ty-0.0.55.tar.gz", hash = "sha256:88ca87073825a79a8327c550efcc86cec94344890244c5946f84c9e44a969f31", size = 6040230, upload-time = "2026-06-27T00:27:29.385Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/08/17/9b89802c26d12d0f7a27bc25d4066d941d42891e8898f9f26499f0067e32/ty-0.0.39-py3-none-linux_armv6l.whl", hash = "sha256:c1bb7ac70f1f7d70cc6655fd96558039e4562b10f489fa49c7ebfd5fcee73ad1", size = 11360431, upload-time = "2026-05-22T21:09:18.689Z" },
{ url = "https://files.pythonhosted.org/packages/9c/c6/663ded50e823dbf9fb9d002eca46b7cb1fb2c72b744b84f22ce732a0ee0b/ty-0.0.39-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3435b64c1e59c14c9aa39c20cc018823937cd38d55db853e74d95b8f420569b0", size = 11096281, upload-time = "2026-05-22T21:09:15.383Z" },
{ url = "https://files.pythonhosted.org/packages/8b/ae/5d38ba9a6456ff4c78d212cf464fd8b9a25d8118465197b0b2dc891c0b19/ty-0.0.39-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5f136377ce46c73677701a9e1ad730bf72f699bcec046e422eb79d0886cac3ab", size = 10529674, upload-time = "2026-05-22T21:09:46.471Z" },
{ url = "https://files.pythonhosted.org/packages/be/6f/43638cb8106445d3c8817256a0731cde9dd7b6a53ae2e881294bc1930ca3/ty-0.0.39-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36b65fb0cc17f03e851d40e210d420be94ab8bc52d041328ad1e45f616036a61", size = 11055561, upload-time = "2026-05-22T21:09:36.981Z" },
{ url = "https://files.pythonhosted.org/packages/91/17/95e62cf4458527ce78dc386eba18f8b10c3fb64cd8c9e7e59b262ff6029d/ty-0.0.39-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4967967bfadf3860ff84c3fccdbaec8edf8aa20d0d727521084733d853de6657", size = 11127185, upload-time = "2026-05-22T21:09:31.395Z" },
{ url = "https://files.pythonhosted.org/packages/4e/c0/93666c213db5c71ab1b1f1a0db5f66bf8c7c0e0b0bf59859f5da8f0b3c36/ty-0.0.39-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e10ecb1297099ddf9a1f054f8bd921d1863ce85fb819a3c96ed27865a1ba6ed", size = 11608459, upload-time = "2026-05-22T21:09:12.862Z" },
{ url = "https://files.pythonhosted.org/packages/79/85/3b26585afc8b50230d6464bb0642feef4fab3f847e38b1f0ffa971a81446/ty-0.0.39-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b19cca70e465d71b0510656343883d62372bbe74b7845cae7c0e701d6d5264b", size = 12177101, upload-time = "2026-05-22T21:09:40.519Z" },
{ url = "https://files.pythonhosted.org/packages/49/4a/1039e4f6afc576dc1c3a4d22a6478904a1ad3766597cd0b93c077ab9dfce/ty-0.0.39-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:56c6704b01b9b3d80ff26b2918423b742516d1e469bef830e9254dcedc9185bf", size = 11827815, upload-time = "2026-05-22T21:09:49.89Z" },
{ url = "https://files.pythonhosted.org/packages/e2/c5/4688652870e350a76a8157f7ffb59ad54f37d5d10725aa7076f66ac94ec8/ty-0.0.39-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b7840ff46764b6a6757f4ade1cd0530fc3e8a0b435ca93e7602360e4cb90b6", size = 11694429, upload-time = "2026-05-22T21:09:21.568Z" },
{ url = "https://files.pythonhosted.org/packages/fc/72/8a1c4e823bb5bdc935a1c8140e100304e36a68a4139592f170aa9736fdb7/ty-0.0.39-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1c62a3a87ce26b50819f0dbf03bd95f23f19eeb87bbc7aa732ec64277c77f1aa", size = 11869846, upload-time = "2026-05-22T21:09:28.053Z" },
{ url = "https://files.pythonhosted.org/packages/17/9f/cf982457b861ae22d657c5dcdbc631199f7f90264279db1d17230dfbc3ff/ty-0.0.39-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f8c34bc81a9c3516e49904e9d8330aac385377cca98390193ea02b903a40fcf0", size = 11029763, upload-time = "2026-05-22T21:09:06.791Z" },
{ url = "https://files.pythonhosted.org/packages/46/c9/95b64f6d43ae6e8f0b7e13dacf9c196d35819af22b1924171fba31383156/ty-0.0.39-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:66f5ab11586a64e79cb692ad685ee5469325c31b5f30bd3554f52f36dbe28cc4", size = 11146761, upload-time = "2026-05-22T21:09:10.178Z" },
{ url = "https://files.pythonhosted.org/packages/52/69/0a89cfb06f7632a05bf56c78e0affb4a40f81759e275376cea75c9c5abe9/ty-0.0.39-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e8d89732bcbbcb091f439e556dfc4932f198b118b47d5b85212c60662099670e", size = 11281843, upload-time = "2026-05-22T21:09:34.234Z" },
{ url = "https://files.pythonhosted.org/packages/0e/53/64c4a27067a46643fea2b3fcf21a8a2f838d91a65ffdd14f2e82945b9538/ty-0.0.39-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:eceb6c91dcd05a231119f82abdd9aa337513de23ca6ac990bc44f88791dc1799", size = 11792477, upload-time = "2026-05-22T21:09:24.923Z" },
{ url = "https://files.pythonhosted.org/packages/1a/e8/02f4dd4a12bcdbda0006f9c7ff3b99a4be06bd0d257d3bd4a5b66de074e6/ty-0.0.39-py3-none-win32.whl", hash = "sha256:891c3262314dbc80bf3e872634d23dd216306945daa9a9fcc206ce5ed21ac4c9", size = 10615377, upload-time = "2026-05-22T21:09:43.167Z" },
{ url = "https://files.pythonhosted.org/packages/b5/5a/aaeb22faa8d4dae90a287d4c3636c671edcff3b99be5f4fc8b79ad71eef6/ty-0.0.39-py3-none-win_amd64.whl", hash = "sha256:ba7f2d54452535419e90f6f03ff39282999e87b43c21c00559f6d7ad711a36d5", size = 11710711, upload-time = "2026-05-22T21:09:53.179Z" },
{ url = "https://files.pythonhosted.org/packages/a3/17/ae7339651bfcaa5f54698c8c70eaf5031baa400ecb67baec31d03a56cbd4/ty-0.0.39-py3-none-win_arm64.whl", hash = "sha256:eb4cf0fefbbfedf9a352597bb2431ebdcb7eb3a595c0f825f228e897a0ec285d", size = 11081409, upload-time = "2026-05-22T21:09:03.741Z" },
{ url = "https://files.pythonhosted.org/packages/87/a3/1a90ba7e5a61c6d09adb92346ddba97668095fc257b577af433e5ac4f404/ty-0.0.55-py3-none-linux_armv6l.whl", hash = "sha256:31e83eef512d066542fe990fe1a3b814423abd1616376c54e48af7045b3e1749", size = 11677249, upload-time = "2026-06-27T00:26:52.18Z" },
{ url = "https://files.pythonhosted.org/packages/82/3a/669f9aa478c38243e213a2684db1502086026cfadc15bb1b29b7cbde030d/ty-0.0.55-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab4bca857950608fea73e269e2da369d43e6467131de85160d68e2fa466fa248", size = 11444180, upload-time = "2026-06-27T00:26:54.576Z" },
{ url = "https://files.pythonhosted.org/packages/15/a4/6a4b2507a53ce6530c66c5b4fe0d58551eb1748ffa9e0696c32fdd55bbd4/ty-0.0.55-py3-none-macosx_11_0_arm64.whl", hash = "sha256:55032bfd31bf2c5355ee81bdc6407b144a1cc7ee41e5681dd1368e4cef2ba327", size = 10963134, upload-time = "2026-06-27T00:26:57.348Z" },
{ url = "https://files.pythonhosted.org/packages/ce/ae/a3b1a0f1cc83b7d258662cb98aa80a720c2e671d0e8fa0d17a4d5d057a7a/ty-0.0.55-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1e049f69ce65b3c269af67624607f435e1c32319786c1e453ef9611502f295", size = 11493517, upload-time = "2026-06-27T00:26:59.26Z" },
{ url = "https://files.pythonhosted.org/packages/0d/9f/311ce39065a979ef40a9b847f685c8e02464e53adf1671e081eea90640ca/ty-0.0.55-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:631409975c681d5a280fc5a99b7b32e9e801f33be7567c6b42ec331362f59d7d", size = 11460590, upload-time = "2026-06-27T00:27:01.425Z" },
{ url = "https://files.pythonhosted.org/packages/cd/8f/3bf29aa77bd78aae48275153135a2052fa7d3ccdf1ecabeb99c8773abd66/ty-0.0.55-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e08cb0436e68b9351555ae8f2697138c9009b4d5b4ae4272232988b2a431a98f", size = 12098430, upload-time = "2026-06-27T00:27:03.596Z" },
{ url = "https://files.pythonhosted.org/packages/bc/6e/e88411a88240b94640bba06fb6d0d92b247fbeef47ee2bc71f39e58c2558/ty-0.0.55-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16c215ad9f823829409b94ee188cfaa4563f6e1384f6ce3fecb1db75f6c7cf7c", size = 12673086, upload-time = "2026-06-27T00:27:05.589Z" },
{ url = "https://files.pythonhosted.org/packages/6c/7e/8f1762fb7f9245a68ba5ae338d73c59403ce57554e5d311b8bb55027b0ec/ty-0.0.55-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b510eb8f4032baf11b7aee2f1d53babc3b4ca03939b9cdcf6a9d15761d575188", size = 12242559, upload-time = "2026-06-27T00:27:07.714Z" },
{ url = "https://files.pythonhosted.org/packages/72/1f/143657daf2670d977dac83435f1fe03d4843efb798d8e1e75950e541aadd/ty-0.0.55-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ddc05e7959709c3b9b83aa627128a80446865e3c1a4882638dcff6d776dc34a", size = 12021409, upload-time = "2026-06-27T00:27:09.881Z" },
{ url = "https://files.pythonhosted.org/packages/6d/30/69487c439dd1fad3a4a3d96f0a472193de297eaba6fc4b8ea687ce434ac2/ty-0.0.55-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:636e8e5078787b8c6916c94e1406719f10189a4ca6b37b813a5922ce5857a8c7", size = 12303807, upload-time = "2026-06-27T00:27:11.986Z" },
{ url = "https://files.pythonhosted.org/packages/e8/ca/cd88b6493dafc7db077f5e17c0438eb3af6e2d6d08f616dbb52a8ddfd567/ty-0.0.55-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ef7d6deaacb73fec603666b5471f1dc5a5699aa84e11a6d4d644dd07ca72121e", size = 11441263, upload-time = "2026-06-27T00:27:14.087Z" },
{ url = "https://files.pythonhosted.org/packages/aa/fe/66b6915671653ab739f71e4f1b0528e69da64429b7ebf3840c625b6e43f2/ty-0.0.55-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9aeea0fe5875d3cf37faf0e44d0fdf9669335467749741b8fc0103916fb5cd32", size = 11484584, upload-time = "2026-06-27T00:27:16.311Z" },
{ url = "https://files.pythonhosted.org/packages/4a/4f/7a9c0bbac8b899e9f6c0ec110c6612f52e4db35f6bb17ddc0ef60384fa3e/ty-0.0.55-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0b699c01310dbd2705a07c97c5f4aaeedef61bd9adeea2e7c46aed32401d3576", size = 11759309, upload-time = "2026-06-27T00:27:18.471Z" },
{ url = "https://files.pythonhosted.org/packages/ca/de/b6f8b1b69aa631b5716ef3f985c3b56de0e46c2499cc00d30c402b41f714/ty-0.0.55-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:32cbeba543e46de2a983ec6d525d8b56514f7422bd1e1b57c44ccf7bfa72c38a", size = 12128755, upload-time = "2026-06-27T00:27:20.55Z" },
{ url = "https://files.pythonhosted.org/packages/7d/90/a912531e51ee7e076b42972479290fa687c0f5e747b7e773f3033164acaa/ty-0.0.55-py3-none-win32.whl", hash = "sha256:52b968e24eb4f7a5c3bd251db1f99f60dd385890356d38fc619d84f1b423446a", size = 11117501, upload-time = "2026-06-27T00:27:22.714Z" },
{ url = "https://files.pythonhosted.org/packages/4c/7a/99d59843bf8908a7f9f4d13fda107dbad07b7faa28ecd7860eacf363fb1c/ty-0.0.55-py3-none-win_amd64.whl", hash = "sha256:bf39cbfdc0add44d94bd3fff1f53c351418d134b6a66b87efdb7876d7b7a2224", size = 12150106, upload-time = "2026-06-27T00:27:24.881Z" },
{ url = "https://files.pythonhosted.org/packages/b3/44/20987505cedf2a865b08482f0eabc181fd9599b062964057ec8a128a4296/ty-0.0.55-py3-none-win_arm64.whl", hash = "sha256:f7f3700a9a060e8f1af11e4fb63fafcaf272b041781f4ccdfda2b3b5c6c1e439", size = 11560157, upload-time = "2026-06-27T00:27:27.332Z" },
]
[[package]]