From df6c7ee0273232815c7c4c46bbb093fbb1bf02d1 Mon Sep 17 00:00:00 2001 From: jorenham Date: Tue, 27 Oct 2026 12:13:29 +0100 Subject: [PATCH 1/2] Fill in missing type annotations in the public API --- CHANGELOG.md | 4 ++++ returns/contrib/hypothesis/laws.py | 2 +- returns/contrib/pytest/plugin.py | 10 +++++----- returns/methods/cond.py | 4 ++-- returns/primitives/asserts.py | 6 +++--- returns/primitives/container.py | 2 +- returns/primitives/exceptions.py | 6 ++++-- returns/primitives/hkt.py | 4 ++-- returns/primitives/laws.py | 2 +- returns/trampolines.py | 6 +++++- .../test_contrib/test_pytest/test_returns_asserts.yml | 7 +++++++ typesafety/test_methods/test_cond.yml | 8 ++++++++ typesafety/test_trampolines/test_trampoline.yml | 11 +++++++++++ 13 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 typesafety/test_contrib/test_pytest/test_returns_asserts.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b9d3250..47bbded4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ See [0Ver](https://0ver.org/). ## 0.31.0 WIP +### Features + +- Adds missing type annotations + ### Bugfixes - Fix `{Success, Failure}.swap` returning `Any` diff --git a/returns/contrib/hypothesis/laws.py b/returns/contrib/hypothesis/laws.py index 12a289073..b9b8a7854 100644 --- a/returns/contrib/hypothesis/laws.py +++ b/returns/contrib/hypothesis/laws.py @@ -177,7 +177,7 @@ def check_all_laws( ) -def pure_functions_factory(thing) -> st.SearchStrategy: +def pure_functions_factory(thing: Any) -> st.SearchStrategy: """Factory to create pure functions.""" like = ( (lambda: None) diff --git a/returns/contrib/pytest/plugin.py b/returns/contrib/pytest/plugin.py index d0e666cd2..16f5f4c0b 100644 --- a/returns/contrib/pytest/plugin.py +++ b/returns/contrib/pytest/plugin.py @@ -42,10 +42,10 @@ def __init__(self, errors_handled: _ErrorsHandled) -> None: @staticmethod # noqa: WPS602 def assert_equal( # noqa: WPS602 - first, - second, + first: object, + second: object, *, - deps=None, + deps: object | None = None, backend: str = 'asyncio', ) -> None: """Can compare two containers even with extra calling and awaiting.""" @@ -53,7 +53,7 @@ def assert_equal( # noqa: WPS602 assert_equal(first, second, deps=deps, backend=backend) - def is_error_handled(self, container) -> bool: + def is_error_handled(self, container: 'ResultLikeN[Any, Any, Any]') -> bool: """Ensures that container has its error handled in the end.""" return id(container) in self._errors_handled @@ -131,7 +131,7 @@ class _DesiredFunctionFound(BaseException): # noqa: WPS418 """Exception to raise when expected function is found.""" -def pytest_configure(config) -> None: +def pytest_configure(config: pytest.Config) -> None: """ Hook to be executed on import. diff --git a/returns/methods/cond.py b/returns/methods/cond.py index 4d1fca14c..8e482f4ed 100644 --- a/returns/methods/cond.py +++ b/returns/methods/cond.py @@ -1,4 +1,4 @@ -from typing import TypeVar, overload +from typing import Final, TypeVar, overload from returns.context import NoDeps from returns.interfaces.failable import DiverseFailableN, SingleFailableN @@ -79,6 +79,6 @@ def internal_cond( return container_type.empty -cond = kinded(internal_cond) +cond: Final = kinded(internal_cond) """Kinded version of :func:`~internal_cond`, use it to infer real return type.""" diff --git a/returns/primitives/asserts.py b/returns/primitives/asserts.py index cf03c7f2f..7841e8912 100644 --- a/returns/primitives/asserts.py +++ b/returns/primitives/asserts.py @@ -1,8 +1,8 @@ def assert_equal( - first, - second, + first: object, + second: object, *, - deps=None, + deps: object | None = None, backend: str = 'asyncio', ) -> None: """ diff --git a/returns/primitives/container.py b/returns/primitives/container.py index a95568aec..e19b117ea 100644 --- a/returns/primitives/container.py +++ b/returns/primitives/container.py @@ -29,7 +29,7 @@ class BaseContainer(Immutable, ABC): __slots__ = ('_inner_value',) _inner_value: Any - def __init__(self, inner_value) -> None: + def __init__(self, inner_value: object) -> None: """ Wraps the given value in the Container. diff --git a/returns/primitives/exceptions.py b/returns/primitives/exceptions.py index 21a65d013..c5a0a7160 100644 --- a/returns/primitives/exceptions.py +++ b/returns/primitives/exceptions.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Self if TYPE_CHECKING: from returns.interfaces.unwrappable import Unwrappable # noqa: WPS433 @@ -11,6 +11,8 @@ class UnwrapFailedError(Exception): __slots__ = ('halted_container',) + halted_container: Unwrappable + def __init__(self, container: Unwrappable) -> None: """ Saves halted container in the inner state. @@ -21,7 +23,7 @@ def __init__(self, container: Unwrappable) -> None: super().__init__() self.halted_container = container - def __reduce__(self): # noqa: WPS603 + def __reduce__(self) -> tuple[type[Self], tuple[Unwrappable]]: # noqa: WPS603 """Custom reduce method for pickle protocol. This helps properly reconstruct the exception during unpickling. diff --git a/returns/primitives/hkt.py b/returns/primitives/hkt.py index 0d21847df..59e2cbff5 100644 --- a/returns/primitives/hkt.py +++ b/returns/primitives/hkt.py @@ -88,7 +88,7 @@ def impossible(generic: T, value: V) -> T[V]: if TYPE_CHECKING: # noqa: WPS604 # pragma: no cover - def __getattr__(self, attrname: str): + def __getattr__(self, attrname: str) -> Any: """ This function is required for ``get_attribute_hook`` in mypy plugin. @@ -214,7 +214,7 @@ class Kinded(Protocol[_FunctionDefType_co]): # type: ignore def __get__( self, instance: _UpdatedType, - type_, + type_: type | None, ) -> Callable[..., _UpdatedType]: """Used to decorate and properly analyze method calls.""" diff --git a/returns/primitives/laws.py b/returns/primitives/laws.py index dcbf14d97..5f0ac277a 100644 --- a/returns/primitives/laws.py +++ b/returns/primitives/laws.py @@ -28,7 +28,7 @@ class Law(Immutable): definition: Callable """Function used to define this law.""" - def __init__(self, function) -> None: + def __init__(self, function: Callable) -> None: """Saves function to the inner state.""" object.__setattr__(self, 'definition', function) diff --git a/returns/trampolines.py b/returns/trampolines.py index b446e63b3..e836d8328 100644 --- a/returns/trampolines.py +++ b/returns/trampolines.py @@ -1,6 +1,6 @@ from collections.abc import Callable from functools import wraps -from typing import Generic, TypeVar, final +from typing import Any, Generic, TypeVar, final from typing_extensions import ParamSpec @@ -18,6 +18,10 @@ class Trampoline(Generic[_ReturnType]): __slots__ = ('args', 'func', 'kwargs') + func: Callable[..., _ReturnType] + args: tuple[Any, ...] + kwargs: dict[str, Any] + def __init__( # noqa: WPS451 self, func: Callable[_FuncParams, _ReturnType], diff --git a/typesafety/test_contrib/test_pytest/test_returns_asserts.yml b/typesafety/test_contrib/test_pytest/test_returns_asserts.yml new file mode 100644 index 000000000..a88451dd4 --- /dev/null +++ b/typesafety/test_contrib/test_pytest/test_returns_asserts.yml @@ -0,0 +1,7 @@ +- case: is_error_handled_non_container + disable_cache: false + main: | + from returns.contrib.pytest import ReturnsAsserts + + def test(returns: ReturnsAsserts) -> None: + returns.is_error_handled(1) # E: Argument 1 to "is_error_handled" of "ReturnsAsserts" has incompatible type "int"; expected "ResultLikeN[Any, Any, Any]" [arg-type] diff --git a/typesafety/test_methods/test_cond.yml b/typesafety/test_methods/test_cond.yml index 9f40126f2..93cd54e5e 100644 --- a/typesafety/test_methods/test_cond.yml +++ b/typesafety/test_methods/test_cond.yml @@ -83,3 +83,11 @@ out: | main:16: note: Revealed type is "main.MyOwn[str, float]" main:16: error: Only concrete class can be given where "type[MyOwn[Any, Any]]" is expected [type-abstract] + + +- case: cond_final + disable_cache: false + main: | + from returns.methods import cond + + cond = cond # E: Cannot assign to final name "cond" [misc] diff --git a/typesafety/test_trampolines/test_trampoline.yml b/typesafety/test_trampolines/test_trampoline.yml index e45c773a6..d44dcda90 100644 --- a/typesafety/test_trampolines/test_trampoline.yml +++ b/typesafety/test_trampolines/test_trampoline.yml @@ -45,3 +45,14 @@ return Trampoline(_accumulate, [1], 2) reveal_type(_accumulate([1, 2])) # N: Revealed type is "int" + + +- case: trampoline_attributes + disable_cache: false + main: | + from returns.trampolines import Trampoline + + def test(t: Trampoline[int]) -> None: + reveal_type(t.func) # N: Revealed type is "def (*Any, **Any) -> int" + reveal_type(t.args) # N: Revealed type is "tuple[Any, ...]" + reveal_type(t.kwargs) # N: Revealed type is "dict[str, Any]" From 46309b89cd4ff71e9fc36037596cd781339ed772 Mon Sep 17 00:00:00 2001 From: jorenham Date: Tue, 27 Oct 2026 16:48:04 +0100 Subject: [PATCH 2/2] Apply review suggestions for unsubscripted special type forms Co-authored-by: sobolevn --- returns/primitives/hkt.py | 2 +- returns/primitives/laws.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/returns/primitives/hkt.py b/returns/primitives/hkt.py index 59e2cbff5..8a502f0e0 100644 --- a/returns/primitives/hkt.py +++ b/returns/primitives/hkt.py @@ -214,7 +214,7 @@ class Kinded(Protocol[_FunctionDefType_co]): # type: ignore def __get__( self, instance: _UpdatedType, - type_: type | None, + type_: type[Any] | None, ) -> Callable[..., _UpdatedType]: """Used to decorate and properly analyze method calls.""" diff --git a/returns/primitives/laws.py b/returns/primitives/laws.py index 5f0ac277a..4df4b8a5c 100644 --- a/returns/primitives/laws.py +++ b/returns/primitives/laws.py @@ -1,5 +1,5 @@ from collections.abc import Callable, Sequence -from typing import ClassVar, Final, Generic, TypeVar, final +from typing import Any, ClassVar, Final, Generic, TypeVar, final from returns.primitives.types import Immutable @@ -25,10 +25,10 @@ class Law(Immutable): __slots__ = ('definition',) - definition: Callable + definition: Callable[..., Any] """Function used to define this law.""" - def __init__(self, function: Callable) -> None: + def __init__(self, function: Callable[..., Any]) -> None: """Saves function to the inner state.""" object.__setattr__(self, 'definition', function)