diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f21c23186b..cd99e4e26a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,9 +28,9 @@ repos: language: unsupported types: [python] - - id: local-mypy - name: mypy check - entry: uv run mypy sqlmodel tests/test_select_typing.py + - id: local-ty + name: ty check + entry: uv run ty check sqlmodel tests/test_select_typing.py require_serial: true language: unsupported pass_filenames: false diff --git a/pyproject.toml b/pyproject.toml index e0819ff8c5..3bc56a16a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,9 +82,9 @@ tests = [ "fastapi >=0.128.0", "httpx >=0.28.1", "jinja2 >=3.1.6", - "mypy >=1.19.1", "pytest >=7.0.1", "ruff >=0.15.6", + "ty>=0.0.25", "typing-extensions >=4.15.0", ] @@ -125,16 +125,6 @@ exclude_lines = [ [tool.coverage.html] show_contexts = true -[tool.mypy] -strict = true -exclude = "sqlmodel.sql._expression_select_gen" - -[[tool.mypy.overrides]] -module = "docs_src.*" -disallow_incomplete_defs = false -disallow_untyped_defs = false -disallow_untyped_calls = false - [tool.ruff.lint] select = [ "E", # pycodestyle errors @@ -161,3 +151,6 @@ known-third-party = ["sqlmodel", "sqlalchemy", "pydantic", "fastapi"] [tool.ruff.lint.pyupgrade] # Preserve types, even if a file imports `from __future__ import annotations`. keep-runtime-typing = true + +[tool.ty.terminal] +error-on-warning = true diff --git a/scripts/generate_select.py b/scripts/generate_select.py index cbb842b367..66729c69dc 100644 --- a/scripts/generate_select.py +++ b/scripts/generate_select.py @@ -37,7 +37,7 @@ class Arg(BaseModel): else: t_type = f"_T{i}" t_var = f"_TCCA[{t_type}]" - arg = Arg(name=f"__ent{i}", annotation=t_var) + arg = Arg(name=f"ent{i}", annotation=t_var) ret_type = t_type args.append(arg) return_types.append(ret_type) diff --git a/scripts/lint.sh b/scripts/lint.sh index e4a7b5bea7..9b2366d226 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,7 +3,7 @@ set -e set -x -mypy sqlmodel -mypy tests/test_select_typing.py +ty check sqlmodel +ty check tests/test_select_typing.py ruff check sqlmodel tests docs_src scripts ruff format sqlmodel tests docs_src scripts --check diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 300031de8b..da47993718 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -3,7 +3,6 @@ import builtins import ipaddress import uuid -import weakref from collections.abc import Callable, Mapping, Sequence, Set from dataclasses import dataclass from datetime import date, datetime, time, timedelta @@ -52,7 +51,7 @@ from sqlalchemy.sql.sqltypes import LargeBinary, Time, Uuid from typing_extensions import deprecated -from ._compat import ( # type: ignore[attr-defined] +from ._compat import ( PYDANTIC_MINOR_VERSION, BaseConfig, ModelMetaclass, @@ -101,7 +100,7 @@ def __dataclass_transform__( return lambda a: a -class FieldInfo(PydanticFieldInfo): # type: ignore[misc] +class FieldInfo(PydanticFieldInfo): # ty: ignore[subclass-of-final-class] # mypy - ignore that PydanticFieldInfo is @final def __init__(self, default: Any = Undefined, **kwargs: Any) -> None: primary_key = kwargs.pop("primary_key", False) @@ -177,7 +176,7 @@ def __init__( cascade_delete: bool | None = False, passive_deletes: bool | Literal["all"] | None = False, link_model: Any | None = None, - sa_relationship: RelationshipProperty | None = None, # type: ignore + sa_relationship: RelationshipProperty | None = None, sa_relationship_args: Sequence[Any] | None = None, sa_relationship_kwargs: Mapping[str, Any] | None = None, ) -> None: @@ -398,7 +397,7 @@ def Field( nullable: bool | UndefinedType = Undefined, index: bool | UndefinedType = Undefined, sa_type: type[Any] | UndefinedType = Undefined, - sa_column: Column | UndefinedType = Undefined, # type: ignore + sa_column: Column | UndefinedType = Undefined, sa_column_args: Sequence[Any] | UndefinedType = Undefined, sa_column_kwargs: Mapping[str, Any] | UndefinedType = Undefined, schema_extra: dict[str, Any] | None = None, @@ -525,13 +524,13 @@ class SQLModelMetaclass(ModelMetaclass, DeclarativeMeta): model_fields: ClassVar[dict[str, FieldInfo]] # Replicate SQLAlchemy - def __setattr__(cls, name: str, value: Any) -> None: + def __setattr__(cls, name: str, value: Any) -> None: # ty: ignore[invalid-method-override] if is_table_model_class(cls): DeclarativeMeta.__setattr__(cls, name, value) else: super().__setattr__(name, value) - def __delattr__(cls, name: str) -> None: + def __delattr__(cls, name: str) -> None: # ty: ignore[invalid-method-override] if is_table_model_class(cls): DeclarativeMeta.__delattr__(cls, name) else: @@ -609,10 +608,10 @@ def get_config(name: str) -> Any: # This could be done by reading new_cls.model_config['table'] in FastAPI, but # that's very specific about SQLModel, so let's have another config that # other future tools based on Pydantic can use. - new_cls.model_config["read_from_attributes"] = True # type: ignore[typeddict-unknown-key] + new_cls.model_config["read_from_attributes"] = True # ty: ignore[invalid-key] # For compatibility with older versions # TODO: remove this in the future - new_cls.model_config["read_with_orm_mode"] = True # type: ignore[typeddict-unknown-key] + new_cls.model_config["read_with_orm_mode"] = True # ty: ignore[invalid-key] config_registry = get_config("registry") if config_registry is not Undefined: @@ -649,7 +648,7 @@ def __init__( # Plain forward references, for models not yet defined, are not # handled well by SQLAlchemy without Mapped, so, wrap the # annotations in Mapped here - cls.__annotations__[rel_name] = Mapped[ann] # type: ignore[valid-type] + cls.__annotations__[rel_name] = Mapped[ann] relationship_to = get_relationship_to( name=rel_name, rel_info=rel_info, annotation=ann ) @@ -738,7 +737,7 @@ def get_sqlalchemy_type(field: Any) -> Any: raise ValueError(f"{type_} has no matching SQLAlchemy type") -def get_column_from_field(field: Any) -> Column: # type: ignore +def get_column_from_field(field: Any) -> Column: field_info = field sa_column = _get_sqlmodel_field_value(field_info, "sa_column", Undefined) if isinstance(sa_column, Column): @@ -773,7 +772,7 @@ def get_column_from_field(field: Any) -> Column: # type: ignore assert isinstance(foreign_key, str) assert isinstance(ondelete_value, (str, type(None))) # for typing args.append(ForeignKey(foreign_key, ondelete=ondelete_value)) - kwargs = { + kwargs: dict[str, Any] = { "primary_key": primary_key, "nullable": nullable, "index": index, @@ -797,8 +796,6 @@ def get_column_from_field(field: Any) -> Column: # type: ignore return Column(sa_type, *args, **kwargs) -class_registry = weakref.WeakValueDictionary() # type: ignore - default_registry = registry() _TSQLModel = TypeVar("_TSQLModel", bound="SQLModel") @@ -850,7 +847,7 @@ def __setattr__(self, name: str, value: Any) -> None: return else: # Set in SQLAlchemy, before Pydantic to trigger events and updates - if is_table_model_class(self.__class__) and is_instrumented(self, name): # type: ignore[no-untyped-call] + if is_table_model_class(self.__class__) and is_instrumented(self, name): set_attribute(self, name, value) # Set in Pydantic model to trigger possible validation changes, only for # non relationship values @@ -870,7 +867,7 @@ def __tablename__(cls) -> str: return cls.__name__.lower() @classmethod - def model_validate( # type: ignore[override] + def model_validate( # ty: ignore[invalid-method-override] cls: type[_TSQLModel], obj: Any, *, diff --git a/sqlmodel/sql/_expression_select_cls.py b/sqlmodel/sql/_expression_select_cls.py index 1229c22935..124929d2c3 100644 --- a/sqlmodel/sql/_expression_select_cls.py +++ b/sqlmodel/sql/_expression_select_cls.py @@ -20,13 +20,13 @@ def where(self, *whereclause: _ColumnExpressionArgument[bool] | bool) -> Self: """Return a new `Select` construct with the given expression added to its `WHERE` clause, joined to the existing clause via `AND`, if any. """ - return super().where(*whereclause) # type: ignore[arg-type] + return super().where(*whereclause) def having(self, *having: _ColumnExpressionArgument[bool] | bool) -> Self: """Return a new `Select` construct with the given expression added to its `HAVING` clause, joined to the existing clause via `AND`, if any. """ - return super().having(*having) # type: ignore[arg-type] + return super().having(*having) class Select(SelectBase[_T]): diff --git a/sqlmodel/sql/_expression_select_gen.py b/sqlmodel/sql/_expression_select_gen.py index 83d934c68b..a1c85c71c9 100644 --- a/sqlmodel/sql/_expression_select_gen.py +++ b/sqlmodel/sql/_expression_select_gen.py @@ -29,9 +29,9 @@ _TScalar_0 = TypeVar( "_TScalar_0", - Column, # type: ignore - Sequence, # type: ignore - Mapping, # type: ignore + Column, + Sequence, + Mapping, UUID, datetime, float, @@ -47,9 +47,9 @@ _TScalar_1 = TypeVar( "_TScalar_1", - Column, # type: ignore - Sequence, # type: ignore - Mapping, # type: ignore + Column, + Sequence, + Mapping, UUID, datetime, float, @@ -65,9 +65,9 @@ _TScalar_2 = TypeVar( "_TScalar_2", - Column, # type: ignore - Sequence, # type: ignore - Mapping, # type: ignore + Column, + Sequence, + Mapping, UUID, datetime, float, @@ -83,9 +83,9 @@ _TScalar_3 = TypeVar( "_TScalar_3", - Column, # type: ignore - Sequence, # type: ignore - Mapping, # type: ignore + Column, + Sequence, + Mapping, UUID, datetime, float, @@ -103,257 +103,284 @@ @overload -def select(__ent0: _TCCA[_T0]) -> SelectOfScalar[_T0]: ... +def select(ent0: _TCCA[_T0], /) -> SelectOfScalar[_T0]: ... @overload -def select(__ent0: _TScalar_0) -> SelectOfScalar[_TScalar_0]: # type: ignore - ... +def select(ent0: _TScalar_0, /) -> SelectOfScalar[_TScalar_0]: ... # Generated overloads start @overload -def select( # type: ignore - __ent0: _TCCA[_T0], - __ent1: _TCCA[_T1], +def select( + ent0: _TCCA[_T0], + ent1: _TCCA[_T1], + /, ) -> Select[tuple[_T0, _T1]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], +def select( + ent0: _TCCA[_T0], entity_1: _TScalar_1, + /, ) -> Select[tuple[_T0, _TScalar_1]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, - __ent1: _TCCA[_T1], + ent1: _TCCA[_T1], + /, ) -> Select[tuple[_TScalar_0, _T1]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, entity_1: _TScalar_1, + /, ) -> Select[tuple[_TScalar_0, _TScalar_1]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], - __ent1: _TCCA[_T1], - __ent2: _TCCA[_T2], +def select( + ent0: _TCCA[_T0], + ent1: _TCCA[_T1], + ent2: _TCCA[_T2], + /, ) -> Select[tuple[_T0, _T1, _T2]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], - __ent1: _TCCA[_T1], +def select( + ent0: _TCCA[_T0], + ent1: _TCCA[_T1], entity_2: _TScalar_2, + /, ) -> Select[tuple[_T0, _T1, _TScalar_2]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], +def select( + ent0: _TCCA[_T0], entity_1: _TScalar_1, - __ent2: _TCCA[_T2], + ent2: _TCCA[_T2], + /, ) -> Select[tuple[_T0, _TScalar_1, _T2]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], +def select( + ent0: _TCCA[_T0], entity_1: _TScalar_1, entity_2: _TScalar_2, + /, ) -> Select[tuple[_T0, _TScalar_1, _TScalar_2]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, - __ent1: _TCCA[_T1], - __ent2: _TCCA[_T2], + ent1: _TCCA[_T1], + ent2: _TCCA[_T2], + /, ) -> Select[tuple[_TScalar_0, _T1, _T2]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, - __ent1: _TCCA[_T1], + ent1: _TCCA[_T1], entity_2: _TScalar_2, + /, ) -> Select[tuple[_TScalar_0, _T1, _TScalar_2]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, entity_1: _TScalar_1, - __ent2: _TCCA[_T2], + ent2: _TCCA[_T2], + /, ) -> Select[tuple[_TScalar_0, _TScalar_1, _T2]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, entity_1: _TScalar_1, entity_2: _TScalar_2, + /, ) -> Select[tuple[_TScalar_0, _TScalar_1, _TScalar_2]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], - __ent1: _TCCA[_T1], - __ent2: _TCCA[_T2], - __ent3: _TCCA[_T3], +def select( + ent0: _TCCA[_T0], + ent1: _TCCA[_T1], + ent2: _TCCA[_T2], + ent3: _TCCA[_T3], + /, ) -> Select[tuple[_T0, _T1, _T2, _T3]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], - __ent1: _TCCA[_T1], - __ent2: _TCCA[_T2], +def select( + ent0: _TCCA[_T0], + ent1: _TCCA[_T1], + ent2: _TCCA[_T2], entity_3: _TScalar_3, + /, ) -> Select[tuple[_T0, _T1, _T2, _TScalar_3]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], - __ent1: _TCCA[_T1], +def select( + ent0: _TCCA[_T0], + ent1: _TCCA[_T1], entity_2: _TScalar_2, - __ent3: _TCCA[_T3], + ent3: _TCCA[_T3], + /, ) -> Select[tuple[_T0, _T1, _TScalar_2, _T3]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], - __ent1: _TCCA[_T1], +def select( + ent0: _TCCA[_T0], + ent1: _TCCA[_T1], entity_2: _TScalar_2, entity_3: _TScalar_3, + /, ) -> Select[tuple[_T0, _T1, _TScalar_2, _TScalar_3]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], +def select( + ent0: _TCCA[_T0], entity_1: _TScalar_1, - __ent2: _TCCA[_T2], - __ent3: _TCCA[_T3], + ent2: _TCCA[_T2], + ent3: _TCCA[_T3], + /, ) -> Select[tuple[_T0, _TScalar_1, _T2, _T3]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], +def select( + ent0: _TCCA[_T0], entity_1: _TScalar_1, - __ent2: _TCCA[_T2], + ent2: _TCCA[_T2], entity_3: _TScalar_3, + /, ) -> Select[tuple[_T0, _TScalar_1, _T2, _TScalar_3]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], +def select( + ent0: _TCCA[_T0], entity_1: _TScalar_1, entity_2: _TScalar_2, - __ent3: _TCCA[_T3], + ent3: _TCCA[_T3], + /, ) -> Select[tuple[_T0, _TScalar_1, _TScalar_2, _T3]]: ... @overload -def select( # type: ignore - __ent0: _TCCA[_T0], +def select( + ent0: _TCCA[_T0], entity_1: _TScalar_1, entity_2: _TScalar_2, entity_3: _TScalar_3, + /, ) -> Select[tuple[_T0, _TScalar_1, _TScalar_2, _TScalar_3]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, - __ent1: _TCCA[_T1], - __ent2: _TCCA[_T2], - __ent3: _TCCA[_T3], + ent1: _TCCA[_T1], + ent2: _TCCA[_T2], + ent3: _TCCA[_T3], + /, ) -> Select[tuple[_TScalar_0, _T1, _T2, _T3]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, - __ent1: _TCCA[_T1], - __ent2: _TCCA[_T2], + ent1: _TCCA[_T1], + ent2: _TCCA[_T2], entity_3: _TScalar_3, + /, ) -> Select[tuple[_TScalar_0, _T1, _T2, _TScalar_3]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, - __ent1: _TCCA[_T1], + ent1: _TCCA[_T1], entity_2: _TScalar_2, - __ent3: _TCCA[_T3], + ent3: _TCCA[_T3], + /, ) -> Select[tuple[_TScalar_0, _T1, _TScalar_2, _T3]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, - __ent1: _TCCA[_T1], + ent1: _TCCA[_T1], entity_2: _TScalar_2, entity_3: _TScalar_3, + /, ) -> Select[tuple[_TScalar_0, _T1, _TScalar_2, _TScalar_3]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, entity_1: _TScalar_1, - __ent2: _TCCA[_T2], - __ent3: _TCCA[_T3], + ent2: _TCCA[_T2], + ent3: _TCCA[_T3], + /, ) -> Select[tuple[_TScalar_0, _TScalar_1, _T2, _T3]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, entity_1: _TScalar_1, - __ent2: _TCCA[_T2], + ent2: _TCCA[_T2], entity_3: _TScalar_3, + /, ) -> Select[tuple[_TScalar_0, _TScalar_1, _T2, _TScalar_3]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, entity_1: _TScalar_1, entity_2: _TScalar_2, - __ent3: _TCCA[_T3], + ent3: _TCCA[_T3], + /, ) -> Select[tuple[_TScalar_0, _TScalar_1, _TScalar_2, _T3]]: ... @overload -def select( # type: ignore +def select( entity_0: _TScalar_0, entity_1: _TScalar_1, entity_2: _TScalar_2, entity_3: _TScalar_3, + /, ) -> Select[tuple[_TScalar_0, _TScalar_1, _TScalar_2, _TScalar_3]]: ... # Generated overloads end -def select(*entities: Any) -> Select | SelectOfScalar: # type: ignore +def select(*entities: Any) -> Select | SelectOfScalar: if len(entities) == 1: return SelectOfScalar(*entities) return Select(*entities) diff --git a/sqlmodel/sql/_expression_select_gen.py.jinja2 b/sqlmodel/sql/_expression_select_gen.py.jinja2 index 2ce54cb2fa..648785dec1 100644 --- a/sqlmodel/sql/_expression_select_gen.py.jinja2 +++ b/sqlmodel/sql/_expression_select_gen.py.jinja2 @@ -28,9 +28,9 @@ _TCCA = TypedColumnsClauseRole[_T] | SQLCoreOperations[_T] | type[_T] {% for i in range(number_of_types) %} _TScalar_{{ i }} = TypeVar( "_TScalar_{{ i }}", - Column, # type: ignore - Sequence, # type: ignore - Mapping, # type: ignore + Column, + Sequence, + Mapping, UUID, datetime, float, @@ -48,12 +48,11 @@ _T{{ i }} = TypeVar("_T{{ i }}") # Generated TypeVars end @overload -def select(__ent0: _TCCA[_T0]) -> SelectOfScalar[_T0]: ... +def select(ent0: _TCCA[_T0], /) -> SelectOfScalar[_T0]: ... @overload -def select(__ent0: _TScalar_0) -> SelectOfScalar[_TScalar_0]: # type: ignore - ... +def select(ent0: _TScalar_0, /) -> SelectOfScalar[_TScalar_0]: ... # Generated overloads start @@ -61,8 +60,8 @@ def select(__ent0: _TScalar_0) -> SelectOfScalar[_TScalar_0]: # type: ignore {% for signature in signatures %} @overload -def select( # type: ignore - {% for arg in signature[0] %}{{ arg.name }}: {{ arg.annotation }}, {% endfor %} +def select( + {% for arg in signature[0] %}{{ arg.name }}: {{ arg.annotation }}, {% endfor %}/, ) -> Select[tuple[{%for ret in signature[1] %}{{ ret }} {% if not loop.last %}, {% endif %}{% endfor %}]]: ... {% endfor %} @@ -70,7 +69,7 @@ def select( # type: ignore # Generated overloads end -def select(*entities: Any) -> Select | SelectOfScalar: # type: ignore +def select(*entities: Any) -> Select | SelectOfScalar: if len(entities) == 1: return SelectOfScalar(*entities) return Select(*entities) diff --git a/sqlmodel/sql/expression.py b/sqlmodel/sql/expression.py index 249d6c461a..92d772a883 100644 --- a/sqlmodel/sql/expression.py +++ b/sqlmodel/sql/expression.py @@ -48,30 +48,30 @@ def all_(expr: _ColumnExpressionArgument[_T] | _T) -> CollectionAggregate[bool]: - return sqlalchemy.all_(expr) # type: ignore[arg-type] + return sqlalchemy.all_(expr) # ty: ignore[invalid-argument-type] def and_( initial_clause: Literal[True] | _ColumnExpressionArgument[bool] | bool, *clauses: _ColumnExpressionArgument[bool] | bool, ) -> ColumnElement[bool]: - return sqlalchemy.and_(initial_clause, *clauses) # type: ignore[arg-type] + return sqlalchemy.and_(initial_clause, *clauses) # ty: ignore[invalid-argument-type] def any_(expr: _ColumnExpressionArgument[_T] | _T) -> CollectionAggregate[bool]: - return sqlalchemy.any_(expr) # type: ignore[arg-type] + return sqlalchemy.any_(expr) # ty: ignore[invalid-argument-type] def asc( column: _ColumnExpressionOrStrLabelArgument[_T] | _T, ) -> UnaryExpression[_T]: - return sqlalchemy.asc(column) # type: ignore[arg-type] + return sqlalchemy.asc(column) # ty: ignore[invalid-argument-type] def collate( expression: _ColumnExpressionArgument[str] | str, collation: str ) -> BinaryExpression[str]: - return sqlalchemy.collate(expression, collation) # type: ignore[arg-type] + return sqlalchemy.collate(expression, collation) # ty: ignore[invalid-argument-type] def between( @@ -84,7 +84,7 @@ def between( def not_(clause: _ColumnExpressionArgument[_T] | _T) -> ColumnElement[_T]: - return sqlalchemy.not_(clause) # type: ignore[arg-type] + return sqlalchemy.not_(clause) # ty: ignore[no-matching-overload] def case( @@ -92,7 +92,7 @@ def case( value: Any | None = None, else_: Any | None = None, ) -> Case[Any]: - return sqlalchemy.case(*whens, value=value, else_=else_) # type: ignore[arg-type] + return sqlalchemy.case(*whens, value=value, else_=else_) # ty: ignore[invalid-argument-type] def cast( @@ -112,15 +112,15 @@ def try_cast( def desc( column: _ColumnExpressionOrStrLabelArgument[_T] | _T, ) -> UnaryExpression[_T]: - return sqlalchemy.desc(column) # type: ignore[arg-type] + return sqlalchemy.desc(column) # ty: ignore[invalid-argument-type] def distinct(expr: _ColumnExpressionArgument[_T] | _T) -> UnaryExpression[_T]: - return sqlalchemy.distinct(expr) # type: ignore[arg-type] + return sqlalchemy.distinct(expr) # ty: ignore[invalid-argument-type] def bitwise_not(expr: _ColumnExpressionArgument[_T] | _T) -> UnaryExpression[_T]: - return sqlalchemy.bitwise_not(expr) # type: ignore[arg-type] + return sqlalchemy.bitwise_not(expr) # ty: ignore[invalid-argument-type] def extract(field: str, expr: _ColumnExpressionArgument[Any] | Any) -> Extract: @@ -130,7 +130,7 @@ def extract(field: str, expr: _ColumnExpressionArgument[Any] | Any) -> Extract: def funcfilter( func: FunctionElement[_T], *criterion: _ColumnExpressionArgument[bool] | bool ) -> FunctionFilter[_T]: - return sqlalchemy.funcfilter(func, *criterion) # type: ignore[arg-type] + return sqlalchemy.funcfilter(func, *criterion) # ty: ignore[invalid-argument-type] def label( @@ -138,24 +138,24 @@ def label( element: _ColumnExpressionArgument[_T] | _T, type_: Optional["_TypeEngineArgument[_T]"] = None, ) -> Label[_T]: - return sqlalchemy.label(name, element, type_=type_) # type: ignore[arg-type] + return sqlalchemy.label(name, element, type_=type_) # ty: ignore[invalid-argument-type] def nulls_first( column: _ColumnExpressionArgument[_T] | _T, ) -> UnaryExpression[_T]: - return sqlalchemy.nulls_first(column) # type: ignore[arg-type] + return sqlalchemy.nulls_first(column) # ty: ignore[invalid-argument-type] def nulls_last(column: _ColumnExpressionArgument[_T] | _T) -> UnaryExpression[_T]: - return sqlalchemy.nulls_last(column) # type: ignore[arg-type] + return sqlalchemy.nulls_last(column) # ty: ignore[invalid-argument-type] def or_( initial_clause: Literal[False] | _ColumnExpressionArgument[bool] | bool, *clauses: _ColumnExpressionArgument[bool] | bool, ) -> ColumnElement[bool]: - return sqlalchemy.or_(initial_clause, *clauses) # type: ignore[arg-type] + return sqlalchemy.or_(initial_clause, *clauses) # ty: ignore[invalid-argument-type] def over( diff --git a/sqlmodel/sql/sqltypes.py b/sqlmodel/sql/sqltypes.py index 512daacbab..3119b1b624 100644 --- a/sqlmodel/sql/sqltypes.py +++ b/sqlmodel/sql/sqltypes.py @@ -4,7 +4,7 @@ from sqlalchemy.engine.interfaces import Dialect -class AutoString(types.TypeDecorator): # type: ignore +class AutoString(types.TypeDecorator): impl = types.String cache_ok = True mysql_default_length = 255 diff --git a/uv.lock b/uv.lock index eb33166230..cbb9c7079e 100644 --- a/uv.lock +++ b/uv.lock @@ -1114,52 +1114,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl", hash = "sha256:0b83513478bdfd803ff05aa43e9b1fca9dd22bcd9471f09ca6257f009bc5ee12", size = 104779, upload-time = "2026-02-20T10:38:34.517Z" }, ] -[[package]] -name = "mypy" -version = "1.19.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, - { name = "mypy-extensions" }, - { name = "pathspec" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/63/e499890d8e39b1ff2df4c0c6ce5d371b6844ee22b8250687a99fd2f657a8/mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", size = 13101333, upload-time = "2025-12-15T05:03:03.28Z" }, - { url = "https://files.pythonhosted.org/packages/72/4b/095626fc136fba96effc4fd4a82b41d688ab92124f8c4f7564bffe5cf1b0/mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", size = 12164102, upload-time = "2025-12-15T05:02:33.611Z" }, - { url = "https://files.pythonhosted.org/packages/0c/5b/952928dd081bf88a83a5ccd49aaecfcd18fd0d2710c7ff07b8fb6f7032b9/mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", size = 12765799, upload-time = "2025-12-15T05:03:28.44Z" }, - { url = "https://files.pythonhosted.org/packages/2a/0d/93c2e4a287f74ef11a66fb6d49c7a9f05e47b0a4399040e6719b57f500d2/mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", size = 13522149, upload-time = "2025-12-15T05:02:36.011Z" }, - { url = "https://files.pythonhosted.org/packages/7b/0e/33a294b56aaad2b338d203e3a1d8b453637ac36cb278b45005e0901cf148/mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", size = 13810105, upload-time = "2025-12-15T05:02:40.327Z" }, - { url = "https://files.pythonhosted.org/packages/0e/fd/3e82603a0cb66b67c5e7abababce6bf1a929ddf67bf445e652684af5c5a0/mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", size = 10057200, upload-time = "2025-12-15T05:02:51.012Z" }, - { url = "https://files.pythonhosted.org/packages/ef/47/6b3ebabd5474d9cdc170d1342fbf9dddc1b0ec13ec90bf9004ee6f391c31/mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", size = 13028539, upload-time = "2025-12-15T05:03:44.129Z" }, - { url = "https://files.pythonhosted.org/packages/5c/a6/ac7c7a88a3c9c54334f53a941b765e6ec6c4ebd65d3fe8cdcfbe0d0fd7db/mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", size = 12083163, upload-time = "2025-12-15T05:03:37.679Z" }, - { url = "https://files.pythonhosted.org/packages/67/af/3afa9cf880aa4a2c803798ac24f1d11ef72a0c8079689fac5cfd815e2830/mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", size = 12687629, upload-time = "2025-12-15T05:02:31.526Z" }, - { url = "https://files.pythonhosted.org/packages/2d/46/20f8a7114a56484ab268b0ab372461cb3a8f7deed31ea96b83a4e4cfcfca/mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331", size = 13436933, upload-time = "2025-12-15T05:03:15.606Z" }, - { url = "https://files.pythonhosted.org/packages/5b/f8/33b291ea85050a21f15da910002460f1f445f8007adb29230f0adea279cb/mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925", size = 13661754, upload-time = "2025-12-15T05:02:26.731Z" }, - { url = "https://files.pythonhosted.org/packages/fd/a3/47cbd4e85bec4335a9cd80cf67dbc02be21b5d4c9c23ad6b95d6c5196bac/mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042", size = 10055772, upload-time = "2025-12-15T05:03:26.179Z" }, - { url = "https://files.pythonhosted.org/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" }, - { url = "https://files.pythonhosted.org/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" }, - { url = "https://files.pythonhosted.org/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" }, - { url = "https://files.pythonhosted.org/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" }, - { url = "https://files.pythonhosted.org/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" }, - { url = "https://files.pythonhosted.org/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" }, - { url = "https://files.pythonhosted.org/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" }, - { url = "https://files.pythonhosted.org/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" }, - { url = "https://files.pythonhosted.org/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" }, - { url = "https://files.pythonhosted.org/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" }, - { url = "https://files.pythonhosted.org/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" }, - { url = "https://files.pythonhosted.org/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", size = 13199744, upload-time = "2025-12-15T05:03:30.823Z" }, - { url = "https://files.pythonhosted.org/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", size = 12215815, upload-time = "2025-12-15T05:02:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", size = 12740047, upload-time = "2025-12-15T05:03:33.168Z" }, - { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, - { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, - { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, - { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, -] - [[package]] name = "mypy-extensions" version = "1.1.0" @@ -1914,12 +1868,12 @@ dev = [ { name = "mkdocs-material" }, { name = "mkdocs-redirects" }, { name = "mkdocstrings", extra = ["python"] }, - { name = "mypy" }, { name = "pillow" }, { name = "prek" }, { name = "pytest" }, { name = "pyyaml" }, { name = "ruff" }, + { name = "ty" }, { name = "typer" }, { name = "typing-extensions" }, ] @@ -1952,9 +1906,9 @@ tests = [ { name = "fastapi" }, { name = "httpx" }, { name = "jinja2" }, - { name = "mypy" }, { name = "pytest" }, { name = "ruff" }, + { name = "ty" }, { name = "typing-extensions" }, ] @@ -1982,12 +1936,12 @@ dev = [ { name = "mkdocs-material", specifier = ">=9.7.5" }, { name = "mkdocs-redirects", specifier = ">=1.2.1" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=1.0.3" }, - { name = "mypy", specifier = ">=1.19.1" }, { name = "pillow", specifier = ">=12.1.1" }, { name = "prek", specifier = ">=0.2.24,<1.0.0" }, { name = "pytest", specifier = ">=7.0.1" }, { name = "pyyaml", specifier = ">=5.3.1" }, { name = "ruff", specifier = ">=0.15.6" }, + { name = "ty", specifier = ">=0.0.25" }, { name = "typer", specifier = ">=0.24.1" }, { name = "typing-extensions", specifier = ">=4.15.0" }, ] @@ -2020,9 +1974,9 @@ tests = [ { name = "fastapi", specifier = ">=0.128.0" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "jinja2", specifier = ">=3.1.6" }, - { name = "mypy", specifier = ">=1.19.1" }, { name = "pytest", specifier = ">=7.0.1" }, { name = "ruff", specifier = ">=0.15.6" }, + { name = "ty", specifier = ">=0.0.25" }, { name = "typing-extensions", specifier = ">=4.15.0" }, ] @@ -2121,6 +2075,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, ] +[[package]] +name = "ty" +version = "0.0.26" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/94/4879b81f8681117ccaf31544579304f6dc2ddcc0c67f872afb35869643a2/ty-0.0.26.tar.gz", hash = "sha256:0496b62405d62de7b954d6d677dc1cc5d3046197215d7a0a7fef37745d7b6d29", size = 5393643, upload-time = "2026-03-26T16:27:11.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/24/99fe33ecd7e16d23c53b0d4244778c6d1b6eb1663b091236dcba22882d67/ty-0.0.26-py3-none-linux_armv6l.whl", hash = "sha256:35beaa56cf59725fd59ab35d8445bbd40b97fe76db39b052b1fcb31f9bf8adf7", size = 10521856, upload-time = "2026-03-26T16:27:06.335Z" }, + { url = "https://files.pythonhosted.org/packages/55/97/1b5e939e2ff69b9bb279ab680bfa8f677d886309a1ac8d9588fd6ce58146/ty-0.0.26-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:487a0be58ab0eb02e31ba71eb6953812a0f88e50633469b0c0ce3fb795fe0fa1", size = 10320958, upload-time = "2026-03-26T16:27:13.849Z" }, + { url = "https://files.pythonhosted.org/packages/71/25/37081461e13d38a190e5646948d7bc42084f7bd1c6b44f12550be3923e7e/ty-0.0.26-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a01b7de5693379646d423b68f119719a1338a20017ba48a93eefaff1ee56f97b", size = 9799905, upload-time = "2026-03-26T16:26:55.805Z" }, + { url = "https://files.pythonhosted.org/packages/a1/1c/295d8f55a7b0e037dfc3a5ec4bdda3ab3cbca6f492f725bf269f96a4d841/ty-0.0.26-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:628c3ee869d113dd2bd249925662fd39d9d0305a6cb38f640ddaa7436b74a1ef", size = 10317507, upload-time = "2026-03-26T16:27:31.887Z" }, + { url = "https://files.pythonhosted.org/packages/1d/62/48b3875c5d2f48fe017468d4bbdde1164c76a8184374f1d5e6162cf7d9b8/ty-0.0.26-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63d04f35f5370cbc91c0b9675dc83e0c53678125a7b629c9c95769e86f123e65", size = 10319821, upload-time = "2026-03-26T16:27:29.647Z" }, + { url = "https://files.pythonhosted.org/packages/ff/28/cfb2d495046d5bf42d532325cea7412fa1189912d549dbfae417a24fd794/ty-0.0.26-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a53c4e6f6a91927f8b90e584a4b12bcde05b0c1870ddff8d17462168ad7947a", size = 10831757, upload-time = "2026-03-26T16:27:37.441Z" }, + { url = "https://files.pythonhosted.org/packages/26/bf/dbc3e42f448a2d862651de070b4108028c543ca18cab096b38d7de449915/ty-0.0.26-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:caf2ced0e58d898d5e3ba5cb843e0ebd377c8a461464748586049afbd9321f51", size = 11369556, upload-time = "2026-03-26T16:26:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/92/4c/6d2f8f34bc6d502ab778c9345a4a936a72ae113de11329c1764bb1f204f6/ty-0.0.26-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:384807bbcb7d7ce9b97ee5aaa6417a8ae03ccfb426c52b08018ca62cf60f5430", size = 11085679, upload-time = "2026-03-26T16:27:21.746Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f4/f3f61c203bc980dd9bba0ba7ed3c6e81ddfd36b286330f9487c2c7d041aa/ty-0.0.26-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a2c766a94d79b4f82995d41229702caf2d76e5c440ec7e543d05c70e98bf8ab", size = 10900581, upload-time = "2026-03-26T16:27:24.39Z" }, + { url = "https://files.pythonhosted.org/packages/3d/fd/3ca1b4e4bdd129829e9ce78677e0f8e0f1038a7702dccecfa52f037c6046/ty-0.0.26-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f41ac45a0f8e3e8e181508d863a0a62156341db0f624ffd004b97ee550a9de80", size = 10294401, upload-time = "2026-03-26T16:27:03.999Z" }, + { url = "https://files.pythonhosted.org/packages/de/20/4ee3d8c3f90e008843795c765cb8bb245f188c23e5e5cc612c7697406fba/ty-0.0.26-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:73eb8327a34d529438dfe4db46796946c4e825167cbee434dc148569892e435f", size = 10351469, upload-time = "2026-03-26T16:27:19.003Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b1/9fb154ade65906d4148f0b999c4a8257c2a34253cb72e15d84c1f04a064e/ty-0.0.26-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4bb53a79259516535a1b55f613ba1619e9c666854946474ca8418c35a5c4fd60", size = 10529488, upload-time = "2026-03-26T16:27:01.378Z" }, + { url = "https://files.pythonhosted.org/packages/a5/70/9b02b03b1862e27b64143db65946d68b138160a5b6bfea193bee0b8bbc34/ty-0.0.26-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2f0e75edc1aeb1b4b84af516c7891f631254a4ca3dcd15e848fa1e061e1fe9da", size = 10999015, upload-time = "2026-03-26T16:27:34.636Z" }, + { url = "https://files.pythonhosted.org/packages/21/16/0a56b8667296e2989b9d48095472d98ebf57a0006c71f2a101bbc62a142d/ty-0.0.26-py3-none-win32.whl", hash = "sha256:943c998c5523ed6b519c899c0c39b26b4c751a9759e460fb964765a44cde226f", size = 9912378, upload-time = "2026-03-26T16:27:08.999Z" }, + { url = "https://files.pythonhosted.org/packages/60/c2/fef0d4bba9cd89a82d725b3b1a66efb1b36629ecf0fb1d8e916cb75b8829/ty-0.0.26-py3-none-win_amd64.whl", hash = "sha256:19c856d343efeb1ecad8ee220848f5d2c424daf7b2feda357763ad3036e2172f", size = 10863737, upload-time = "2026-03-26T16:27:27.06Z" }, + { url = "https://files.pythonhosted.org/packages/4d/05/888ebcb3c4d3b6b72d5d3241fddd299142caa3c516e6d26a9cd887dfed3b/ty-0.0.26-py3-none-win_arm64.whl", hash = "sha256:2cde58ccffa046db1223dc28f3e7d4f2c7da8267e97cc5cd186af6fe85f1758a", size = 10285408, upload-time = "2026-03-26T16:27:16.432Z" }, +] + [[package]] name = "typer" version = "0.24.1"